Skip to content

Commit

Permalink
refact(security/auth-module): removing tokens, password, and password…
Browse files Browse the repository at this point in the history
…-reset related code
  • Loading branch information
Krr0ptioN committed Sep 14, 2024
1 parent d8af47e commit 64e58c6
Show file tree
Hide file tree
Showing 98 changed files with 272 additions and 1,630 deletions.
7 changes: 5 additions & 2 deletions libs/core/security/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# security
# @goran/security

This library was generated with [Nx](https://nx.dev).
- Session Management
- SecurityMetrics
- Password Reset
- Authentication

## Running unit tests

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,2 @@
export * from './request-password-reset';
export * from './verify-password-reset-attempt';
export * from './reset-password';
export * from './signup';
export * from './signin';

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
import { Logger } from '@nestjs/common';
import { SigninCommand } from './signin.command';
import { CommandHandler, ICommandHandler } from '@nestjs/cqrs';
import { PasswordService } from '../../services';
import { UsersService } from '@goran/users';
import { PasswordService, SessionsService } from '@goran/security';
import { UserMapper, UsersService } from '@goran/users';
import { Result, Err, Ok } from 'oxide.ts';
import { InvalidAuthenticationCredentials } from '../../../domain';
import { AuthenticationCredentialDto } from '../../dtos';
import { ExceptionBase } from '@goran/common';
import { AuthenticationTokenFactory } from '../../factories';
import { ExceptionBase, Guard } from '@goran/common';
import { IpLocatorService } from '@goran/ip-locator';
import { DeviceDetectorService } from '@goran/device-detector';

@CommandHandler(SigninCommand)
export class SigninCommandHandler implements ICommandHandler<SigninCommand> {
private readonly logger = new Logger(SigninCommand.name);

constructor(
private tokenFactory: AuthenticationTokenFactory,
private passwordService: PasswordService,
private readonly passwordService: PasswordService,
private readonly ipLocator: IpLocatorService,
private readonly sessionsService: SessionsService,
private readonly deviceDetector: DeviceDetectorService,
private readonly userMapper: UserMapper,
private usersService: UsersService
) {}

Expand All @@ -31,21 +35,32 @@ export class SigninCommandHandler implements ICommandHandler<SigninCommand> {
if (userResult.isErr()) {
return Err(new InvalidAuthenticationCredentials());
}
const user = userResult.unwrap();
const passwordIsValid = await this.passwordService.validatePassword(
const userDto = userResult.unwrap();
const passwordIsValid = await this.passwordService.comparePassword(
password,
user.password
userDto.password
);

const user = await this.userMapper.toDomain(userDto);
if (!passwordIsValid) {
return Err(new InvalidAuthenticationCredentials());
}

const tokens = this.tokenFactory.generateTokens({
userId: user.id,
});
const sessionCreationResult = await this.sessionsService.createSession(
user,
command.clientInfo.ip ?? '',
await this.ipLocator.getLocation(command.clientInfo.ip ?? ''),
!Guard.isEmpty(command.clientInfo.userAgent)
? this.deviceDetector.getDevice(
command.clientInfo.userAgent ?? ''
)
: undefined
);

this.logger.verbose(`User with ${user.email} email is authenticated`);
const [tokens, session] = sessionCreationResult.unwrap();

this.logger.verbose(
`User with ${userDto.email} email is authenticated`
);

return Ok(new AuthenticationCredentialDto({ userId: user.id, tokens }));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Command, CommandProps } from '@goran/common';
import { Command, CommandProps, Optional } from '@goran/common';
import { ClientInfoDto } from '../../dtos';

/**
* Signup - User Registration
Expand All @@ -9,14 +10,15 @@ import { Command, CommandProps } from '@goran/common';
* @param email
*/
export class SigninCommand extends Command {
readonly email?: string;
readonly username?: string;
readonly password: string;
readonly email: Optional<string>;
readonly username: Optional<string>;
readonly password: string;
readonly clientInfo: ClientInfoDto;

constructor(props: CommandProps<SigninCommand>) {
super(props);
this.username = props.username;
this.email = props.email;
this.password = props.password;
}
constructor(props: CommandProps<SigninCommand>) {
super(props);
this.username = props.username;
this.email = props.email;
this.password = props.password;
}
}
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
import { Logger } from '@nestjs/common';
import { SignupCommand } from './signup.command';
import { CommandHandler, ICommandHandler } from '@nestjs/cqrs';
import { PasswordService } from '../../services';
import { UsersService } from '@goran/users';
import { Ok, Result } from 'oxide.ts';
import { ExceptionBase } from '@goran/common';
import { ExceptionBase, Guard } from '@goran/common';
import { AuthenticationCredentialDto } from '../../dtos';
import { AuthenticationTokenFactory } from '../../factories';
import { PasswordService, SessionsService } from '@goran/security';
import { IpLocatorService } from '@goran/ip-locator';
import { DeviceDetectorService } from '@goran/device-detector';

@CommandHandler(SignupCommand)
export class SignupCommandHandler implements ICommandHandler<SignupCommand> {
constructor(
private tokenFactory: AuthenticationTokenFactory,
private passwordService: PasswordService,
private usersService: UsersService
) { }
private readonly sessionsService: SessionsService,
private readonly passwordService: PasswordService,
private readonly usersService: UsersService,
private readonly ipLocator: IpLocatorService,
private readonly deviceDetector: DeviceDetectorService
) {}
private readonly logger = new Logger(SignupCommand.name);

async execute(
command: SignupCommand
): Promise<Result<AuthenticationCredentialDto, ExceptionBase>> {
const hashedPassword = this.passwordService.hashPassword(
const hashedPassword = await this.passwordService.hashPassword(
command.password
);
const userResult = await this.usersService.create({
Expand All @@ -33,12 +36,20 @@ export class SignupCommandHandler implements ICommandHandler<SignupCommand> {
}

const user = userResult.unwrap();
const tokens = this.tokenFactory.generateTokens({
userId: user.getProps().id,
});

this.logger.verbose(`User with ${user.email} email signed up`);

const sessionCreationResult = await this.sessionsService.createSession(
user,
command.clientInfo.ip ?? '',
await this.ipLocator.getLocation(command.clientInfo.ip ?? ''),
!Guard.isEmpty(command.clientInfo.userAgent)
? this.deviceDetector.getDevice(command.clientInfo.userAgent ?? '')
: undefined
);

const [tokens, session] = sessionCreationResult.unwrap();

return Ok(new AuthenticationCredentialDto({ userId: user.id, tokens }));
}
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
import { Command, CommandProps } from '@goran/common';
import { Command, CommandProps, Optional } from '@goran/common';
import { ClientInfoDto } from '../../dtos';

/**
* Signup - User Registration
*
* @param fullname
* @param username
* @param password
* @param email
* @param {Optional<string>} fullname
* @param {string} username
* @param {string} password
* @param {string} email
* @param {ClientInfoDto} clientInfo @readonly
*/
export class SignupCommand extends Command {
readonly email: string;
readonly fullname?: string | null;
readonly username: string;
readonly password: string;
readonly email: string;
readonly fullname: Optional<string>;
readonly username: string;
readonly password: string;
readonly clientInfo: ClientInfoDto;

constructor(props: CommandProps<SignupCommand>) {
super(props);
this.fullname = props.fullname;
this.username = props.username;
this.email = props.email;
this.password = props.password;
}
constructor(props: CommandProps<SignupCommand>) {
super(props);
this.fullname = props.fullname;
this.username = props.username;
this.email = props.email;
this.password = props.password;
this.clientInfo = props.clientInfo;
}
}

This file was deleted.

Loading

0 comments on commit 64e58c6

Please sign in to comment.