-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: implement registration service and registration confirm service
- Loading branch information
1 parent
f872282
commit 1fa209f
Showing
10 changed files
with
183 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 13 additions & 5 deletions
18
src/interfaces/repositories/verification-code.repository.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,19 @@ | ||
import type { VerificationCode } from '../models/verification-code'; | ||
import type { | ||
VerificationCode, | ||
VerificationCodeTypeEnum, | ||
} from '../models/verification-code'; | ||
|
||
export type VerificationCodeRepositoryFilterDto = { | ||
type: VerificationCodeTypeEnum; | ||
code: string; | ||
}; | ||
|
||
export interface VerificationCodeRepository { | ||
create(dto: Omit<VerificationCode, 'code'>): Promise<void>; | ||
|
||
findByCode(dto: { code: string }): Promise<VerificationCode | null>; | ||
|
||
findByContent(dto: { content: string }): Promise<VerificationCode | null>; | ||
findOne( | ||
dto: VerificationCodeRepositoryFilterDto, | ||
): Promise<VerificationCode | null>; | ||
|
||
deleteByCode(dto: { code: string }): Promise<void>; | ||
deleteOne(dto: VerificationCodeRepositoryFilterDto): Promise<void>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
export type RegistrationConfirmServiceDto = { | ||
code: string; | ||
}; | ||
|
||
export interface RegistrationConfirmService { | ||
execute(dto: RegistrationConfirmServiceDto): Promise<void>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
export type RegistrationServiceDto = { | ||
password: string; | ||
email: string; | ||
name: string; | ||
}; | ||
|
||
export interface RegistrationService { | ||
execute(dto: RegistrationServiceDto): Promise<void>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,8 @@ | ||
export * from './create-register-token.service'; | ||
export * from './registration-confirm.service'; | ||
export * from './get-register-token.service'; | ||
export * from './refresh-login.service'; | ||
export * from './registration.service'; | ||
export * from './create-user.service'; | ||
export * from './logout.service'; | ||
export * from './login.service'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import { inject, injectable } from 'tsyringe'; | ||
|
||
import { AppErrorCodeEnum, HttpStatusCodesEnum } from '@/constants'; | ||
import { AppError } from '@/errors'; | ||
import { | ||
type RegistrationConfirmServiceDto, | ||
type RegistrationConfirmService as RegistrationConfirmServiceInterface, | ||
type User, | ||
type UserRepository, | ||
type VerificationCodeRepository, | ||
VerificationCodeTypeEnum, | ||
} from '@/interfaces'; | ||
|
||
@injectable() | ||
export class RegistrationConfirmService | ||
implements RegistrationConfirmServiceInterface | ||
{ | ||
constructor( | ||
@inject('UserRepository') | ||
private readonly userRepository: UserRepository, | ||
|
||
@inject('VerificationCodeRepository') | ||
private verificationCodeRepository: VerificationCodeRepository, | ||
) {} | ||
|
||
public async execute({ code }: RegistrationConfirmServiceDto): Promise<void> { | ||
const verificationCode = await this.verificationCodeRepository.findOne({ | ||
type: VerificationCodeTypeEnum.Registration, | ||
code, | ||
}); | ||
|
||
if (!verificationCode) { | ||
throw new AppError({ | ||
message: AppErrorCodeEnum.VerificationCodeNotFound, | ||
status_code: HttpStatusCodesEnum.NOT_FOUND, | ||
}); | ||
} | ||
|
||
const user = this.parseUser(verificationCode.content); | ||
|
||
const userExists = await this.userRepository.findByEmail({ | ||
email: user.email, | ||
}); | ||
|
||
if (userExists) { | ||
throw new AppError({ | ||
message: AppErrorCodeEnum.EmailAlreadyInUse, | ||
status_code: HttpStatusCodesEnum.CONFLICT, | ||
}); | ||
} | ||
|
||
await this.userRepository.create(user); | ||
} | ||
|
||
private parseUser(content: string): User { | ||
const user = JSON.parse(content) as User; | ||
|
||
return user; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import { inject, injectable } from 'tsyringe'; | ||
|
||
import type { HashAdapter } from '@/adapters'; | ||
import { AppErrorCodeEnum, HttpStatusCodesEnum } from '@/constants'; | ||
import { AppError } from '@/errors'; | ||
import { | ||
type RegistrationServiceDto, | ||
type RegistrationService as RegistrationServiceInterface, | ||
type User, | ||
type UserRepository, | ||
type VerificationCodeRepository, | ||
VerificationCodeTypeEnum, | ||
} from '@/interfaces'; | ||
|
||
@injectable() | ||
export class RegistrationService implements RegistrationServiceInterface { | ||
constructor( | ||
@inject('UserRepository') | ||
private readonly userRepository: UserRepository, | ||
|
||
@inject('VerificationCodeRepository') | ||
private verificationCodeRepository: VerificationCodeRepository, | ||
|
||
@inject('HashAdapter') | ||
private hashAdapter: HashAdapter, | ||
) {} | ||
|
||
public async execute({ | ||
password, | ||
email, | ||
name, | ||
}: RegistrationServiceDto): Promise<void> { | ||
const userExists = await this.userRepository.findByEmail({ | ||
email, | ||
}); | ||
|
||
if (userExists) { | ||
throw new AppError({ | ||
message: AppErrorCodeEnum.EmailAlreadyInUse, | ||
status_code: HttpStatusCodesEnum.CONFLICT, | ||
}); | ||
} | ||
|
||
const salt = this.hashAdapter.generateSalt(); | ||
const hashedPassword = this.hashAdapter.hash({ | ||
text: password, | ||
salt, | ||
}); | ||
|
||
const content: Omit<User, 'id'> = { | ||
password: hashedPassword, | ||
password_salt: salt, | ||
email, | ||
name, | ||
}; | ||
|
||
const expirationTimeInMinutes = 60; // 1 hour | ||
const expiresAt = new Date( | ||
Date.now() + expirationTimeInMinutes * 60 * 1000, | ||
).toISOString(); | ||
|
||
await this.verificationCodeRepository.create({ | ||
type: VerificationCodeTypeEnum.Registration, | ||
content: JSON.stringify(content), | ||
expires_at: expiresAt, | ||
}); | ||
} | ||
} |