new authorization

This commit is contained in:
sbriat
2023-07-06 16:23:18 +02:00
parent bbcd2cdb9e
commit 470a93879e
97 changed files with 847 additions and 172 deletions

View File

@@ -0,0 +1,43 @@
import { AggregateRoot, AggregateID } from '@mobicoop/ddd-library';
import * as bcrypt from 'bcrypt';
import {
AuthenticationProps,
CreateAuthenticationProps,
} from './authentication.types';
import { AuthenticationCreatedDomainEvent } from './events/authentication-created.domain-event';
import { AuthenticationDeletedDomainEvent } from './events/authentication-deleted.domain-event';
export class AuthenticationEntity extends AggregateRoot<AuthenticationProps> {
protected readonly _id: AggregateID;
static create = async (
create: CreateAuthenticationProps,
): Promise<AuthenticationEntity> => {
const props: AuthenticationProps = { ...create };
const hash = await bcrypt.hash(props.password, 10);
const authentication = new AuthenticationEntity({
id: props.userId,
props: {
userId: props.userId,
password: hash,
usernames: props.usernames,
},
});
authentication.addEvent(
new AuthenticationCreatedDomainEvent({ aggregateId: props.userId }),
);
return authentication;
};
delete(): void {
this.addEvent(
new AuthenticationDeletedDomainEvent({
aggregateId: this.id,
}),
);
}
validate(): void {
// entity business rules validation to protect it's invariant before saving entity to a database
}
}

View File

@@ -0,0 +1,21 @@
import { ExceptionBase } from '@mobicoop/ddd-library';
export class AuthenticationAlreadyExistsException extends ExceptionBase {
static readonly message = 'Authentication already exists';
public readonly code = 'AUTHENTICATION.ALREADY_EXISTS';
constructor(cause?: Error, metadata?: unknown) {
super(AuthenticationAlreadyExistsException.message, cause, metadata);
}
}
export class UsernameAlreadyExistsException extends ExceptionBase {
static readonly message = 'Username already exists';
public readonly code = 'USERNAME.ALREADY_EXISTS';
constructor(cause?: Error, metadata?: unknown) {
super(UsernameAlreadyExistsException.message, cause, metadata);
}
}

View File

@@ -0,0 +1,15 @@
import { UsernameProps } from './username.types';
// All properties that an Authentication has
export interface AuthenticationProps {
userId: string;
password: string;
usernames: UsernameProps[];
}
// Properties that are needed for an Authentication creation
export interface CreateAuthenticationProps {
userId: string;
password: string;
usernames: UsernameProps[];
}

View File

@@ -0,0 +1,7 @@
import { DomainEvent, DomainEventProps } from '@mobicoop/ddd-library';
export class AuthenticationCreatedDomainEvent extends DomainEvent {
constructor(props: DomainEventProps<AuthenticationCreatedDomainEvent>) {
super(props);
}
}

View File

@@ -0,0 +1,7 @@
import { DomainEvent, DomainEventProps } from '@mobicoop/ddd-library';
export class AuthenticationDeletedDomainEvent extends DomainEvent {
constructor(props: DomainEventProps<AuthenticationDeletedDomainEvent>) {
super(props);
}
}

View File

@@ -0,0 +1,7 @@
import { DomainEvent, DomainEventProps } from '@mobicoop/ddd-library';
export class UsernameAddedDomainEvent extends DomainEvent {
constructor(props: DomainEventProps<UsernameAddedDomainEvent>) {
super(props);
}
}

View File

@@ -0,0 +1,27 @@
import { AggregateID, AggregateRoot } from '@mobicoop/ddd-library';
import { UsernameProps } from './username.types';
import { UsernameAddedDomainEvent } from './events/username-added.domain-event';
export class UsernameEntity extends AggregateRoot<UsernameProps> {
protected readonly _id: AggregateID;
static create = async (create: UsernameProps): Promise<UsernameEntity> => {
const props: UsernameProps = { ...create };
const username = new UsernameEntity({
id: props.name,
props: {
name: props.name,
userId: props.userId,
type: props.type,
},
});
username.addEvent(
new UsernameAddedDomainEvent({ aggregateId: props.name }),
);
return username;
};
validate(): void {
// entity business rules validation to protect it's invariant before saving entity to a database
}
}

View File

@@ -0,0 +1,11 @@
// All properties that a Username has
export interface UsernameProps {
name: string;
userId?: string;
type: Type;
}
export enum Type {
EMAIL = 'EMAIL',
PHONE = 'PHONE',
}