Skip to content

Conversation

@ojn03
Copy link

@ojn03 ojn03 commented Oct 3, 2023

ℹ️

Closes #5

📝 Description

Added an endpoint that allows users to update information in the database so that:

  • Only admins can update another person's info
  • Members and Alumni cannot update Applicant info
  • Applicants can only update their own info

Briefly list the changes made to the code:

  1. Added a PUT route in the user controller to accept queries for updateUser and direct logic accordingly. The query accepts userId param as a string and a body as a UpdateUserDTO (defined below)
  2. defined a data transfer object class (UpdateUserDTO), to define the expected structure of the body in the put request.
  3. updated user service to handle the request. Essentially, this first checks the database for the userid, and if it exists, updates the corresponding user with the given DTO. This then returns the updated user on success.
  4. Added input validation to the UpdateUserDTO

✔️ Verification

Created an exampleUser (lets call him Bob) to simulate endpoint callers. Created a local MongoDB database "c4cOpsTest" with multiple users and updated Bob to check for expected behavior in the following scenarios:

  • change Bob's status to Admin. Given an existing userID and valid shema body-> 200 OK + update any userID's associated User and return the updated user
  • change Bob's status to Applicant. Given a userID that is not Bob's -> 400 Bad Request
  • change Bob's status to Applicant/ALUMNI. Given a UserId with Applicant Status -> 400 BAD REQUEST

🏕️ (Optional) Future Work / Notes

  • maybe add an error for when no parameters given
  • Update UpdateUserDTO input validation with Regex to check whether links are in valid format

Copy link
Member

@chromium-52 chromium-52 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯 great job on this! Just a couple notes here and there

@@ -0,0 +1,31 @@
// TODO: Probably want these types to be available to both the frontend and backend in a "common" folder
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯

APPLICANT = 'Applicant',
}

export enum Team {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💭 should we add EBOARD as one of the possible values for this enum since the roles also contain all of the eboard positions? I think this will depend on what the purpose of the team property is (which we should follow up with product about)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Im not too familiar with how the org's structure should be represented here but this does sound sensible. I think once we get clearer specifications, we can make a quick change here

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added EBOARD to the types. We can see what the purpose of the team property is and remove it if necessary

DIRECTOR_OF_FINANCE = 'Director of Finance',
DIRECTOR_OF_MARKETING = 'Director of Marketing',
DIRECTOR_OF_RECRUITMENT = 'Director of Recruitment',
CO_DIRECTOR_OF_OPERATIONS = 'Co-Director of Operations',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔧 can we take out the CO_ prefix from ops and events? It's only fairly recent that we started having co-directors (so that we'll probably have just one co-director of ops in a year or two again) and we could theoretically have multiple people with the same position for most of the other director-level positions as well. And some teams have co-tech leads too so I think it'll be better to just ignore the "co-" part and we'll know if there are co-directors if there are multiple people with the same role

export class User {
@PrimaryGeneratedColumn()
id: number;
@ObjectIdColumn()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔧 just to make our lives easier, I think we should have this column be a number column instead so we're not dealing with too many ObjectIds (which can get a little tedious):

  @Column({ primary: true })
  userId: number;

return this.usersService.findAll();
}

@Put(':userId')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⛏️ should this be a patch route?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⛏️ could we be able to update the name of this file to update-user.dto.ts? Generally, for a dto, we want the name to be name-of-the-dto.dto.ts so that it's easier to tell which file contains which dto

profilePicture?: string;

@IsOptional()
linkedIn?: string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⛏️ for linkedIn and github properties, can we also make sure that they're links (i.e. @IsUrl())?

}

async updateUser(
UpdateUserDTO: UpdateUserDTO,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⛏️ can we make UpdateUserDTO camelCase?

Suggested change
UpdateUserDTO: UpdateUserDTO,
updateUserDTO: UpdateUserDTO,

Comment on lines 89 to 94
await this.usersRepository.update(id, UpdateUserDTO);
return await this.usersRepository.findOne({
where: {
_id: { $eq: id },
},
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⛏️ does something like this also work?

Suggested change
await this.usersRepository.update(id, UpdateUserDTO);
return await this.usersRepository.findOne({
where: {
_id: { $eq: id },
},
});
return await this.usersRepository.save(id, UpdateUserDTO);

);
}

if (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❓ does this mean that only admins can update other people's info? If so, do the two checks above (on lines 63 and 72) check anything that this check misses (in other words, is it possible for someone to change someone's info such that it triggers the checks on either 63 or 72 but not the check on line 82)?

@kimharr24 kimharr24 requested a review from chromium-52 October 14, 2023 23:14
Copy link
Member

@chromium-52 chromium-52 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Just two small nitpicks but looks great overall!

if (exampleUser.status == Status.APPLICANT) {
const currentUser = getCurrentUser();

if (currentUser.status == Status.APPLICANT) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⛏️

Suggested change
if (currentUser.status == Status.APPLICANT) {
if (currentUser.status === Status.APPLICANT) {


@IsOptional()
@IsUrl({
protocols: ['http', 'https'],
Copy link
Member

@chromium-52 chromium-52 Oct 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⛏️ Very cool! If we do this, I think we should restrict the protocol to just https. Linkedin and github both support https and there's no reason to prefer http over https

Copy link

@ananyar807 ananyar807 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great Job!


@Column()
profilePicture: string;
profilePicture: string | null;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💭 maybe instead of having a null profilePicture, we could have a placeholder picture? Just an idea, maybe for a future enhancement

@kimharr24 kimharr24 merged commit a72c127 into main Oct 19, 2023
chromium-52 added a commit that referenced this pull request Oct 31, 2023
* feat: completed updateUser endpoint resolves #5

* style: used strict comparison operators and modified error messages

* added error handling for objectID

* feat: added input validation to UpdateUserDTO

* fix: applied suggestions from PR review

* fix: added domain specific URL validators for DTO

* fix: converted ObjectId primary column to numbers and finalized PR suggestions

* fix: strict equality and https restricted protocol

---------

Co-authored-by: Harrison Kim <kim.harr@northeastern.edu>
@chromium-52 chromium-52 deleted the ojn03/feat-updateUser branch February 22, 2024 22:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Create updateUser endpoint

5 participants