Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BC-5521 - Implement of KNL Control Module #4486

Merged
merged 19 commits into from
Nov 7, 2023
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions apps/server/src/modules/deletion/deletion.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Module } from '@nestjs/common';
import { Logger } from '@src/core/logger';
import { DeletionRequestService } from './services/deletion-request.service';
import { DeletionRequestRepo } from './repo/deletion-request.repo';

@Module({
providers: [Logger, DeletionRequestService, DeletionRequestRepo],
WojciechGrancow marked this conversation as resolved.
Show resolved Hide resolved
exports: [DeletionRequestService],
})
export class DeletionModule {}
70 changes: 70 additions & 0 deletions apps/server/src/modules/deletion/domain/deletion-log.do.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { ObjectId } from '@mikro-orm/mongodb';
import { deletionLogFactory } from './testing/factory/deletion-log.factory';
import { DeletionLog } from './deletion-log.do';
import { DeletionOperationModel } from './types/deletion-operation-model.enum';
import { DeletionDomainModel } from './types/deletion-domain-model.enum';

describe(DeletionLog.name, () => {
describe('constructor', () => {
describe('When constructor is called', () => {
it('should create a deletionRequest by passing required properties', () => {
const domainObject: DeletionLog = deletionLogFactory.build();

expect(domainObject instanceof DeletionLog).toEqual(true);
});
});

describe('when passed a valid id', () => {
const setup = () => {
const domainObject: DeletionLog = deletionLogFactory.buildWithId();

return { domainObject };
};

it('should set the id', () => {
const { domainObject } = setup();

const deletionLogDomainObject: DeletionLog = new DeletionLog(domainObject);

expect(deletionLogDomainObject.id).toEqual(domainObject.id);
});
});
});

describe('getters', () => {
describe('When getters are used', () => {
const setup = () => {
const props = {
id: new ObjectId().toHexString(),
domain: DeletionDomainModel.USER,
operation: DeletionOperationModel.DELETE,
modifiedCount: 0,
deletedCount: 1,
deletionRequestId: new ObjectId().toHexString(),
createdAt: new Date(),
updatedAt: new Date(),
};

const deletionLogDo = new DeletionLog(props);
WojciechGrancow marked this conversation as resolved.
Show resolved Hide resolved

return { props, deletionLogDo };
};
it('getters should return proper values', () => {
const { props, deletionLogDo } = setup();

const gettersValues = {
id: deletionLogDo.id,
domain: deletionLogDo.domain,
operation: deletionLogDo.operation,
modifiedCount: deletionLogDo.modifiedCount,
deletedCount: deletionLogDo.deletedCount,
deletionRequestId: deletionLogDo.deletionRequestId,
createdAt: deletionLogDo.createdAt,
updatedAt: deletionLogDo.updatedAt,
};

expect(gettersValues).toEqual(props);
});
});
});
});
44 changes: 44 additions & 0 deletions apps/server/src/modules/deletion/domain/deletion-log.do.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { EntityId } from '@shared/domain/types';
import { AuthorizableObject, DomainObject } from '@shared/domain/domain-object';
import { DeletionDomainModel } from './types/deletion-domain-model.enum';
import { DeletionOperationModel } from './types/deletion-operation-model.enum';

export interface DeletionLogProps extends AuthorizableObject {
createdAt?: Date;
updatedAt?: Date;
domain: DeletionDomainModel;
operation?: DeletionOperationModel;
modifiedCount?: number;
deletedCount?: number;
deletionRequestId?: EntityId;
}

