Skip to content

Commit

Permalink
Refactor createUser to addUser
Browse files Browse the repository at this point in the history
  • Loading branch information
alexeh committed Oct 13, 2024
1 parent 835e998 commit 2fca502
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 18 deletions.
12 changes: 7 additions & 5 deletions api/src/modules/admin/admin.controller.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Controller, UseGuards } from '@nestjs/common';
import { Controller, Headers, UseGuards } from '@nestjs/common';
import { RolesGuard } from '@api/modules/auth/guards/roles.guard';
import { JwtAuthGuard } from '@api/modules/auth/guards/jwt-auth.guard';
import { RequiredRoles } from '@api/modules/auth/decorators/roles.decorator';
Expand All @@ -14,10 +14,12 @@ export class AdminController {
constructor(private readonly auth: AuthenticationService) {}

@RequiredRoles(ROLES.ADMIN)
@TsRestHandler(adminContract.createUser)
async createUser(): Promise<ControllerResponse> {
return tsRestHandler(adminContract.createUser, async ({ body }) => {
await this.auth.createUser(body);
@TsRestHandler(adminContract.addUser)
async createUser(
@Headers('origin') origin: string,
): Promise<ControllerResponse> {
return tsRestHandler(adminContract.addUser, async ({ body }) => {
await this.auth.addUser(origin, body);
return {
status: 201,
body: null,
Expand Down
44 changes: 32 additions & 12 deletions api/src/modules/auth/authentication.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { Injectable, Logger, UnauthorizedException } from '@nestjs/common';
import { UsersService } from '@api/modules/users/users.service';
import { User } from '@shared/entities/users/user.entity';
import * as bcrypt from 'bcrypt';
Expand All @@ -15,6 +15,7 @@ import { UpdateUserPasswordDto } from '@shared/dtos/users/update-user-password.d

@Injectable()
export class AuthenticationService {
logger: Logger = new Logger(AuthenticationService.name);
constructor(
private readonly usersService: UsersService,
private readonly jwtManager: JwtManager,
Expand All @@ -29,21 +30,37 @@ export class AuthenticationService {
throw new UnauthorizedException(`Invalid credentials`);
}

async createUser(createUser: CreateUserDto): Promise<void> {
async addUser(origin: string, dto: CreateUserDto) {
const { newUser, plainTextPassword } = await this.createUser(dto);
try {
await this.commandBus.execute(
new SendWelcomeEmailCommand(newUser, plainTextPassword, origin),
);
} catch (e) {
await this.usersService.delete(newUser);
this.logger.error(e);
throw e;
}
}

async createUser(
createUser: CreateUserDto,
): Promise<{ newUser: User; plainTextPassword: string }> {
// TODO: This is sync, check how to improve it
const { email, name, partnerName } = createUser;
const plainTextPassword = randomBytes(8).toString('hex');
const passwordHash = await bcrypt.hash(plainTextPassword, 10);
const newUser = await this.usersService.createUser({
const newUser = await this.usersService.saveUser({
name,
email,
password: passwordHash,
partnerName,
isActive: false,
});
await this.commandBus
.execute(new SendWelcomeEmailCommand(newUser, plainTextPassword))
.catch(() => this.usersService.delete(newUser));
return {
newUser,
plainTextPassword,
};
}

async logIn(user: User): Promise<UserWithAccessToken> {
Expand All @@ -53,11 +70,12 @@ export class AuthenticationService {

async signUp(user: User, signUpDto: SignUpDto): Promise<void> {
const { oneTimePassword, newPassword } = signUpDto;
if (!(await bcrypt.compare(oneTimePassword, user.password))) {
if (await this.isPasswordValid(user, oneTimePassword)) {
throw new UnauthorizedException();
}
user.isActive = true;
await this.usersService.saveNewHashedPassword(user, newPassword);
user.password = await this.hashPassword(newPassword);
await this.usersService.saveUser(user);
this.eventBus.publish(new UserSignedUpEvent(user.id, user.email));
}

Expand All @@ -71,20 +89,22 @@ export class AuthenticationService {
async updatePassword(user: User, dto: UpdateUserPasswordDto): Promise<User> {
const { password, newPassword } = dto;
if (await this.isPasswordValid(user, password)) {
return this.usersService.saveNewHashedPassword(user, newPassword);
user.password = await this.hashPassword(newPassword);
return this.usersService.saveUser(user);
}
throw new UnauthorizedException();
}

async resetPassword(user: User, newPassword: string): Promise<void> {
await this.usersService.saveNewHashedPassword(user, newPassword);
user.password = await this.hashPassword(newPassword);
await this.usersService.saveUser(user);
}

async isPasswordValid(user: User, password: string): Promise<boolean> {
return bcrypt.compare(password, user.password);
}

async token(userid: User['id']) {
return this.jwtManager.signSignUpToken(userid);
async hashPassword(password: string) {
return bcrypt.hash(password, 10);
}
}
2 changes: 1 addition & 1 deletion shared/contracts/admin.contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { CreateUserSchema } from "@shared/schemas/users/create-user.schema";

const contract = initContract();
export const adminContract = contract.router({
createUser: {
addUser: {
method: "POST",
path: "/admin/users",
responses: {
Expand Down

0 comments on commit 2fca502

Please sign in to comment.