import { Body, Controller, Delete, Get, HttpException, HttpStatus, Logger, Param, Post, Put, UseGuards, } from '@nestjs/common'; import { ApiBearerAuth, ApiOperation, ApiParam, ApiResponse, ApiTags } from '@nestjs/swagger'; import { validate } from 'class-validator'; import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'; import { NewsletterSubscription } from '../newsletter/newsletter-subscription.schema'; import { NewsletterService } from '../newsletter/newsletter.service'; import { Structure } from '../structures/schemas/structure.schema'; import { StructuresService } from '../structures/services/structures.service'; import { Roles } from '../users/decorators/roles.decorator'; import { RolesGuard } from '../users/guards/roles.guard'; import { IUser } from '../users/interfaces/user.interface'; import { EmployerService } from '../users/services/employer.service'; import { JobsService } from '../users/services/jobs.service'; import { UsersService } from '../users/services/users.service'; import { AdminService } from './admin.service'; import { PendingStructureDto } from './dto/pending-structure.dto'; import { SetUserEmployerDto } from './dto/set-user-employer.dto'; import { SetUserJobDto } from './dto/set-user-job.dto'; @ApiTags('admin') @Controller('admin') export class AdminController { private readonly logger = new Logger(AdminController.name); constructor( private usersService: UsersService, private structuresService: StructuresService, private jobsService: JobsService, private employerService: EmployerService, private newsletterService: NewsletterService, private adminService: AdminService ) {} @UseGuards(JwtAuthGuard, RolesGuard) @Roles('admin') @Get('pendingStructures') @ApiOperation({ description: 'Get pending structures for validation' }) public async getPendingAttachments(): Promise<PendingStructureDto[]> { const pendingStructure = await this.usersService.getPendingStructures(); return Promise.all( pendingStructure.map(async (structure) => { const structureDocument = await this.structuresService.findOne(structure.structureId); structure.structureName = structureDocument.structureName; structure.updatedAt = structureDocument.updatedAt; return structure; }) ); } @UseGuards(JwtAuthGuard, RolesGuard) @Roles('admin') @Get('adminStructuresList') @ApiOperation({ description: 'Get pending structures for validation' }) public async getAdminStructuresList() { this.logger.debug('getAdminStructuresList'); const structuresList = { claimed: [], inClaim: [], toClaim: [], incomplete: [] }; const inClaimStructures = await this.getPendingAttachments(); structuresList.inClaim = inClaimStructures.map((structure) => { const lastUpdateDate = this.adminService.getLastUpdateDate(structure); return { structureId: structure.structureId, structureName: structure.structureName, updatedAt: lastUpdateDate, isOutdated: this.adminService.isDateOutdated(lastUpdateDate, 6), }; }); const toClaimStructures = await this.structuresService.findAllUnclaimed(); structuresList.toClaim = toClaimStructures .filter((demand) => !structuresList.inClaim.find((elem) => elem.structureId == demand.structureId)) .map((structure) => { const lastUpdateDate = this.adminService.getLastUpdateDate(structure); return { structureId: structure.structureId, structureName: structure.structureName, updatedAt: lastUpdateDate, isOutdated: this.adminService.isDateOutdated(lastUpdateDate, 6), }; }); const allStructures = await this.structuresService.findAll(); structuresList.claimed = allStructures .filter( (demand) => !structuresList.inClaim.find((elem) => elem.structureId == demand.id) && !structuresList.toClaim.find((elem) => elem.structureId == demand.id) ) .map((structure) => { const lastUpdateDate = this.adminService.getLastUpdateDate(structure); return { structureId: structure.id, structureName: structure.structureName, updatedAt: lastUpdateDate, isOutdated: this.adminService.isDateOutdated(lastUpdateDate, 6), }; }); structuresList.incomplete = await Promise.all( allStructures.map(async (struct) => { const validity = await validate(new Structure(struct)); if (validity.length > 0) { this.logger.debug(`getAdminStructuresList - validation failed. errors: ${validity.toString()}`); const lastUpdateDate = this.adminService.getLastUpdateDate(struct); return { structureId: struct.id, structureName: struct.structureName, updatedAt: lastUpdateDate, isOutdated: this.adminService.isDateOutdated(lastUpdateDate, 6), }; } else { this.logger.debug('getAdminStructuresList - validation succeed'); return null; } }) ); structuresList.incomplete = structuresList.incomplete.filter((structure) => structure); structuresList.claimed.sort((a, b) => a.structureName.localeCompare(b.structureName)); structuresList.inClaim.sort((a, b) => a.structureName.localeCompare(b.structureName)); structuresList.toClaim.sort((a, b) => a.structureName.localeCompare(b.structureName)); structuresList.incomplete.sort((a, b) => a.structureName.localeCompare(b.structureName)); return structuresList; } @UseGuards(JwtAuthGuard, RolesGuard) @Roles('admin') @Post('validatePendingStructure') @ApiOperation({ description: 'Validate structure ownership' }) public async validatePendingStructure(@Body() pendingStructureDto: PendingStructureDto) { const structure = await this.structuresService.findOne(pendingStructureDto.structureId.toString()); if (!structure || structure.deletedAt) { throw new HttpException('Structure does not exist', HttpStatus.NOT_FOUND); } await this.usersService.validatePendingStructure( pendingStructureDto.userEmail, pendingStructureDto.structureId.toString(), structure.structureName, true ); const pendingStructure = await this.usersService.getPendingStructures(); return Promise.all( pendingStructure.map(async (pendingStructureData) => { pendingStructureData.structureName = ( await this.structuresService.findOne(pendingStructureData.structureId) ).structureName; return pendingStructureData; }) ); } @UseGuards(JwtAuthGuard, RolesGuard) @Roles('admin') @Post('rejectPendingStructure') @ApiOperation({ description: 'Refuse structure ownership' }) public async refusePendingStructure(@Body() pendingStructureDto: PendingStructureDto) { const structure = await this.structuresService.findOne(pendingStructureDto.structureId.toString()); if (!structure || structure.deletedAt) { throw new HttpException('Structure does not exist', HttpStatus.NOT_FOUND); } await this.usersService.validatePendingStructure( pendingStructureDto.userEmail, pendingStructureDto.structureId.toString(), structure.structureName, false ); const pendingStructure = await this.usersService.getPendingStructures(); return Promise.all( pendingStructure.map(async (pendingStructureData) => { pendingStructureData.structureName = ( await this.structuresService.findOne(pendingStructureData.structureId) ).structureName; return pendingStructureData; }) ); } @UseGuards(JwtAuthGuard, RolesGuard) @Roles('admin') @Delete('user/:id') @ApiBearerAuth('JWT') @ApiParam({ name: 'id', type: String, required: true }) public async deleteUser(@Param() params) { const user = await this.usersService.deleteOneId(params.id); user.structuresLink.forEach((structureId) => { this.usersService.isStructureClaimed(structureId.toString()).then(async (userFound) => { if (!userFound) { const structure = await this.structuresService.findOne(structureId.toString()); this.structuresService.deleteOne(structure); } }); }); return user; } @UseGuards(JwtAuthGuard, RolesGuard) @Roles('admin') @ApiBearerAuth('JWT') @Post('searchUsers') public async searchUsers(@Body() searchString: { searchString: string }) { if (searchString && searchString.searchString && searchString.searchString.length > 0) return this.usersService.searchUsers(searchString.searchString); else return this.usersService.findAll(); } @UseGuards(JwtAuthGuard, RolesGuard) @Roles('admin') @ApiBearerAuth('JWT') @Get('unAttachedUsers') public async findUnattachedUsers() { return this.usersService.findAllUnattached().then((formatUsers) => { return formatUsers.map((user) => { return { id: user._id, createdAt: user.createdAt ? user.createdAt.toLocaleDateString('fr-FR') : '', unattachedSince: user.unattachedSince ? user.unattachedSince.toLocaleDateString('fr-FR') : '', surname: user.surname, name: user.name, email: user.email, phone: user.phone, job: user.job, employer: user.employer, }; }); }); } @UseGuards(JwtAuthGuard, RolesGuard) @Roles('admin') @ApiBearerAuth('JWT') @Get('attachedUsers') public async findAttachedUsers() { return this.usersService.findAllAttached().then(async (users: IUser[]) => { return this.structuresService.getAllUserCompletedStructures(users); }); } @UseGuards(JwtAuthGuard, RolesGuard) @ApiBearerAuth('JWT') @Roles('admin') @Get('unVerifiedUsers') public async findUnVerifiedUsers() { return this.usersService.findAllUnVerified().then(async (users: IUser[]) => { return this.structuresService.getAllUserCompletedStructures(users); }); } @UseGuards(JwtAuthGuard, RolesGuard) @Roles('admin') @ApiBearerAuth('JWT') @Delete('newsletterSubscription/:email') @ApiParam({ name: 'email', type: String, required: true }) public async unsubscribeUserFromNewsletter(@Param() params): Promise<NewsletterSubscription> { return this.newsletterService.newsletterUnsubscribe(params.email); } @UseGuards(JwtAuthGuard, RolesGuard) @Roles('admin') @ApiBearerAuth('JWT') @ApiOperation({ description: 'Set user job' }) @ApiResponse({ status: HttpStatus.OK, description: 'Return user profile' }) @ApiResponse({ status: HttpStatus.BAD_REQUEST, description: 'User does not exist' }) @ApiResponse({ status: HttpStatus.BAD_REQUEST, description: 'Job does not exist' }) @Put('setUserJob') public async setUserJob(@Body() setUserJob: SetUserJobDto): Promise<IUser> { this.logger.debug(`setUserJob`); const jobDocument = await this.jobsService.findOne(setUserJob.jobId); if (!jobDocument) { this.logger.warn(`Job does not exist: ${setUserJob.jobId}`); throw new HttpException('Job does not exist', HttpStatus.BAD_REQUEST); } const userDocument = await this.usersService.findById(setUserJob.userId); if (!userDocument) { this.logger.warn(`User does not exist: ${setUserJob.userId}`); throw new HttpException('User does not exist', HttpStatus.BAD_REQUEST); } await this.usersService.updateUserJob(userDocument._id, jobDocument); return this.usersService.findById(setUserJob.userId); } @UseGuards(JwtAuthGuard, RolesGuard) @Roles('admin') @ApiBearerAuth('JWT') @ApiOperation({ description: 'Set user employer' }) @ApiResponse({ status: HttpStatus.OK, description: 'Return user profile' }) @ApiResponse({ status: HttpStatus.BAD_REQUEST, description: 'User does not exist' }) @ApiResponse({ status: HttpStatus.BAD_REQUEST, description: 'Employer does not exist' }) @Put('setUserEmployer') public async setUserEmployer(@Body() setUserEmployer: SetUserEmployerDto): Promise<IUser> { this.logger.debug(`setUserEmployer`); const employerDocument = await this.employerService.findOne(setUserEmployer.employerId); if (!employerDocument) { this.logger.warn(`Employer does not exist: ${setUserEmployer.employerId}`); throw new HttpException('Employer does not exist', HttpStatus.BAD_REQUEST); } const userDocument = await this.usersService.findById(setUserEmployer.userId); if (!userDocument) { this.logger.warn(`User does not exist: ${setUserEmployer.userId}`); throw new HttpException('User does not exist', HttpStatus.BAD_REQUEST); } await this.usersService.updateUserEmployer(userDocument._id, employerDocument); return this.usersService.findById(setUserEmployer.userId); } @UseGuards(JwtAuthGuard, RolesGuard) @Roles('admin') @ApiBearerAuth('JWT') @ApiOperation({ description: 'Get deleted structures' }) @Get('getDeletedStructures') public async getDeletedStructures() { this.logger.debug('getDeletedStructures'); const deletedStructures = await this.structuresService.findAll(true); this.logger.debug(`Found ${deletedStructures.length} deleted structures`); return deletedStructures; } }