mirror of
https://github.com/steveiliop56/tinyauth.git
synced 2025-10-28 12:45:47 +00:00
feat: add oauth logic
This commit is contained in:
15
frontend/src/lib/hooks/use-is-mounted.ts
Normal file
15
frontend/src/lib/hooks/use-is-mounted.ts
Normal file
@@ -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, [])
|
||||
}
|
||||
@@ -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 (
|
||||
<Card className="min-w-xs sm:min-w-sm">
|
||||
<CardHeader>
|
||||
@@ -81,6 +112,7 @@ export const LoginPage = () => {
|
||||
title="Google"
|
||||
icon={<GoogleIcon />}
|
||||
className="w-full"
|
||||
onClick={() => oauthMutation.mutate("google")}
|
||||
/>
|
||||
)}
|
||||
{configuredProviders.includes("github") && (
|
||||
@@ -88,6 +120,7 @@ export const LoginPage = () => {
|
||||
title="Github"
|
||||
icon={<GithubIcon />}
|
||||
className="w-full"
|
||||
onClick={() => oauthMutation.mutate("github")}
|
||||
/>
|
||||
)}
|
||||
{configuredProviders.includes("generic") && (
|
||||
@@ -95,6 +128,7 @@ export const LoginPage = () => {
|
||||
title="Generic"
|
||||
icon={<GenericIcon />}
|
||||
className="w-full"
|
||||
onClick={() => oauthMutation.mutate("generic")}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -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: <code />,
|
||||
}}
|
||||
values={{
|
||||
username: email,
|
||||
username: username,
|
||||
provider:
|
||||
provider === "generic" ? genericName : capitalize(provider),
|
||||
}}
|
||||
|
||||
@@ -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(),
|
||||
|
||||
Reference in New Issue
Block a user