mirror of
https://github.com/Myzel394/kleckrelay-website.git
synced 2025-06-20 08:15:26 +02:00
current stand
This commit is contained in:
parent
f9f1a1708c
commit
9fd322ec9a
@ -331,6 +331,12 @@
|
|||||||
"title": "Are you sure you want to leave?",
|
"title": "Are you sure you want to leave?",
|
||||||
"description": "You have unsaved changes. If you leave, your changes will be lost.",
|
"description": "You have unsaved changes. If you leave, your changes will be lost.",
|
||||||
"continueLabel": "Leave"
|
"continueLabel": "Leave"
|
||||||
|
},
|
||||||
|
"passwordShareConfirmationDialog": {
|
||||||
|
"title": "Share Password?",
|
||||||
|
"description": "An extension is asking for your password. Do you want to share it? Only continue if you initiated this action.",
|
||||||
|
"warning": "THIS WILL SHARE YOUR PASSWORD WITH THE EXTENSION. ALL YOUR DATA CAN BE DECRYPTED USING IT. ONLY CONTINUE IF YOU TRUST THE EXTENSION AND IF YOU INITIATED THE REQUEST.",
|
||||||
|
"continueAction": "Share Password"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
import {ReactElement, ReactNode, useCallback, useEffect, useMemo} from "react"
|
import {ReactElement, ReactNode, useCallback, useEffect, useMemo, useState} from "react"
|
||||||
import {useLocalStorage} from "react-use"
|
import {useLocalStorage, useSessionStorage} from "react-use"
|
||||||
import {AxiosError} from "axios"
|
import {AxiosError} from "axios"
|
||||||
import {decrypt, readMessage, readPrivateKey} from "openpgp"
|
import {decrypt, readMessage, readPrivateKey} from "openpgp"
|
||||||
import {useNavigate} from "react-router-dom"
|
import {useNavigate} from "react-router-dom"
|
||||||
|
|
||||||
import {useMutation} from "@tanstack/react-query"
|
import {useMutation} from "@tanstack/react-query"
|
||||||
|
|
||||||
|
import {Dialog} from "@mui/material"
|
||||||
|
import AuthContext, {AuthContextType, EncryptionStatus} from "./AuthContext"
|
||||||
|
|
||||||
import {ServerUser, User} from "~/server-types"
|
import {ServerUser, User} from "~/server-types"
|
||||||
import {REFRESH_TOKEN_URL, RefreshTokenResult, logout as logoutUser, refreshToken} from "~/apis"
|
import {REFRESH_TOKEN_URL, RefreshTokenResult, logout as logoutUser, refreshToken} from "~/apis"
|
||||||
import {client} from "~/constants/axios-client"
|
import {client} from "~/constants/axios-client"
|
||||||
import {decryptString, encryptString} from "~/utils"
|
import {decryptString, encryptString} from "~/utils"
|
||||||
|
import PasswordShareConfirmationDialog from "~/AuthContext/PasswordShareConfirmationDialog"
|
||||||
import AuthContext, {AuthContextType, EncryptionStatus} from "./AuthContext"
|
|
||||||
|
|
||||||
export interface AuthContextProviderProps {
|
export interface AuthContextProviderProps {
|
||||||
children: ReactNode
|
children: ReactNode
|
||||||
@ -22,6 +24,12 @@ export default function AuthContextProvider({children}: AuthContextProviderProps
|
|||||||
onError: () => logout(false),
|
onError: () => logout(false),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const [askForPassword, setAskForPassword] = useState<boolean>(false)
|
||||||
|
const [doNotAskForPassword, setDoNotAskForPassword] = useSessionStorage<boolean>(
|
||||||
|
"do-not-ask-again-for-password",
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
|
||||||
const [decryptionPassword, setDecryptionPassword] = useLocalStorage<string | null>(
|
const [decryptionPassword, setDecryptionPassword] = useLocalStorage<string | null>(
|
||||||
"_global-context-auth-decryption-password",
|
"_global-context-auth-decryption-password",
|
||||||
null,
|
null,
|
||||||
@ -190,5 +198,16 @@ export default function AuthContextProvider({children}: AuthContextProviderProps
|
|||||||
return () => client.interceptors.response.eject(interceptor)
|
return () => client.interceptors.response.eject(interceptor)
|
||||||
}, [logout, refresh])
|
}, [logout, refresh])
|
||||||
|
|
||||||
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>
|
// Handle extension password request
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<AuthContext.Provider value={value}>{children}</AuthContext.Provider>
|
||||||
|
<PasswordShareConfirmationDialog
|
||||||
|
open={askForPassword}
|
||||||
|
onShare={}
|
||||||
|
onClose={() => setAskForPassword(false)}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
69
src/AuthContext/PasswordShareConfirmationDialog.tsx
Normal file
69
src/AuthContext/PasswordShareConfirmationDialog.tsx
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import {ReactElement, useMemo, useState} from "react"
|
||||||
|
import {useTranslation} from "react-i18next"
|
||||||
|
import {TiCancel} from "react-icons/ti"
|
||||||
|
|
||||||
|
import {
|
||||||
|
Alert,
|
||||||
|
Button,
|
||||||
|
Checkbox,
|
||||||
|
Dialog,
|
||||||
|
DialogActions,
|
||||||
|
DialogContent,
|
||||||
|
DialogContentText,
|
||||||
|
DialogTitle,
|
||||||
|
FormControlLabel,
|
||||||
|
} from "@mui/material"
|
||||||
|
|
||||||
|
export interface PasswordShareConfirmationDialogProps {
|
||||||
|
open: boolean
|
||||||
|
onShare: (doNotAskAgain: boolean) => void
|
||||||
|
onClose: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function PasswordShareConfirmationDialog({
|
||||||
|
open,
|
||||||
|
onShare,
|
||||||
|
onClose,
|
||||||
|
}: PasswordShareConfirmationDialogProps): ReactElement {
|
||||||
|
const [doNotAskAgain, setDoNotAskAgain] = useState<boolean>(false)
|
||||||
|
const askAmount = useMemo<number>(
|
||||||
|
() => Number(sessionStorage.getItem("password-share-ask-amount") || 0) + 1,
|
||||||
|
[],
|
||||||
|
)
|
||||||
|
const {t} = useTranslation()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={open} onClose={onClose}>
|
||||||
|
<DialogTitle>{t("components.passwordShareConfirmationDialog.title")}</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogContentText>
|
||||||
|
{t("components.passwordShareConfirmationDialog.description")}
|
||||||
|
</DialogContentText>
|
||||||
|
<Alert severity="warning">
|
||||||
|
{t("components.passwordShareConfirmationDialog.warning")}
|
||||||
|
</Alert>
|
||||||
|
{askAmount > 1 && (
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Checkbox
|
||||||
|
value={doNotAskAgain}
|
||||||
|
onChange={event =>
|
||||||
|
setDoNotAskAgain(event.target.value as any as boolean)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label={t("components.passwordShareConfirmationDialog.doNotAskAgain")}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button startIcon={<TiCancel />} onClick={onClose}>
|
||||||
|
{t("components.general.cancelLabel")}
|
||||||
|
</Button>
|
||||||
|
<Button onClick={() => onShare(doNotAskAgain)}>
|
||||||
|
{t("components.passwordShareConfirmationDialog.continueAction")}
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
)
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
import {ReactElement, useContext} from "react"
|
import {ReactElement, useContext} from "react"
|
||||||
|
|
||||||
|
import {useEffectOnce} from "react-use"
|
||||||
import AuthContext from "~/AuthContext/AuthContext"
|
import AuthContext from "~/AuthContext/AuthContext"
|
||||||
|
|
||||||
export default function ExtensionSignalHandler(): ReactElement {
|
export default function ExtensionSignalHandler(): ReactElement {
|
||||||
@ -7,7 +8,6 @@ export default function ExtensionSignalHandler(): ReactElement {
|
|||||||
const appDomain = import.meta.env.VITE_SERVER_BASE_URL
|
const appDomain = import.meta.env.VITE_SERVER_BASE_URL
|
||||||
const instanceData = {
|
const instanceData = {
|
||||||
appDomain,
|
appDomain,
|
||||||
isAuthenticated: Boolean(user),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
Loading…
x
Reference in New Issue
Block a user