Skip to content

Commit

Permalink
Add identity deletion debug APIs (#310)
Browse files Browse the repository at this point in the history
* chore: add debug api for identity deletion

* chore: test only non debug api's

* feat: add get and cancle to debug api and add test

* chore: make code pretty and usable

* fix: change to delete

* chore: one-liner

---------

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Co-authored-by: Julian König <[email protected]>
  • Loading branch information
3 people authored Nov 13, 2024
1 parent de54d46 commit 79d6366
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 2 deletions.
4 changes: 4 additions & 0 deletions src/modules/coreHttpApi/CoreHttpApiModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ export default class CoreHttpApiModule extends ConnectorRuntimeModule<CoreHttpAp
}

this.runtime.infrastructure.httpServer.addControllers(["controllers/*.js", "controllers/*.ts", "!controllers/*.d.ts"], this.baseDirectory);

if (this.connectorMode === "debug") {
this.runtime.infrastructure.httpServer.addControllers(["debug-controllers/*.js", "debug-controllers/*.ts", "!debug-controllers/*.d.ts"], this.baseDirectory);
}
}

private addDocumentation() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { TransportServices } from "@nmshd/runtime";
import { Inject } from "@nmshd/typescript-ioc";
import { Accept, DELETE, GET, Path, POST } from "@nmshd/typescript-rest";
import { Envelope } from "../../../infrastructure";
import { BaseController } from "../common/BaseController";

@Path("/api/v2/IdentityDeletionProcess")
export class IdentityDeletionProcessController extends BaseController {
public constructor(@Inject private readonly transportServices: TransportServices) {
super();
}

@POST
@Accept("application/json")
public async initiateIdentityDeletionProcess(): Promise<Envelope> {
const result = await this.transportServices.identityDeletionProcesses.initiateIdentityDeletionProcess();
return this.ok(result);
}

@GET
@Accept("application/json")
public async getActiveIdentityDeletionProcess(): Promise<Envelope> {
const result = await this.transportServices.identityDeletionProcesses.getActiveIdentityDeletionProcess();
return this.ok(result);
}

@DELETE
@Accept("application/json")
public async cancelIdentityDeletionProcess(): Promise<Envelope> {
const result = await this.transportServices.identityDeletionProcesses.cancelIdentityDeletionProcess();
return this.ok(result);
}
}
80 changes: 80 additions & 0 deletions test/debug/identityDeletionProcess.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { ConnectorClient } from "@nmshd/connector-sdk";
import { AxiosInstance } from "axios";
import { DateTime } from "luxon";
import { Launcher } from "../lib/Launcher";
import { getTimeout } from "../lib/setTimeout";

const launcher = new Launcher();
let client: ConnectorClient;
let axiosInstance: AxiosInstance;

beforeAll(async () => {
[client] = await launcher.launch(1);

axiosInstance = (client.account as any).httpClient;
}, getTimeout(30000));
afterAll(() => launcher.stop());

interface IdentityDeletionProcess {
id: string;
status: "WaitingForApproval" | "Rejected" | "Approved" | "Cancelled";
createdAt?: string;
createdByDevice?: string;
approvalPeriodEndsAt?: string;
rejectedAt?: string;
rejectedByDevice?: string;
approvedAt?: string;
approvedByDevice?: string;
gracePeriodEndsAt?: string;
cancelledAt?: string;
cancelledByDevice?: string;
}

describe("Identity Deletion Process", () => {
afterEach(async () => await axiosInstance.delete("/api/v2/IdentityDeletionProcess"));

test("should return 400 when no identity deletion process is active", async () => {
const getResult = await axiosInstance.get("/api/v2/IdentityDeletionProcess");
expect(getResult.status).toBe(400);
});

test("should start an identity deletion and get its status", async () => {
const response = await axiosInstance.post<{ result: IdentityDeletionProcess }>("/api/v2/IdentityDeletionProcess");

expect(response.status).toBe(200);
const identityDeletionProcess = response.data.result;
expect(identityDeletionProcess.status).toBe("Approved");
expect(DateTime.fromISO(identityDeletionProcess.gracePeriodEndsAt!).toMillis()).toBeGreaterThan(DateTime.now().toMillis());
});

test("should get the active identity deletion process", async () => {
const initiateResult = await axiosInstance.post<{ result: IdentityDeletionProcess }>("/api/v2/IdentityDeletionProcess");
expect(initiateResult.status).toBe(200);
const identityDeletionProcess = initiateResult.data.result;

const getResult = await axiosInstance.get<{ result: IdentityDeletionProcess }>("/api/v2/IdentityDeletionProcess");
expect(getResult.status).toBe(200);
expect(getResult.data.result.status).toBe(identityDeletionProcess.status);
expect(getResult.data.result.gracePeriodEndsAt).toBe(identityDeletionProcess.gracePeriodEndsAt);
});

test("should return 400 when trying to start a new identity deletion process", async () => {
const initiateResult = await axiosInstance.post<{ result: IdentityDeletionProcess }>("/api/v2/IdentityDeletionProcess");
expect(initiateResult.status).toBe(200);

const initiateResult2 = await axiosInstance.post("/api/v2/IdentityDeletionProcess");
expect(initiateResult2.status).toBe(400);
});

test("should cancel an identity deletion", async () => {
const initiateResult = await axiosInstance.post<{ result: IdentityDeletionProcess }>("/api/v2/IdentityDeletionProcess");
expect(initiateResult.status).toBe(200);

const cancelResult = await axiosInstance.delete("/api/v2/IdentityDeletionProcess");
expect(cancelResult.status).toBe(200);
expect(cancelResult.data.result.status).toBe("Cancelled");

const getResult = await axiosInstance.get("/api/v2/IdentityDeletionProcess");
expect(getResult.status).toBe(400);
});
});
2 changes: 1 addition & 1 deletion test/lib/Launcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,6 @@ export class Launcher {

public stopClient(connector: ChildProcess, webhookServer: Server | undefined): void {
connector.kill();
webhookServer?.close();
connector.on("exit", () => webhookServer?.close());
}
}
2 changes: 1 addition & 1 deletion test/spec.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ describe("test openapi spec against routes", () => {
beforeAll(async () => {
manualOpenApiSpec = yamljs.load("src/modules/coreHttpApi/openapi.yml");

const files = "src/modules/**/*.ts";
const files = "src/modules/coreHttpApi/controllers/**/*.ts";
const metadata = new MetadataGenerator([files], "tsconfig.json").generate();
const defaultOptions = {
basePath: "/",
Expand Down

0 comments on commit 79d6366

Please sign in to comment.