feat: Intégration du backend NestJS depuis YNOV
- Framework: NestJS avec TypeORM - Authentification: JWT (access + refresh tokens) - Gestion utilisateurs: CRUD complet avec validation - Routes: auth, users, parents, assistantes maternelles - Dockerfile pour conteneurisation
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { ParentsController } from './parents.controller';
|
||||
|
||||
describe('ParentsController', () => {
|
||||
let controller: ParentsController;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
controllers: [ParentsController],
|
||||
}).compile();
|
||||
|
||||
controller = module.get<ParentsController>(ParentsController);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,58 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Param,
|
||||
Patch,
|
||||
Post,
|
||||
} from '@nestjs/common';
|
||||
import { ParentsService } from './parents.service';
|
||||
import { Parents } from 'src/entities/parents.entity';
|
||||
import { Roles } from 'src/common/decorators/roles.decorator';
|
||||
import { RoleType } from 'src/entities/users.entity';
|
||||
import { ApiBody, ApiResponse, ApiTags } from '@nestjs/swagger';
|
||||
import { CreateParentDto } from '../user/dto/create_parent.dto';
|
||||
import { UpdateParentsDto } from '../user/dto/update_parent.dto';
|
||||
|
||||
@ApiTags('Parents')
|
||||
@Controller('parents')
|
||||
export class ParentsController {
|
||||
constructor(private readonly parentsService: ParentsService) {}
|
||||
|
||||
@Roles(RoleType.SUPER_ADMIN, RoleType.GESTIONNAIRE)
|
||||
@Get()
|
||||
@ApiResponse({ status: 200, type: [Parents], description: 'Liste des parents' })
|
||||
@ApiResponse({ status: 403, description: 'Accès refusé !' })
|
||||
getAll(): Promise<Parents[]> {
|
||||
return this.parentsService.findAll();
|
||||
}
|
||||
|
||||
@Roles(RoleType.SUPER_ADMIN, RoleType.GESTIONNAIRE)
|
||||
@Get(':id')
|
||||
@ApiResponse({ status: 200, type: Parents, description: 'Détails du parent par ID utilisateur' })
|
||||
@ApiResponse({ status: 404, description: 'Parent non trouvé' })
|
||||
@ApiResponse({ status: 403, description: 'Accès refusé !' })
|
||||
getOne(@Param('id') user_id: string): Promise<Parents> {
|
||||
return this.parentsService.findOne(user_id);
|
||||
}
|
||||
|
||||
@Roles(RoleType.SUPER_ADMIN, RoleType.GESTIONNAIRE)
|
||||
@Post()
|
||||
@ApiBody({ type: CreateParentDto })
|
||||
@ApiResponse({ status: 201, type: Parents, description: 'Parent créé avec succès' })
|
||||
@ApiResponse({ status: 403, description: 'Accès refusé !' })
|
||||
create(@Body() dto: CreateParentDto): Promise<Parents> {
|
||||
return this.parentsService.create(dto);
|
||||
}
|
||||
|
||||
@Roles(RoleType.SUPER_ADMIN, RoleType.GESTIONNAIRE)
|
||||
@Patch(':id')
|
||||
@ApiBody({ type: UpdateParentsDto })
|
||||
@ApiResponse({ status: 200, type: Parents, description: 'Parent mis à jour avec succès' })
|
||||
@ApiResponse({ status: 404, description: 'Parent introuvable' })
|
||||
@ApiResponse({ status: 403, description: 'Accès refusé !' })
|
||||
update(@Param('id') id: string, @Body() dto: UpdateParentsDto): Promise<Parents> {
|
||||
return this.parentsService.update(id, dto);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { Parents } from 'src/entities/parents.entity';
|
||||
import { ParentsController } from './parents.controller';
|
||||
import { ParentsService } from './parents.service';
|
||||
import { Users } from 'src/entities/users.entity';
|
||||
|
||||
@Module({
|
||||
imports: [TypeOrmModule.forFeature([Parents, Users])],
|
||||
controllers: [ParentsController],
|
||||
providers: [ParentsService],
|
||||
exports: [ParentsService,
|
||||
TypeOrmModule,
|
||||
],
|
||||
})
|
||||
export class ParentsModule { }
|
||||
@@ -0,0 +1,18 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { ParentsService } from './parents.service';
|
||||
|
||||
describe('ParentsService', () => {
|
||||
let service: ParentsService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [ParentsService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<ParentsService>(ParentsService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,74 @@
|
||||
import {
|
||||
BadRequestException,
|
||||
ConflictException,
|
||||
Injectable,
|
||||
NotFoundException,
|
||||
} from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { Parents } from 'src/entities/parents.entity';
|
||||
import { RoleType, Users } from 'src/entities/users.entity';
|
||||
import { CreateParentDto } from '../user/dto/create_parent.dto';
|
||||
import { UpdateParentsDto } from '../user/dto/update_parent.dto';
|
||||
|
||||
@Injectable()
|
||||
export class ParentsService {
|
||||
constructor(
|
||||
@InjectRepository(Parents)
|
||||
private readonly parentsRepository: Repository<Parents>,
|
||||
@InjectRepository(Users)
|
||||
private readonly usersRepository: Repository<Users>,
|
||||
) {}
|
||||
|
||||
// Création d’un parent
|
||||
async create(dto: CreateParentDto): Promise<Parents> {
|
||||
const user = await this.usersRepository.findOneBy({ id: dto.user_id });
|
||||
if (!user) throw new NotFoundException('Utilisateur introuvable');
|
||||
if (user.role !== RoleType.PARENT) {
|
||||
throw new BadRequestException('Accès réservé aux parents');
|
||||
}
|
||||
|
||||
const exist = await this.parentsRepository.findOneBy({ user_id: dto.user_id });
|
||||
if (exist) throw new ConflictException('Ce parent existe déjà');
|
||||
|
||||
let co_parent: Users | null = null;
|
||||
if (dto.co_parent_id) {
|
||||
co_parent = await this.usersRepository.findOneBy({ id: dto.co_parent_id });
|
||||
if (!co_parent) throw new NotFoundException('Co-parent introuvable');
|
||||
if (co_parent.role !== RoleType.PARENT) {
|
||||
throw new BadRequestException('Accès réservé aux parents');
|
||||
}
|
||||
}
|
||||
|
||||
const entity = this.parentsRepository.create({
|
||||
user_id: dto.user_id,
|
||||
user,
|
||||
co_parent: co_parent ?? undefined,
|
||||
});
|
||||
|
||||
return this.parentsRepository.save(entity);
|
||||
}
|
||||
|
||||
// Liste des parents
|
||||
async findAll(): Promise<Parents[]> {
|
||||
return this.parentsRepository.find({
|
||||
relations: ['user', 'co_parent', 'parentChildren', 'dossiers'],
|
||||
});
|
||||
}
|
||||
|
||||
// Récupérer un parent par user_id
|
||||
async findOne(user_id: string): Promise<Parents> {
|
||||
const parent = await this.parentsRepository.findOne({
|
||||
where: { user_id },
|
||||
relations: ['user', 'co_parent', 'parentChildren', 'dossiers'],
|
||||
});
|
||||
if (!parent) throw new NotFoundException('Parent introuvable');
|
||||
return parent;
|
||||
}
|
||||
|
||||
// Mise à jour
|
||||
async update(id: string, dto: UpdateParentsDto): Promise<Parents> {
|
||||
await this.parentsRepository.update(id, dto);
|
||||
return this.findOne(id);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user