From 0d661d43ee547892be82249771b0835deaf1937b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Wed, 16 Oct 2024 22:16:02 -0600 Subject: [PATCH 1/3] correo confirmacion --- backend/src/app.module.ts | 2 + backend/src/auth/user/authUser.module.ts | 3 +- backend/src/auth/user/authUsercontroller.ts | 36 +++++++++++++-- backend/src/auth/user/authUserservice.ts | 40 +++++++++++++++-- .../auth/user/dto/user-reset-password.dto.ts | 33 ++++++++------ .../user/entities/user-confirm-code.entity.ts | 17 +++++++ .../user/entities/user-reset-code.entity.ts | 7 ++- backend/src/email/email.service.ts | 44 ++++++++++++------- backend/src/route/route.module.ts | 4 ++ backend/src/user/entities/user.entity.ts | 9 +++- backend/src/user/user.controller.ts | 13 ++++++ backend/src/user/user.module.ts | 6 ++- backend/src/user/user.service.ts | 17 +++++++ backend/src/visited/visited.module.ts | 18 +++++++- 14 files changed, 203 insertions(+), 46 deletions(-) create mode 100644 backend/src/auth/user/entities/user-confirm-code.entity.ts diff --git a/backend/src/app.module.ts b/backend/src/app.module.ts index 829a1ca9..4d8145bd 100644 --- a/backend/src/app.module.ts +++ b/backend/src/app.module.ts @@ -36,6 +36,7 @@ import { EmailService } from './email/email.service'; import { UserResetCode } from './auth/user/entities/user-reset-code.entity'; import { MailerModule } from '@nestjs-modules/mailer'; import { MailConstants } from './constants/mail.constants'; +import { UserConfirmCode } from './auth/user/entities/user-confirm-code.entity'; @Module({ imports: [ @@ -62,6 +63,7 @@ import { MailConstants } from './constants/mail.constants'; TravelPlace, Visited, UserResetCode, + UserConfirmCode, ], synchronize: DbConstants.DB_SYNC, logging: false, diff --git a/backend/src/auth/user/authUser.module.ts b/backend/src/auth/user/authUser.module.ts index f6186015..824f8c7d 100644 --- a/backend/src/auth/user/authUser.module.ts +++ b/backend/src/auth/user/authUser.module.ts @@ -10,10 +10,11 @@ import { Category } from 'src/category/entities/category.entity'; import { CategoryService } from 'src/category/category.service'; import { UserResetCode } from './entities/user-reset-code.entity'; import { EmailService } from 'src/email/email.service'; +import { UserConfirmCode } from './entities/user-confirm-code.entity'; @Module({ controllers: [AuthUserController], providers: [UserService, JwtService, EncryptionService, AuthUserService, CategoryService, EmailService], - imports: [TypeOrmModule.forFeature([User, Category, UserResetCode])], + imports: [TypeOrmModule.forFeature([User, Category, UserResetCode, UserConfirmCode])], }) export class AuthUserModule {} diff --git a/backend/src/auth/user/authUsercontroller.ts b/backend/src/auth/user/authUsercontroller.ts index 9723c608..2c2afcb6 100644 --- a/backend/src/auth/user/authUsercontroller.ts +++ b/backend/src/auth/user/authUsercontroller.ts @@ -1,4 +1,4 @@ -import { Body, Controller, Get, Patch, Post, Req, UseGuards } from '@nestjs/common'; +import { Body, Controller, Patch, Post, Req, UseGuards } from '@nestjs/common'; import { ApiBearerAuth, ApiBody, ApiCreatedResponse, ApiTags, ApiUnauthorizedResponse } from '@nestjs/swagger'; import { AuthUserService } from './authUserservice'; import { CreateUserDto } from 'src/user/dto/create-user.dto'; @@ -10,11 +10,15 @@ import { UpdatePwdDto } from './dto/update-pwd.dto'; import { UserRequestCodeBody, UserResetPasswordBody, UserResetPasswordDto } from './dto/user-reset-password.dto'; import { GetResetCode } from './dto/get-reset-code.dto'; import { EmailService } from 'src/email/email.service'; +import { UserConfirmCode } from './entities/user-confirm-code.entity'; @Controller('') @ApiTags('Create user account and sign in as user') export class AuthUserController { - constructor(private readonly authUserService: AuthUserService, private readonly mailService: EmailService) {} + constructor( + private readonly authUserService: AuthUserService, + private readonly mailService: EmailService, + ) {} @ApiBody({ type: CreateUserDto }) @ApiCreatedResponse({ @@ -60,11 +64,37 @@ export class AuthUserController { @ApiBody({ type: UserRequestCodeBody }) @Post('user/get-reset-code') async getResetCode(@Body() resetPasswordInfo: GetResetCode) { - try{ + try { const code = await this.authUserService.getResetPasswordCode(resetPasswordInfo.email); await this.mailService.sendResetPasswordEmail(resetPasswordInfo.email, code); } catch (e) { throw e; } } + + @ApiBearerAuth('jwt') + @UseGuards(AuthUserGuard) + @Post('user/resend-confirmation-code') + async resendConfirmationCode(@Req() req: CustomUserRequest) { + try { + const email = req.user.email; + await this.authUserService.sendConfirmationCode(email); + return { message: 'Confirmation code sent' }; + } catch (e) { + throw e; + } + } + + @ApiBody({ type: UserConfirmCode }) + @ApiBearerAuth('jwt') + @UseGuards(AuthUserGuard) + @Post('user/confirm-email') + async confirmEmail(@Body() { code }: UserConfirmCode, @Req() req: CustomUserRequest) { + try { + const email = req.user.email; + return await this.authUserService.confirmEmail(email, { code }); + } catch (e) { + throw e; + } + } } diff --git a/backend/src/auth/user/authUserservice.ts b/backend/src/auth/user/authUserservice.ts index 7f53e41b..1d702bc4 100644 --- a/backend/src/auth/user/authUserservice.ts +++ b/backend/src/auth/user/authUserservice.ts @@ -14,15 +14,19 @@ import { InjectRepository } from '@nestjs/typeorm'; import { UserResetCode } from './entities/user-reset-code.entity'; import { Repository } from 'typeorm'; import { randomInt } from 'crypto'; -import { UserResetPasswordDto } from './dto/user-reset-password.dto'; +import { UserConfirmEmailBody, UserResetPasswordDto } from './dto/user-reset-password.dto'; +import { UserConfirmCode } from './entities/user-confirm-code.entity'; +import { EmailService } from 'src/email/email.service'; @Injectable() export class AuthUserService { constructor( @InjectRepository(UserResetCode) private userResetCodeRepository: Repository, + @InjectRepository(UserConfirmCode) private userConfirmCodeRepository: Repository, private userService: UserService, private jwtService: JwtService, private encryptionService: EncryptionService, + private readonly mailService: EmailService, ) {} async signUp(createAdminDto: CreateUserDto): Promise { @@ -38,6 +42,8 @@ export class AuthUserService { await this.userService.create(createAdminDto); const adminSigninResDto: UserSigninResDto = await this.signIn(loginAdminDto); + createAdminDto.email = 'diegoivan.10290@gmail.com'; + await this.sendConfirmationCode(createAdminDto.email); return adminSigninResDto; } @@ -91,7 +97,7 @@ export class AuthUserService { expirationDate.setHours(expirationDate.getHours() + 1); const existUserCode = await this.userResetCodeRepository.findBy({ user, code: resetCode }); console.log(existUserCode); - + if (existUserCode.length > 0) { await this.userResetCodeRepository.delete(existUserCode[0].id); } @@ -102,7 +108,7 @@ export class AuthUserService { async resetPassword({ email, resetCode, newPassword }: UserResetPasswordDto) { const user: User = await this.userService.findOne(email); if (!user) throw new UnauthorizedException('Invalid email'); - + const userResetCode: UserResetCode[] = await this.userResetCodeRepository.findBy({ user, code: resetCode }); if (userResetCode.length === 0) throw new UnauthorizedException('Invalid code'); @@ -112,4 +118,32 @@ export class AuthUserService { await this.userService.updatePassword(email, newPwdHashed); await this.userResetCodeRepository.delete(userResetCode[0].id); } + + async sendConfirmationCode(email: string) { + const user: User = await this.userService.findOne(email); + if (!user) throw new UnauthorizedException('Invalid email'); + const resetCode = randomInt(100000, 999999).toString(); + const expirationDate = new Date(); + expirationDate.setHours(expirationDate.getHours() + 1); + const existUserCode = await this.userConfirmCodeRepository.findBy({ user, code: resetCode }); + if (existUserCode.length > 0) { + await this.userResetCodeRepository.delete(existUserCode[0].id); + } + await this.userResetCodeRepository.save({ user, code: resetCode, expirationDate }); + await this.mailService.sendConfirmationCode(email, resetCode); + return resetCode; + } + + async confirmEmail(email: string, { code }: UserConfirmEmailBody) { + const user: User = await this.userService.findOne(email); + if (!user) throw new UnauthorizedException('Invalid email'); + + const userConfirmCode: UserResetCode[] = await this.userConfirmCodeRepository.findBy({ user, code: code }); + + if (userConfirmCode.length === 0) throw new UnauthorizedException('Invalid code'); + if (userConfirmCode[0].expirationDate < new Date()) throw new UnauthorizedException('Code expired'); + + await this.userService.confirmEmail(email); + await this.userConfirmCodeRepository.delete(userConfirmCode[0].id); + } } diff --git a/backend/src/auth/user/dto/user-reset-password.dto.ts b/backend/src/auth/user/dto/user-reset-password.dto.ts index c301d1fd..35ac81ec 100644 --- a/backend/src/auth/user/dto/user-reset-password.dto.ts +++ b/backend/src/auth/user/dto/user-reset-password.dto.ts @@ -1,21 +1,26 @@ -import { ApiProperty } from "@nestjs/swagger"; +import { ApiProperty } from '@nestjs/swagger'; export interface UserResetPasswordDto { - email: string; - resetCode: string; - newPassword: string; -} + email: string; + resetCode: string; + newPassword: string; +} export class UserResetPasswordBody { - @ApiProperty() - email: string; - @ApiProperty() - resetCode: string; - @ApiProperty() - newPassword: string; + @ApiProperty() + email: string; + @ApiProperty() + resetCode: string; + @ApiProperty() + newPassword: string; } export class UserRequestCodeBody { - @ApiProperty() - email: string; -} \ No newline at end of file + @ApiProperty() + email: string; +} + +export class UserConfirmEmailBody { + @ApiProperty() + code: string; +} diff --git a/backend/src/auth/user/entities/user-confirm-code.entity.ts b/backend/src/auth/user/entities/user-confirm-code.entity.ts new file mode 100644 index 00000000..d5a48770 --- /dev/null +++ b/backend/src/auth/user/entities/user-confirm-code.entity.ts @@ -0,0 +1,17 @@ +import { User } from 'src/user/entities/user.entity'; +import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; + +@Entity() +export class UserConfirmCode { + @PrimaryGeneratedColumn() + id: number; + + @ManyToOne(() => User, (user) => user.resetCodes) + user: User; + + @Column() + code: string; + + @Column() + expirationDate: Date; +} diff --git a/backend/src/auth/user/entities/user-reset-code.entity.ts b/backend/src/auth/user/entities/user-reset-code.entity.ts index 8f58222d..2bf019ac 100644 --- a/backend/src/auth/user/entities/user-reset-code.entity.ts +++ b/backend/src/auth/user/entities/user-reset-code.entity.ts @@ -1,13 +1,12 @@ -import { User } from "src/user/entities/user.entity"; -import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from "typeorm"; - +import { User } from 'src/user/entities/user.entity'; +import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; @Entity() export class UserResetCode { @PrimaryGeneratedColumn() id: number; - @ManyToOne(() => User, user => user.resetCodes) + @ManyToOne(() => User, (user) => user.resetCodes) user: User; @Column() diff --git a/backend/src/email/email.service.ts b/backend/src/email/email.service.ts index 621bed1f..3d553b37 100644 --- a/backend/src/email/email.service.ts +++ b/backend/src/email/email.service.ts @@ -1,25 +1,35 @@ import { MailerService } from '@nestjs-modules/mailer'; import { Injectable } from '@nestjs/common'; -import { MailConstants } from 'src/constants/mail.constants'; -import { text } from 'stream/consumers'; @Injectable() export class EmailService { - constructor( - private readonly mailerService: MailerService, - ) { } + constructor(private readonly mailerService: MailerService) {} - async sendResetPasswordEmail(email: string, resetCode: string): Promise { - const mailOptions = { - to: email, - subject: 'Reset your password', - html: `

Your reset code is ${resetCode}

`, - }; - try { - await this.mailerService.sendMail(mailOptions); - } catch (error) { - console.error(error); - throw new Error('Error sending email'); - } + async sendResetPasswordEmail(email: string, resetCode: string): Promise { + const mailOptions = { + to: email, + subject: 'Reset your password', + html: `

Your reset code is ${resetCode}

`, + }; + try { + await this.mailerService.sendMail(mailOptions); + } catch (error) { + console.error(error); + throw new Error('Error sending email'); } + } + + async sendConfirmationCode(email: string, confirmationCode: string): Promise { + const mailOptions = { + to: email, + subject: 'Confirm your email', + html: `

Your confirmation code is ${confirmationCode}

`, + }; + try { + await this.mailerService.sendMail(mailOptions); + } catch (error) { + console.error(error); + throw new Error('Error sending email'); + } + } } diff --git a/backend/src/route/route.module.ts b/backend/src/route/route.module.ts index ed23bcf7..14a9b77b 100644 --- a/backend/src/route/route.module.ts +++ b/backend/src/route/route.module.ts @@ -20,6 +20,8 @@ import { PlaceTraduction } from 'src/place/entities/place-traduction.entity'; import { VisitedService } from 'src/visited/visited.service'; import { Visited } from 'src/visited/entities/visited.entity'; import { UserResetCode } from 'src/auth/user/entities/user-reset-code.entity'; +import { UserConfirmCode } from 'src/auth/user/entities/user-confirm-code.entity'; +import { EmailService } from 'src/email/email.service'; @Module({ controllers: [RouteController], @@ -33,6 +35,7 @@ import { UserResetCode } from 'src/auth/user/entities/user-reset-code.entity'; TravelPlaceService, PlaceService, VisitedService, + EmailService, ], imports: [ TypeOrmModule.forFeature([ @@ -46,6 +49,7 @@ import { UserResetCode } from 'src/auth/user/entities/user-reset-code.entity'; AvailableDate, PlaceTraduction, Visited, + UserConfirmCode, ]), ], }) diff --git a/backend/src/user/entities/user.entity.ts b/backend/src/user/entities/user.entity.ts index 36aa4bba..9de86956 100644 --- a/backend/src/user/entities/user.entity.ts +++ b/backend/src/user/entities/user.entity.ts @@ -1,3 +1,4 @@ +import { UserConfirmCode } from 'src/auth/user/entities/user-confirm-code.entity'; import { UserResetCode } from 'src/auth/user/entities/user-reset-code.entity'; import { Category } from 'src/category/entities/category.entity'; import { Entity, Column, ManyToMany, JoinTable, PrimaryColumn, OneToMany } from 'typeorm'; @@ -23,6 +24,12 @@ export class User { @Column() password: string; - @OneToMany(() => UserResetCode, resetCode => resetCode.user) + @Column({ default: false }) + isEmailConfirmed: boolean; + + @OneToMany(() => UserResetCode, (resetCode) => resetCode.user) resetCodes: UserResetCode[]; + + @OneToMany(() => UserConfirmCode, (confirmCode) => confirmCode.user) + confirmCodes: UserConfirmCode[]; } diff --git a/backend/src/user/user.controller.ts b/backend/src/user/user.controller.ts index 18ec00e5..ebb7f80f 100644 --- a/backend/src/user/user.controller.ts +++ b/backend/src/user/user.controller.ts @@ -40,4 +40,17 @@ export class UserController { throw error; } } + + @Get('is-verfied') + @ApiBearerAuth('jwt') + @UseGuards(AuthUserGuard) + async isVerified(@Req() req: CustomUserRequest) { + try { + const { email } = req.user; + const isVerified = await this.userService.isVerified(email); + return { isVerified }; + } catch (error) { + throw error; + } + } } diff --git a/backend/src/user/user.module.ts b/backend/src/user/user.module.ts index 80b6273b..0ff6a8e0 100644 --- a/backend/src/user/user.module.ts +++ b/backend/src/user/user.module.ts @@ -9,10 +9,12 @@ import { AuthUserService } from 'src/auth/user/authUserservice'; import { JwtService } from '@nestjs/jwt'; import { EncryptionService } from 'src/auth/encryption/encryption.service'; import { UserResetCode } from 'src/auth/user/entities/user-reset-code.entity'; +import { UserConfirmCode } from 'src/auth/user/entities/user-confirm-code.entity'; +import { EmailService } from 'src/email/email.service'; @Module({ controllers: [UserController], - providers: [UserService, CategoryService, AuthUserService, JwtService, EncryptionService], - imports: [TypeOrmModule.forFeature([User, Category, UserResetCode])], + providers: [UserService, CategoryService, AuthUserService, JwtService, EncryptionService, EmailService], + imports: [TypeOrmModule.forFeature([User, Category, UserResetCode, UserConfirmCode])], }) export class UserModule {} diff --git a/backend/src/user/user.service.ts b/backend/src/user/user.service.ts index 62e7b4d5..d466391f 100644 --- a/backend/src/user/user.service.ts +++ b/backend/src/user/user.service.ts @@ -68,4 +68,21 @@ export class UserService { }); return user?.preferedCategories || []; } + + async confirmEmail(email: string) { + try { + await this.userRepository.update({ email }, { isEmailConfirmed: true }); + } catch (error) { + throw new BadRequestException('Error confirming email'); + } + } + + async isVerified(email: string): Promise { + try { + const user = await this.userRepository.findOneBy({ email }); + return user.isEmailConfirmed; + } catch (error) { + throw new BadRequestException('Error getting email verification status'); + } + } } diff --git a/backend/src/visited/visited.module.ts b/backend/src/visited/visited.module.ts index 7a9aad88..f79ac46e 100644 --- a/backend/src/visited/visited.module.ts +++ b/backend/src/visited/visited.module.ts @@ -16,6 +16,8 @@ import { AuthUserService } from 'src/auth/user/authUserservice'; import { JwtService } from '@nestjs/jwt'; import { EncryptionService } from 'src/auth/encryption/encryption.service'; import { UserResetCode } from 'src/auth/user/entities/user-reset-code.entity'; +import { UserConfirmCode } from 'src/auth/user/entities/user-confirm-code.entity'; +import { EmailService } from 'src/email/email.service'; @Module({ controllers: [VisitedController], @@ -27,7 +29,21 @@ import { UserResetCode } from 'src/auth/user/entities/user-reset-code.entity'; AuthUserService, JwtService, EncryptionService, + EmailService, + ], + imports: [ + TypeOrmModule.forFeature([ + User, + Place, + Visited, + Category, + AvailableDate, + PlaceTraduction, + Town, + Visited, + UserResetCode, + UserConfirmCode, + ]), ], - imports: [TypeOrmModule.forFeature([User, Place, Visited, Category, AvailableDate, PlaceTraduction, Town, Visited, UserResetCode])], }) export class VisitedModule {} -- GitLab From e9e2cdfa114700f54a73b68ab45dc1bd16a67dc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Wed, 16 Oct 2024 22:56:48 -0600 Subject: [PATCH 2/3] get visited por usuario --- backend/src/visited/visited.controller.ts | 21 +++++---------- backend/src/visited/visited.service.ts | 31 ++++++++++++----------- 2 files changed, 23 insertions(+), 29 deletions(-) diff --git a/backend/src/visited/visited.controller.ts b/backend/src/visited/visited.controller.ts index e5a6741e..a2f1f386 100644 --- a/backend/src/visited/visited.controller.ts +++ b/backend/src/visited/visited.controller.ts @@ -24,22 +24,15 @@ export class VisitedController { } @Get('/getImage/:routeId') - async getVisitedPlacesImage(@Param('routeId') routeId: string) { + async getVisitedPlacesImage() { return await this.visitedService.getVisitedPlacesImage(); } - @Get() - findAll() { - return this.visitedService.findAll(); - } - - @Get(':id') - findOne(@Param('id') id: string) { - return this.visitedService.findOne(+id); - } - - @Delete(':id') - remove(@Param('id') id: string) { - return this.visitedService.remove(+id); + @UseGuards(AuthUserGuard) + @ApiBearerAuth('jwt') + @Get('/user/') + async findAllByUser(@Req() req: CustomUserRequest) { + const { email } = req.user; + return this.visitedService.findAllByUser(email); } } diff --git a/backend/src/visited/visited.service.ts b/backend/src/visited/visited.service.ts index 6b3f1d13..83ee992f 100644 --- a/backend/src/visited/visited.service.ts +++ b/backend/src/visited/visited.service.ts @@ -10,6 +10,7 @@ import { PlaceService } from 'src/place/place.service'; import { LANGUAGES } from 'src/shared/enum/languages.enum'; import { VisitedPlacesImageCreator } from './utils/visited_places_image_creator'; import { HttpErrorByCode } from '@nestjs/common/utils/http-error-by-code.util'; +import { ServerConstants } from 'src/constants/server.contants'; @Injectable() export class VisitedService { @@ -35,26 +36,26 @@ export class VisitedService { }); } - findAll() { - return `This action returns all visited`; - } - - findOne(id: number) { - return `This action returns a #${id} visited`; - } - - // update(id: number, updateVisitedDto: UpdateVisitedDto) { - // return `This action updates a #${id} visited`; - // } - - remove(id: number) { - return `This action removes a #${id} visited`; + async findAllByUser(email: string) { + const res = await this.visitedRepository.find({ where: { user: { email } } }); + const visited = res.map((visit: Visited) => { + return { + ...visit, + place: { + ...visit.place, + imageName: `${ServerConstants.HOST}/places/${visit.place.imageName}`, + }, + }; + }); + return visited; } async getVisitedPlacesImage() { // obtener imágenes de los lugares visitados en una ruta try { - const visitedPlaces = (await this.placeService.findAllByTown(1, LANGUAGES.EN)).map((place) => place.imageName).slice(0, 5); + const visitedPlaces = (await this.placeService.findAllByTown(1, LANGUAGES.EN)) + .map((place) => place.imageName) + .slice(0, 5); const visitedPlacesImageCreator = new VisitedPlacesImageCreator(); return await visitedPlacesImageCreator.generateImage(visitedPlaces); } catch (error) { -- GitLab From 2b0035da70b4038922c992ba40db6a1cf6f0ed15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Thu, 17 Oct 2024 10:39:09 -0600 Subject: [PATCH 3/3] update --- backend/src/auth/user/authUsercontroller.ts | 12 ++++++++---- backend/src/auth/user/authUserservice.ts | 6 +++--- backend/src/place/entities/place.entity.ts | 4 ++++ backend/src/route/route.controller.ts | 8 ++++++++ backend/src/route/route.service.ts | 15 ++++++++++++++- backend/src/visited/entities/visited.entity.ts | 4 ++-- backend/src/visited/visited.service.ts | 3 +-- 7 files changed, 40 insertions(+), 12 deletions(-) diff --git a/backend/src/auth/user/authUsercontroller.ts b/backend/src/auth/user/authUsercontroller.ts index 2c2afcb6..6d345f8d 100644 --- a/backend/src/auth/user/authUsercontroller.ts +++ b/backend/src/auth/user/authUsercontroller.ts @@ -7,10 +7,14 @@ import { UserSigninResDto } from './dto/user-signin-res.dto'; import { AuthUserGuard } from './authUser.guard'; import { CustomUserRequest } from './interface/customUserReq'; import { UpdatePwdDto } from './dto/update-pwd.dto'; -import { UserRequestCodeBody, UserResetPasswordBody, UserResetPasswordDto } from './dto/user-reset-password.dto'; +import { + UserConfirmEmailBody, + UserRequestCodeBody, + UserResetPasswordBody, + UserResetPasswordDto, +} from './dto/user-reset-password.dto'; import { GetResetCode } from './dto/get-reset-code.dto'; import { EmailService } from 'src/email/email.service'; -import { UserConfirmCode } from './entities/user-confirm-code.entity'; @Controller('') @ApiTags('Create user account and sign in as user') @@ -85,11 +89,11 @@ export class AuthUserController { } } - @ApiBody({ type: UserConfirmCode }) + @ApiBody({ type: UserConfirmEmailBody }) @ApiBearerAuth('jwt') @UseGuards(AuthUserGuard) @Post('user/confirm-email') - async confirmEmail(@Body() { code }: UserConfirmCode, @Req() req: CustomUserRequest) { + async confirmEmail(@Body() { code }, @Req() req: CustomUserRequest) { try { const email = req.user.email; return await this.authUserService.confirmEmail(email, { code }); diff --git a/backend/src/auth/user/authUserservice.ts b/backend/src/auth/user/authUserservice.ts index 1d702bc4..ee0a07dc 100644 --- a/backend/src/auth/user/authUserservice.ts +++ b/backend/src/auth/user/authUserservice.ts @@ -42,8 +42,8 @@ export class AuthUserService { await this.userService.create(createAdminDto); const adminSigninResDto: UserSigninResDto = await this.signIn(loginAdminDto); - createAdminDto.email = 'diegoivan.10290@gmail.com'; await this.sendConfirmationCode(createAdminDto.email); + return adminSigninResDto; } @@ -127,9 +127,9 @@ export class AuthUserService { expirationDate.setHours(expirationDate.getHours() + 1); const existUserCode = await this.userConfirmCodeRepository.findBy({ user, code: resetCode }); if (existUserCode.length > 0) { - await this.userResetCodeRepository.delete(existUserCode[0].id); + await this.userConfirmCodeRepository.delete(existUserCode[0].id); } - await this.userResetCodeRepository.save({ user, code: resetCode, expirationDate }); + await this.userConfirmCodeRepository.save({ user, code: resetCode, expirationDate }); await this.mailService.sendConfirmationCode(email, resetCode); return resetCode; } diff --git a/backend/src/place/entities/place.entity.ts b/backend/src/place/entities/place.entity.ts index b4ed14c7..ea48f3f0 100644 --- a/backend/src/place/entities/place.entity.ts +++ b/backend/src/place/entities/place.entity.ts @@ -9,11 +9,13 @@ import { ManyToMany, ManyToOne, OneToMany, + OneToOne, PrimaryGeneratedColumn, } from 'typeorm'; import { AvailableDate } from './available-date.entity'; import { Category } from 'src/category/entities/category.entity'; import { PlaceTraduction } from './place-traduction.entity'; +import { Visited } from 'src/visited/entities/visited.entity'; @Entity() export class Place { @@ -37,6 +39,8 @@ export class Place { @OneToMany(() => PlaceTraduction, (placeTraduction) => placeTraduction.idPlace) placeTraduction: PlaceTraduction[]; + @OneToOne(() => Visited, (visited) => visited.place) + visited: Visited[]; @Column() available: Available; diff --git a/backend/src/route/route.controller.ts b/backend/src/route/route.controller.ts index a4ea8743..db4760ed 100644 --- a/backend/src/route/route.controller.ts +++ b/backend/src/route/route.controller.ts @@ -66,4 +66,12 @@ export class RouteController { async updateRoute(@Body() updateRouteStatusDto: UpdateRouteStatusDto, @Param('idRoute') idRoute: number) { return await this.routeService.updateRoute(idRoute, updateRouteStatusDto.status); } + + @Get('/info/:idRoute') + @ApiParam({ name: 'idRoute', type: Number }) + @ApiBearerAuth('jwt') + @UseGuards(AuthUserGuard) + async getRouteInfo(@Param('idRoute') idRoute: number) { + return await this.routeService.getRouteInfoById(idRoute); + } } diff --git a/backend/src/route/route.service.ts b/backend/src/route/route.service.ts index 048ca136..6ee25f6f 100644 --- a/backend/src/route/route.service.ts +++ b/backend/src/route/route.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Route, RouteStatus } from './entities/route.entity'; -import { MoreThan, Repository } from 'typeorm'; +import { DataSource, MoreThan, Repository } from 'typeorm'; import { User } from 'src/user/entities/user.entity'; import { Town } from 'src/town/entities/town.entity'; import { TravelPlaceService } from 'src/travel-place/travel-place.service'; @@ -28,6 +28,7 @@ export class RouteService { private readonly placeService: PlaceService, private readonly visitedService: VisitedService, private readonly userService: UserService, + private dataSource: DataSource, ) {} async recommend(idTown: number, email: string, language: LANGUAGES, start, end) { @@ -139,4 +140,16 @@ export class RouteService { return res; } + + async getRouteInfoById(idRoute: number) { + const res = await this.dataSource + .createQueryBuilder(Route, 'route') + .leftJoinAndSelect('route.travelPlace', 'travelPlace') + .leftJoinAndSelect('travelPlace.place', 'place') + .leftJoinAndSelect('place.visited', 'visited') + .where('route.idRoute = :idRoute', { idRoute }) + .getOne(); + + return res; + } } diff --git a/backend/src/visited/entities/visited.entity.ts b/backend/src/visited/entities/visited.entity.ts index 2ed305b3..e99296ce 100644 --- a/backend/src/visited/entities/visited.entity.ts +++ b/backend/src/visited/entities/visited.entity.ts @@ -1,13 +1,13 @@ import { Place } from 'src/place/entities/place.entity'; import { User } from 'src/user/entities/user.entity'; -import { Column, Entity, JoinColumn, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; +import { Column, Entity, JoinColumn, ManyToOne, OneToOne, PrimaryGeneratedColumn } from 'typeorm'; @Entity() export class Visited { @PrimaryGeneratedColumn() idVisited: number; - @ManyToOne(() => Place, (place) => place.idPlace, { eager: true }) + @OneToOne(() => Place, (place) => place.idPlace, { eager: true }) @JoinColumn({ name: 'place' }) place: Place; diff --git a/backend/src/visited/visited.service.ts b/backend/src/visited/visited.service.ts index 83ee992f..7f0c17e0 100644 --- a/backend/src/visited/visited.service.ts +++ b/backend/src/visited/visited.service.ts @@ -1,4 +1,4 @@ -import { BadRequestException, HttpException, Injectable, InternalServerErrorException } from '@nestjs/common'; +import { BadRequestException, Injectable, InternalServerErrorException } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Visited } from './entities/visited.entity'; import { Repository } from 'typeorm'; @@ -9,7 +9,6 @@ import { Place } from 'src/place/entities/place.entity'; import { PlaceService } from 'src/place/place.service'; import { LANGUAGES } from 'src/shared/enum/languages.enum'; import { VisitedPlacesImageCreator } from './utils/visited_places_image_creator'; -import { HttpErrorByCode } from '@nestjs/common/utils/http-error-by-code.util'; import { ServerConstants } from 'src/constants/server.contants'; @Injectable() -- GitLab