Oauth est fonctionnel. Le mécanisme de session est à terminer, probablement via un JWT ou autre méthode.

This commit is contained in:
batche
2022-11-02 17:57:06 +01:00
parent 9a6ad5b328
commit 4622792534
192 changed files with 26111 additions and 275 deletions

View File

@@ -6,10 +6,12 @@ import { TypeOrmModule } from '@nestjs/typeorm';
import { ConfigModule } from '@nestjs/config';
import { FriendshipsModule } from './friendship/friendships.module';
import { AuthenticationModule } from './auth/42/authentication.module';
import { PassportModule } from '@nestjs/passport';
@Module({
imports: [UsersModule,
AuthenticationModule,
PassportModule.register({ session: true }),
FriendshipsModule,
ConfigModule.forRoot(),
TypeOrmModule.forRoot({

View File

@@ -8,20 +8,14 @@ export class AuthenticationController {
constructor(private readonly authService: AuthenticationService) {}
@Get()
hello() {
console.log('AUTHENTICATION CONTROLLER');
return 'hello';
}
/**
* GET /api/v2/auth/login
* Route pour l'autentification des utilisateurs
*/
@Get('login')
@UseGuards(FortyTwoAuthGuard)
login(@Res() res: Response) {
return res.sendStatus(200);
login() {
return;
}
/**
@@ -30,6 +24,7 @@ export class AuthenticationController {
* L'api de 42 redirige vers cette route après l'autentification.
*/
@Get('redirect')
@UseGuards(FortyTwoAuthGuard)
redirect(@Res() res: Response) {
console.log(`Redirection performed`);
res.sendStatus(200);

View File

@@ -1,12 +1,17 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Friendship } from 'src/friendship/entities/friendship.entity';
import { User } from 'src/users/entities/user.entity';
import { UsersModule } from 'src/users/users.module';
import { UsersService } from 'src/users/users.service';
import { AuthenticationController } from './authentication.controller';
import { AuthenticationService } from './authentication.service';
import { FortyTwoStrategy } from './strategy/strategy';
import { SessionSerializer } from './utils/serializer';
@Module({
imports: [UsersModule],
providers: [AuthenticationService, FortyTwoStrategy],
imports: [TypeOrmModule.forFeature([User, Friendship]), UsersModule],
providers: [AuthenticationService, FortyTwoStrategy, UsersService, SessionSerializer],
exports: [AuthenticationService],
controllers: [AuthenticationController],
})

View File

@@ -1,4 +1,26 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { CreateUsersDto } from 'src/users/dto/create-users.dto';
import { User } from 'src/users/entities/user.entity';
import { Repository } from 'typeorm';
import { UsersService } from 'src/users/users.service';
@Injectable()
export class AuthenticationService {}
export class AuthenticationService {
constructor(
private readonly userService: UsersService,
) {}
async validateUser(createUsersDto :CreateUsersDto){
console.log("Validate inside authentication.service.ts");
const user = await this.userService.findOneByFourtyTwoId(createUsersDto.fourtyTwoId);
if (user)
return user;
return this.userService.create(createUsersDto);
}
async findUser(fourtytwo_id : string): Promise<User | undefined> {
return await this.userService.findOneByFourtyTwoId(fourtytwo_id);
}
}

View File

@@ -6,7 +6,6 @@ export class FortyTwoAuthGuard extends AuthGuard('42') {
async canActivate(context: ExecutionContext): Promise<any> {
const activate = (await super.canActivate(context)) as boolean;
const request = context.switchToHttp().getRequest();
console.log(request.user);
await super.logIn(request);
return activate;
}

View File

@@ -1,11 +1,12 @@
import { Strategy, Profile } from "passport-42/lib";
import { PassportStrategy } from "@nestjs/passport";
import { Injectable } from "@nestjs/common";
import { Injectable, UnauthorizedException } from "@nestjs/common";
import { AuthenticationService } from "../authentication.service";
import { CreateUsersDto } from "src/users/dto/create-users.dto";
@Injectable()
export class FortyTwoStrategy extends PassportStrategy(Strategy, "42") {
constructor(private readonly authenticationService: AuthenticationService) {
constructor(private authenticationService: AuthenticationService) {
super({
clientID: process.env.FORTYTWO_CLIENT_ID,
clientSecret: process.env.FORTYTWO_CLIENT_SECRET,
@@ -15,7 +16,12 @@ export class FortyTwoStrategy extends PassportStrategy(Strategy, "42") {
}
async validate(accessToken: string, refreshToken: string, profile: Profile, callbackURL: string) {
const { id, username, displayName, photos } = profile;
console.log(profile);
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 = { fourtyTwoId: profile.id, username: profile.username, email: profile.emails[0].value, image_url: profile.photos[0].value };
const user = await this.authenticationService.validateUser(userDTO);
if (!user)
throw new UnauthorizedException();
return user;
}
}

View File

@@ -0,0 +1,23 @@
import { PassportSerializer } from "@nestjs/passport";
import { Injectable } from "@nestjs/common";
import { User } from "src/users/entities/user.entity";
import { AuthenticationService } from "../authentication.service";
@Injectable()
export class SessionSerializer extends PassportSerializer {
constructor(private readonly authservice : AuthenticationService) {
super();
}
serializeUser(user : User, done : (err : Error, user : User) => void ){
done(null, user);
}
async deserializeUser(user : User, done : (err : Error, user : User) => void){
const userDB = await this.authservice.findUser(user.fourtyTwoId);
if (userDB)
done(null, userDB);
else
done(null, null);
}
}

View File

@@ -0,0 +1,3 @@
export const constants = {
secret: process.env.COOKIE_SECRET,
};

View File

@@ -1,4 +1,5 @@
import { Body, Controller, Delete, Get, HttpCode, HttpException, HttpStatus, Param, Patch, Post } from '@nestjs/common';
import { Body, Controller, Delete, Get, HttpCode, HttpException, HttpStatus, Param, Patch, Post, UseGuards } from '@nestjs/common';
import { FortyTwoAuthGuard } from 'src/auth/42/guards/guards';
import { CreateUsersDto } from 'src/users/dto/create-users.dto';
import { CreateFriendshipDto } from './dto/create-friendship.dto';
import { UpdateFriendshipDto } from './dto/update-friendship.dto';
@@ -10,42 +11,50 @@ export class FriendshipController {
constructor(private readonly friendshipService: FriendshipService) {}
@Get(':userId/friends')
@UseGuards(FortyTwoAuthGuard)
findEmpty(@Param('userId') userId: string) {
return this.friendshipService.findAllFriends(userId);
}
@Get(':userId/blocked')
@UseGuards(FortyTwoAuthGuard)
findAllBlocked(@Param('userId') userId: string) {
return this.friendshipService.findAllBlockedFriends(userId);
}
@Get(':userId/pending')
@UseGuards(FortyTwoAuthGuard)
findAllPendantFriendshipRequested(@Param('userId') userId: string) {
return this.friendshipService.findAllPendantRequestsForFriendship(userId);
}
@Get(':userId/received')
@UseGuards(FortyTwoAuthGuard)
findAllPendantFriendshipReceived(@Param('userId') userId: string) {
return this.friendshipService.findAllReceivedRequestsForFriendship(userId);
}
@Get(':userId/myfriends/:friendId')
@UseGuards(FortyTwoAuthGuard)
findOneFriend(@Param('friendId') friendId: string) {
return this.friendshipService.findOneFriend(friendId);
}
@Post()
@HttpCode(HttpStatus.CREATED)
@UseGuards(FortyTwoAuthGuard)
create(@Body() createFriendshipDto: CreateFriendshipDto) {
return this.friendshipService.create(createFriendshipDto);
}
@Patch(':userId/received/:relationshipId')
@UseGuards(FortyTwoAuthGuard)
update(@Param('friendId') relationshipId: string, @Body() {status}: UpdateFriendshipDto) {
return this.friendshipService.updateFriendship(relationshipId, {status});
}
@Delete(':userId/:friendId')
@UseGuards(FortyTwoAuthGuard)
remove(@Param('friendId') friendId: string) {
return this.friendshipService.removeFriendship(friendId);
}

View File

@@ -1,7 +1,7 @@
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { User } from 'src/users/entities/user.entity';
import { Any, Repository } from 'typeorm';
import { Repository } from 'typeorm';
import { CreateFriendshipDto } from './dto/create-friendship.dto';
import { UpdateFriendshipDto } from './dto/update-friendship.dto';
import { Friendship, FriendshipStatus } from './entities/friendship.entity';

View File

@@ -1,7 +1,9 @@
import { NestFactory } from '@nestjs/core';
import { ValidationPipe } from '@nestjs/common';
import { AppModule } from './app.module';
import * as session from 'express-session';
import * as passport from 'passport';
import { constants } from './conf/constant';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
@@ -20,8 +22,20 @@ async function bootstrap() {
},
}),
);
const port = process.env.PORT || 3000;
const port = process.env.PORT || 3001;
app.setGlobalPrefix('api/v2');
await app.listen(port, () => { console.log(`Listening on port ${port}`); });
app.use(
session({
cookie: {
maxAge: 3600000 * 24,
},
secret: constants.secret,
resave: false,
saveUninitialized: false,
}),
);
app.use(passport.initialize());
app.use(passport.session());
await app.listen(port, () => { console.log(`Listening on port ${port}`); });
}
bootstrap();

View File

@@ -4,8 +4,10 @@ import { Unique } from 'typeorm';
export class CreateUsersDto {
@IsString()
readonly username: string;
@IsString()
readonly fourtyTwoId: string;
@IsEmail()
readonly email: string;
@IsString()
readonly password: string;
readonly image_url: string;
}

View File

@@ -11,7 +11,7 @@ export class User {
@PrimaryGeneratedColumn()
id: number;
@Column({ name: 'fourty_two_id' })
@Column({unique: true})
fourtyTwoId: string;
@Column()
@@ -21,11 +21,11 @@ export class User {
@IsEmail()
email: string;
@Column()
password: string;
@Column({ nullable: true })
image_url : string;
@Column({ nullable: true })
avatar: string;
phone: string;
@Column('json', { nullable: true })
status: [string];

View File

@@ -1,7 +1,8 @@
import {
Body, Controller, Delete, Get, HttpCode,
HttpStatus, Param, Patch, Post, Query
HttpStatus, Param, Patch, Post, Query, UseGuards
} from '@nestjs/common';
import { FortyTwoAuthGuard } from 'src/auth/42/guards/guards';
import { PaginationQueryDto } from 'src/common/dto/pagination-query.dto';
import { CreateUsersDto } from './dto/create-users.dto';
import { UpdateUsersDto } from './dto/update-users.dto';
@@ -15,17 +16,20 @@ export class UsersController {
// par exemple dans postamn ou insomnia http://localhost:3000/users?limit=10&offset=20
@Get('all')
@UseGuards(FortyTwoAuthGuard)
findAll(@Query() paginationquery : PaginationQueryDto) {
//const { limit, offset } = query;
return this.usersService.findAll(paginationquery);
}
@Get(':id')
@UseGuards(FortyTwoAuthGuard)
findOne(@Param('id') id: string) {
return this.usersService.findOne(id);
}
@Post()
@UseGuards(FortyTwoAuthGuard)
@HttpCode(HttpStatus.CREATED)
create(@Body() createUsersDto : CreateUsersDto ) {
console.log(createUsersDto);
@@ -33,11 +37,13 @@ export class UsersController {
}
@Patch(':id')
@UseGuards(FortyTwoAuthGuard)
update(@Param('id') id: string, @Body() usersUpdateDto: UpdateUsersDto) {
return this.usersService.update(id, usersUpdateDto);
}
@Delete(':id')
@UseGuards(FortyTwoAuthGuard)
remove(@Param('id') id: string) {
return this.usersService.remove(id);
}

View File

@@ -21,6 +21,20 @@ export class UsersService {
private readonly friendshipRepository: Repository<Friendship>,
) {}
async findOneByFourtyTwoId(fourtytwo_id: string) {
console.log(`Find user with fourtytwo_id ${fourtytwo_id}`);
if (!isNumberString(fourtytwo_id))
throw new HttpException(`The requested user not found.`,HttpStatus.NOT_FOUND);
const user = await this.userRepository.findOneBy({fourtyTwoId: fourtytwo_id});
if (!user)
{
console.log(`The requested user not found.`);
return null;
}
console.log(`The requested user found.`);
return user;
}
async findOne(id: string) {
if (!isNumberString(id))
throw new HttpException(`The requested user not found.`,HttpStatus.NOT_FOUND);
@@ -40,7 +54,8 @@ export class UsersService {
}
async create(createUserDto: CreateUsersDto) {
if (await this.userRepository.findOneBy({email: createUserDto.email}))
console.log(`Create user with ${createUserDto}`);
if (await this.userRepository.findOneBy({fourtyTwoId: createUserDto.fourtyTwoId}))
throw new HttpException(`The user already exists.`,HttpStatus.CONFLICT);
const user = this.userRepository.create(createUserDto);
if (!user)