From 551b2e9659f1875ad6d20361fe74bdf0d0c9a768 Mon Sep 17 00:00:00 2001 From: Igor Propisnov Date: Mon, 3 Jun 2024 14:20:54 +0200 Subject: [PATCH] refactored signup process --- .../src/entities/user-credentials.entity.ts | 5 +- backend/src/entities/user-data.entity.ts | 6 +- .../auth-module/controller/auth.controller.ts | 2 +- .../user-credentials.repository.ts | 18 ++-- .../auth-module/services/auth.service.ts | 98 +++++++++++-------- .../services/token-management.service.ts | 32 ++---- .../repositories/user-data.repository.ts | 14 +-- .../services/email-verification.service.ts | 6 +- 8 files changed, 91 insertions(+), 90 deletions(-) diff --git a/backend/src/entities/user-credentials.entity.ts b/backend/src/entities/user-credentials.entity.ts index 2f8eff4..efa21e3 100644 --- a/backend/src/entities/user-credentials.entity.ts +++ b/backend/src/entities/user-credentials.entity.ts @@ -15,10 +15,7 @@ export class UserCredentials { public email: string; @Column() - public hash: string; - - @Column({ nullable: true }) - public refreshToken?: string; + public hashedPassword: string; @CreateDateColumn() public createdAt: Date; diff --git a/backend/src/entities/user-data.entity.ts b/backend/src/entities/user-data.entity.ts index b0ab112..6471ad1 100644 --- a/backend/src/entities/user-data.entity.ts +++ b/backend/src/entities/user-data.entity.ts @@ -18,9 +18,9 @@ export class UserData { @Column({ default: false }) public isEmailConfirmed: boolean; - @OneToOne(() => UserCredentials) - @JoinColumn({ name: 'userCredentialsId' }) - public user: UserCredentials; + @OneToOne(() => UserCredentials, { eager: true }) // eager: true lädt UserCredentials automatisch, wenn Sie UserData laden + @JoinColumn() // Diese Dekoration sagt TypeORM, welche Spalte der Fremdschlüssel ist + public userCredentials: UserCredentials; @CreateDateColumn() public createdAt: Date; diff --git a/backend/src/modules/auth-module/controller/auth.controller.ts b/backend/src/modules/auth-module/controller/auth.controller.ts index fbd7caa..03fd70b 100644 --- a/backend/src/modules/auth-module/controller/auth.controller.ts +++ b/backend/src/modules/auth-module/controller/auth.controller.ts @@ -19,7 +19,7 @@ export class AuthController { @HttpCode(HttpStatus.CREATED) public async signup( @Body() userCredentials: UserCredentialsDto - ): Promise { + ): Promise<{ success: boolean }> { return this.authService.signup(userCredentials); } diff --git a/backend/src/modules/auth-module/repositories/user-credentials.repository.ts b/backend/src/modules/auth-module/repositories/user-credentials.repository.ts index a2bf7f0..48671ef 100644 --- a/backend/src/modules/auth-module/repositories/user-credentials.repository.ts +++ b/backend/src/modules/auth-module/repositories/user-credentials.repository.ts @@ -12,9 +12,9 @@ export class UserCredentialsRepository { public async createUser( email: string, - hash: string + hashedPassword: string ): Promise { - const user = this.repository.create({ email, hash }); + const user = this.repository.create({ email, hashedPassword }); return this.repository.save(user); } @@ -31,12 +31,12 @@ export class UserCredentialsRepository { return this.repository.findOne({ where: { id: userId } }); } - public async updateUserRefreshToken( - userId: string, - refreshToken: string | null - ): Promise { - const result = await this.repository.update(userId, { refreshToken }); + // public async updateUserRefreshToken( + // userId: string, + // refreshToken: string | null + // ): Promise { + // const result = await this.repository.update(userId, { refreshToken }); - return result.affected ?? 0; - } + // return result.affected ?? 0; + // } } diff --git a/backend/src/modules/auth-module/services/auth.service.ts b/backend/src/modules/auth-module/services/auth.service.ts index 7c1ad84..285fed3 100644 --- a/backend/src/modules/auth-module/services/auth.service.ts +++ b/backend/src/modules/auth-module/services/auth.service.ts @@ -1,4 +1,9 @@ -import { Injectable } from '@nestjs/common'; +import { + ConflictException, + HttpException, + HttpStatus, + Injectable, +} from '@nestjs/common'; import { EncryptionService } from 'src/shared'; import { PasswordConfirmationMailService } from '../../sendgrid-module/services/password-confirmation.mail.service'; @@ -23,29 +28,52 @@ export class AuthService { public async signup( userCredentials: UserCredentialsDto - ): Promise { - const passwordHashed = await EncryptionService.hashData( - userCredentials.password - ); - - const user = await this.userCredentialsRepository.createUser( - userCredentials.email, - passwordHashed - ); - - await this.userDataRepository.createInitialUserData(user); - - const token = - await this.emailVerificationService.generateEmailVerificationToken( - user.id + ): Promise<{ success: boolean }> { + try { + const existingUser = await this.userCredentialsRepository.findUserByEmail( + userCredentials.email ); - await this.passwordConfirmationMailService.sendPasswordConfirmationMail( - user.email, - token - ); + if (existingUser) { + throw new ConflictException('User already exists'); + } - //return this.generateAndPersistTokens(user.id, user.email); + const passwordHashed = await EncryptionService.hashData( + userCredentials.password + ); + + const user = await this.userCredentialsRepository.createUser( + userCredentials.email, + passwordHashed + ); + + await this.userDataRepository.createInitialUserData(user); + + const token = + await this.emailVerificationService.generateEmailVerificationToken( + user.id + ); + + await this.passwordConfirmationMailService.sendPasswordConfirmationMail( + user.email, + token + ); + + return { + success: true, + }; + } catch (error) { + if (error instanceof ConflictException) { + throw new ConflictException( + 'Diese E-Mail-Adresse ist bereits registriert.' + ); + } else { + throw new HttpException( + 'Fehler bei der Registrierung', + HttpStatus.INTERNAL_SERVER_ERROR + ); + } + } } // public async signin( @@ -129,25 +157,17 @@ export class AuthService { // return { access_token: newTokens.access_token }; // } - // private async generateAndPersistTokens( - // userId: string, - // email: string, - // updateRefreshToken: boolean = false - // ): Promise { - // const tokens = await this.tokenManagementService.generateTokens( - // userId, - // email - // ); + private async generateAndPersistTokens( + userId: string, + email: string + ): Promise { + const tokens = await this.tokenManagementService.generateTokens( + userId, + email + ); - // if (updateRefreshToken) { - // await this.userCredentialsRepository.updateUserRefreshToken( - // userId, - // tokens.refresh_token - // ); - // } - - // return { access_token: tokens.access_token, email: email, userId: userId }; - // } + return { access_token: tokens.access_token, email: email, userId: userId }; + } // private async validateRefreshToken(userId: string): Promise { // const user = await this.userCredentialsRepository.findUserById(userId); diff --git a/backend/src/modules/auth-module/services/token-management.service.ts b/backend/src/modules/auth-module/services/token-management.service.ts index 6b56f8f..5e10e1c 100644 --- a/backend/src/modules/auth-module/services/token-management.service.ts +++ b/backend/src/modules/auth-module/services/token-management.service.ts @@ -2,14 +2,13 @@ import { Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { JwtService } from '@nestjs/jwt'; -import { TokenPayload, Tokens } from '../models/types'; +import { AccessTokenDto } from '../models/dto'; +import { TokenPayload } from '../models/types'; @Injectable() export class TokenManagementService { private readonly ACCESS_TOKEN_EXPIRY: string; - private readonly REFRESH_TOKEN_EXPIRY: string; private readonly JWT_SECRET_AT: string; - private readonly JWT_SECRET_RT: string; public constructor( private readonly jwt: JwtService, @@ -18,23 +17,21 @@ export class TokenManagementService { this.ACCESS_TOKEN_EXPIRY = this.configService.get( 'ACCESS_TOKEN_EXPIRY' ); - this.REFRESH_TOKEN_EXPIRY = this.configService.get( - 'REFRESH_TOKEN_EXPIRY' - ); this.JWT_SECRET_AT = this.configService.get('JWT_SECRET_AT'); - this.JWT_SECRET_RT = this.configService.get('JWT_SECRET_RT'); } - public async generateTokens(userId: string, email: string): Promise { + public async generateTokens( + userId: string, + email: string + ): Promise { const access_token: string = await this.createAccessToken(userId, email); - const refresh_token: string = await this.createRefreshToken(userId, email); - return { access_token, refresh_token }; + return { access_token }; } public async verifyRefreshToken(token: string): Promise { return this.jwt.verifyAsync(token, { - secret: this.JWT_SECRET_RT, + secret: this.JWT_SECRET_AT, }); } @@ -50,17 +47,4 @@ export class TokenManagementService { } ); } - - private async createRefreshToken( - userId: string, - email: string - ): Promise { - return this.jwt.signAsync( - { sub: userId, email }, - { - expiresIn: this.REFRESH_TOKEN_EXPIRY, - secret: this.JWT_SECRET_RT, - } - ); - } } diff --git a/backend/src/modules/user-module/repositories/user-data.repository.ts b/backend/src/modules/user-module/repositories/user-data.repository.ts index 767a91d..11056eb 100644 --- a/backend/src/modules/user-module/repositories/user-data.repository.ts +++ b/backend/src/modules/user-module/repositories/user-data.repository.ts @@ -15,16 +15,16 @@ export class UserDataRepository { ): Promise { const userData = new UserData(); - userData.user = userCredentials; + userData.userCredentials = userCredentials; userData.isEmailConfirmed = false; return this.repository.save(userData); } - public async updateEmailVerificationStatus(userId: string): Promise { - await this.repository.update( - { user: { id: userId } }, - { isEmailConfirmed: true } - ); - } + // public async updateEmailVerificationStatus(userId: string): Promise { + // await this.repository.update( + // { user: { id: userId } }, + // { isEmailConfirmed: true } + // ); + // } } diff --git a/backend/src/modules/verify-module/services/email-verification.service.ts b/backend/src/modules/verify-module/services/email-verification.service.ts index 272b065..288d2ef 100644 --- a/backend/src/modules/verify-module/services/email-verification.service.ts +++ b/backend/src/modules/verify-module/services/email-verification.service.ts @@ -42,9 +42,9 @@ export class EmailVerificationService { await this.deleteEmailVerificationToken(tokenToVerify); if (emailVerification && emailVerification.user) { - await this.userDataRepository.updateEmailVerificationStatus( - emailVerification.user.id - ); + // await this.userDataRepository.updateEmailVerificationStatus( + // emailVerification.user.id + // ); return true; } else { return false;