mirror of
https://github.com/Myzel394/kleckrelay-website.git
synced 2025-06-19 07:55:25 +02:00
improving AuthContextProvider.tsx
This commit is contained in:
parent
d5e9234f3c
commit
cf21360509
@ -1,17 +1,18 @@
|
|||||||
import {ReactElement, ReactNode, useCallback, useEffect, useMemo} from "react"
|
import {ReactElement, ReactNode, useCallback, useEffect} from "react"
|
||||||
import {AxiosError} from "axios"
|
import {AxiosError} from "axios"
|
||||||
import {decrypt, readMessage, readPrivateKey} from "openpgp"
|
import {decrypt, readMessage, readPrivateKey} from "openpgp"
|
||||||
|
|
||||||
import {useLocalStorage} from "react-use"
|
import {useLocalStorage} from "react-use"
|
||||||
import AuthContext, {AuthContextType, EncryptionStatus} from "./AuthContext"
|
import AuthContext from "./AuthContext"
|
||||||
import useExtensionHandler from "~/AuthContext/use-extension-handler"
|
import useExtensionHandler from "~/AuthContext/use-extension-handler"
|
||||||
import useMasterPassword from "~/AuthContext/use-master-password"
|
import useMasterPassword from "~/AuthContext/use-master-password"
|
||||||
|
|
||||||
import {AuthenticationDetails, ServerUser, User} from "~/server-types"
|
import {AuthenticationDetails, ServerUser, User} from "~/server-types"
|
||||||
import {getMe, REFRESH_TOKEN_URL, refreshToken, RefreshTokenResult} from "~/apis"
|
import {REFRESH_TOKEN_URL, RefreshTokenResult, getMe, refreshToken} from "~/apis"
|
||||||
import {client} from "~/constants/axios-client"
|
import {client} from "~/constants/axios-client"
|
||||||
import {useMutation, useQuery} from "@tanstack/react-query"
|
import {useMutation, useQuery} from "@tanstack/react-query"
|
||||||
import PasswordShareConfirmationDialog from "~/AuthContext/PasswordShareConfirmationDialog"
|
import PasswordShareConfirmationDialog from "~/AuthContext/PasswordShareConfirmationDialog"
|
||||||
|
import useContextValue from "~/AuthContext/use-context-value"
|
||||||
|
|
||||||
export interface AuthContextProviderProps {
|
export interface AuthContextProviderProps {
|
||||||
children: ReactNode
|
children: ReactNode
|
||||||
@ -41,6 +42,40 @@ export default function AuthContextProvider({children}: AuthContextProviderProps
|
|||||||
onError: () => logout(),
|
onError: () => logout(),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const decryptUsingPrivateKey = useCallback(
|
||||||
|
async (message: string): Promise<string> => {
|
||||||
|
if (!user) {
|
||||||
|
throw new Error("User not set.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!user.isDecrypted) {
|
||||||
|
throw new Error("User is not decrypted.")
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
await decrypt({
|
||||||
|
message: await readMessage({
|
||||||
|
armoredMessage: message,
|
||||||
|
}),
|
||||||
|
decryptionKeys: await readPrivateKey({
|
||||||
|
armoredKey: user.notes.privateKey,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
).data.toString()
|
||||||
|
},
|
||||||
|
[user],
|
||||||
|
)
|
||||||
|
|
||||||
|
const contextValue = useContextValue({
|
||||||
|
decryptUsingPrivateKey,
|
||||||
|
encryptUsingMasterPassword,
|
||||||
|
decryptUsingMasterPassword,
|
||||||
|
setDecryptionPassword,
|
||||||
|
logout,
|
||||||
|
login: setUser,
|
||||||
|
user: user || null,
|
||||||
|
})
|
||||||
|
|
||||||
useQuery<AuthenticationDetails, AxiosError>(["get_me"], getMe, {
|
useQuery<AuthenticationDetails, AxiosError>(["get_me"], getMe, {
|
||||||
refetchOnWindowFocus: "always",
|
refetchOnWindowFocus: "always",
|
||||||
refetchOnReconnect: "always",
|
refetchOnReconnect: "always",
|
||||||
@ -90,65 +125,11 @@ export default function AuthContextProvider({children}: AuthContextProviderProps
|
|||||||
return () => client.interceptors.response.eject(interceptor)
|
return () => client.interceptors.response.eject(interceptor)
|
||||||
}, [logout, refresh])
|
}, [logout, refresh])
|
||||||
|
|
||||||
const decryptUsingPrivateKey = useCallback(
|
|
||||||
async (message: string): Promise<string> => {
|
|
||||||
if (!user) {
|
|
||||||
throw new Error("User not set.")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!user.isDecrypted) {
|
|
||||||
throw new Error("User is not decrypted.")
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
await decrypt({
|
|
||||||
message: await readMessage({
|
|
||||||
armoredMessage: message,
|
|
||||||
}),
|
|
||||||
decryptionKeys: await readPrivateKey({
|
|
||||||
armoredKey: user.notes.privateKey,
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
).data.toString()
|
|
||||||
},
|
|
||||||
[user],
|
|
||||||
)
|
|
||||||
|
|
||||||
const value = useMemo<AuthContextType>(
|
|
||||||
() => ({
|
|
||||||
user: user ?? null,
|
|
||||||
login: setUser,
|
|
||||||
encryptionStatus: (() => {
|
|
||||||
if (!user) {
|
|
||||||
return EncryptionStatus.Unavailable
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!user.encryptedPassword) {
|
|
||||||
return EncryptionStatus.Unavailable
|
|
||||||
}
|
|
||||||
|
|
||||||
if (user.isDecrypted) {
|
|
||||||
return EncryptionStatus.Available
|
|
||||||
}
|
|
||||||
|
|
||||||
return EncryptionStatus.PasswordRequired
|
|
||||||
})(),
|
|
||||||
logout,
|
|
||||||
isAuthenticated: user !== null,
|
|
||||||
_encryptUsingMasterPassword: encryptUsingMasterPassword,
|
|
||||||
_decryptUsingMasterPassword: decryptUsingMasterPassword,
|
|
||||||
_decryptUsingPrivateKey: decryptUsingPrivateKey,
|
|
||||||
_setDecryptionPassword: updateDecryptionPassword,
|
|
||||||
_updateUser: setUser,
|
|
||||||
}),
|
|
||||||
[user, logout, encryptUsingMasterPassword, decryptUsingMasterPassword],
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<AuthContext.Provider value={value}>{children}</AuthContext.Provider>
|
<AuthContext.Provider value={contextValue}>{children}</AuthContext.Provider>
|
||||||
<PasswordShareConfirmationDialog
|
<PasswordShareConfirmationDialog
|
||||||
open={Boolean(masterPassword && showDialog)}
|
open={Boolean(_masterPassword && showDialog)}
|
||||||
onShare={sharePassword}
|
onShare={sharePassword}
|
||||||
onClose={doNotAskAgain => {
|
onClose={doNotAskAgain => {
|
||||||
closeDialog(doNotAskAgain)
|
closeDialog(doNotAskAgain)
|
||||||
|
49
src/AuthContext/use-context-value.ts
Normal file
49
src/AuthContext/use-context-value.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import {AuthContextType, EncryptionStatus} from "~/AuthContext/AuthContext"
|
||||||
|
import {ServerUser, User} from "~/server-types"
|
||||||
|
|
||||||
|
export interface UseContextValueData {
|
||||||
|
user: User | ServerUser | null
|
||||||
|
login: (user: User | ServerUser) => void
|
||||||
|
logout: () => void
|
||||||
|
encryptUsingMasterPassword: (content: string) => string
|
||||||
|
decryptUsingMasterPassword: (content: string) => string
|
||||||
|
decryptUsingPrivateKey: (message: string) => Promise<string>
|
||||||
|
setDecryptionPassword: (password: string) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function useContextValue({
|
||||||
|
user,
|
||||||
|
login,
|
||||||
|
logout,
|
||||||
|
encryptUsingMasterPassword,
|
||||||
|
decryptUsingMasterPassword,
|
||||||
|
setDecryptionPassword,
|
||||||
|
decryptUsingPrivateKey,
|
||||||
|
}: UseContextValueData): AuthContextType {
|
||||||
|
return {
|
||||||
|
user,
|
||||||
|
login,
|
||||||
|
logout,
|
||||||
|
isAuthenticated: Boolean(user),
|
||||||
|
encryptionStatus: (() => {
|
||||||
|
if (!user) {
|
||||||
|
return EncryptionStatus.Unavailable
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!user.encryptedPassword) {
|
||||||
|
return EncryptionStatus.Unavailable
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user.isDecrypted) {
|
||||||
|
return EncryptionStatus.Available
|
||||||
|
}
|
||||||
|
|
||||||
|
return EncryptionStatus.PasswordRequired
|
||||||
|
})(),
|
||||||
|
_updateUser: login,
|
||||||
|
_setDecryptionPassword: setDecryptionPassword,
|
||||||
|
_encryptUsingMasterPassword: encryptUsingMasterPassword,
|
||||||
|
_decryptUsingMasterPassword: decryptUsingMasterPassword,
|
||||||
|
_decryptUsingPrivateKey: decryptUsingPrivateKey,
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user