ajout de l'upload. Reste un mystérieux problème à régler avec l'extenstion et multer

This commit is contained in:
batche
2022-11-16 19:12:02 +01:00
parent fd61ea56d2
commit f98e1fdb4e
21 changed files with 609 additions and 54 deletions

View File

@@ -46,6 +46,7 @@ export class AuthenticationController {
@UseGuards(AuthenticateGuard)
logout(@Req() request, @Res() response, @Next() next) {
this.userService.setIsTwoFactorAuthenticatedWhenLogout(request.user.id);
this.userService.updateStatus(request.user.id, 'disconnected');
request.logout(function(err) {
if (err) { return next(err); }
response.redirect('/');

View File

@@ -24,7 +24,7 @@ export class AuthenticateGuard implements CanActivate {
export class TwoFactorGuard implements CanActivate {
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
console.log("TwoFactorGuard : Is User authenticated : " + request.isAuthenticated() + " and has 2FA enabled : " + request.user.isEnabledTwoFactorAuth + " and has 2FA verified : " + request.user.isTwoFactorAuthenticated);
//console.log("TwoFactorGuard : Is User authenticated : " + request.isAuthenticated() + " and has 2FA enabled : " + request.user.isEnabledTwoFactorAuth + " and has 2FA verified : " + request.user.isTwoFactorAuthenticated);
return request.isAuthenticated() && (request.user.isEnabledTwoFactorAuth === false
|| request.user.isTwoFactorAuthenticated === true);
}

View File

@@ -5,23 +5,23 @@ import { AuthenticationService } from "../authentication.service";
import { CreateUsersDto } from "src/users/dto/create-users.dto";
@Injectable()
export class FortyTwoStrategy extends PassportStrategy(Strategy, "42") {
constructor(private authenticationService: AuthenticationService) {
super({
clientID: process.env.FORTYTWO_CLIENT_ID,
clientSecret: process.env.FORTYTWO_CLIENT_SECRET,
callbackURL: process.env.FORTYTWO_CALLBACK_URL,
scope: ["public"],
});
}
export class FortyTwoStrategy extends PassportStrategy(Strategy, "42") {
constructor(private authenticationService: AuthenticationService) {
super({
clientID: process.env.FORTYTWO_CLIENT_ID,
clientSecret: process.env.FORTYTWO_CLIENT_SECRET,
callbackURL: process.env.FORTYTWO_CALLBACK_URL,
scope: ["public"],
});
}
async validate(accessToken: string, refreshToken: string, profile: Profile, callbackURL: string) {
console.log("Validate inside strategy.ts");
console.log(profile.id, profile.username, profile.phoneNumbers[0].value, profile.emails[0].value, profile.photos[0].value);
const userDTO: CreateUsersDto = { fortyTwoId: profile.id, username: profile.username, email: profile.emails[0].value, image_url: profile.photos[0].value, isEnabledTwoFactorAuth: false };
const user = await this.authenticationService.validateUser(userDTO);
if (!user)
throw new UnauthorizedException();
return user;
}
async validate(accessToken: string, refreshToken: string, profile: Profile, callbackURL: string) {
console.log("Validate inside strategy.ts");
console.log(profile.id, profile.username, profile.phoneNumbers[0].value, profile.emails[0].value, profile.photos[0].value);
const userDTO: CreateUsersDto = { fortyTwoId: profile.id, username: profile.username, email: profile.emails[0].value, image_url: 'default.png', isEnabledTwoFactorAuth: false , status: "connected" };
const user = await this.authenticationService.validateUser(userDTO);
if (!user)
throw new UnauthorizedException();
return user;
}
}

View File

@@ -0,0 +1,15 @@
import { randomUUID } from "crypto";
import { diskStorage } from "multer";
import path from "path";
export const storageForAvatar = {
storage: diskStorage({
destination: './uploads/avatars',
filename: (req, file, cb) => {
console.log(file);
const filename : string = file.originalname.split(' ').join('_') + randomUUID();
const extension : string = path.extname(file.originalname);
cb(null, `${filename}${extension}`);
}
})
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -9,6 +9,8 @@ export class CreateUsersDto {
readonly email: string;
@IsString()
readonly image_url: string;
@IsString()
readonly status: string;
@IsBoolean()
readonly isEnabledTwoFactorAuth: boolean;
}

View File

@@ -5,4 +5,4 @@
import { OmitType, PartialType } from "@nestjs/mapped-types";
import { CreateUsersDto } from "./create-users.dto";
export class UpdateUsersDto extends OmitType(CreateUsersDto, ['fortyTwoId', 'email'] as const){}
export class UpdateUsersDto extends OmitType(CreateUsersDto, ['fortyTwoId', 'email', 'image_url', 'status'] as const){}

View File

@@ -21,14 +21,14 @@ export class User {
@IsEmail()
email: string;
@Column({ nullable: true })
@Column()
image_url : string;
@Column({ nullable: true })
phone: string;
@Column('json', { nullable: true })
status: [string];
@Column({ default: 'disconnected' })
status: string;
// @Column()
// isFirstConnection: boolean;

View File

@@ -1,15 +1,29 @@
import {
Body, Controller, Delete, Get, HttpCode,
HttpStatus, Param, Patch, Post, Query, Req, UseGuards
Body, Controller, Delete, Get, HttpException, NotFoundException, Patch, Post, Query, Req, Res, UploadedFile, UseGuards, UseInterceptors
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { AuthenticateGuard, TwoFactorGuard } from 'src/auth/42/guards/42guards';
import { PaginationQueryDto } from 'src/common/dto/pagination-query.dto';
import { ValidationPipe } from 'src/common/validation/validation.pipe';
import { CreateUsersDto } from './dto/create-users.dto';
import { UpdateUsersDto } from './dto/update-users.dto';
import { UsersService } from './users.service';
import { User } from './entities/user.entity';
import { diskStorage } from 'multer';
import path from 'path';
import { randomUUID } from 'crypto';
import { of } from 'rxjs';
export const storageForAvatar = {
storage: diskStorage({
destination: './uploads/avatars',
filename: (req, file, cb) => {
const filename : string = file.originalname.split(' ').join('_') + randomUUID();
console.log("RES : " )
const extension : string = path.extname(file.originalname);
cb(null, `${filename}${extension}`);
}
})
}
@Controller('user')
export class UsersController {
@@ -61,4 +75,28 @@ export class UsersController {
remove(@Req() req) {
return this.usersService.remove(req.user.id);
}
@UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard)
@Post('avatar')
@UseInterceptors(FileInterceptor('file', storageForAvatar))
uploadAvatar(@UploadedFile() file, @Req() request){
const user : User = request.user;
this.usersService.updateAvatar(user.id, file.filename);
}
@UseGuards(AuthenticateGuard)
@UseGuards(TwoFactorGuard)
@Get('avatar')
getAvatar(@Req() request, @Res() response) {
const promise = this.usersService.getAvatarUrl(request.user.id).then((url) =>
{
if (url)
return of(response.sendFile(process.cwd() + '/uploads/avatars/' + url));
else
throw new NotFoundException('Avatar not found');
});
return promise;
}
}

View File

@@ -1,6 +1,6 @@
import { HttpCode, HttpException, HttpStatus, Injectable, NotFoundException, } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { NotFoundError } from 'rxjs';
import { NotFoundError, of } from 'rxjs';
import { User } from './entities/user.entity';
import { ConnectionOptionsReader, Repository } from 'typeorm';
import { CreateUsersDto } from './dto/create-users.dto';
@@ -9,6 +9,7 @@ import { Friendship } from '../friendship/entities/friendship.entity';
import { isNumberString } from 'class-validator';
import { PaginationQueryDto } from 'src/common/dto/pagination-query.dto';
import { PartialUsersDto } from './dto/partial-users.dto';
import { join } from 'path';
// On va devoir sûrement trouver un moyen plus simple pour passer l'id, sûrement via des pipes
// ou des interceptors, mais pour l'instant on va faire comme ça.
@@ -65,7 +66,7 @@ export class UsersService {
}
async update(id: string, updateUserDto: UpdateUsersDto) {
console.log(`Update user ${id} with ${updateUserDto.image_url} + ${updateUserDto.isEnabledTwoFactorAuth}`);
console.log(`Update user ${id} with ${updateUserDto.isEnabledTwoFactorAuth}`);
const user = await this.userRepository.preload(
{id: +id,
...updateUserDto});
@@ -92,4 +93,22 @@ export class UsersService {
async setAuthenticatorSecret(id: number, secret: string) {
return this.userRepository.update(id, {secretTwoFactorAuth: secret});
}
async updateStatus(id: number, status: string) {
return this.userRepository.update(id, {status: status});
}
async updateAvatar(id: number, avatar: string) {
return this.userRepository.update(id, {image_url: avatar});
}
async getAvatarUrl(id: number) {
const user = await this.userRepository.findOneBy({id: id});
if (!user)
throw new HttpException(`The user could not be found.`,HttpStatus.NOT_FOUND);
if (!user.image_url)
throw new HttpException(`The user has no avatar.`,HttpStatus.NOT_FOUND);
console.log(user.image_url);
return user.image_url;
}
}