refactored signup process

This commit is contained in:
Igor Hrenowitsch Propisnov 2024-06-03 14:20:54 +02:00
parent 9993c63a56
commit 551b2e9659
8 changed files with 91 additions and 90 deletions

View File

@ -15,10 +15,7 @@ export class UserCredentials {
public email: string; public email: string;
@Column() @Column()
public hash: string; public hashedPassword: string;
@Column({ nullable: true })
public refreshToken?: string;
@CreateDateColumn() @CreateDateColumn()
public createdAt: Date; public createdAt: Date;

View File

@ -18,9 +18,9 @@ export class UserData {
@Column({ default: false }) @Column({ default: false })
public isEmailConfirmed: boolean; public isEmailConfirmed: boolean;
@OneToOne(() => UserCredentials) @OneToOne(() => UserCredentials, { eager: true }) // eager: true lädt UserCredentials automatisch, wenn Sie UserData laden
@JoinColumn({ name: 'userCredentialsId' }) @JoinColumn() // Diese Dekoration sagt TypeORM, welche Spalte der Fremdschlüssel ist
public user: UserCredentials; public userCredentials: UserCredentials;
@CreateDateColumn() @CreateDateColumn()
public createdAt: Date; public createdAt: Date;

View File

@ -19,7 +19,7 @@ export class AuthController {
@HttpCode(HttpStatus.CREATED) @HttpCode(HttpStatus.CREATED)
public async signup( public async signup(
@Body() userCredentials: UserCredentialsDto @Body() userCredentials: UserCredentialsDto
): Promise<LoginResponseDto> { ): Promise<{ success: boolean }> {
return this.authService.signup(userCredentials); return this.authService.signup(userCredentials);
} }

View File

@ -12,9 +12,9 @@ export class UserCredentialsRepository {
public async createUser( public async createUser(
email: string, email: string,
hash: string hashedPassword: string
): Promise<UserCredentials> { ): Promise<UserCredentials> {
const user = this.repository.create({ email, hash }); const user = this.repository.create({ email, hashedPassword });
return this.repository.save(user); return this.repository.save(user);
} }
@ -31,12 +31,12 @@ export class UserCredentialsRepository {
return this.repository.findOne({ where: { id: userId } }); return this.repository.findOne({ where: { id: userId } });
} }
public async updateUserRefreshToken( // public async updateUserRefreshToken(
userId: string, // userId: string,
refreshToken: string | null // refreshToken: string | null
): Promise<number> { // ): Promise<number> {
const result = await this.repository.update(userId, { refreshToken }); // const result = await this.repository.update(userId, { refreshToken });
return result.affected ?? 0; // return result.affected ?? 0;
} // }
} }

View File

@ -1,4 +1,9 @@
import { Injectable } from '@nestjs/common'; import {
ConflictException,
HttpException,
HttpStatus,
Injectable,
} from '@nestjs/common';
import { EncryptionService } from 'src/shared'; import { EncryptionService } from 'src/shared';
import { PasswordConfirmationMailService } from '../../sendgrid-module/services/password-confirmation.mail.service'; import { PasswordConfirmationMailService } from '../../sendgrid-module/services/password-confirmation.mail.service';
@ -23,7 +28,16 @@ export class AuthService {
public async signup( public async signup(
userCredentials: UserCredentialsDto userCredentials: UserCredentialsDto
): Promise<LoginResponseDto> { ): Promise<{ success: boolean }> {
try {
const existingUser = await this.userCredentialsRepository.findUserByEmail(
userCredentials.email
);
if (existingUser) {
throw new ConflictException('User already exists');
}
const passwordHashed = await EncryptionService.hashData( const passwordHashed = await EncryptionService.hashData(
userCredentials.password userCredentials.password
); );
@ -45,7 +59,21 @@ export class AuthService {
token token
); );
//return this.generateAndPersistTokens(user.id, user.email); 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( // public async signin(
@ -129,25 +157,17 @@ export class AuthService {
// return { access_token: newTokens.access_token }; // return { access_token: newTokens.access_token };
// } // }
// private async generateAndPersistTokens( private async generateAndPersistTokens(
// userId: string, userId: string,
// email: string, email: string
// updateRefreshToken: boolean = false ): Promise<LoginResponseDto> {
// ): Promise<LoginResponseDto> { const tokens = await this.tokenManagementService.generateTokens(
// const tokens = await this.tokenManagementService.generateTokens( userId,
// userId, email
// email );
// );
// if (updateRefreshToken) { return { access_token: tokens.access_token, email: email, userId: userId };
// await this.userCredentialsRepository.updateUserRefreshToken( }
// userId,
// tokens.refresh_token
// );
// }
// return { access_token: tokens.access_token, email: email, userId: userId };
// }
// private async validateRefreshToken(userId: string): Promise<TokenPayload> { // private async validateRefreshToken(userId: string): Promise<TokenPayload> {
// const user = await this.userCredentialsRepository.findUserById(userId); // const user = await this.userCredentialsRepository.findUserById(userId);

View File

@ -2,14 +2,13 @@ import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config'; import { ConfigService } from '@nestjs/config';
import { JwtService } from '@nestjs/jwt'; import { JwtService } from '@nestjs/jwt';
import { TokenPayload, Tokens } from '../models/types'; import { AccessTokenDto } from '../models/dto';
import { TokenPayload } from '../models/types';
@Injectable() @Injectable()
export class TokenManagementService { export class TokenManagementService {
private readonly ACCESS_TOKEN_EXPIRY: string; private readonly ACCESS_TOKEN_EXPIRY: string;
private readonly REFRESH_TOKEN_EXPIRY: string;
private readonly JWT_SECRET_AT: string; private readonly JWT_SECRET_AT: string;
private readonly JWT_SECRET_RT: string;
public constructor( public constructor(
private readonly jwt: JwtService, private readonly jwt: JwtService,
@ -18,23 +17,21 @@ export class TokenManagementService {
this.ACCESS_TOKEN_EXPIRY = this.configService.get<string>( this.ACCESS_TOKEN_EXPIRY = this.configService.get<string>(
'ACCESS_TOKEN_EXPIRY' 'ACCESS_TOKEN_EXPIRY'
); );
this.REFRESH_TOKEN_EXPIRY = this.configService.get<string>(
'REFRESH_TOKEN_EXPIRY'
);
this.JWT_SECRET_AT = this.configService.get<string>('JWT_SECRET_AT'); this.JWT_SECRET_AT = this.configService.get<string>('JWT_SECRET_AT');
this.JWT_SECRET_RT = this.configService.get<string>('JWT_SECRET_RT');
} }
public async generateTokens(userId: string, email: string): Promise<Tokens> { public async generateTokens(
userId: string,
email: string
): Promise<AccessTokenDto> {
const access_token: string = await this.createAccessToken(userId, email); 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<TokenPayload> { public async verifyRefreshToken(token: string): Promise<TokenPayload> {
return this.jwt.verifyAsync(token, { 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<string> {
return this.jwt.signAsync(
{ sub: userId, email },
{
expiresIn: this.REFRESH_TOKEN_EXPIRY,
secret: this.JWT_SECRET_RT,
}
);
}
} }

View File

@ -15,16 +15,16 @@ export class UserDataRepository {
): Promise<UserData> { ): Promise<UserData> {
const userData = new UserData(); const userData = new UserData();
userData.user = userCredentials; userData.userCredentials = userCredentials;
userData.isEmailConfirmed = false; userData.isEmailConfirmed = false;
return this.repository.save(userData); return this.repository.save(userData);
} }
public async updateEmailVerificationStatus(userId: string): Promise<void> { // public async updateEmailVerificationStatus(userId: string): Promise<void> {
await this.repository.update( // await this.repository.update(
{ user: { id: userId } }, // { user: { id: userId } },
{ isEmailConfirmed: true } // { isEmailConfirmed: true }
); // );
} // }
} }

View File

@ -42,9 +42,9 @@ export class EmailVerificationService {
await this.deleteEmailVerificationToken(tokenToVerify); await this.deleteEmailVerificationToken(tokenToVerify);
if (emailVerification && emailVerification.user) { if (emailVerification && emailVerification.user) {
await this.userDataRepository.updateEmailVerificationStatus( // await this.userDataRepository.updateEmailVerificationStatus(
emailVerification.user.id // emailVerification.user.id
); // );
return true; return true;
} else { } else {
return false; return false;