export class DeletionLog extends DomainObject<DeletionLogProps> {
get createdAt(): Date | undefined {
return this.props.createdAt;
}

get updatedAt(): Date | undefined {
return this.props.updatedAt;
}

get domain(): DeletionDomainModel {
return this.props.domain;
}

get operation(): DeletionOperationModel | undefined {
return this.props.operation;
}

get modifiedCount(): number | undefined {
return this.props.modifiedCount;
}

get deletedCount(): number | undefined {
return this.props.deletedCount;
}

get deletionRequestId(): EntityId | undefined {
return this.props.deletionRequestId;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { ObjectId } from '@mikro-orm/mongodb';
import { DeletionRequest } from './deletion-request.do';
import { DeletionDomainModel } from './types/deletion-domain-model.enum';
import { deletionRequestFactory } from './testing/factory/deletion-request.factory';
import { DeletionStatusModel } from './types/deletion-status-model.enum';

describe(DeletionRequest.name, () => {
describe('constructor', () => {
describe('When constructor is called', () => {
it('should create a deletionRequest by passing required properties', () => {
const domainObject: DeletionRequest = deletionRequestFactory.build();

expect(domainObject instanceof DeletionRequest).toEqual(true);
});
});

describe('when passed a valid id', () => {
const setup = () => {
const domainObject: DeletionRequest = deletionRequestFactory.buildWithId();

return { domainObject };
};

it('should set the id', () => {
const { domainObject } = setup();

const deletionRequestDomainObject: DeletionRequest = new DeletionRequest(domainObject);

expect(deletionRequestDomainObject.id).toEqual(domainObject.id);
});
});
});

describe('getters', () => {
describe('When getters are used', () => {
const setup = () => {
const props = {
id: new ObjectId().toHexString(),
targetRefDomain: DeletionDomainModel.USER,
deleteAfter: new Date(),
targetRefId: new ObjectId().toHexString(),
status: DeletionStatusModel.REGISTERED,
createdAt: new Date(),
updatedAt: new Date(),
};

const deletionRequestDo = new DeletionRequest(props);

return { props, deletionRequestDo };
};

it('getters should return proper values', () => {
const { props, deletionRequestDo } = setup();

const gettersValues = {
id: deletionRequestDo.id,
targetRefDomain: deletionRequestDo.targetRefDomain,
deleteAfter: deletionRequestDo.deleteAfter,
targetRefId: deletionRequestDo.targetRefId,
status: deletionRequestDo.status,
createdAt: deletionRequestDo.createdAt,
updatedAt: deletionRequestDo.updatedAt,
};

expect(gettersValues).toEqual(props);
});
});
});
});
39 changes: 39 additions & 0 deletions apps/server/src/modules/deletion/domain/deletion-request.do.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { EntityId } from '@shared/domain/types';
import { AuthorizableObject, DomainObject } from '@shared/domain/domain-object';
import { DeletionDomainModel } from './types/deletion-domain-model.enum';
import { DeletionStatusModel } from './types/deletion-status-model.enum';

export interface DeletionRequestProps extends AuthorizableObject {
createdAt?: Date;
updatedAt?: Date;
targetRefDomain: DeletionDomainModel;
deleteAfter: Date;
targetRefId: EntityId;
status: DeletionStatusModel;
}

export class DeletionRequest extends DomainObject<DeletionRequestProps> {
get createdAt(): Date | undefined {
return this.props.createdAt;
}

get updatedAt(): Date | undefined {
return this.props.updatedAt;
}

get targetRefDomain(): DeletionDomainModel {
return this.props.targetRefDomain;
}

get deleteAfter(): Date {
return this.props.deleteAfter;
}

get targetRefId(): EntityId {
return this.props.targetRefId;
}

get status(): DeletionStatusModel {
return this.props.status;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { DoBaseFactory } from '@shared/testing';
import { ObjectId } from '@mikro-orm/mongodb';
import { DeletionLog, DeletionLogProps } from '../../deletion-log.do';
import { DeletionOperationModel } from '../../types/deletion-operation-model.enum';
import { DeletionDomainModel } from '../../types/deletion-domain-model.enum';

export const deletionLogFactory = DoBaseFactory.define<DeletionLog, DeletionLogProps>(DeletionLog, () => {
return {
id: new ObjectId().toHexString(),
domain: DeletionDomainModel.USER,
operation: DeletionOperationModel.DELETE,
modifiedCount: 0,
deletedCount: 1,
deletionRequestId: new ObjectId().toHexString(),
createdAt: new Date(),
updatedAt: new Date(),
};
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { DoBaseFactory } from '@shared/testing';
import { ObjectId } from '@mikro-orm/mongodb';
import { DeepPartial } from 'fishery';
import { DeletionRequest, DeletionRequestProps } from '../../deletion-request.do';
import { DeletionDomainModel } from '../../types/deletion-domain-model.enum';
import { DeletionStatusModel } from '../../types/deletion-status-model.enum';

class DeletionRequestFactory extends DoBaseFactory<DeletionRequest, DeletionRequestProps> {
withUserIds(id: string): this {
const params: DeepPartial<DeletionRequestProps> = {
targetRefId: id,
};

return this.params(params);
}
}

export const deletionRequestFactory = DeletionRequestFactory.define(DeletionRequest, () => {
return {
id: new ObjectId().toHexString(),
targetRefDomain: DeletionDomainModel.USER,
deleteAfter: new Date(),
targetRefId: new ObjectId().toHexString(),
status: DeletionStatusModel.REGISTERED,
createdAt: new Date(),
updatedAt: new Date(),
};
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export const enum DeletionDomainModel {
ACCOUNT = 'account',
CLASS = 'class',
COURSEGROUP = 'courseGroup',
COURSE = 'course',
FILE = 'file',
LESSONS = 'lessons',
PSEUDONYMS = 'pseudonyms',
TEAMS = 'teams',
USER = 'user',
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const enum DeletionOperationModel {
DELETE = 'delete',
UPDATE = 'update',
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const enum DeletionStatusModel {
FAILED = 'failed',
REGISTERED = 'registered',
SUCCESS = 'success',
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { setupEntities } from '@shared/testing';
import { ObjectId } from '@mikro-orm/mongodb';
import { DeletionLogEntity } from './deletion-log.entity';
import { DeletionOperationModel } from '../domain/types/deletion-operation-model.enum';
import { DeletionDomainModel } from '../domain/types/deletion-domain-model.enum';

describe(DeletionLogEntity.name, () => {
beforeAll(async () => {
await setupEntities();
});

describe('constructor', () => {
describe('When constructor is called', () => {
const setup = () => {
const props = {
id: new ObjectId().toHexString(),
domain: DeletionDomainModel.USER,
operation: DeletionOperationModel.DELETE,
modifiedCount: 0,
deletedCount: 1,
deletionRequestId: new ObjectId(),
createdAt: new Date(),
updatedAt: new Date(),
};

return { props };
};
it('should throw an error by empty constructor', () => {
// @ts-expect-error: Test case
const test = () => new DeletionLogEntity();
expect(test).toThrow();
});

it('should create a deletionLog by passing required properties', () => {
const { props } = setup();
const entity: DeletionLogEntity = new DeletionLogEntity(props);

expect(entity instanceof DeletionLogEntity).toEqual(true);
});

it(`should return a valid object with fields values set from the provided complete props object`, () => {
const { props } = setup();
const entity: DeletionLogEntity = new DeletionLogEntity(props);

const entityProps = {
id: entity.id,
domain: entity.domain,
operation: entity.operation,
modifiedCount: entity.modifiedCount,
deletedCount: entity.deletedCount,
deletionRequestId: entity.deletionRequestId,
createdAt: entity.createdAt,
updatedAt: entity.updatedAt,
};

expect(entityProps).toEqual(props);
});
});
});
});
Loading
Loading