update oauth2 (#84)

* update oauth2

* i18n

* fix validation

* chore: auto-fix linting and formatting issues

---------

Co-authored-by: uubulb <uubulb@users.noreply.github.com>
This commit is contained in:
UUBulb
2024-12-31 23:11:41 +08:00
committed by GitHub
parent d54372fb0c
commit 5517a8df38
8 changed files with 418 additions and 435 deletions

View File

@@ -16,35 +16,9 @@ export const getOauth2RedirectURL = async (
})
}
export const bindOauth2 = async (
provider: string,
state: string,
code: string,
): Promise<ModelOauth2LoginResponse> => {
return fetcher<ModelOauth2LoginResponse>(
FetcherMethod.POST,
`/api/v1/oauth2/${provider}/bind`,
{
state: state,
code: code,
},
)
}
export const unbindOauth2 = async (provider: string): Promise<ModelOauth2LoginResponse> => {
return fetcher<ModelOauth2LoginResponse>(
FetcherMethod.POST,
`/api/v1/oauth2/${provider}/unbind`,
)
}
export const oauth2callback = async (
provider: string,
state: string,
code: string,
): Promise<void> => {
return fetcher<void>(FetcherMethod.POST, `/api/v1/oauth2/${provider}/callback`, {
state,
code,
})
}

View File

@@ -1,5 +1,6 @@
import { getProfile, updateProfile } from "@/api/user"
import { Button } from "@/components/ui/button"
import { Checkbox } from "@/components/ui/checkbox"
import {
Dialog,
DialogClose,
@@ -19,8 +20,10 @@ import {
FormMessage,
} from "@/components/ui/form"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { ScrollArea } from "@/components/ui/scroll-area"
import { useMainStore } from "@/hooks/useMainStore"
import { asOptionalField } from "@/lib/utils"
import { zodResolver } from "@hookform/resolvers/zod"
import { useState } from "react"
import { useForm } from "react-hook-form"
@@ -32,6 +35,7 @@ const profileFormSchema = z.object({
original_password: z.string().min(5).max(72),
new_password: z.string().min(8).max(72),
new_username: z.string().min(1).max(32),
reject_password: asOptionalField(z.boolean()),
})
export const ProfileCard = ({ className }: { className: string }) => {
@@ -44,6 +48,7 @@ export const ProfileCard = ({ className }: { className: string }) => {
original_password: "",
new_password: "",
new_username: profile?.username,
reject_password: profile?.reject_password,
},
resetOptions: {
keepDefaultValues: false,
@@ -122,6 +127,26 @@ export const ProfileCard = ({ className }: { className: string }) => {
</FormItem>
)}
/>
<FormField
control={form.control}
name="reject_password"
render={({ field }) => (
<FormItem className="flex items-center space-x-2">
<FormControl>
<div className="flex items-center gap-2">
<Checkbox
checked={field.value}
onCheckedChange={field.onChange}
/>
<Label className="text-sm">
{t("RejectPassword")}
</Label>
</div>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<DialogFooter className="justify-end">
<DialogClose asChild>

View File

@@ -1,4 +1,3 @@
import { oauth2callback } from "@/api/oauth2"
import { getProfile, login as loginRequest } from "@/api/user"
import { AuthContextProps } from "@/types"
import { createContext, useContext, useEffect, useMemo } from "react"
@@ -45,9 +44,8 @@ export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
}
}
const loginOauth2 = async (provider: string, state: string, code: string) => {
const loginOauth2 = async () => {
try {
await oauth2callback(provider, state, code)
const user = await getProfile()
user.role = user.role || 0
setProfile(user)

View File

@@ -174,5 +174,6 @@
"ConnectedAt": "Connected at",
"OnlineUser": "Online User",
"Total": "Total",
"ConfirmBlock": "Confirm Block"
"ConfirmBlock": "Confirm Block",
"RejectPassword": "Reject Password Login"
}

View File

@@ -35,11 +35,9 @@ function Login() {
const { data: settingData } = useSetting()
useEffect(() => {
const oauth2Code = new URLSearchParams(window.location.search).get("code")
const oauth2State = new URLSearchParams(window.location.search).get("state")
const oauth2Provider = new URLSearchParams(window.location.search).get("provider")
if (oauth2Code && oauth2State && oauth2Provider) {
loginOauth2(oauth2Provider, oauth2State, oauth2Code)
const oauth2 = new URLSearchParams(window.location.search).get("oauth2")
if (oauth2) {
loginOauth2()
}
}, [window.location.search])

View File

@@ -1,4 +1,4 @@
import { Oauth2RequestType, bindOauth2, getOauth2RedirectURL, unbindOauth2 } from "@/api/oauth2"
import { Oauth2RequestType, getOauth2RedirectURL, unbindOauth2 } from "@/api/oauth2"
import { getProfile } from "@/api/user"
import { ProfileCard } from "@/components/profile"
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
@@ -19,22 +19,12 @@ export default function ProfilePage() {
const isDesktop = useMediaQuery("(min-width: 890px)")
useEffect(() => {
const oauth2Code = new URLSearchParams(window.location.search).get("code")
const oauth2State = new URLSearchParams(window.location.search).get("state")
const oauth2Provider = new URLSearchParams(window.location.search).get("provider")
if (oauth2Code && oauth2State && oauth2Provider) {
bindOauth2(oauth2Provider, oauth2State, oauth2Code)
.catch((error) => {
toast.error(error.message)
})
.then(() => {
getProfile().then((profile) => {
setProfile(profile)
})
})
.finally(() => {
window.history.replaceState({}, document.title, window.location.pathname)
})
const oauth2 = new URLSearchParams(window.location.search).get("oauth2")
if (oauth2) {
getProfile().then((profile) => {
setProfile(profile)
})
window.history.replaceState({}, document.title, window.location.pathname)
}
}, [window.location.search])
@@ -50,9 +40,8 @@ export default function ProfilePage() {
const unbindO2 = async (provider: string) => {
try {
await unbindOauth2(provider)
getProfile().then((profile) => {
setProfile(profile)
})
const profile = await getProfile()
setProfile(profile)
} catch (error: any) {
toast.error(error.message)
}

File diff suppressed because it is too large Load Diff

View File

@@ -3,6 +3,6 @@ import { ModelProfile } from "@/types"
export interface AuthContextProps {
profile: ModelProfile | undefined
login: (username: string, password: string) => void
loginOauth2: (provider: string, state: string, code: string) => void
loginOauth2: () => void
logout: () => void
}