-
Notifications
You must be signed in to change notification settings - Fork 453
Add ability for user to delete themselves if permission present #1307
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
9bbc084
32176e1
2e1de91
4b57f0b
f6a2f81
9f5272d
2b40775
c4c3206
6d26a5e
2c259d4
6b25c40
3eeb5bd
5570dc8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| --- | ||
| '@clerk/localizations': minor | ||
| '@clerk/clerk-js': minor | ||
| '@clerk/types': minor | ||
| --- | ||
|
|
||
| Adds the ability for users to delete their own accounts, as long as they have permission to do so |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -224,6 +224,10 @@ export class User extends BaseResource implements UserResource { | |
| }); | ||
| }; | ||
|
|
||
| delete = (): Promise<void> => { | ||
| return this._baseDelete({ path: '/me' }); | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just want to flag this, as it's a somewhat non-standard path. Once we fully roll this out in the API there's no going back without a major version boost. |
||
| }; | ||
|
|
||
| getSessions = async (): Promise<SessionWithActivities[]> => { | ||
| if (this.cachedSessionsWithActivities) { | ||
| return this.cachedSessionsWithActivities; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| import type { | ||
| Attributes, | ||
| Actions, | ||
| OAuthProviders, | ||
| OAuthStrategy, | ||
| PasswordSettingsData, | ||
|
|
@@ -29,6 +30,7 @@ export class UserSettings extends BaseResource implements UserSettingsResource { | |
| saml!: SamlSettings; | ||
|
|
||
| attributes!: Attributes; | ||
| actions!: Actions; | ||
| signIn!: SignInData; | ||
| signUp!: SignUpData; | ||
| passwordSettings!: PasswordSettingsData; | ||
|
|
@@ -65,6 +67,7 @@ export class UserSettings extends BaseResource implements UserSettingsResource { | |
| this.attributes = Object.fromEntries( | ||
| Object.entries(data.attributes).map(a => [a[0], { ...a[1], name: a[0] }]), | ||
| ) as Attributes; | ||
| this.actions = data.actions; | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This small modification allows the environment context to have access to this new "actions" property which contains the values for permissions associated with user actions, which are needed for the user delete feature. Big thanks for @SokratisVidros for helping me to find this and patch this value into the right place. |
||
| this.signIn = data.sign_in; | ||
| this.signUp = data.sign_up; | ||
| this.passwordSettings = { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| import { useEnvironment, useCoreUser, useCoreClerk } from '../../contexts'; | ||
| import { localizationKeys, Text } from '../../customizables'; | ||
| import { ContentPage, Form, FormButtons, useCardState, withCardStateProvider } from '../../elements'; | ||
| import { handleError } from '../../utils'; | ||
| import { UserProfileBreadcrumbs } from './UserProfileNavbar'; | ||
| import { useRouter } from '../../router'; | ||
|
|
||
| export const DeletePage = withCardStateProvider(() => { | ||
| const card = useCardState(); | ||
| const environment = useEnvironment(); | ||
| const router = useRouter(); | ||
| const user = useCoreUser(); | ||
| const clerk = useCoreClerk(); | ||
|
|
||
| const deleteUser = async () => { | ||
| try { | ||
| await user.delete(); | ||
| if (clerk.client.activeSessions.length > 0) { | ||
| await router.navigate(environment.displayConfig.afterSignOutOneUrl); | ||
| } else { | ||
| await router.navigate(environment.displayConfig.afterSignOutAllUrl); | ||
| } | ||
| } catch (e) { | ||
| handleError(e, [], card.setError); | ||
| } | ||
| }; | ||
|
|
||
| return ( | ||
| <ContentPage | ||
| headerTitle={localizationKeys('userProfile.deletePage.title')} | ||
| Breadcrumbs={UserProfileBreadcrumbs} | ||
| > | ||
| <Form.Root onSubmit={deleteUser}> | ||
| <Text localizationKey={localizationKeys('userProfile.deletePage.description')} /> | ||
| <FormButtons | ||
| submitLabel={localizationKeys('userProfile.deletePage.confirm')} | ||
| colorScheme='danger' | ||
| /> | ||
| </Form.Root> | ||
| </ContentPage> | ||
| ); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| import { localizationKeys, Flex, Text, Col, Button } from '../../customizables'; | ||
| import { ProfileSection } from '../../elements'; | ||
| import { useRouter } from '../../router'; | ||
|
|
||
| export const DeleteSection = () => { | ||
| const { navigate } = useRouter(); | ||
|
|
||
| return ( | ||
| <ProfileSection | ||
| title={localizationKeys('userProfile.start.dangerSection.title')} | ||
| id='danger' | ||
| > | ||
| <Flex | ||
| justify='between' | ||
| sx={t => ({ marginTop: t.space.$2, marginLeft: t.space.$6 })} | ||
| > | ||
| <Col gap={1}> | ||
| <Text | ||
| variant='regularMedium' | ||
| localizationKey={localizationKeys('userProfile.start.dangerSection.deleteAccountTitle')} | ||
| /> | ||
| <Text | ||
| variant='smallRegular' | ||
| colorScheme='neutral' | ||
| localizationKey={localizationKeys('userProfile.start.dangerSection.deleteAccountDescription')} | ||
| /> | ||
| </Col> | ||
| <Button | ||
| aria-label='Delete account' | ||
| colorScheme='danger' | ||
| textVariant='buttonExtraSmallBold' | ||
| onClick={() => navigate(`delete`)} | ||
| localizationKey={localizationKeys('userProfile.start.dangerSection.deleteAccountButton')} | ||
| /> | ||
| </Flex> | ||
| </ProfileSection> | ||
| ); | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added this command to pair with the playground file I added here while developing the feature. When running this in the terminal, it will rebuild changed files more quickly than running a full build after every save.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense to me. Just curious, does HMR work correctly when using
playground.html? I think HMR won't work unless the file is served underhttpsas HMR relies on webhooks.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does not, requires a manual reload. Maybe we can tinker with this to make it smoother down the line!