feat: delete passkey

This commit is contained in:
httpjamesm 2023-12-24 16:44:08 -05:00
parent 38728df71a
commit 2d43b8d7c4
No known key found for this signature in database
5 changed files with 146 additions and 35 deletions

View file

@ -1,20 +1,28 @@
import React from 'react';
import React, { createContext } from 'react';
import { ThemeProvider } from '@mui/material/styles';
import { getTheme } from '@ente/shared/themes';
import { useLocalState } from '@ente/shared/hooks/useLocalState';
import { LS_KEYS } from '@ente/shared/storage/localStorage';
import { THEME_COLOR } from '@ente/shared/themes/constants';
import { APPS } from '@ente/shared/apps/constants';
import { CssBaseline } from '@mui/material';
import { CssBaseline, useMediaQuery } from '@mui/material';
import { EnteAppProps } from '@ente/shared/apps/types';
import createEmotionCache from '@ente/shared/themes/createEmotionCache';
import { CacheProvider } from '@emotion/react';
import 'styles/global.css';
export const AppContext = createContext(
{} as {
isMobile: boolean;
}
);
// Client-side cache, shared for the whole session of the user in the browser.
const clientSideEmotionCache = createEmotionCache();
export default function App(props: EnteAppProps) {
const isMobile = useMediaQuery('(max-width:428px)');
const {
Component,
emotionCache = clientSideEmotionCache,
@ -27,7 +35,9 @@ export default function App(props: EnteAppProps) {
<CacheProvider value={emotionCache}>
<ThemeProvider theme={getTheme(themeColor, APPS.PHOTOS)}>
<CssBaseline enableColorScheme />
<AppContext.Provider value={{ isMobile }}>
<Component {...pageProps} />
</AppContext.Provider>
</ThemeProvider>
</CacheProvider>
);

View file

@ -0,0 +1,70 @@
import DialogBoxV2 from '@ente/shared/components/DialogBoxV2';
import EnteButton from '@ente/shared/components/EnteButton';
import { Button, Stack, Typography } from '@mui/material';
import { AppContext } from 'pages/_app';
import { useContext, useState } from 'react';
import { deletePasskey } from 'services/passkeysService';
import { PasskeysContext } from '.';
interface IProps {
open: boolean;
onClose: () => void;
}
const DeletePasskeyModal = (props: IProps) => {
const { isMobile } = useContext(AppContext);
const { selectedPasskey } = useContext(PasskeysContext);
const [loading, setLoading] = useState(false);
const doDelete = async () => {
setLoading(true);
try {
await deletePasskey(selectedPasskey.id);
} catch (error) {
console.error(error);
return;
} finally {
setLoading(false);
}
props.onClose();
};
return (
<DialogBoxV2
fullWidth
open={props.open}
onClose={props.onClose}
fullScreen={isMobile}
attributes={{
title: 'Delete Passkey',
secondary: {
action: props.onClose,
text: 'Cancel',
},
}}>
<Stack spacing={'8px'}>
<Typography>
Are you sure you want to delete this passkey? This action is
irreversible.
</Typography>
<EnteButton
type="submit"
size="large"
color="critical"
loading={loading}
onClick={doDelete}>
Delete Passkey
</EnteButton>
<Button
size="large"
color={'secondary'}
onClick={props.onClose}>
Cancel
</Button>
</Stack>
</DialogBoxV2>
);
};
export default DeletePasskeyModal;

View file

@ -4,10 +4,11 @@ import { Stack } from '@mui/material';
import Titlebar from '@ente/shared/components/Titlebar';
import { MenuItemGroup } from '@ente/shared/components/Menu/MenuItemGroup';
import { EnteMenuItem } from '@ente/shared/components/Menu/EnteMenuItem';
import { useContext } from 'react';
import { useContext, useState } from 'react';
import EditIcon from '@mui/icons-material/Edit';
import DeleteIcon from '@mui/icons-material/Delete';
import MenuItemDivider from '@ente/shared/components/Menu/MenuItemDivider';
import DeletePasskeyModal from './DeletePasskeyModal';
interface IProps {
open: boolean;
@ -15,7 +16,11 @@ interface IProps {
const ManagePasskeyDrawer = (props: IProps) => {
const { setShowPasskeyDrawer } = useContext(PasskeysContext);
const [showDeletePasskeyModal, setShowDeletePasskeyModal] = useState(false);
return (
<>
<EnteDrawer
anchor="right"
open={props.open}
@ -40,13 +45,22 @@ const ManagePasskeyDrawer = (props: IProps) => {
/>
<MenuItemDivider />
<EnteMenuItem
onClick={() => {}}
onClick={() => {
setShowDeletePasskeyModal(true);
}}
startIcon={<DeleteIcon />}
label={'Delete Passkey'}
/>
</MenuItemGroup>
</Stack>
</EnteDrawer>
<DeletePasskeyModal
open={showDeletePasskeyModal}
onClose={() => {
setShowDeletePasskeyModal(false);
}}
/>
</>
);
};

View file

@ -9,7 +9,7 @@ const PasskeyComponent = () => {
const init = async () => {
const data = await getPasskeys();
setPasskeys(data.passkeys);
setPasskeys(data.passkeys || []);
};
useEffect(() => {

View file

@ -21,6 +21,23 @@ export const getPasskeys = async () => {
}
};
export const deletePasskey = async (id: string) => {
try {
const token = getToken();
if (!token) return;
const response = await HTTPService.delete(
`${ENDPOINT}/passkeys/${id}`,
{},
{},
{ 'X-Auth-Token': token }
);
return await response.data;
} catch (e) {
logError(e, 'delete passkey failed');
throw e;
}
};
export const getPasskeyRegistrationOptions = async () => {
try {
const token = getToken();