Challenge Overview
Challenge objectives
-
Create new endpoints for inviting users into Connect projects
Project Background
Topcoder Connect is client facing application of Topcoder. Customer use Topcoder connect to input requirements of their projects, then managers and copilots take it from there. You can see Topcoder Connect in action here: https://connect.topcoder-dev.com
We're making changes to user management - users will be invited to projects and they will have the option of accepting and removing the invitation
Technology Stack
-
NodeJS
-
Sequelize
-
Postgres
-
Elasticsearch
Code Access
Base code can be accessed at https://github.com/topcoder-platform/tc-project-service - dev branch should be used as base
Individual requirements
-
Create a ProjectMemberInvite model
Add a model class with these fields
id,
projectId,
userId,
email,
role,
status (enum: PENDING, ACCEPTED, REFUSED, CANCELED),
createdBy,
createdAt
Create a database migration in /migrations directory
2. Create a new endpoint for inviting members to project
POST /v4/projects/:projectId/members/invite
parameters:
userIds: string list - list of user ids to invite to the project
emails: string list - list of email addresses to invite to the project (in case the user isn't registered already)
role: string - one of PROJECT_MEMBER_ROLE - role to assign to the invited member
Permissions:
users with MANAGER_ROLES can invite all users
users with COPILOT role can invite only PROJECT_MEMBER_ROLE.CUSTOMER
all other users (project members) can invite only PROJECT_MEMBER_ROLE.CUSTOMER
user has to have constants.MANAGER_ROLES role (this is topcoder user role) to be invited as PROJECT_MEMBER_ROLE.MANAGER (this is project level role)
Validations:
each userId - validate that user is not already a member and there isn't an existing invitation
each email - validate it's a valid email address and there isn't an existing invitation
email invites can only be used for CUSTOMER role
implementation:
each user in userIds and emails list:
save the ProjectMemberInvite entity with status PENDING
create a notification event using busApi service (req.app.emit):
topic: notifications.connect.project.member.invite
payload: {projectId, userId, email}
NOTE: this requires adding a handler in src/events/busApi.js
emit a new event type EVENT.ROUTING_KEY.PROJECT_MEMBER_INVITE_CREATED (pubsub.publish)
return a list of ProjectMemberInvite entities
NOTE: implementation should be very similar to the existing "add member" endpoint in src/routes/projectMembers/create.js
3. Create a new endpoint for updating invites to project (changing status)
PUT /v4/projects/:projectId/members/invite
parameters (query):
userId
Status (CANCELED, ACCEPTED, REFUSED)
Permissions:
users with MANAGER_ROLES can cancel the invite for all users
users with COPILOT role can cancel invites only for PROJECT_MEMBER_ROLE.CUSTOMER
all other users (project members) can cancel invites only for PROJECT_MEMBER_ROLE.CUSTOMER
all users can approve or refuse invites for themselves
Validations:
only userId or email is provided
there is an existing invite for the user with status PENDING
implementation:
Update the ProjectMemberInvite entity status from pending to the new STATUS
create a notification event using busApi service (req.app.emit):
topic: notifications.connect.project.member.invite.updated
payload: {projectId, userId, email, status}
NOTE: this requires adding a handler in src/events/busApi.js
emit a new event type EVENT.ROUTING_KEY.PROJECT_MEMBER_INVITE_UPDATED (pubsub.publish)
Add the user to the project - see requirement #7 - refactor the common features into a helper method
4. Create a new endpoint for retrieving current user invite
GET /v4/projects/:projectId/members/invite
Permissions:
all authenticated users can check their invites to the project
Validations:
none
implementation:
get current user email
fetch and return an existing ProjectMemberInvite entity with userId or email equal to current user details and status PENDING
return a 404 if no invitation is found
5. Create an event handler for EVENT.ROUTING_KEY.PROJECT_MEMBER_INVITE_CREATED event
NOTE: implementation is similar to projectMembers event handlers in src/events/projectMembers/index.js #projectMemberAddedHandler
Implementation:
NOTE: goal is to update project document in elasticsearch to save the new member invite into document.invites array
NOTE2: use and refactor src/events/projectMembers/index.js#updateESPromise function
get the document from elasticsearch
add the member to the document.invites array
update the document
6. Create an event handler for EVENT.ROUTING_KEY.PROJECT_MEMBER_INVITE_UPDATED event
NOTE: implementation is similar to projectMembers event handlers in src/events/projectMembers/index.js #projectMemberRemovedHandler
Implementation:
NOTE: goal is to update project document in elasticsearch to delete the new member invite from document.invites array
NOTE2: use and refactor src/events/projectMembers/index.js#updateESPromise function
get the document from elasticsearch
remove the member from the document.invites array
update the document
7. Update addMember endpoint (src/routes/projectMembers/create.js) - this endpoint will be used to add members directly (only managers and copilots) - user being added is current user
- remove all body parameters
Permissions:
all users can call this endpoint
Implementation:
check if the user has constants.USER_ROLE.MANAGER role or constants.USER_ROLE.COPILOT :
keep the current behavior for adding the user and remove handling of isPrimary attribute
If there is any invite to the user in PENDING status, mark it as ACCEPTED
8. Update EVENT.ROUTING_KEY.PROJECT_MEMBER_ADDED event handler
NOTE: implementation at src/events/projectMembers/index.js#projectMemberAddedHandler
Update the handler to remove the invite from document.invites array
General requirements
Consistent logging is required for all endpoints and event handlers - follow the existing implementations
Error handling logic should be followed from the existing implementations
Postman requests are required for all endpoints - update ./postman.json collection
Update swagger api definition (./swagger.yaml)
Unit tests are required for all endpoints (created and updated)
What to submit
Submit a git patch with all the required changes
Submit a short deployment and verification guide
Final Submission Guidelines
Submit a git patch with all the required changes
Submit a short deployment and verification guide