mirror of
https://github.com/steveiliop56/tinyauth.git
synced 2025-10-28 20:55:42 +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 { SeperatorWithChildren } from "@/components/ui/separator";
|
||||||
import { useAppContext } from "@/context/app-context";
|
import { useAppContext } from "@/context/app-context";
|
||||||
import { useUserContext } from "@/context/user-context";
|
import { useUserContext } from "@/context/user-context";
|
||||||
|
import { useIsMounted } from "@/lib/hooks/use-is-mounted";
|
||||||
import { LoginSchema } from "@/schemas/login-schema";
|
import { LoginSchema } from "@/schemas/login-schema";
|
||||||
import { useMutation } from "@tanstack/react-query";
|
import { useMutation } from "@tanstack/react-query";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import { useEffect } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Navigate } from "react-router";
|
import { Navigate } from "react-router";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
@@ -25,7 +27,7 @@ export const LoginPage = () => {
|
|||||||
const redirectUri = searchParams.get("redirect_uri");
|
const redirectUri = searchParams.get("redirect_uri");
|
||||||
|
|
||||||
const { isLoggedIn } = useUserContext();
|
const { isLoggedIn } = useUserContext();
|
||||||
const { configuredProviders, title } = useAppContext();
|
const { configuredProviders, title, oauthAutoRedirect } = useAppContext();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
if (isLoggedIn) {
|
if (isLoggedIn) {
|
||||||
@@ -37,6 +39,27 @@ export const LoginPage = () => {
|
|||||||
0;
|
0;
|
||||||
const userAuthConfigured = configuredProviders.includes("username");
|
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({
|
const loginMutation = useMutation({
|
||||||
mutationFn: (values: LoginSchema) => axios.post("/api/login", values),
|
mutationFn: (values: LoginSchema) => axios.post("/api/login", values),
|
||||||
mutationKey: ["login"],
|
mutationKey: ["login"],
|
||||||
@@ -63,6 +86,14 @@ export const LoginPage = () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isMounted()) {
|
||||||
|
if (oauthConfigured && configuredProviders.includes(oauthAutoRedirect)) {
|
||||||
|
oauthMutation.mutate(oauthAutoRedirect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="min-w-xs sm:min-w-sm">
|
<Card className="min-w-xs sm:min-w-sm">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
@@ -81,6 +112,7 @@ export const LoginPage = () => {
|
|||||||
title="Google"
|
title="Google"
|
||||||
icon={<GoogleIcon />}
|
icon={<GoogleIcon />}
|
||||||
className="w-full"
|
className="w-full"
|
||||||
|
onClick={() => oauthMutation.mutate("google")}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{configuredProviders.includes("github") && (
|
{configuredProviders.includes("github") && (
|
||||||
@@ -88,6 +120,7 @@ export const LoginPage = () => {
|
|||||||
title="Github"
|
title="Github"
|
||||||
icon={<GithubIcon />}
|
icon={<GithubIcon />}
|
||||||
className="w-full"
|
className="w-full"
|
||||||
|
onClick={() => oauthMutation.mutate("github")}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{configuredProviders.includes("generic") && (
|
{configuredProviders.includes("generic") && (
|
||||||
@@ -95,6 +128,7 @@ export const LoginPage = () => {
|
|||||||
title="Generic"
|
title="Generic"
|
||||||
icon={<GenericIcon />}
|
icon={<GenericIcon />}
|
||||||
className="w-full"
|
className="w-full"
|
||||||
|
onClick={() => oauthMutation.mutate("generic")}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import { Navigate } from "react-router";
|
|||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
|
|
||||||
export const LogoutPage = () => {
|
export const LogoutPage = () => {
|
||||||
const { provider, username, email, isLoggedIn } = useUserContext();
|
const { provider, username, isLoggedIn } = useUserContext();
|
||||||
const { genericName } = useAppContext();
|
const { genericName } = useAppContext();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@ export const LogoutPage = () => {
|
|||||||
code: <code />,
|
code: <code />,
|
||||||
}}
|
}}
|
||||||
values={{
|
values={{
|
||||||
username: email,
|
username: username,
|
||||||
provider:
|
provider:
|
||||||
provider === "generic" ? genericName : capitalize(provider),
|
provider === "generic" ? genericName : capitalize(provider),
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import { z } from "zod";
|
|||||||
export const userContextSchema = z.object({
|
export const userContextSchema = z.object({
|
||||||
isLoggedIn: z.boolean(),
|
isLoggedIn: z.boolean(),
|
||||||
username: z.string(),
|
username: z.string(),
|
||||||
name: z.string(),
|
// name: z.string(), not yet implemented
|
||||||
email: z.string(),
|
// email: z.string(),
|
||||||
provider: z.string(),
|
provider: z.string(),
|
||||||
oauth: z.boolean(),
|
oauth: z.boolean(),
|
||||||
totpPending: z.boolean(),
|
totpPending: z.boolean(),
|
||||||
|
|||||||
Reference in New Issue
Block a user