init import projet
This commit is contained in:
@@ -0,0 +1,188 @@
|
||||
import {
|
||||
BadRequestException,
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
MaxFileSizeValidator,
|
||||
Param,
|
||||
Patch,
|
||||
Req,
|
||||
Post,
|
||||
ParseFilePipe,
|
||||
UploadedFile,
|
||||
UseGuards,
|
||||
UseInterceptors,
|
||||
} from '@nestjs/common';
|
||||
import { UserRole } from '@prisma/client';
|
||||
import { FileInterceptor } from '@nestjs/platform-express';
|
||||
import { diskStorage } from 'multer';
|
||||
import { extname, join } from 'path';
|
||||
import { existsSync, mkdirSync, readdirSync } from 'fs';
|
||||
import { JwtAuthGuard } from '../auth/jwt-auth.guard';
|
||||
import type { AuthenticatedRequest } from '../auth/jwt-auth.guard';
|
||||
import { Roles } from '../auth/roles.decorator';
|
||||
import { RolesGuard } from '../auth/roles.guard';
|
||||
import { CreateUserDto } from './dto/create-user.dto';
|
||||
import { AssignUserProjectDto } from './dto/assign-user-project.dto';
|
||||
import { UpdateMyProfileDto } from './dto/update-my-profile.dto';
|
||||
import { UpdateUserDto } from './dto/update-user.dto';
|
||||
import { UsersService } from './users.service';
|
||||
|
||||
const uploadsDir = join(process.cwd(), 'uploads');
|
||||
|
||||
const storage = diskStorage({
|
||||
destination: (_req, _file, callback) => {
|
||||
if (!existsSync(uploadsDir)) {
|
||||
mkdirSync(uploadsDir, { recursive: true });
|
||||
}
|
||||
callback(null, uploadsDir);
|
||||
},
|
||||
filename: (_req, file, callback) => {
|
||||
const uniqueSuffix = `${Date.now()}-${Math.round(Math.random() * 1e9)}`;
|
||||
callback(null, `profile-${uniqueSuffix}${extname(file.originalname)}`);
|
||||
},
|
||||
});
|
||||
|
||||
@Controller('users')
|
||||
export class UsersController {
|
||||
private readonly defaultAvatars: string[];
|
||||
|
||||
constructor(private readonly usersService: UsersService) {
|
||||
const avatarsDir = join(process.cwd(), 'public', 'default-avatars');
|
||||
const imageExts = ['.png', '.jpg', '.jpeg', '.webp'];
|
||||
try {
|
||||
this.defaultAvatars = readdirSync(avatarsDir)
|
||||
.filter((f) => imageExts.includes(extname(f).toLowerCase()))
|
||||
.sort()
|
||||
.map((f) => `/default-avatars/${f}`);
|
||||
} catch {
|
||||
this.defaultAvatars = [];
|
||||
}
|
||||
}
|
||||
|
||||
@Get('default-avatars')
|
||||
listDefaultAvatars() {
|
||||
return this.defaultAvatars;
|
||||
}
|
||||
|
||||
@Get('me')
|
||||
@UseGuards(JwtAuthGuard)
|
||||
me(@Req() request: AuthenticatedRequest) {
|
||||
return this.usersService.getProfile(request.user!.sub);
|
||||
}
|
||||
|
||||
@Patch('me')
|
||||
@UseGuards(JwtAuthGuard)
|
||||
updateMe(
|
||||
@Req() request: AuthenticatedRequest,
|
||||
@Body() updateMyProfileDto: UpdateMyProfileDto,
|
||||
) {
|
||||
return this.usersService.updateMyProfile(
|
||||
request.user!.sub,
|
||||
updateMyProfileDto.displayName,
|
||||
);
|
||||
}
|
||||
|
||||
@Post('me/photo')
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@UseInterceptors(FileInterceptor('file', { storage }))
|
||||
uploadPhoto(
|
||||
@Req() request: AuthenticatedRequest,
|
||||
@Body() body: { bgColor?: string },
|
||||
@UploadedFile(
|
||||
new ParseFilePipe({
|
||||
validators: [
|
||||
new MaxFileSizeValidator({ maxSize: 5 * 1024 * 1024 }),
|
||||
],
|
||||
fileIsRequired: false,
|
||||
}),
|
||||
)
|
||||
file?: Express.Multer.File,
|
||||
) {
|
||||
if (file) {
|
||||
const allowedMimeTypes = ['image/png', 'image/jpeg', 'image/jpg', 'image/webp'];
|
||||
if (!allowedMimeTypes.includes(file.mimetype)) {
|
||||
throw new BadRequestException('Format non supporté. Utilisez PNG, JPG ou WEBP.');
|
||||
}
|
||||
}
|
||||
|
||||
const profileImageUrl = file ? `/uploads/${file.filename}` : body.bgColor && !file ? undefined : undefined;
|
||||
const bgColor = body.bgColor ?? undefined;
|
||||
|
||||
if (!file && !bgColor) {
|
||||
throw new BadRequestException('Envoyez une image ou une couleur de fond.');
|
||||
}
|
||||
|
||||
return this.usersService.updateProfileImage(
|
||||
request.user!.sub,
|
||||
file ? `/uploads/${file.filename}` : undefined,
|
||||
bgColor,
|
||||
);
|
||||
}
|
||||
|
||||
@Delete('me/photo')
|
||||
@UseGuards(JwtAuthGuard)
|
||||
deletePhoto(@Req() request: AuthenticatedRequest) {
|
||||
return this.usersService.updateProfileImage(request.user!.sub, null, null);
|
||||
}
|
||||
|
||||
@Patch('me/avatar')
|
||||
@UseGuards(JwtAuthGuard)
|
||||
setDefaultAvatar(
|
||||
@Req() request: AuthenticatedRequest,
|
||||
@Body() body: { avatarUrl: string; bgColor?: string },
|
||||
) {
|
||||
if (!body.avatarUrl || !this.defaultAvatars.includes(body.avatarUrl)) {
|
||||
throw new BadRequestException('Avatar par defaut invalide.');
|
||||
}
|
||||
return this.usersService.updateProfileImage(
|
||||
request.user!.sub,
|
||||
body.avatarUrl,
|
||||
body.bgColor,
|
||||
);
|
||||
}
|
||||
|
||||
@Post()
|
||||
@UseGuards(JwtAuthGuard, RolesGuard)
|
||||
@Roles(UserRole.ADMIN)
|
||||
create(@Req() request: AuthenticatedRequest, @Body() createUserDto: CreateUserDto) {
|
||||
return this.usersService.create(createUserDto, request.user?.sub);
|
||||
}
|
||||
|
||||
@Get()
|
||||
@UseGuards(JwtAuthGuard, RolesGuard)
|
||||
@Roles(UserRole.ADMIN)
|
||||
list() {
|
||||
return this.usersService.list();
|
||||
}
|
||||
|
||||
@Patch(':id')
|
||||
@UseGuards(JwtAuthGuard, RolesGuard)
|
||||
@Roles(UserRole.ADMIN)
|
||||
update(
|
||||
@Param('id') id: string,
|
||||
@Body() updateUserDto: UpdateUserDto,
|
||||
@Req() request: AuthenticatedRequest,
|
||||
) {
|
||||
return this.usersService.updateById(id, updateUserDto, request.user?.sub);
|
||||
}
|
||||
|
||||
@Patch(':id/project')
|
||||
@UseGuards(JwtAuthGuard, RolesGuard)
|
||||
@Roles(UserRole.ADMIN)
|
||||
assignProject(
|
||||
@Param('id') id: string,
|
||||
@Body() dto: AssignUserProjectDto,
|
||||
@Req() request: AuthenticatedRequest,
|
||||
) {
|
||||
return this.usersService.assignProjectById(id, dto.projectId, request.user?.sub);
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
@UseGuards(JwtAuthGuard, RolesGuard)
|
||||
@Roles(UserRole.ADMIN)
|
||||
remove(@Param('id') id: string, @Req() request: AuthenticatedRequest) {
|
||||
return this.usersService.removeById(id, request.user?.sub);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user