feat: add oauth logic

This commit is contained in:
Stavros
2025-05-12 23:03:14 +03:00
parent 4e91e567b2
commit a488b70bbe
4 changed files with 54 additions and 5 deletions

View 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, [])
}

View File

@@ -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>

View File

@@ -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),
}}

View File

@@ -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(),