diff --git a/frontend/src/lib/hooks/use-is-mounted.ts b/frontend/src/lib/hooks/use-is-mounted.ts new file mode 100644 index 0000000..35829cc --- /dev/null +++ b/frontend/src/lib/hooks/use-is-mounted.ts @@ -0,0 +1,15 @@ +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, []) +} \ No newline at end of file diff --git a/frontend/src/pages/login-page.tsx b/frontend/src/pages/login-page.tsx index fc9a2cb..c670e06 100644 --- a/frontend/src/pages/login-page.tsx +++ b/frontend/src/pages/login-page.tsx @@ -13,9 +13,11 @@ 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 from "axios"; +import { useEffect } from "react"; import { useTranslation } from "react-i18next"; import { Navigate } from "react-router"; import { toast } from "sonner"; @@ -25,7 +27,7 @@ export const LoginPage = () => { const redirectUri = searchParams.get("redirect_uri"); const { isLoggedIn } = useUserContext(); - const { configuredProviders, title } = useAppContext(); + const { configuredProviders, title, oauthAutoRedirect } = useAppContext(); const { t } = useTranslation(); if (isLoggedIn) { @@ -37,6 +39,27 @@ export const LoginPage = () => { 0; const userAuthConfigured = configuredProviders.includes("username"); + const isMounted = useIsMounted(); + + const oauthMutation = useMutation({ + mutationFn: (provider: string) => axios.get(`/api/oauth/url/${provider}`), + mutationKey: ["oauth"], + onSuccess: (data) => { + toast.info(t("loginOauthSuccessTitle"), { + description: t("loginOauthSuccessSubtitle"), + }); + + setTimeout(() => { + window.location.href = data.data.url; + }, 500); + }, + onError: () => { + toast.error(t("loginOauthFailTitle"), { + description: t("loginOauthFailSubtitle"), + }); + }, + }); + const loginMutation = useMutation({ mutationFn: (values: LoginSchema) => axios.post("/api/login", values), mutationKey: ["login"], @@ -63,6 +86,14 @@ export const LoginPage = () => { }, }); + useEffect(() => { + if (isMounted()) { + if (oauthConfigured && configuredProviders.includes(oauthAutoRedirect)) { + oauthMutation.mutate(oauthAutoRedirect); + } + } + }); + return ( @@ -81,6 +112,7 @@ export const LoginPage = () => { title="Google" icon={} className="w-full" + onClick={() => oauthMutation.mutate("google")} /> )} {configuredProviders.includes("github") && ( @@ -88,6 +120,7 @@ export const LoginPage = () => { title="Github" icon={} className="w-full" + onClick={() => oauthMutation.mutate("github")} /> )} {configuredProviders.includes("generic") && ( @@ -95,6 +128,7 @@ export const LoginPage = () => { title="Generic" icon={} className="w-full" + onClick={() => oauthMutation.mutate("generic")} /> )} diff --git a/frontend/src/pages/logout-page.tsx b/frontend/src/pages/logout-page.tsx index 4553a4a..8ce5c21 100644 --- a/frontend/src/pages/logout-page.tsx +++ b/frontend/src/pages/logout-page.tsx @@ -16,7 +16,7 @@ import { Navigate } from "react-router"; import { toast } from "sonner"; export const LogoutPage = () => { - const { provider, username, email, isLoggedIn } = useUserContext(); + const { provider, username, isLoggedIn } = useUserContext(); const { genericName } = useAppContext(); const { t } = useTranslation(); @@ -56,7 +56,7 @@ export const LogoutPage = () => { code: , }} values={{ - username: email, + username: username, provider: provider === "generic" ? genericName : capitalize(provider), }} diff --git a/frontend/src/schemas/user-context-schema.ts b/frontend/src/schemas/user-context-schema.ts index 08b0b32..3c0a95a 100644 --- a/frontend/src/schemas/user-context-schema.ts +++ b/frontend/src/schemas/user-context-schema.ts @@ -3,8 +3,8 @@ import { z } from "zod"; export const userContextSchema = z.object({ isLoggedIn: z.boolean(), username: z.string(), - name: z.string(), - email: z.string(), + // name: z.string(), not yet implemented + // email: z.string(), provider: z.string(), oauth: z.boolean(), totpPending: z.boolean(),