From 21d29cfd9b7fd48e9b1b01344f3725af6743c95d Mon Sep 17 00:00:00 2001 From: tacettinburakeren Date: Fri, 10 Nov 2023 22:46:49 +0300 Subject: [PATCH 1/6] get-user-info endpoint --- .../src/controllers/user.controller.ts | 22 ++++++++++++++++++- .../dtos/user/request/get-user-info.dto.ts | 10 +++++++++ .../response/get-user-info-response.dto.ts | 11 ++++++++++ .../src/repositories/user.repository.ts | 11 ++++++++++ ludos/backend/src/services/game.service.ts | 3 ++- ludos/backend/src/services/user.service.ts | 22 ++++++++++++++++++- 6 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 ludos/backend/src/dtos/user/request/get-user-info.dto.ts create mode 100644 ludos/backend/src/dtos/user/response/get-user-info-response.dto.ts diff --git a/ludos/backend/src/controllers/user.controller.ts b/ludos/backend/src/controllers/user.controller.ts index c9d50d8f..5233b086 100644 --- a/ludos/backend/src/controllers/user.controller.ts +++ b/ludos/backend/src/controllers/user.controller.ts @@ -1,7 +1,9 @@ import { Body, Controller, + Get, HttpCode, + Param, Post, Put, Req, @@ -28,11 +30,12 @@ import { ChangePasswordResponseDto } from '../dtos/user/response/change-password import { ChangePasswordDto } from '../dtos/user/request/change-password.dto'; import { AuthGuard } from '../services/guards/auth.guard'; import { AuthorizedRequest } from '../interfaces/common/authorized-request.interface'; +import { GetUserInfoDto } from 'dtos/user/request/get-user-info.dto'; @ApiTags('user') @Controller('user') export class UserController { - constructor(private readonly userService: UserService) {} + constructor(private readonly userService: UserService) { } @ApiOkResponse({ description: 'Successful Register', type: RegisterResponseDto, @@ -76,6 +79,7 @@ export class UserController { @ApiBadRequestResponse({ description: 'Bad Request', }) + @HttpCode(200) @ApiOperation({ summary: 'Password Reset Request Endpoint' }) @Post('/reset-password') @@ -115,4 +119,20 @@ export class UserController { ) { return await this.userService.changePassword(req.user.id, input); } + + + @HttpCode(200) + @ApiUnauthorizedResponse({ + description: 'Invalid User', + }) + @ApiBadRequestResponse({ + description: 'Bad Request', + }) + + @ApiBearerAuth() + @ApiOperation({ summary: 'Get User Info Request Endpoint' }) + @Get('/info') + public async getUserInfoById(@Req() req: AuthorizedRequest) { + return await this.userService.getUserInfo(req.user.id); + } } diff --git a/ludos/backend/src/dtos/user/request/get-user-info.dto.ts b/ludos/backend/src/dtos/user/request/get-user-info.dto.ts new file mode 100644 index 00000000..8fac37d5 --- /dev/null +++ b/ludos/backend/src/dtos/user/request/get-user-info.dto.ts @@ -0,0 +1,10 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { IsString } from 'class-validator'; + +export class GetUserInfoDto { + @ApiProperty({ + example: '1', + }) + @IsString() + id: string; +} diff --git a/ludos/backend/src/dtos/user/response/get-user-info-response.dto.ts b/ludos/backend/src/dtos/user/response/get-user-info-response.dto.ts new file mode 100644 index 00000000..482a9109 --- /dev/null +++ b/ludos/backend/src/dtos/user/response/get-user-info-response.dto.ts @@ -0,0 +1,11 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { Game } from '../../../entities/game.entity'; + +export class GetUserInfoResponseDto { + @ApiProperty() + username: string; + @ApiProperty() + email: string; + @ApiProperty() + followedGames: Game[]; +} diff --git a/ludos/backend/src/repositories/user.repository.ts b/ludos/backend/src/repositories/user.repository.ts index f59eb17b..27f0f87a 100644 --- a/ludos/backend/src/repositories/user.repository.ts +++ b/ludos/backend/src/repositories/user.repository.ts @@ -1,6 +1,7 @@ import { Injectable } from '@nestjs/common'; import { User } from '../entities/user.entity'; import { DataSource, Repository } from 'typeorm'; +import { Game } from '../entities/game.entity'; @Injectable() export class UserRepository extends Repository { @@ -30,4 +31,14 @@ export class UserRepository extends Repository { public findUserById(id: string): Promise { return this.findOneBy({ id }); } + + public async getFollowedGamesByUserId(userId: string): Promise { + const user = await this.createQueryBuilder('users') + .leftJoinAndSelect('users.followedGames', 'followedGames') + .where('users.id = :userId', { userId }) + .getOne(); + + return user ? user.followedGames : []; + } + } diff --git a/ludos/backend/src/services/game.service.ts b/ludos/backend/src/services/game.service.ts index 19a6031d..135b971c 100644 --- a/ludos/backend/src/services/game.service.ts +++ b/ludos/backend/src/services/game.service.ts @@ -15,7 +15,7 @@ export class GameService { constructor( private readonly gameRepository: GameRepository, private readonly userRepository: UserRepository, - ) {} + ) { } public async createGame( input: GameCreateDto, @@ -31,6 +31,7 @@ export class GameService { developer: game.developer, }; } catch (e) { + console.log(e) if (e.code == '23505') { throw new ConflictException(e.detail); } diff --git a/ludos/backend/src/services/user.service.ts b/ludos/backend/src/services/user.service.ts index 01a0608e..2056e6eb 100644 --- a/ludos/backend/src/services/user.service.ts +++ b/ludos/backend/src/services/user.service.ts @@ -22,6 +22,8 @@ import { RegisterResponseDto } from '../dtos/user/response/register-response.dto import { Payload } from '../interfaces/user/payload.interface'; import { ResetPasswordRepository } from '../repositories/reset-password.repository'; import { UserRepository } from '../repositories/user.repository'; +import { GetUserInfoResponseDto } from '../dtos/user/response/get-user-info-response.dto'; +import { GameRepository } from '../repositories/game.repository'; @Injectable() export class UserService { @@ -30,7 +32,8 @@ export class UserService { private readonly resetPasswordRepository: ResetPasswordRepository, private readonly jwtService: JwtService, private readonly configService: ConfigService, - ) {} + private readonly gameRepository: GameRepository + ) { } public async register(input: RegisterDto): Promise { try { @@ -179,4 +182,21 @@ export class UserService { await this.userRepository.save(user); return new ChangePasswordResponseDto(true); } + + public async getUserInfo(userId: string): Promise { + const user = await this.userRepository.findUserById(userId); + if (!user) { + throw new NotFoundException('User not found'); + } + + let games = await this.userRepository.getFollowedGamesByUserId(userId); + + console.log('games ->', games) + let returnObject = new GetUserInfoResponseDto(); + returnObject.username = user.username; + returnObject.email = user.email; + returnObject.followedGames = games ?? [] + + return returnObject; + } } From 3ab5f8c16e9d7aa175643b070bae217dd76392c7 Mon Sep 17 00:00:00 2001 From: tacettinburakeren Date: Sat, 11 Nov 2023 00:08:29 +0300 Subject: [PATCH 2/6] get-user-info endpoint fixed --- ludos/backend/src/controllers/user.controller.ts | 1 - ludos/backend/src/services/game.service.ts | 2 +- ludos/backend/src/services/user.service.ts | 4 +--- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/ludos/backend/src/controllers/user.controller.ts b/ludos/backend/src/controllers/user.controller.ts index 5233b086..6477fc8d 100644 --- a/ludos/backend/src/controllers/user.controller.ts +++ b/ludos/backend/src/controllers/user.controller.ts @@ -30,7 +30,6 @@ import { ChangePasswordResponseDto } from '../dtos/user/response/change-password import { ChangePasswordDto } from '../dtos/user/request/change-password.dto'; import { AuthGuard } from '../services/guards/auth.guard'; import { AuthorizedRequest } from '../interfaces/common/authorized-request.interface'; -import { GetUserInfoDto } from 'dtos/user/request/get-user-info.dto'; @ApiTags('user') @Controller('user') diff --git a/ludos/backend/src/services/game.service.ts b/ludos/backend/src/services/game.service.ts index 135b971c..d101d795 100644 --- a/ludos/backend/src/services/game.service.ts +++ b/ludos/backend/src/services/game.service.ts @@ -15,7 +15,7 @@ export class GameService { constructor( private readonly gameRepository: GameRepository, private readonly userRepository: UserRepository, - ) { } + ) {} public async createGame( input: GameCreateDto, diff --git a/ludos/backend/src/services/user.service.ts b/ludos/backend/src/services/user.service.ts index 2056e6eb..e232dea5 100644 --- a/ludos/backend/src/services/user.service.ts +++ b/ludos/backend/src/services/user.service.ts @@ -23,7 +23,6 @@ import { Payload } from '../interfaces/user/payload.interface'; import { ResetPasswordRepository } from '../repositories/reset-password.repository'; import { UserRepository } from '../repositories/user.repository'; import { GetUserInfoResponseDto } from '../dtos/user/response/get-user-info-response.dto'; -import { GameRepository } from '../repositories/game.repository'; @Injectable() export class UserService { @@ -32,8 +31,7 @@ export class UserService { private readonly resetPasswordRepository: ResetPasswordRepository, private readonly jwtService: JwtService, private readonly configService: ConfigService, - private readonly gameRepository: GameRepository - ) { } + ) {} public async register(input: RegisterDto): Promise { try { From 5c1bfa1de1c1a33910b74d2bdb9ce6b1e0690b0a Mon Sep 17 00:00:00 2001 From: tacettinburakeren Date: Sat, 11 Nov 2023 12:05:25 +0300 Subject: [PATCH 3/6] get-user-info fixed some issues --- ludos/backend/src/controllers/user.controller.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/ludos/backend/src/controllers/user.controller.ts b/ludos/backend/src/controllers/user.controller.ts index 6477fc8d..fcaed40c 100644 --- a/ludos/backend/src/controllers/user.controller.ts +++ b/ludos/backend/src/controllers/user.controller.ts @@ -3,7 +3,6 @@ import { Controller, Get, HttpCode, - Param, Post, Put, Req, From eaf6c79a612a3685698d264a2e5f7828b98c2cfa Mon Sep 17 00:00:00 2001 From: tacettinburakeren Date: Wed, 15 Nov 2023 00:33:19 +0300 Subject: [PATCH 4/6] some issues fixed --- .../src/repositories/user.repository.ts | 14 ++++++++------ ludos/backend/src/services/user.service.ts | 19 ++++++++++--------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/ludos/backend/src/repositories/user.repository.ts b/ludos/backend/src/repositories/user.repository.ts index 27f0f87a..bd309768 100644 --- a/ludos/backend/src/repositories/user.repository.ts +++ b/ludos/backend/src/repositories/user.repository.ts @@ -32,13 +32,15 @@ export class UserRepository extends Repository { return this.findOneBy({ id }); } - public async getFollowedGamesByUserId(userId: string): Promise { - const user = await this.createQueryBuilder('users') - .leftJoinAndSelect('users.followedGames', 'followedGames') - .where('users.id = :userId', { userId }) - .getOne(); + public async findUserByIdWithRelations(id: string): Promise { + return await this.findOne({ + relations: this.getAllRelationsAsList(), + where: { id: id }, + }); + } - return user ? user.followedGames : []; + public getAllRelationsAsList() { + return this.metadata.relations.map((relation) => relation.propertyName); } } diff --git a/ludos/backend/src/services/user.service.ts b/ludos/backend/src/services/user.service.ts index e232dea5..a0e04989 100644 --- a/ludos/backend/src/services/user.service.ts +++ b/ludos/backend/src/services/user.service.ts @@ -182,19 +182,20 @@ export class UserService { } public async getUserInfo(userId: string): Promise { - const user = await this.userRepository.findUserById(userId); + const user = await this.userRepository.findUserByIdWithRelations(userId); if (!user) { throw new NotFoundException('User not found'); } - let games = await this.userRepository.getFollowedGamesByUserId(userId); - - console.log('games ->', games) - let returnObject = new GetUserInfoResponseDto(); - returnObject.username = user.username; - returnObject.email = user.email; - returnObject.followedGames = games ?? [] + const response = new GetUserInfoResponseDto(); + response.email = user.email; + response.username = user.username; + response.followedGames = user.followedGames; + response.fullName = user.fullName; + response.avatar = user.avatar; + response.aboutMe = user.aboutMe; + response.steamUrl = user.steamUrl; - return returnObject; + return response; } } From cde30cb369f953cccc629997fb33e918f48341ea Mon Sep 17 00:00:00 2001 From: tacettinburakeren Date: Wed, 15 Nov 2023 01:06:30 +0300 Subject: [PATCH 5/6] conflicts fixed --- .../src/controllers/user.controller.ts | 21 ++++++++++++++++++- .../src/repositories/user.repository.ts | 10 ++++----- ludos/backend/src/services/user.service.ts | 6 ++++++ 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/ludos/backend/src/controllers/user.controller.ts b/ludos/backend/src/controllers/user.controller.ts index fcaed40c..0469df9a 100644 --- a/ludos/backend/src/controllers/user.controller.ts +++ b/ludos/backend/src/controllers/user.controller.ts @@ -118,7 +118,26 @@ export class UserController { return await this.userService.changePassword(req.user.id, input); } - + @ApiOperation({ summary: 'Edit User Info Endpoint' }) + @ApiOkResponse({ + description: 'User information edited.', + }) + @ApiUnauthorizedResponse({ + description: 'Invalid Credentials', + }) + @ApiBadRequestResponse({ + description: 'Bad Request', + }) + @ApiBearerAuth() + @UseGuards(AuthGuard) + @Put('/edit-info') + public async editUserInfo( + @Req() req: AuthorizedRequest, + @Body() input: EditUserInfoDto, + ) { + await this.userService.editInfo(req.user.id, input); + } + @HttpCode(200) @ApiUnauthorizedResponse({ description: 'Invalid User', diff --git a/ludos/backend/src/repositories/user.repository.ts b/ludos/backend/src/repositories/user.repository.ts index bd309768..82f48583 100644 --- a/ludos/backend/src/repositories/user.repository.ts +++ b/ludos/backend/src/repositories/user.repository.ts @@ -1,7 +1,6 @@ import { Injectable } from '@nestjs/common'; import { User } from '../entities/user.entity'; import { DataSource, Repository } from 'typeorm'; -import { Game } from '../entities/game.entity'; @Injectable() export class UserRepository extends Repository { @@ -22,16 +21,17 @@ export class UserRepository extends Repository { public findUserByEmail(email: string): Promise { return this.findOneBy({ email: email }); } + + public findUserById(id: string): Promise { + return this.findOneBy({ id }); + } public async updateUserPassword(input: Partial, newPassword: string) { const user = await this.findUserByUsername(input.username); user.password = newPassword; await this.save(user); } - public findUserById(id: string): Promise { - return this.findOneBy({ id }); - } - + public async findUserByIdWithRelations(id: string): Promise { return await this.findOne({ relations: this.getAllRelationsAsList(), diff --git a/ludos/backend/src/services/user.service.ts b/ludos/backend/src/services/user.service.ts index a0e04989..ecd4f815 100644 --- a/ludos/backend/src/services/user.service.ts +++ b/ludos/backend/src/services/user.service.ts @@ -181,6 +181,12 @@ export class UserService { return new ChangePasswordResponseDto(true); } + public async editInfo(userId: string, editInfoDto: EditUserInfoDto) { + let user = await this.userRepository.findUserById(userId); + let updated = Object.assign(user, editInfoDto); + await this.userRepository.save(updated); + } + public async getUserInfo(userId: string): Promise { const user = await this.userRepository.findUserByIdWithRelations(userId); if (!user) { From d8e980ab455eaec2ae38d2160ffba69dcc1344af Mon Sep 17 00:00:00 2001 From: tacettinburakeren Date: Wed, 15 Nov 2023 01:13:59 +0300 Subject: [PATCH 6/6] fixed some bugs --- ludos/backend/src/repositories/user.repository.ts | 6 +----- ludos/backend/src/services/user.service.ts | 4 ---- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/ludos/backend/src/repositories/user.repository.ts b/ludos/backend/src/repositories/user.repository.ts index fce9d4d8..5d604739 100644 --- a/ludos/backend/src/repositories/user.repository.ts +++ b/ludos/backend/src/repositories/user.repository.ts @@ -26,11 +26,7 @@ export class UserRepository extends Repository { return this.findOneBy({ id }); } - public findUserById(id: string): Promise { - return this.findOneBy({ id }); - } - - public async updateUserPassword(input: Partial, newPassword: string) { + public async updateUserPassword(input: Partial, newPassword: string) { const user = await this.findUserByUsername(input.username); user.password = newPassword; await this.save(user); diff --git a/ludos/backend/src/services/user.service.ts b/ludos/backend/src/services/user.service.ts index dcd90845..6efed627 100644 --- a/ludos/backend/src/services/user.service.ts +++ b/ludos/backend/src/services/user.service.ts @@ -199,10 +199,6 @@ export class UserService { response.email = user.email; response.username = user.username; response.followedGames = user.followedGames; - response.fullName = user.fullName; - response.avatar = user.avatar; - response.aboutMe = user.aboutMe; - response.steamUrl = user.steamUrl; return response; }