In case you missed the first part of this article, read here to catch up
In the last article, we were able to
- Create a team
- Send team invitation,
- Accept team invitation
In this article, we will be talking about
- Rejecting Invitation
- Leaving a team
- Removing member from a team
- Managing roles in a team
Quickly,
- let us create two new users,
- Send invitation from one user to another,
- then we continue from there
PAYLOAD
// user 1
{
"name": "john doe",
"email": "johndoe@gmail.com",
"password": "test1234"
}
// user 2
{
"name": "jane doe",
"email": "janedoe@gmail.com",
"password": "test1234"
}
STEP 1
Let us send invitation from john doe to jane doe
PAYLOAD:
{
"email": "janedoe@gmail.com"
}
RESPONSE:
{
"status": "success",
"data": "invitation sent to janedoe@gmail.com"
}
STEP 2
Let us take a look at the user object for john and jane
// john
"data": {
"user": {
"_id": "647afd1914c2f48dfc18c846",
"name": "john doe",
"email": "johndoe@gmail.com",
"teams": [
{
"_id": "647aff306dcdb9d9546c7b1b",
"name": "nodejs team",
"members": [
{
"name": "john doe",
"email": "johndoe@gmail.com",
"id": "647afd1914c2f48dfc18c846",
"role": "admin"
}
],
"userId": "647afd1914c2f48dfc18c846",
"createdAt": "2023-06-03T08:51:44.822Z",
"__v": 1,
"id": "647aff306dcdb9d9546c7b1b"
}
],
"invitations": [],
"createdAt": "2023-06-03T08:41:06.544Z",
"__v": 5,
"id": "647afd1914c2f48dfc18c846"
}
}
Inside john's object, the team array contains a team with only one member, which is john, and he is the admin
{
"status": "success",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjY0N2FmZDQwMTRjMmY0OGRmYzE4Yzg0OSIsImlhdCI6MTY4NTc4MjUwMiwiZXhwIjoxNjkzNTU4NTAyfQ.NABFYJzvEvOfWUwy5cBnecIrHgDflrF3QVaAsYw_rcc",
"data": {
"user": {
"_id": "647afd4014c2f48dfc18c849",
"name": "jane doe",
"email": "janedoe@gmail.com",
"teams": [],
"invitations": [
{
"_id": "647aff306dcdb9d9546c7b1b",
"name": "nodejs team",
"id": "647aff306dcdb9d9546c7b1b"
}
],
"createdAt": "2023-06-03T08:41:06.544Z",
"__v": 2,
"id": "647afd4014c2f48dfc18c849"
}
}
}
In the jane user object, the team array is empty, because obviously, jane is not a member of any team yet,
And the invitation array contains one team, nodejs team
, the invitation that was sent by john.
STEP 3
REJECTING INVITATION
Now let us compute how to reject the invitation sent by john.
Back to our team controller file
NOTE: Basically the concept is finding the index of the team in the invitation array and deleting it with the Array.splice()
method.
// reject team invitation
exports.rejectInvitation = async (req, res) => {
// find user in db
const user = await User.findById(req.user.id);
// find team in db
// teamID will be gotted as a parameter when we run the request
const team = await Team.findById(req.params.teamId);
// check if team exists
if (!team) {
return res.status(404).json({
status: "failed",
message: "team not found",
});
}
// if team exists, let us find the index of the team in the invitations array
const teamIndex = user.invitations.indexOf(team.id);
// remove team id from the invitations array
user.invitations.splice(teamIndex);
// save changes
await user.save();
return res.status(200).json({
status: "success",
message: "invitation rejected",
});
};
STEP 4
Let us create a route for this request and run it on post man,
NOTE: Pass the team ID as a parameter for this request
router.post(
"/reject-invitation/:teamId",
middleware.protect,
teamController.rejectInvitation
);
RESPONSE:
{
"status": "success",
"message": "invitation rejected"
}
To confirm the invitation was rejected, let us take a look at the user object for jane again.
"data": {
"user": {
"_id": "647afd4014c2f48dfc18c849",
"name": "jane doe",
"email": "janedoe@gmail.com",
"teams": [],
"invitations": [],
"createdAt": "2023-06-03T08:41:06.544Z",
"__v": 3,
"id": "647afd4014c2f48dfc18c849"
}
}
Now the invitation array is empty, because we have successfully deleted the team from the invitation array.
STEP 5
LEAVING A TEAM
To compute this, let us send a new invitation to jane, then login to jane account to accept the invitation, then we can proceed to leave a team.
Because you have to be a member of a team to leave a team.
RESPONSE:
{
"status": "success",
"data": "invitation sent to janedoe@gmail.com"
}
RESPONSE:
{
"status": "success",
"message": "invitation to nodejs team accepted"
}
Let us take a look at jane user object to be sure she's now a member of nodejs team
"data": {
"user": {
"_id": "647afd4014c2f48dfc18c849",
"name": "jane doe",
"email": "janedoe@gmail.com",
"teams": [
{
"_id": "647aff306dcdb9d9546c7b1b",
"name": "nodejs team",
"members": [
{
"name": "john doe",
"email": "johndoe@gmail.com",
"id": "647afd1914c2f48dfc18c846",
"role": "admin"
},
{
"name": "jane doe",
"email": "janedoe@gmail.com",
"id": "647afd4014c2f48dfc18c849",
"role": "member"
}
],
"userId": "647afd1914c2f48dfc18c846",
"createdAt": "2023-06-03T08:51:44.822Z",
"__v": 2,
"id": "647aff306dcdb9d9546c7b1b"
}
],
"invitations": [],
"createdAt": "2023-06-03T08:41:06.544Z",
"__v": 5,
"id": "647afd4014c2f48dfc18c849"
}
}
As you can see, the node.js team has two members, the admin which is john doe, and a jane doe, a member.
STEP 6
Let us proceed to our controller and compute leaving a team
exports.leaveTeam = async (req, res) => {
// find user in db
const user = await User.findById(req.user.id);
// find team in db
const team = await Team.findById(req.params.teamId);
// check if team exists
if (!team) {
return res.status(404).json({
status: "failed",
message: "team not found",
});
}
// if team exist, check if user is a member of the team
const member = team.members.find((item) => item.id === user.id);
// if user is not a member, throw an error and terminate
if (!member) {
return res.status(400).json({
status: "failed",
message: `you are not a member of ${team.name.toUpperCase()}`,
});
}
// if user is a member, find index of team in the team array on the user object
const teamIndex = user.teams.indexOf(team.id);
// delete team from team array
user.teams.splice(teamIndex);
// remove user from member array on the team
const newMembers = team.members.filter((item) => item.id !== member.id);
team.members = newMembers;
// save changes
await team.save();
await user.save();
return res.status(200).json({
status: "success",
message: `successfully exited ${team.name}`,
});
};
STEP 7
Let us create a route for this request and run it on postman
router.post(
"/leave-team/:teamId",
middleware.protect,
teamController.leaveTeam
);
RESPONSE:
{
"status": "success",
"message": "successfully exited nodejs team"
}
To confirm it was successful, let us take a look at the jane user object once again,
"data": {
"user": {
"_id": "647afd4014c2f48dfc18c849",
"name": "jane doe",
"email": "janedoe@gmail.com",
"teams": [],
"invitations": [],
"createdAt": "2023-06-03T08:41:06.544Z",
"__v": 6,
"id": "647afd4014c2f48dfc18c849"
}
}
As expected, the teams array is empty, which means the request was successful.
STEP 8
REMOVING MEMBER FROM A TEAM
Let us repeat the process of sending an invitation to jane and accepting the invitation, then logging in back to john account to remove jane from the team
"data": {
"user": {
"_id": "647afd4014c2f48dfc18c849",
"name": "jane doe",
"email": "janedoe@gmail.com",
"teams": [
{
"_id": "647aff306dcdb9d9546c7b1b",
"name": "nodejs team",
"members": [
{
"name": "john doe",
"email": "johndoe@gmail.com",
"id": "647afd1914c2f48dfc18c846",
"role": "admin"
},
{
"name": "jane doe",
"email": "janedoe@gmail.com",
"id": "647afd4014c2f48dfc18c849",
"role": "member"
}
],
"userId": "647afd1914c2f48dfc18c846",
"createdAt": "2023-06-03T08:51:44.822Z",
"__v": 4,
"id": "647aff306dcdb9d9546c7b1b"
}
],
"invitations": [],
"createdAt": "2023-06-03T08:41:06.544Z",
"__v": 8,
"id": "647afd4014c2f48dfc18c849"
}
}
Jane is already a member of the nodejs team, now let us log back in to john's account to compute removing jane from the nodejs team.
exports.removeMemberFromTeam = async (req, res) => {
// extract userId and teamId from the request query
const { userId, teamId } = req.query;
// find team in db
const team = await Team.findById(teamId);
const user = await User.findById(userId);
// check if team exist
if (!team) {
return res.status(404).json({
status: "failed",
message: "team not found",
});
}
// if team exist, check if user is a member of the team
const member = team.members.find((item) => item.id === userId);
// if user is not a member, throw an error and terminate
if (!member) {
return res.status(400).json({
status: "failed",
message: `you are not a member of ${team.name.toUpperCase()}`,
});
}
// if user is a member, filter user out of the team
const newTeamMember = team.members.filter((item) => item.id !== userId);
team.members = newTeamMember;
// remove teamId from teams array on user object
const teamIndex = user.teams.indexOf(team.id);
user.teams.splice(teamIndex);
// save changes
await team.save();
await user.save();
return res.status(200).json({
status: "success",
message: `${user.name} successfully removed from ${team.name}`,
});
};
STEP 9
Let us create a route for this request and run it in postman
router.post(
"/remove-member",
middleware.protect,
teamController.removeMemberFromTeam
);
// request url
http://localhost:8000/api/v1/team/remove-member?teamId=647aff306dcdb9d9546c7b1b&userId=647afd4014c2f48dfc18c849
RESPONSE:
{
"status": "success",
"message": "jane doe successfully removed from nodejs team"
}
To confirm, let us take a look at the nodejs team again
"teams": [
{
"_id": "647aff306dcdb9d9546c7b1b",
"name": "nodejs team",
"members": [
{
"name": "john doe",
"email": "johndoe@gmail.com",
"id": "647afd1914c2f48dfc18c846",
"role": "admin"
}
],
Nodejs team only contains john, who is the admin, meaning our logic works too.
So far we have been able to
- Create a team
- Send team invitation
- Accept team invitation
- Reject team invitation
- Leave team
- Remove member from team
In the final part of this article, we will be talking about ROLE MANAGEMENT IN A TEAM
I hope you are excited.
Meanwhile Let me know your thoughts on this in the comments section.
Top comments (0)