-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This reverts commit 30ab3f4.
- Loading branch information
Showing
56 changed files
with
1,483 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/* istanbul ignore file */ | ||
import { BootstrapConsole } from 'nestjs-console'; | ||
import { DeletionConsoleModule } from '@modules/deletion'; | ||
|
||
async function run() { | ||
const bootstrap = new BootstrapConsole({ | ||
module: DeletionConsoleModule, | ||
useDecorators: true, | ||
}); | ||
|
||
const app = await bootstrap.init(); | ||
|
||
try { | ||
await app.init(); | ||
|
||
// Execute console application with provided arguments. | ||
await bootstrap.boot(); | ||
} catch (err) { | ||
// eslint-disable-next-line no-console, @typescript-eslint/no-unsafe-call | ||
console.error(err); | ||
|
||
// Set the exit code to 1 to indicate a console app failure. | ||
process.exitCode = 1; | ||
} | ||
|
||
// Always close the app, even if some exception | ||
// has been thrown from the console app. | ||
await app.close(); | ||
} | ||
|
||
void run(); |
33 changes: 33 additions & 0 deletions
33
apps/server/src/modules/deletion/client/builder/deletion-request-input.builder.spec.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 |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { ObjectId } from 'bson'; | ||
import { DeletionRequestInput } from '../interface'; | ||
import { DeletionRequestInputBuilder } from './deletion-request-input.builder'; | ||
|
||
describe(DeletionRequestInputBuilder.name, () => { | ||
describe(DeletionRequestInputBuilder.build.name, () => { | ||
describe('when called with proper arguments', () => { | ||
const setup = () => { | ||
const targetRefDomain = 'school'; | ||
const targetRefId = new ObjectId().toHexString(); | ||
const deleteInMinutes = 43200; | ||
|
||
const expectedOutput: DeletionRequestInput = { | ||
targetRef: { | ||
domain: targetRefDomain, | ||
id: targetRefId, | ||
}, | ||
deleteInMinutes, | ||
}; | ||
|
||
return { targetRefDomain, targetRefId, deleteInMinutes, expectedOutput }; | ||
}; | ||
|
||
it('should return valid object with expected values', () => { | ||
const { targetRefDomain, targetRefId, deleteInMinutes, expectedOutput } = setup(); | ||
|
||
const output = DeletionRequestInputBuilder.build(targetRefDomain, targetRefId, deleteInMinutes); | ||
|
||
expect(output).toStrictEqual(expectedOutput); | ||
}); | ||
}); | ||
}); | ||
}); |
11 changes: 11 additions & 0 deletions
11
apps/server/src/modules/deletion/client/builder/deletion-request-input.builder.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 |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { DeletionRequestInput } from '../interface'; | ||
import { DeletionRequestTargetRefInputBuilder } from './deletion-request-target-ref-input.builder'; | ||
|
||
export class DeletionRequestInputBuilder { | ||
static build(targetRefDomain: string, targetRefId: string, deleteInMinutes?: number): DeletionRequestInput { | ||
return { | ||
targetRef: DeletionRequestTargetRefInputBuilder.build(targetRefDomain, targetRefId), | ||
deleteInMinutes, | ||
}; | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
apps/server/src/modules/deletion/client/builder/deletion-request-output.builder.spec.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 |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { ObjectId } from 'bson'; | ||
import { DeletionRequestOutput } from '../interface'; | ||
import { DeletionRequestOutputBuilder } from './deletion-request-output.builder'; | ||
|
||
describe(DeletionRequestOutputBuilder.name, () => { | ||
describe(DeletionRequestOutputBuilder.build.name, () => { | ||
describe('when called with proper arguments', () => { | ||
const setup = () => { | ||
const requestId = new ObjectId().toHexString(); | ||
const deletionPlannedAt = new Date(); | ||
|
||
const expectedOutput: DeletionRequestOutput = { | ||
requestId, | ||
deletionPlannedAt, | ||
}; | ||
|
||
return { requestId, deletionPlannedAt, expectedOutput }; | ||
}; | ||
|
||
it('should return valid object with expected values', () => { | ||
const { requestId, deletionPlannedAt, expectedOutput } = setup(); | ||
|
||
const output = DeletionRequestOutputBuilder.build(requestId, deletionPlannedAt); | ||
|
||
expect(output).toStrictEqual(expectedOutput); | ||
}); | ||
}); | ||
}); | ||
}); |
10 changes: 10 additions & 0 deletions
10
apps/server/src/modules/deletion/client/builder/deletion-request-output.builder.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 |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { DeletionRequestOutput } from '../interface'; | ||
|
||
export class DeletionRequestOutputBuilder { | ||
static build(requestId: string, deletionPlannedAt: Date): DeletionRequestOutput { | ||
return { | ||
requestId, | ||
deletionPlannedAt, | ||
}; | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
...ver/src/modules/deletion/client/builder/deletion-request-target-ref-input.builder.spec.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 |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { ObjectId } from 'bson'; | ||
import { DeletionRequestTargetRefInput } from '../interface'; | ||
import { DeletionRequestTargetRefInputBuilder } from './deletion-request-target-ref-input.builder'; | ||
|
||
describe(DeletionRequestTargetRefInputBuilder.name, () => { | ||
describe(DeletionRequestTargetRefInputBuilder.build.name, () => { | ||
describe('when called with proper arguments', () => { | ||
const setup = () => { | ||
const domain = 'user'; | ||
const id = new ObjectId().toHexString(); | ||
|
||
const expectedOutput: DeletionRequestTargetRefInput = { domain, id }; | ||
|
||
return { domain, id, expectedOutput }; | ||
}; | ||
|
||
it('should return valid object with expected values', () => { | ||
const { domain, id, expectedOutput } = setup(); | ||
|
||
const output = DeletionRequestTargetRefInputBuilder.build(domain, id); | ||
|
||
expect(output).toStrictEqual(expectedOutput); | ||
}); | ||
}); | ||
}); | ||
}); |
7 changes: 7 additions & 0 deletions
7
apps/server/src/modules/deletion/client/builder/deletion-request-target-ref-input.builder.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 |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { DeletionRequestTargetRefInput } from '../interface'; | ||
|
||
export class DeletionRequestTargetRefInputBuilder { | ||
static build(domain: string, id: string): DeletionRequestTargetRefInput { | ||
return { domain, id }; | ||
} | ||
} |
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,3 @@ | ||
export * from './deletion-request-target-ref-input.builder'; | ||
export * from './deletion-request-input.builder'; | ||
export * from './deletion-request-output.builder'; |
41 changes: 41 additions & 0 deletions
41
apps/server/src/modules/deletion/client/deletion-client.config.spec.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 |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { IConfig } from '@hpi-schul-cloud/commons/lib/interfaces/IConfig'; | ||
import { Configuration } from '@hpi-schul-cloud/commons/lib'; | ||
import { DeletionClientConfig } from './interface'; | ||
import { getDeletionClientConfig } from './deletion-client.config'; | ||
|
||
describe(getDeletionClientConfig.name, () => { | ||
let configBefore: IConfig; | ||
|
||
beforeAll(() => { | ||
configBefore = Configuration.toObject({ plainSecrets: true }); | ||
}); | ||
|
||
afterEach(() => { | ||
Configuration.reset(configBefore); | ||
}); | ||
|
||
describe('when called', () => { | ||
const setup = () => { | ||
const baseUrl = 'http://api-admin:4030'; | ||
const apiKey = '652559c2-93da-42ad-94e1-640e3afbaca0'; | ||
|
||
Configuration.set('ADMIN_API_CLIENT__BASE_URL', baseUrl); | ||
Configuration.set('ADMIN_API_CLIENT__API_KEY', apiKey); | ||
|
||
const expectedConfig: DeletionClientConfig = { | ||
ADMIN_API_CLIENT_BASE_URL: baseUrl, | ||
ADMIN_API_CLIENT_API_KEY: apiKey, | ||
}; | ||
|
||
return { expectedConfig }; | ||
}; | ||
|
||
it('should return config with proper values', () => { | ||
const { expectedConfig } = setup(); | ||
|
||
const config = getDeletionClientConfig(); | ||
|
||
expect(config).toEqual(expectedConfig); | ||
}); | ||
}); | ||
}); |
9 changes: 9 additions & 0 deletions
9
apps/server/src/modules/deletion/client/deletion-client.config.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 |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { Configuration } from '@hpi-schul-cloud/commons/lib'; | ||
import { DeletionClientConfig } from './interface'; | ||
|
||
export const getDeletionClientConfig = (): DeletionClientConfig => { | ||
return { | ||
ADMIN_API_CLIENT_BASE_URL: Configuration.get('ADMIN_API_CLIENT__BASE_URL') as string, | ||
ADMIN_API_CLIENT_API_KEY: Configuration.get('ADMIN_API_CLIENT__API_KEY') as string, | ||
}; | ||
}; |
154 changes: 154 additions & 0 deletions
154
apps/server/src/modules/deletion/client/deletion.client.spec.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 |
---|---|---|
@@ -0,0 +1,154 @@ | ||
import { of } from 'rxjs'; | ||
import { AxiosResponse } from 'axios'; | ||
import { HttpService } from '@nestjs/axios'; | ||
import { ConfigService } from '@nestjs/config'; | ||
import { Test, TestingModule } from '@nestjs/testing'; | ||
import { createMock, DeepMocked } from '@golevelup/ts-jest'; | ||
import { axiosResponseFactory } from '@shared/testing'; | ||
import { DeletionRequestInputBuilder, DeletionRequestOutputBuilder } from '.'; | ||
import { DeletionRequestOutput } from './interface'; | ||
import { DeletionClient } from './deletion.client'; | ||
|
||
describe(DeletionClient.name, () => { | ||
let module: TestingModule; | ||
let client: DeletionClient; | ||
let httpService: DeepMocked<HttpService>; | ||
|
||
beforeEach(async () => { | ||
module = await Test.createTestingModule({ | ||
providers: [ | ||
DeletionClient, | ||
{ | ||
provide: ConfigService, | ||
useValue: createMock<ConfigService>({ | ||
get: jest.fn((key: string) => { | ||
if (key === 'ADMIN_API_CLIENT_BASE_URL') { | ||
return 'http://localhost:4030'; | ||
} | ||
|
||
// Default is for the Admin APIs API Key. | ||
return '6b3df003-61e9-467c-9e6b-579634801896'; | ||
}), | ||
}), | ||
}, | ||
{ | ||
provide: HttpService, | ||
useValue: createMock<HttpService>(), | ||
}, | ||
], | ||
}).compile(); | ||
|
||
client = module.get(DeletionClient); | ||
httpService = module.get(HttpService); | ||
}); | ||
|
||
afterEach(() => { | ||
jest.resetAllMocks(); | ||
}); | ||
|
||
afterAll(async () => { | ||
await module.close(); | ||
}); | ||
|
||
describe('queueDeletionRequest', () => { | ||
describe('when received valid response with expected HTTP status code', () => { | ||
const setup = () => { | ||
const input = DeletionRequestInputBuilder.build('user', '652f1625e9bc1a13bdaae48b'); | ||
|
||
const output: DeletionRequestOutput = DeletionRequestOutputBuilder.build( | ||
'6536ce29b595d7c8e5faf200', | ||
new Date('2024-10-15T12:42:50.521Z') | ||
); | ||
|
||
const response: AxiosResponse<DeletionRequestOutput> = axiosResponseFactory.build({ | ||
data: output, | ||
status: 202, | ||
}); | ||
|
||
httpService.post.mockReturnValueOnce(of(response)); | ||
|
||
return { input, output }; | ||
}; | ||
|
||
it('should return proper output', async () => { | ||
const { input, output } = setup(); | ||
|
||
const result = await client.queueDeletionRequest(input); | ||
|
||
expect(result).toEqual(output); | ||
}); | ||
}); | ||
|
||
describe('when received invalid HTTP status code in a response', () => { | ||
const setup = () => { | ||
const input = DeletionRequestInputBuilder.build('user', '652f1625e9bc1a13bdaae48b'); | ||
|
||
const output: DeletionRequestOutput = DeletionRequestOutputBuilder.build('', new Date()); | ||
|
||
const response: AxiosResponse<DeletionRequestOutput> = axiosResponseFactory.build({ | ||
data: output, | ||
status: 200, | ||
}); | ||
|
||
httpService.post.mockReturnValueOnce(of(response)); | ||
|
||
return { input }; | ||
}; | ||
|
||
it('should throw an exception', async () => { | ||
const { input } = setup(); | ||
|
||
await expect(client.queueDeletionRequest(input)).rejects.toThrow(Error); | ||
}); | ||
}); | ||
|
||
describe('when received no requestId in a response', () => { | ||
const setup = () => { | ||
const input = DeletionRequestInputBuilder.build('user', '652f1625e9bc1a13bdaae48b'); | ||
|
||
const output: DeletionRequestOutput = DeletionRequestOutputBuilder.build( | ||
'', | ||
new Date('2024-10-15T12:42:50.521Z') | ||
); | ||
|
||
const response: AxiosResponse<DeletionRequestOutput> = axiosResponseFactory.build({ | ||
data: output, | ||
status: 202, | ||
}); | ||
|
||
httpService.post.mockReturnValueOnce(of(response)); | ||
|
||
return { input }; | ||
}; | ||
|
||
it('should throw an exception', async () => { | ||
const { input } = setup(); | ||
|
||
await expect(client.queueDeletionRequest(input)).rejects.toThrow(Error); | ||
}); | ||
}); | ||
|
||
describe('when received no deletionPlannedAt in a response', () => { | ||
const setup = () => { | ||
const input = DeletionRequestInputBuilder.build('user', '652f1625e9bc1a13bdaae48b'); | ||
|
||
const response: AxiosResponse<DeletionRequestOutput> = axiosResponseFactory.build({ | ||
data: { | ||
requestId: '6536ce29b595d7c8e5faf200', | ||
}, | ||
status: 202, | ||
}); | ||
|
||
httpService.post.mockReturnValueOnce(of(response)); | ||
|
||
return { input }; | ||
}; | ||
|
||
it('should throw an exception', async () => { | ||
const { input } = setup(); | ||
|
||
await expect(client.queueDeletionRequest(input)).rejects.toThrow(Error); | ||
}); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.