import {
Body,
Controller,
Delete,
Get,
HttpException,
HttpStatus,
Param,
ParseIntPipe,
Post,
Put,
Query,
UseGuards,
} from '@nestjs/common';
import { ApiParam } from '@nestjs/swagger';
import { Types } from 'mongoose';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { CreateTempUserDto } from '../temp-user/dto/create-temp-user.dto';
import { TempUser } from '../temp-user/temp-user.schema';
import { TempUserService } from '../temp-user/temp-user.service';
import { Roles } from '../users/decorators/roles.decorator';
import { IsStructureOwnerGuard } from '../users/guards/isStructureOwner.guard';
import { RolesGuard } from '../users/guards/roles.guard';
import { User } from '../users/schemas/user.schema';
import { UsersService } from '../users/users.service';
import { CreateStructureDto } from './dto/create-structure.dto';
import { QueryStructure } from './dto/query-structure.dto';
import { structureDto } from './dto/structure.dto';
import { Structure } from './schemas/structure.schema';
import { StructuresService } from './services/structures.service';
@Controller('structures')
export class StructuresController {
constructor(
private readonly structureService: StructuresService,
private readonly userService: UsersService,
private readonly tempUserService: TempUserService
) {}
@Post()
public async create(@Body() createStructureDto: CreateStructureDto): Promise<Structure> {
return this.structureService.create(createStructureDto.idUser, createStructureDto.structure);
}
@Post('search')
public async search(@Query() query: QueryStructure, @Body() body): Promise<Structure[]> {
return this.structureService.search(query.query, body ? body.filters : null);
}
@Put('updateAfterOwnerVerify/:id')
public async updateAfterOwnerVerify(
@Param('id') id: string,
@Body() body: { emailUser: string }
): Promise<Structure> {
return this.structureService.updateAccountVerified(id, body.emailUser);
}
@Put(':id')
@UseGuards(JwtAuthGuard, IsStructureOwnerGuard)
@Roles('admin')
public async update(@Param('id') id: string, @Body() body: structureDto): Promise<Structure> {
return this.structureService.update(id, body);
}
@Get()
public async findAll(): Promise<Structure[]> {
return this.structureService.findAll();
}
@Post(':id/isClaimed')
public async isClaimed(@Param('id') id: string, @Body() user?: User): Promise<boolean> {
return this.structureService.isClaimed(id, user);
}
@Post(':id/claim')
public async claim(@Param('id') idStructure: string, @Body() user: User): Promise<Types.ObjectId[]> {
return this.userService.updateStructureLinkedClaim(user.email, idStructure);
}
@Get('count')
public async countCategories(): Promise<Array<{ id: string; count: number }>> {
const data = await Promise.all([
this.structureService.countByStructureKey('proceduresAccompaniment'),
this.structureService.countByStructureKey('accessRight'),
this.structureService.countByStructureKey('baseSkills'),
this.structureService.countByStructureKey('parentingHelp'),
this.structureService.countByStructureKey('digitalCultureSecurity'),
this.structureService.countByStructureKey('socialAndProfessional'),
this.structureService.countByStructureKey('publicsAccompaniment'),
this.structureService.countByStructureKey('labelsQualifications'),
this.structureService.countByStructureKey('publics'),
this.structureService.countByStructureKey('accessModality'),
this.structureService.countByStructureKey('equipmentsAndServices'),
]);
// Return a concat of all arrays
return data.reduce((a, b) => [...a, ...b]);
}
@Post('address')
public async searchAddress(@Body() data: { searchQuery: string }) {
return await this.structureService.searchAddress(data);
}
@Get(':id')
public async find(@Param('id') id: string) {
return this.structureService.findOne(id);
}
@Delete(':id')
@UseGuards(JwtAuthGuard, IsStructureOwnerGuard)
@Roles('admin')
@ApiParam({ name: 'id', type: String, required: true })
public async delete(@Param('id') id: string) {
return this.structureService.deleteOne(id);
}
@Post(':id/addOwner')
@UseGuards(JwtAuthGuard, IsStructureOwnerGuard)
@Roles('admin')
@ApiParam({ name: 'id', type: String, required: true })
public async addOwner(@Param('id') id: string, @Body() user: CreateTempUserDto): Promise<any> {
// Get structure name
const structure = await this.structureService.findOne(id);
if (!structure) {
throw new HttpException('Invalid Structure', HttpStatus.NOT_FOUND);
}
user.pendingStructuresLink = [Types.ObjectId(id)];
// If user already exist, use created account
if (await this.userService.verifyUserExist(user.email)) {
return this.userService.updateStructureLinked(user.email, id);
}
// If temp user exist, update it
if (await this.tempUserService.findOne(user.email)) {
return this.tempUserService.updateStructureLinked(user);
}
// If not, create
return this.tempUserService.create(user, structure.structureName);
}
@Post(':id/join')
@ApiParam({ name: 'id', type: String, required: true })
public async join(@Param('id') id: string, @Body() user: User): Promise<void> {
// Get structure name
const structure = await this.structureService.findOne(id);
if (!structure) {
throw new HttpException('Invalid Structure', HttpStatus.NOT_FOUND);
}
// Get user and add pending structure
const userFromDb = await this.userService.findOne(user.email);
if (!userFromDb) {
throw new HttpException('Invalid User', HttpStatus.NOT_FOUND);
}
// If user has not already request it, send owner's validation email
if (!userFromDb.pendingStructuresLink.includes(Types.ObjectId(id))) {
userFromDb.pendingStructuresLink.push(Types.ObjectId(id));
userFromDb.save();
// Send structure owner's an email
this.structureService.sendStructureJoinRequest(userFromDb, structure);
}
}
@Post(':id/join/:userId/:status')
@UseGuards(JwtAuthGuard, IsStructureOwnerGuard)
@ApiParam({ name: 'id', type: String, required: true })
@ApiParam({ name: 'userId', type: String, required: true })
@ApiParam({ name: 'status', type: String, required: true })
public async joinValidation(
@Param('id') id: string,
@Param('status') status: string,
@Param('userId') userId: string
): Promise<any> {
// Get structure name
const structure = await this.structureService.findOne(id);
if (!structure) {
throw new HttpException('Invalid Structure', HttpStatus.NOT_FOUND);
}
// Get user and add pending structure
const userFromDb = await this.userService.findById(userId);
if (!userFromDb) {
throw new HttpException('Invalid User', HttpStatus.NOT_FOUND);
}
if (!userFromDb.pendingStructuresLink.includes(Types.ObjectId(id))) {
throw new HttpException('User not linked to structure', HttpStatus.NOT_FOUND);
}
if (status === 'true') {
// Accept
await this.userService.updateStructureLinked(userFromDb.email, id);
await this.userService.removeFromPendingStructureLinked(userFromDb.email, id);
} else {
// Refuse
this.userService.removeFromPendingStructureLinked(userFromDb.email, id);
}
}
@Delete(':id/owner/:userId')
@UseGuards(JwtAuthGuard, IsStructureOwnerGuard)
@Roles('admin')
@ApiParam({ name: 'id', type: String, required: true })
@ApiParam({ name: 'userId', type: String, required: true })
public async removeOwner(@Param('id') id: string, @Param('userId') userId: string): Promise<void> {
// Get structure
const structure = await this.structureService.findOne(id);
if (!structure) {
throw new HttpException('Invalid Structure', HttpStatus.NOT_FOUND);
}
// Get user
const userFromDb = await this.userService.findById(userId);
if (!userFromDb || !userFromDb.structuresLink.includes(Types.ObjectId(id))) {
throw new HttpException('Invalid User', HttpStatus.NOT_FOUND);
}
this.userService.removeFromStructureLinked(userFromDb.email, id);
}
}