Add ability for user to delete themselves if permission present#1307
Add ability for user to delete themselves if permission present#1307
Conversation
🦋 Changeset detectedLatest commit: 5570dc8 The changes in this PR will be included in the next version bump. This PR includes changesets to release 12 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Hi, I’m Jit, a friendly security platform designed to help developers build secure applications from day zero with an MVS (Minimal viable security) mindset. In case there are security findings, they will be communicated to you as a comment inside the PR. Hope you’ll enjoy using Jit. Questions? Comments? Want to learn more? Get in touch with us. |
|
I don't think we need a changeset for this alone, but I can continue to actually implement the effects of these properties on this PR if desired, and that would definitely merit one. |
| membersCount: number; | ||
| pendingInvitationsCount: number; | ||
| publicMetadata: OrganizationPublicMetadata; | ||
| adminDeleteEnabled: boolean; |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
There was a problem hiding this comment.
🤦♂️ pushed before I hit save on the file - thank you! just added
a1cb208 to
fc388c9
Compare
128d75e to
94891e6
Compare
jescalan
left a comment
There was a problem hiding this comment.
Self-review as this is my first PR to Clerk!
| "test": "jest", | ||
| "test:coverage": "jest --collectCoverage && open coverage/lcov-report/index.html" | ||
| "test:coverage": "jest --collectCoverage && open coverage/lcov-report/index.html", | ||
| "watch": "webpack --config webpack.config.js --env production --watch" |
There was a problem hiding this comment.
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.
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 under https as HMR relies on webhooks.
There was a problem hiding this comment.
It does not, requires a manual reload. Maybe we can tinker with this to make it smoother down the line!
| @@ -0,0 +1,170 @@ | |||
| <!DOCTYPE html> | |||
There was a problem hiding this comment.
This playground file is something I built alongside the feature to help me to develop it. This requires little to no setup - you just add your API key, open the file, and its off to the races. I also feel like having a pure js testbed for things is helpful in general - I turned up a number of bugs that I bet are not present in higher abstractions like react & nextjs libs.
There was a problem hiding this comment.
This is great, I wonder if we should move this inside the top-level playground dir instead
There was a problem hiding this comment.
Nice one. Jeff, do you think we can move it under playground as Pantelis suggested? The playground directory hosts other example apps. Not related to this PR but it might be a good idea to do a few cleanups such as:
- move the examples from
packages/sdk-node/examplesintoplaygroundor remove them completely - remove any
playgroundapps that we don't use often - automatically deploy some playground apps to Vercel on every staging release (merge into main) as we do for Accounts.
- align the interface of all package.json files (this is something I'm currently working on)
Hope the extra context is useful to you. I'm very interested to hear your thoughts and more ideas about the playgrounds apps :)
| this.publicMetadata = data.public_metadata; | ||
| this.membersCount = data.members_count; | ||
| this.pendingInvitationsCount = data.pending_invitations_count; | ||
| this.adminDeleteEnabled = data.admin_delete_enabled; |
There was a problem hiding this comment.
I kind of snuck this addition in here - the original PR was just too add these new properties as they were finished in the backend, but it expanded to covering the user delete feature. We decided to move the other two paired features, allowing admins to delete organizations, and gating organization creation permissions for users, to separate PRs, which I will be submitting soon.
If you want, I can move these out to the other PRs to keep the history squeaky clean, just let me know.
There was a problem hiding this comment.
We can leave it as is. No need for extra work.
| publicMetadata: UserPublicMetadata = {}; | ||
| unsafeMetadata: UserUnsafeMetadata = {}; | ||
| lastSignInAt: Date | null = null; | ||
| createOrganizationEnabled: boolean = false; |
There was a problem hiding this comment.
Same here with the leaked properties note above
There was a problem hiding this comment.
❓ Are these named based on the FAPI payload? Another naming that'd make sense to me would be canCreateOrganization but I'm fine with createOrganizationEnabled as well. Same applies to the deleteSelfEnabled prop as well (deleteSelfEnabled -> canDeleteSelf)
This is an extremely nitpicky comment, please feel free to completely ignore :)
There was a problem hiding this comment.
Yes, it is based on FAPI. We iterated a lot on naming these parameters. I can't recall why we didn't pick the canX proposal that was discussed at some point.
@mzhong9723 @jescalan Do you maybe remember?
@nikosdouvlis FYI this is the design doc. You can also check the comments section for naming decisions.
There was a problem hiding this comment.
I poked into this more last night and I don't think these properties are actually needed at all on the User/Org resources directly. They are accessed through UserSettings and OrganizationSettings on the actions sub-property, as it is returned from bapi, and currently the properties are here but they are not actually populated or used, so I'm going to remove them I think.
There was a problem hiding this comment.
as far as canX, I'm not sure to be honest, I just mirrored the property name from bapi for consistency
| this.backupCodeEnabled = data.backup_code_enabled; | ||
| this.twoFactorEnabled = data.two_factor_enabled; | ||
|
|
||
| this.createOrganizationEnabled = data.create_organization_enabled; |
| this.attributes = Object.fromEntries( | ||
| Object.entries(data.attributes).map(a => [a[0], { ...a[1], name: a[0] }]), | ||
| ) as Attributes; | ||
| this.actions = data.actions; |
There was a problem hiding this comment.
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.
| await clerk.signOut({ sessionId: session.id }); | ||
| router.navigate(environment.displayConfig.homeUrl); | ||
| // TODO: for routerless mode, explicitly open the "choose" route | ||
| clerk.openSignIn(); |
There was a problem hiding this comment.
Want to add a little extra context here - after deleting a user, you get signed out, and the router will navigate to the home route, which should contain the sign in UI, in theory. If you have a multi-session app, the sign in UI should allow the user to select the next available session data to log into.
However, if the implementation is just using pure JS and is not associated with a router, the navigation will do nothing other than changing the url hash, so we explicitly open the sign in window. This is a slight bug IMO for router-less apps, since we want to show the "choose" route within the sign in UI to allow to user to choose other sessions if there are any. If you refresh the page, it will automatically log into any other available sessions for a multi-session app, but a refresh shouldn't be necessary.
There was a problem hiding this comment.
Is this fix targeted for multi-session or single-session apps? The sign-in choose screen is only available in multi-session apps.
This behavior is opinionated when it comes to UX. ClerkJS supports afterSignOut props that should also be used in this case as they are the main control for Clerk users to handle post sign-out behavior.
Most importantly, I'd also that FAPI signs out the user during await user.delete. So, the clerk.signOut shouldn't be necessary as the payload of user.delete should purge the current session, and should unmount. Let me double-check that.
| deleteAccountButton: 'Delete Account', | ||
| deleteAccountTitle: 'Delete Account', | ||
| deleteAccountDescription: 'Delete your account and all its associated data', | ||
| }, |
There was a problem hiding this comment.
Just as a note, I only ran the english translation here. I can probably cover a couple more but I'm not sure how we normally tackle translation.
There was a problem hiding this comment.
😀 We officially support only the english translation. It's a personal decision if you want to do the rest as well.
There was a problem hiding this comment.
As Pantelis said, only the en-US localization is officially supported. Localizations that don't have these values set will simply fallback to the en-US one.
bb957fa to
6ff753f
Compare
| this.publicMetadata = data.public_metadata; | ||
| this.membersCount = data.members_count; | ||
| this.pendingInvitationsCount = data.pending_invitations_count; | ||
| this.adminDeleteEnabled = data.admin_delete_enabled; |
There was a problem hiding this comment.
We can leave it as is. No need for extra work.
| await clerk.signOut({ sessionId: session.id }); | ||
| router.navigate(environment.displayConfig.homeUrl); | ||
| // TODO: for routerless mode, explicitly open the "choose" route | ||
| clerk.openSignIn(); |
There was a problem hiding this comment.
Is this fix targeted for multi-session or single-session apps? The sign-in choose screen is only available in multi-session apps.
This behavior is opinionated when it comes to UX. ClerkJS supports afterSignOut props that should also be used in this case as they are the main control for Clerk users to handle post sign-out behavior.
Most importantly, I'd also that FAPI signs out the user during await user.delete. So, the clerk.signOut shouldn't be necessary as the payload of user.delete should purge the current session, and should unmount. Let me double-check that.
| }; | ||
|
|
||
| return ( | ||
| <> |
There was a problem hiding this comment.
❓ Is this fragment required?
There was a problem hiding this comment.
Ah, no it isn't - good catch. This came from me removing the wizard initially, but also ended up removing the success page state then it was no longer needed. Will clean up now.
|
@SokratisVidros removed the unneeded fragment, tested whether |
c03f173 to
3485e0f
Compare
SokratisVidros
left a comment
There was a problem hiding this comment.
Nicely done @jescalan.
One last comment about the router.navigate and it's good to go!
…roperties to User
- When permissions are present, users will see a section in their settings allowing them to delete their account. - `createOrganizationEnabled` property was also added to users in anticipation of a feature allowing permission-gated org creation that should be landing in the next couple days - When a user's account is deleted, they are signed out and nav to the home page.
Co-authored-by: Sokratis Vidros <SokratisVidros@users.noreply.github.com>
cc10097 to
2c259d4
Compare
| }; | ||
|
|
||
| delete = (): Promise<void> => { | ||
| return this._baseDelete({ path: '/me' }); |
There was a problem hiding this comment.
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.
…k#1307) feat(clerk-js): Add delete self feature for users - When permissions are present, users will see a section in their settings allowing them to delete their account. - `createOrganizationEnabled` property was also added to users in anticipation of a feature allowing permission-gated org creation that should be landing in the next couple days. - When a user's account is deleted, they are signed out and nav to the home page.
|
This PR has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Type of change
Packages affected
@clerk/clerk-js@clerk/clerk-react@clerk/nextjs@clerk/remix@clerk/types@clerk/themes@clerk/localizations@clerk/clerk-expo@clerk/backend@clerk/clerk-sdk-node@clerk/shared@clerk/fastify@clerk/chrome-extensiongatsby-plugin-clerkbuild/tooling/choreDescription
createOrganizationEnabledproperty was also added to users in anticipation of a feature allowing permission-gated org creation that should be landing in the next couple days.