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;
@Column()
public hash: string;
@Column({ nullable: true })
public refreshToken?: string;
public hashedPassword: string;
@CreateDateColumn()
public createdAt: Date;

View File

@ -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;

View File

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

View File

@ -12,9 +12,9 @@ export class UserCredentialsRepository {
public async createUser(
email: string,
hash: string
hashedPassword: string
): Promise<UserCredentials> {
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<number> {
const result = await this.repository.update(userId, { refreshToken });
// public async updateUserRefreshToken(
// userId: string,
// refreshToken: string | null
// ): Promise<number> {
// 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 { PasswordConfirmationMailService } from '../../sendgrid-module/services/password-confirmation.mail.service';
@ -23,29 +28,52 @@ export class AuthService {
public async signup(
userCredentials: UserCredentialsDto
): Promise<LoginResponseDto> {
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<LoginResponseDto> {
// const tokens = await this.tokenManagementService.generateTokens(
// userId,
// email
// );
private async generateAndPersistTokens(
userId: string,
email: string
): Promise<LoginResponseDto> {
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<TokenPayload> {
// const user = await this.userCredentialsRepository.findUserById(userId);

View File

@ -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<string>(
'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_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 refresh_token: string = await this.createRefreshToken(userId, email);
return { access_token, refresh_token };
return { access_token };
}
public async verifyRefreshToken(token: string): Promise<TokenPayload> {
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> {
const userData = new UserData();
userData.user = userCredentials;
userData.userCredentials = userCredentials;
userData.isEmailConfirmed = false;
return this.repository.save(userData);
}
public async updateEmailVerificationStatus(userId: string): Promise<void> {
await this.repository.update(
{ user: { id: userId } },
{ isEmailConfirmed: true }
);
}
// public async updateEmailVerificationStatus(userId: string): Promise<void> {
// await this.repository.update(
// { user: { id: userId } },
// { isEmailConfirmed: true }
// );
// }
}

View File

@ -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;