This commit is contained in:
2025-05-22 22:02:54 +07:00
parent 38d1bbf647
commit b2a4cd3f4f
5 changed files with 73 additions and 11 deletions

View File

@@ -1,13 +1,13 @@
import { Module } from '@nestjs/common'; import {Module} from '@nestjs/common';
import { AppController } from './app.controller'; import {AppController} from './app.controller';
import { AppService } from './app.service'; import {AppService} from './app.service';
import { TypeOrmModule } from '@nestjs/typeorm'; import {TypeOrmModule} from '@nestjs/typeorm';
import { ConfigModule, ConfigService } from '@nestjs/config'; import {ConfigModule, ConfigService} from '@nestjs/config';
import * as Joi from 'joi'; import * as Joi from 'joi';
import {UsersModule} from "./users/user.module"; import {UsersModule} from "./users/user.module";
import {AuthenticationModule} from "./authentication/authentication.module"; import {AuthenticationModule} from "./authentication/authentication.module";
import { PostsModule } from './posts/posts.module'; import {PostsModule} from './posts/posts.module';
import { CategoriesModule } from './categories/categories.module'; import {CategoriesModule} from './categories/categories.module';
import {FilesModule} from "./files/file.module"; import {FilesModule} from "./files/file.module";
@Module({ @Module({
@@ -36,6 +36,10 @@ import {FilesModule} from "./files/file.module";
S3_BUCKET: Joi.string().required(), S3_BUCKET: Joi.string().required(),
S3_ACCESS_KEY: Joi.string().required(), S3_ACCESS_KEY: Joi.string().required(),
S3_ENDPOINT: Joi.string().required(), S3_ENDPOINT: Joi.string().required(),
JWT_ACCESS_TOKEN_SECRET: Joi.string().required(),
JWT_ACCESS_TOKEN_EXPIRATION_TIME: Joi.string().required(),
JWT_REFRESH_TOKEN_SECRET: Joi.string().required(),
JWT_REFRESH_TOKEN_EXPIRATION_TIME: Joi.string().required(),
}) })
}), }),
UsersModule, UsersModule,
@@ -47,4 +51,5 @@ import {FilesModule} from "./files/file.module";
controllers: [AppController], controllers: [AppController],
providers: [AppService], providers: [AppService],
}) })
export class AppModule {} export class AppModule {
}

View File

@@ -17,7 +17,7 @@ import JwtAuthenticationGuard from './jwt-authentication.guard';
// import {EmailConfirmationService} from '../emailConfirmation/emailConfirmation.service'; // import {EmailConfirmationService} from '../emailConfirmation/emailConfirmation.service';
import {ApiBody} from '@nestjs/swagger'; import {ApiBody} from '@nestjs/swagger';
import LogInDto from './dto/logIn.dto'; import LogInDto from './dto/logIn.dto';
import { UsersService } from 'src/users/user.service'; import {UsersService} from 'src/users/user.service';
@Controller('authentication') @Controller('authentication')
@UseInterceptors(ClassSerializerInterceptor) @UseInterceptors(ClassSerializerInterceptor)
@@ -87,4 +87,14 @@ export class AuthenticationController {
return user; return user;
} }
@UseGuards(JwtRefreshGuard)
@Get('refresh')
refresh(@Req() request: RequestWithUser) {
const accessTokenCookie = this.authenticationService.getCookieWithJwtAccessToken(request.user.id);
request.res.setHeader('Set-Cookie', accessTokenCookie);
return request.user;
}
} }

View File

@@ -0,0 +1,30 @@
import { ExtractJwt, Strategy } from 'passport-jwt';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { Request } from 'express';
import {UsersService} from "../users/user.service";
@Injectable()
export class JwtRefreshTokenStrategy extends PassportStrategy(
Strategy,
'jwt-refresh-token'
) {
constructor(
private readonly configService: ConfigService,
private readonly userService: UsersService,
) {
super({
jwtFromRequest: ExtractJwt.fromExtractors([(request: Request) => {
return request?.cookies?.Refresh;
}]),
secretOrKey: configService.get('JWT_REFRESH_TOKEN_SECRET'),
passReqToCallback: true,
});
}
async validate(request: Request, payload: TokenPayload) {
const refreshToken = request.cookies?.Refresh;
return this.userService.getUserIfRefreshTokenMatches(refreshToken, payload.userId);
}
}

View File

@@ -0,0 +1,5 @@
import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
@Injectable()
export default class JwtRefreshGuard extends AuthGuard('jwt-refresh-token') {}

View File

@@ -34,6 +34,19 @@ export class UsersService {
throw new HttpException('User with this id does not exist', HttpStatus.NOT_FOUND); throw new HttpException('User with this id does not exist', HttpStatus.NOT_FOUND);
} }
async getUserIfRefreshTokenMatches(refreshToken: string, userId: number) {
const user = await this.getById(userId);
const isRefreshTokenMatching = await bcrypt.compare(
refreshToken,
user.currentHashedRefreshToken
);
if (isRefreshTokenMatching) {
return user;
}
}
async addAvatar(userId: number, imageBuffer: Buffer, filename: string) { async addAvatar(userId: number, imageBuffer: Buffer, filename: string) {
const avatar = await this.filesService.uploadPublicFile(imageBuffer, filename); const avatar = await this.filesService.uploadPublicFile(imageBuffer, filename);
const user = await this.getById(userId); const user = await this.getById(userId);
@@ -62,5 +75,4 @@ export class UsersService {
currentHashedRefreshToken: null, currentHashedRefreshToken: null,
}); });
} }
} }