Skip to content

Commit

Permalink
feat: update team members endpoint (#666)
Browse files Browse the repository at this point in the history
  • Loading branch information
patricia-mdias authored Dec 12, 2022
1 parent cc1b744 commit 28bbda4
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { PopulateOptions, UpdateQuery } from 'mongoose';
import { FilterQuery, PopulateOptions, UpdateQuery } from 'mongoose';
import { ModelProps, SelectedValues } from '../types';

export type PopulateType = PopulateOptions | (PopulateOptions | string)[];
Expand All @@ -18,9 +18,11 @@ export interface BaseInterfaceRepository<T> {

create(item: T): Promise<T>;

insertMany(listOfItems: T[]): Promise<T[]>;

update(id: string, item: T): Promise<T>;

deleteMany(field: ModelProps<T>, withSession: boolean): Promise<number>;
deleteMany(field: FilterQuery<T>, withSession: boolean): Promise<number>;

countDocuments(): Promise<number>;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ClientSession, Model, UpdateQuery } from 'mongoose';
import { ClientSession, FilterQuery, Model, UpdateQuery } from 'mongoose';
import { BaseInterfaceRepository, PopulateType } from '../interfaces/base.repository.interface';
import { ModelProps, SelectedValues } from '../types';

Expand Down Expand Up @@ -47,6 +47,10 @@ export class MongoGenericRepository<T> implements BaseInterfaceRepository<T> {
return this._repository.create(item);
}

insertMany(listOfItems: T[]): Promise<T[]> {
return this._repository.insertMany(listOfItems);
}

update(id: string, item: T): Promise<T> {
return this._repository.findByIdAndUpdate(id, item).exec();
}
Expand Down Expand Up @@ -74,7 +78,7 @@ export class MongoGenericRepository<T> implements BaseInterfaceRepository<T> {
.exec();
}

async deleteMany(field: ModelProps<T>, withSession = false): Promise<number> {
async deleteMany(field: FilterQuery<T>, withSession = false): Promise<number> {
const { deletedCount } = await this._repository
.deleteMany(field, { session: withSession ? this._session : undefined })
.exec();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,7 @@ export class UpdateTeamApplication implements UpdateTeamApplicationInterface {
updateTeamUser(teamData: TeamUserDto) {
return this.updateTeamService.updateTeamUser(teamData);
}
addAndRemoveTeamUsers(addUsers: TeamUserDto[], removeUsers: string[]) {
return this.updateTeamService.addAndRemoveTeamUsers(addUsers, removeUsers);
}
}
35 changes: 35 additions & 0 deletions backend/src/modules/teams/controller/team.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import { UpdateTeamApplication } from '../applications/update.team.application';
import { CreateTeamDto } from '../dto/crate-team.dto';
import TeamDto from '../dto/team.dto';
import TeamUserDto from '../dto/team.user.dto';
import UpdateTeamUserDto from '../dto/update.team.user.dto';
import { CreateTeamApplicationInterface } from '../interfaces/applications/create.team.application.interface';
import { GetTeamApplicationInterface } from '../interfaces/applications/get.team.application.interface';
import { TYPES } from '../interfaces/types';
Expand Down Expand Up @@ -225,6 +226,40 @@ export default class TeamsController {
return teamUser;
}

@ApiOperation({ summary: 'Add and remove team members' })
@ApiParam({ type: String, name: 'teamId', required: true })
@ApiBody({ type: UpdateTeamUserDto })
@ApiOkResponse({
type: TeamUserDto,
description: 'Team member updated successfully!'
})
@ApiBadRequestResponse({
description: 'Bad Request',
type: BadRequestResponse
})
@ApiUnauthorizedResponse({
description: 'Unauthorized',
type: UnauthorizedResponse
})
@ApiNotFoundResponse({
type: NotFoundResponse,
description: 'Not found!'
})
@ApiForbiddenResponse({
description: 'Forbidden',
type: ForbiddenResponse
})
@ApiInternalServerErrorResponse({
description: 'Internal Server Error',
type: InternalServerErrorResponse
})
@TeamUser([TeamRoles.ADMIN, TeamRoles.STAKEHOLDER])
@UseGuards(TeamUserGuard)
@Put('/:teamId/addAndRemove')
addAndRemoveTeamUsers(@Body() users: UpdateTeamUserDto) {
return this.updateTeamApp.addAndRemoveTeamUsers(users.addUsers, users.removeUsers);
}

@ApiOperation({ summary: 'Delete a specific team' })
@ApiParam({ type: String, name: 'teamId', required: true })
@ApiOkResponse({ type: Boolean, description: 'Team successfully deleted!' })
Expand Down
13 changes: 13 additions & 0 deletions backend/src/modules/teams/dto/update.team.user.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import TeamUserDto from 'src/modules/teams/dto/team.user.dto';
import { ApiProperty } from '@nestjs/swagger';
import { IsArray } from 'class-validator';

export default class UpdateTeamUserDto {
@ApiProperty({ description: 'List of users to add on team' })
@IsArray()
addUsers!: TeamUserDto[];

@ApiProperty({ description: 'List of users ids to remove from team' })
@IsArray()
removeUsers!: string[];
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,8 @@ import { TeamUserDocument } from '../../entities/team.user.schema';

export interface UpdateTeamApplicationInterface {
updateTeamUser(teamData: TeamUserDto): Promise<LeanDocument<TeamUserDocument> | null>;
addAndRemoveTeamUsers(
addUsers: TeamUserDto[],
removeUsers: string[]
): Promise<LeanDocument<TeamUserDocument[]>>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,8 @@ import { TeamUserDocument } from '../../entities/team.user.schema';

export interface UpdateTeamServiceInterface {
updateTeamUser(teamData: TeamUserDto): Promise<LeanDocument<TeamUserDocument> | null>;
addAndRemoveTeamUsers(
addUsers: TeamUserDto[],
removeUsers: string[]
): Promise<LeanDocument<TeamUserDocument[]>>;
}
36 changes: 35 additions & 1 deletion backend/src/modules/teams/services/update.team.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Inject, Injectable } from '@nestjs/common';
import { BadRequestException, Inject, Injectable } from '@nestjs/common';
import { DELETE_FAILED, INSERT_FAILED, UPDATE_FAILED } from 'src/libs/exceptions/messages';
import TeamUserDto from '../dto/team.user.dto';
import TeamUser from '../entities/team.user.schema';
import { UpdateTeamServiceInterface } from '../interfaces/services/update.team.service.interface';
Expand All @@ -15,4 +16,37 @@ export default class UpdateTeamService implements UpdateTeamServiceInterface {
updateTeamUser(teamData: TeamUserDto): Promise<TeamUser | null> {
return this.teamUserRepository.updateTeamUser(teamData);
}

async addAndRemoveTeamUsers(addUsers: TeamUserDto[], removeUsers: string[]) {
try {
let createdTeamUsers: TeamUser[] = [];

if (addUsers.length > 0) createdTeamUsers = await this.addTeamUsers(addUsers);

if (removeUsers.length > 0) await this.deleteTeamUsers(removeUsers, true);

return createdTeamUsers;
} catch (error) {
throw new BadRequestException(UPDATE_FAILED);
}
}

async addTeamUsers(teamUsers: TeamUserDto[]) {
const createdTeamUsers = await this.teamUserRepository.insertMany(teamUsers);

if (createdTeamUsers.length < 1) throw new Error(INSERT_FAILED);

return createdTeamUsers;
}

async deleteTeamUsers(teamUsers: string[], withSession: boolean) {
const deletedCount = await this.teamUserRepository.deleteMany(
{
_id: { $in: teamUsers }
},
withSession
);

if (deletedCount <= 0) throw new Error(DELETE_FAILED);
}
}

0 comments on commit 28bbda4

Please sign in to comment.