-
Notifications
You must be signed in to change notification settings - Fork 113
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
Introducing User Resource + removing User.find callsites #6222
Conversation
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.
First batch of comments post reviewing the resource itself
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.
Left some questions to discuss with @flvndvd but this looks great!!
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.
🔥
|
||
import { MembershipResource } from "../resources/membership_resource"; | ||
|
||
export function renderUserType(user: User): UserType { |
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.
😘
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.
Getting closer!
Principles to ensure:
- lib/api functions should not expose UserResource as return type if callers don't need to act on the resource. Keep UserType in that case
- lib/api functions should not accept USerResource as arguments if they don't need to interact with the resource and instead continue rely on UserType
As a consequence all of tracking/* should not be changed and receive UserType with .toJSON calls when going into them.
@@ -400,7 +399,7 @@ async function handler( | |||
|
|||
// Delete newly created user if SSO is mandatory. | |||
if (userCreated) { | |||
await deleteUser(user); | |||
await user.unsafeDelete(); |
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.
I'm not super happy with that unsafeDelete()
but I don't think I can get an Authenticator here as we don't seem to always know the workspaceId
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.
LGTM
Given the blast radius of this PR. Let's block on a LGTM from @flvndvd as well 🙏
Can you also try to test most of the flows potentially impacted on front-edge (sign-in, membership edition, general use of the app) 🙏
Looks great! |
front/lib/iam/users.ts
Outdated
} | ||
} | ||
|
||
await user.save(); | ||
await user.updateInfo( |
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.
This is different from what we are currently doing, as user.save()
was not doing a "saving" if the user has not been modified.
front/lib/resources/user_resource.ts
Outdated
return users.map((user) => new UserResource(User, user.get())); | ||
} | ||
|
||
static async fetchNonNullableByModelId( |
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.
I'm not a big fan of this approach since it introduces more entry points and variations for the fetching method.
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.
LGTM, left a few comments that can be addressed in a follow up PR as this one is already pretty big. Just fix the throw in this PR please 🙏
front/lib/api/user.ts
Outdated
if (!memberships.length) { | ||
const message = "Unreachable: user has no memberships."; | ||
logger.error({ userId: user.id, panic: true }, message); | ||
throw new Error(message); |
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.
We should not throw here, but instead return a result.
await user.save(); | ||
if (Object.keys(updateArgs).length > 0) { | ||
const needsUpdate = Object.entries(updateArgs).some( | ||
([key, value]) => user[key as keyof typeof user] !== value |
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.
nit
not a big fan, could be removed if user.updateInfo was taking an object 😉
(can be fixed in a follow up PR)
transaction?: Transaction | ||
): Promise<Result<undefined, Error>> { | ||
try { | ||
await this.model.destroy({ |
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.
nit
at least we should ensure that the user does not have an active membership as this function should solely be used to delete users that did not pass the login.
(Can be fixed in a follow up PR).
front/lib/resources/user_resource.ts
Outdated
getAttribute(attribute: string): any { | ||
switch (attribute) { | ||
case "fullName": | ||
return [this.firstName, this.lastName].filter(Boolean).join(" "); | ||
default: | ||
return ""; | ||
} | ||
} |
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.
IHMO over-engineered, a simple, would have done the job
getAttribute(attribute: string): any { | |
switch (attribute) { | |
case "fullName": | |
return [this.firstName, this.lastName].filter(Boolean).join(" "); | |
default: | |
return ""; | |
} | |
} | |
get fullName(){ | |
return [this.firstName, this.lastName].filter(Boolean).join(" "); | |
} |
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.
Hmm, you litterally told me to change this that was like that to a 'normal getter to which you pass an attribute' 🤔
Reverted
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.
Misunderstood then 🙈
CustomerioServerSideTracking.backfillUser({ | ||
user: u, | ||
}).catch((err) => { | ||
(async () => { |
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.
FWIW, map does not support async function. I'd simply comment out this migration as it was a one time thing.
front/pages/no-workspace.tsx
Outdated
} else { | ||
workspace = res.value; |
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.
You don't need the else as you throw.
9630190
to
b8a2a15
Compare
* Introducing User Resource * Lint * Lint * Add transaction to fecthByProvider * Lint * Removing a lot more renderUserTypes() * Use UserResource almost everywhere * cleanup * Remove transaction from delete() * Migrate the last few things to userResource * fetchAll* -> list* * Return resource * Rename userRes -> user * userRes ToCIOpayload * Fullname getter * getFullName * fecthbyid * Remove deleteUser() * Move fetchRevokedWorkspace to lib/api * UpdateInfo and updateAuth0Sub * UpdateName * Use toJSON * Migrate to usertype * Add fetchNonNullableByModelId * Remove try catch * fectNonNullable * Introduce unsafeDelete * move getFullname() to getAttribute() * Remove nonNullable * Remove userRes * lint * Updateinfo fix * fullName() * Change throw to error * Removing else * typo
Description
This PR introduces a new UserResource class to centralize user-related operations and replace direct User model interactions. It removes the renderUserType function and updates all callsites to use UserResource methods instead. The change aims to improve code organization, type safety, and consistency in user-related operations across the codebase.
This PR:
renderUserType
functionRisk
This change impacts user fetching and manipulation throughout the application. There's a risk of breaking user-related functionality if any use cases were missed during the refactoring. Thorough testing of user authentication, profile management, and any features involving user data is crucial.
Deploy Plan
Tested on edge
To keep under surveillance