mirror of
https://github.com/steveiliop56/tinyauth.git
synced 2025-12-08 01:06:34 +00:00
feat: add option to disable ui warnings
This commit is contained in:
@@ -71,6 +71,7 @@ func (c *rootCmd) Register() {
|
||||
{"disable-analytics", false, "Disable anonymous version collection."},
|
||||
{"disable-resources", false, "Disable the resources server."},
|
||||
{"socket-path", "", "Path to the Unix socket to bind the server to."},
|
||||
{"disable-ui-warnings", false, "Disable UI warnings about insecure configurations."},
|
||||
}
|
||||
|
||||
for _, opt := range configOptions {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "tinyauth-shadcn",
|
||||
"name": "tinyauth",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
|
||||
@@ -31,7 +31,7 @@ const BaseLayout = ({ children }: { children: React.ReactNode }) => {
|
||||
};
|
||||
|
||||
export const Layout = () => {
|
||||
const { appUrl } = useAppContext();
|
||||
const { appUrl, disableUiWarnings } = useAppContext();
|
||||
const [ignoreDomainWarning, setIgnoreDomainWarning] = useState(() => {
|
||||
return window.sessionStorage.getItem("ignoreDomainWarning") === "true";
|
||||
});
|
||||
@@ -42,7 +42,7 @@ export const Layout = () => {
|
||||
setIgnoreDomainWarning(true);
|
||||
}, [setIgnoreDomainWarning]);
|
||||
|
||||
if (!ignoreDomainWarning && appUrl !== currentUrl) {
|
||||
if (!ignoreDomainWarning && !disableUiWarnings && appUrl !== currentUrl) {
|
||||
return (
|
||||
<BaseLayout>
|
||||
<DomainWarning
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
import { useCallback, useEffect, useRef } from "react";
|
||||
|
||||
export function useIsMounted(): () => boolean {
|
||||
const isMounted = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
isMounted.current = true;
|
||||
|
||||
return () => {
|
||||
isMounted.current = false;
|
||||
};
|
||||
}, []);
|
||||
|
||||
return useCallback(() => isMounted.current, []);
|
||||
}
|
||||
@@ -14,7 +14,7 @@ import { Navigate, useLocation, useNavigate } from "react-router";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export const ContinuePage = () => {
|
||||
const { cookieDomain } = useAppContext();
|
||||
const { cookieDomain, disableUiWarnings } = useAppContext();
|
||||
const { isLoggedIn } = useUserContext();
|
||||
const { search } = useLocation();
|
||||
const { t } = useTranslation();
|
||||
@@ -53,12 +53,16 @@ export const ContinuePage = () => {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!isLoggedIn) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
!isLoggedIn ||
|
||||
!isValidRedirectUri ||
|
||||
!isTrustedRedirectUri ||
|
||||
!isAllowedRedirectProto ||
|
||||
isHttpsDowngrade
|
||||
(!isValidRedirectUri ||
|
||||
!isAllowedRedirectProto ||
|
||||
!isTrustedRedirectUri ||
|
||||
isHttpsDowngrade) &&
|
||||
!disableUiWarnings
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@@ -76,14 +80,7 @@ export const ContinuePage = () => {
|
||||
clearTimeout(auto);
|
||||
clearTimeout(reveal);
|
||||
};
|
||||
}, [
|
||||
handleRedirect,
|
||||
isAllowedRedirectProto,
|
||||
isHttpsDowngrade,
|
||||
isLoggedIn,
|
||||
isTrustedRedirectUri,
|
||||
isValidRedirectUri,
|
||||
]);
|
||||
}, []);
|
||||
|
||||
if (!isLoggedIn) {
|
||||
return (
|
||||
@@ -98,7 +95,7 @@ export const ContinuePage = () => {
|
||||
return <Navigate to="/logout" replace />;
|
||||
}
|
||||
|
||||
if (!isTrustedRedirectUri) {
|
||||
if (!isTrustedRedirectUri && !disableUiWarnings) {
|
||||
return (
|
||||
<Card role="alert" aria-live="assertive" className="min-w-xs sm:min-w-sm">
|
||||
<CardHeader>
|
||||
@@ -136,7 +133,7 @@ export const ContinuePage = () => {
|
||||
);
|
||||
}
|
||||
|
||||
if (isHttpsDowngrade) {
|
||||
if (isHttpsDowngrade && !disableUiWarnings) {
|
||||
return (
|
||||
<Card role="alert" aria-live="assertive" className="min-w-xs sm:min-w-sm">
|
||||
<CardHeader>
|
||||
|
||||
@@ -18,7 +18,6 @@ import { OAuthButton } from "@/components/ui/oauth-button";
|
||||
import { SeperatorWithChildren } from "@/components/ui/separator";
|
||||
import { useAppContext } from "@/context/app-context";
|
||||
import { useUserContext } from "@/context/user-context";
|
||||
import { useIsMounted } from "@/lib/hooks/use-is-mounted";
|
||||
import { LoginSchema } from "@/schemas/login-schema";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import axios, { AxiosError } from "axios";
|
||||
@@ -40,7 +39,6 @@ export const LoginPage = () => {
|
||||
const { providers, title, oauthAutoRedirect } = useAppContext();
|
||||
const { search } = useLocation();
|
||||
const { t } = useTranslation();
|
||||
const isMounted = useIsMounted();
|
||||
const [oauthAutoRedirectHandover, setOauthAutoRedirectHandover] =
|
||||
useState(false);
|
||||
const [showRedirectButton, setShowRedirectButton] = useState(false);
|
||||
@@ -112,31 +110,20 @@ export const LoginPage = () => {
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (isMounted()) {
|
||||
if (
|
||||
oauthProviders.length !== 0 &&
|
||||
providers.find((provider) => provider.id === oauthAutoRedirect) &&
|
||||
!isLoggedIn &&
|
||||
redirectUri
|
||||
) {
|
||||
// Not sure of a better way to do this
|
||||
// eslint-disable-next-line react-hooks/set-state-in-effect
|
||||
setOauthAutoRedirectHandover(true);
|
||||
oauthMutation.mutate(oauthAutoRedirect);
|
||||
redirectButtonTimer.current = window.setTimeout(() => {
|
||||
setShowRedirectButton(true);
|
||||
}, 5000);
|
||||
}
|
||||
if (
|
||||
providers.find((provider) => provider.id === oauthAutoRedirect) &&
|
||||
!isLoggedIn &&
|
||||
redirectUri
|
||||
) {
|
||||
// Not sure of a better way to do this
|
||||
// eslint-disable-next-line react-hooks/set-state-in-effect
|
||||
setOauthAutoRedirectHandover(true);
|
||||
oauthMutation.mutate(oauthAutoRedirect);
|
||||
redirectButtonTimer.current = window.setTimeout(() => {
|
||||
setShowRedirectButton(true);
|
||||
}, 5000);
|
||||
}
|
||||
}, [
|
||||
isMounted,
|
||||
oauthProviders.length,
|
||||
providers,
|
||||
isLoggedIn,
|
||||
redirectUri,
|
||||
oauthAutoRedirect,
|
||||
oauthMutation,
|
||||
]);
|
||||
}, []);
|
||||
|
||||
useEffect(
|
||||
() => () => {
|
||||
|
||||
@@ -14,6 +14,7 @@ export const appContextSchema = z.object({
|
||||
forgotPasswordMessage: z.string(),
|
||||
backgroundImage: z.string(),
|
||||
oauthAutoRedirect: z.string(),
|
||||
disableUiWarnings: z.boolean(),
|
||||
});
|
||||
|
||||
export type AppContextSchema = z.infer<typeof appContextSchema>;
|
||||
|
||||
@@ -236,6 +236,7 @@ func (app *BootstrapApp) Setup() error {
|
||||
ForgotPasswordMessage: app.config.ForgotPasswordMessage,
|
||||
BackgroundImage: app.config.BackgroundImage,
|
||||
OAuthAutoRedirect: app.config.OAuthAutoRedirect,
|
||||
DisableUIWarnings: app.config.DisableUIWarnings,
|
||||
}, apiRouter)
|
||||
|
||||
oauthController := controller.NewOAuthController(controller.OAuthControllerConfig{
|
||||
|
||||
@@ -41,6 +41,7 @@ type Config struct {
|
||||
TrustedProxies string `mapstructure:"trusted-proxies"`
|
||||
DisableAnalytics bool `mapstructure:"disable-analytics"`
|
||||
DisableResources bool `mapstructure:"disable-resources"`
|
||||
DisableUIWarnings bool `mapstructure:"disable-ui-warnings"`
|
||||
SocketPath string `mapstructure:"socket-path"`
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ type AppContextResponse struct {
|
||||
ForgotPasswordMessage string `json:"forgotPasswordMessage"`
|
||||
BackgroundImage string `json:"backgroundImage"`
|
||||
OAuthAutoRedirect string `json:"oauthAutoRedirect"`
|
||||
DisableUIWarnings bool `json:"disableUiWarnings"`
|
||||
}
|
||||
|
||||
type Provider struct {
|
||||
@@ -48,6 +49,7 @@ type ContextControllerConfig struct {
|
||||
ForgotPasswordMessage string
|
||||
BackgroundImage string
|
||||
OAuthAutoRedirect string
|
||||
DisableUIWarnings bool
|
||||
}
|
||||
|
||||
type ContextController struct {
|
||||
@@ -56,6 +58,10 @@ type ContextController struct {
|
||||
}
|
||||
|
||||
func NewContextController(config ContextControllerConfig, router *gin.RouterGroup) *ContextController {
|
||||
if config.DisableUIWarnings {
|
||||
log.Warn().Msg("UI warnings are disabled. This may expose users to security risks. Proceed with caution.")
|
||||
}
|
||||
|
||||
return &ContextController{
|
||||
config: config,
|
||||
router: router,
|
||||
@@ -117,5 +123,6 @@ func (controller *ContextController) appContextHandler(c *gin.Context) {
|
||||
ForgotPasswordMessage: controller.config.ForgotPasswordMessage,
|
||||
BackgroundImage: controller.config.BackgroundImage,
|
||||
OAuthAutoRedirect: controller.config.OAuthAutoRedirect,
|
||||
DisableUIWarnings: controller.config.DisableUIWarnings,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ var controllerCfg = controller.ContextControllerConfig{
|
||||
ForgotPasswordMessage: "Contact admin to reset your password.",
|
||||
BackgroundImage: "/assets/bg.jpg",
|
||||
OAuthAutoRedirect: "google",
|
||||
DisableUIWarnings: false,
|
||||
}
|
||||
|
||||
var userContext = config.UserContext{
|
||||
@@ -75,6 +76,7 @@ func TestAppContextHandler(t *testing.T) {
|
||||
ForgotPasswordMessage: controllerCfg.ForgotPasswordMessage,
|
||||
BackgroundImage: controllerCfg.BackgroundImage,
|
||||
OAuthAutoRedirect: controllerCfg.OAuthAutoRedirect,
|
||||
DisableUIWarnings: controllerCfg.DisableUIWarnings,
|
||||
}
|
||||
|
||||
router, recorder := setupContextController(nil)
|
||||
@@ -102,6 +104,7 @@ func TestUserContextHandler(t *testing.T) {
|
||||
Provider: userContext.Provider,
|
||||
OAuth: userContext.OAuth,
|
||||
TotpPending: userContext.TotpPending,
|
||||
OAuthName: userContext.OAuthName,
|
||||
}
|
||||
|
||||
// Test with context
|
||||
|
||||
Reference in New Issue
Block a user