Skip to content

Commit b28516f

Browse files
authored
Merge branch 'main' into refactor-accountcontroller
2 parents 3c7baa0 + d2ecc42 commit b28516f

File tree

16 files changed

+1202
-91
lines changed

16 files changed

+1202
-91
lines changed

.dev/appsettings.override.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@
2020
}
2121
},
2222
"Modules": {
23+
"Announcements": {
24+
"Infrastructure": {
25+
"SqlDatabase": {
26+
"Provider": "Postgres",
27+
"ConnectionString": "User ID=announcements;Password=Passw0rd;Server=postgres;Port=5432;Database=enmeshed;"
28+
}
29+
}
30+
},
2331
"Challenges": {
2432
"Infrastructure": {
2533
"SqlDatabase": {

.dev/compose.backbone.env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
BACKBONE_VERSION=6.20.0
1+
BACKBONE_VERSION=6.22.0

.dev/compose.backbone.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,10 @@ services:
124124
Database__Provider: Postgres
125125
Database__ConnectionString: "Server=postgres;Database=enmeshed;User Id=devices;Password=Passw0rd;Port=5432"
126126

127+
networks:
128+
default:
129+
name: backbone
130+
127131
configs:
128132
Config:
129133
file: appsettings.override.json

package-lock.json

Lines changed: 985 additions & 49 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
"jest-expect-message": "^1.1.3",
3838
"madge": "^8.0.0",
3939
"npm-check-updates": "^17.1.11",
40-
"prettier": "^3.4.1",
40+
"prettier": "^3.4.2",
4141
"ts-jest": "^29.2.5",
4242
"ts-node": "^10.9.2",
4343
"tsconfig-paths": "^4.2.0",

packages/consumption/test/modules/requests/testHelpers/TestObjectFactory.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,8 +261,7 @@ export class TestObjectFactory {
261261
createdAt: CoreDate.from("2022-01-03T00:00:00.000Z"),
262262
createdBy: CoreAddress.from("did:e:a-domain:dids:anidentity"),
263263
createdByDevice: CoreId.from("DVC1"),
264-
// must be DecompositionDueToIdentityDeletion in the future
265-
reason: RelationshipAuditLogEntryReason.Decomposition,
264+
reason: RelationshipAuditLogEntryReason.DecompositionDueToIdentityDeletion,
266265
oldStatus: RelationshipStatus.Active,
267266
newStatus: RelationshipStatus.DeletionProposed
268267
}

packages/runtime/src/useCases/common/Schemas.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22772,6 +22772,33 @@ export const GetRelationshipTemplatesRequest: any = {
2277222772
}
2277322773
}
2277422774
]
22775+
},
22776+
"passwordProtection": {
22777+
"type": "string",
22778+
"enum": [
22779+
"",
22780+
"!"
22781+
]
22782+
},
22783+
"passwordProtection.password": {
22784+
"anyOf": [
22785+
{
22786+
"type": "string"
22787+
},
22788+
{
22789+
"type": "array",
22790+
"items": {
22791+
"type": "string"
22792+
}
22793+
}
22794+
]
22795+
},
22796+
"passwordProtection.passwordIsPin": {
22797+
"type": "string",
22798+
"enum": [
22799+
"true",
22800+
"!"
22801+
]
2277522802
}
2277622803
},
2277722804
"additionalProperties": false

packages/runtime/src/useCases/transport/relationshipTemplates/GetRelationshipTemplates.ts

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { QueryTranslator } from "@js-soft/docdb-querytranslator";
22
import { Result } from "@js-soft/ts-utils";
3-
import { CachedRelationshipTemplate, RelationshipTemplate, RelationshipTemplateController } from "@nmshd/transport";
3+
import { CachedRelationshipTemplate, PasswordProtection, RelationshipTemplate, RelationshipTemplateController } from "@nmshd/transport";
44
import { Inject } from "@nmshd/typescript-ioc";
55
import { nameof } from "ts-simple-nameof";
66
import { RelationshipTemplateDTO } from "../../../types";
@@ -15,6 +15,9 @@ export interface GetRelationshipTemplatesQuery {
1515
createdByDevice?: string | string[];
1616
maxNumberOfAllocations?: string | string[];
1717
forIdentity?: string | string[];
18+
passwordProtection?: "" | "!";
19+
"passwordProtection.password"?: string | string[];
20+
"passwordProtection.passwordIsPin"?: "true" | "!";
1821
}
1922

2023
export interface GetRelationshipTemplatesRequest {
@@ -37,7 +40,10 @@ export class GetRelationshipTemplatesUseCase extends UseCase<GetRelationshipTemp
3740
[nameof<RelationshipTemplateDTO>((r) => r.createdBy)]: true,
3841
[nameof<RelationshipTemplateDTO>((r) => r.createdByDevice)]: true,
3942
[nameof<RelationshipTemplateDTO>((r) => r.maxNumberOfAllocations)]: true,
40-
[nameof<RelationshipTemplateDTO>((r) => r.forIdentity)]: true
43+
[nameof<RelationshipTemplateDTO>((r) => r.forIdentity)]: true,
44+
[nameof<RelationshipTemplateDTO>((r) => r.passwordProtection)]: true,
45+
[`${nameof<RelationshipTemplateDTO>((r) => r.passwordProtection)}.password`]: true,
46+
[`${nameof<RelationshipTemplateDTO>((r) => r.passwordProtection)}.passwordIsPin`]: true
4147
},
4248
alias: {
4349
[nameof<RelationshipTemplateDTO>((r) => r.isOwn)]: nameof<RelationshipTemplate>((r) => r.isOwn),
@@ -50,7 +56,23 @@ export class GetRelationshipTemplatesUseCase extends UseCase<GetRelationshipTemp
5056
[nameof<RelationshipTemplateDTO>((r) => r.maxNumberOfAllocations)]: `${nameof<RelationshipTemplate>((r) => r.cache)}.${nameof<CachedRelationshipTemplate>(
5157
(t) => t.maxNumberOfAllocations
5258
)}`,
53-
[nameof<RelationshipTemplateDTO>((r) => r.forIdentity)]: `${nameof<RelationshipTemplate>((r) => r.cache)}.${nameof<CachedRelationshipTemplate>((t) => t.forIdentity)}`
59+
[nameof<RelationshipTemplateDTO>((r) => r.forIdentity)]: `${nameof<RelationshipTemplate>((r) => r.cache)}.${nameof<CachedRelationshipTemplate>((t) => t.forIdentity)}`,
60+
[nameof<RelationshipTemplateDTO>((r) => r.passwordProtection)]: nameof<RelationshipTemplate>((r) => r.passwordProtection)
61+
},
62+
custom: {
63+
[`${nameof<RelationshipTemplateDTO>((r) => r.passwordProtection)}.password`]: (query: any, input: string) => {
64+
query[`${nameof<RelationshipTemplate>((t) => t.passwordProtection)}.${nameof<PasswordProtection>((t) => t.password)}`] = input;
65+
},
66+
[`${nameof<RelationshipTemplateDTO>((t) => t.passwordProtection)}.passwordIsPin`]: (query: any, input: string) => {
67+
if (input === "true") {
68+
query[`${nameof<RelationshipTemplate>((t) => t.passwordProtection)}.${nameof<PasswordProtection>((t) => t.passwordType)}`] = {
69+
$regex: "^pin"
70+
};
71+
}
72+
if (input === "!") {
73+
query[`${nameof<RelationshipTemplate>((t) => t.passwordProtection)}.${nameof<PasswordProtection>((t) => t.passwordType)}`] = "pw";
74+
}
75+
}
5476
}
5577
});
5678

packages/runtime/test/transport/messages.test.ts

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import {
2929
reactivateTerminatedRelationship,
3030
RuntimeServiceProvider,
3131
sendMessage,
32-
sendMessageToMultipleRecipients,
3332
syncUntilHasEvent,
3433
syncUntilHasMessage,
3534
syncUntilHasMessages,
@@ -360,43 +359,41 @@ describe("Message errors", () => {
360359

361360
describe("Message errors for peers that are in deletion", () => {
362361
let relationshipIdToClient2: string;
363-
let relationshipIdToClient5: string;
364362

365363
beforeAll(async () => {
366364
relationshipIdToClient2 = (await client1.transport.relationships.getRelationshipByAddress({ address: client2.address })).value.id;
367-
relationshipIdToClient5 = (await ensureActiveRelationship(client1.transport, client5.transport)).id;
365+
await ensureActiveRelationship(client1.transport, client5.transport);
368366
});
369367

370368
afterEach(async () => {
371-
for (const client of [client2, client5]) {
372-
const activeIdentityDeletionProcess = await client.transport.identityDeletionProcesses.getActiveIdentityDeletionProcess();
373-
if (!activeIdentityDeletionProcess.isSuccess) {
374-
return;
375-
}
376-
let abortResult;
377-
if (activeIdentityDeletionProcess.value.status === IdentityDeletionProcessStatus.Approved) {
378-
abortResult = await client.transport.identityDeletionProcesses.cancelIdentityDeletionProcess();
379-
} else if (activeIdentityDeletionProcess.value.status === IdentityDeletionProcessStatus.WaitingForApproval) {
380-
abortResult = await client.transport.identityDeletionProcesses.rejectIdentityDeletionProcess();
381-
}
382-
await syncUntilHasEvent(client1, PeerDeletionCancelledEvent);
383-
if (abortResult?.isError) throw abortResult.error;
369+
const activeIdentityDeletionProcess = await client2.transport.identityDeletionProcesses.getActiveIdentityDeletionProcess();
370+
if (!activeIdentityDeletionProcess.isSuccess) {
371+
return;
384372
}
373+
let abortResult;
374+
if (activeIdentityDeletionProcess.value.status === IdentityDeletionProcessStatus.Approved) {
375+
abortResult = await client2.transport.identityDeletionProcesses.cancelIdentityDeletionProcess();
376+
} else if (activeIdentityDeletionProcess.value.status === IdentityDeletionProcessStatus.WaitingForApproval) {
377+
abortResult = await client2.transport.identityDeletionProcesses.rejectIdentityDeletionProcess();
378+
}
379+
await syncUntilHasEvent(client1, PeerDeletionCancelledEvent);
380+
if (abortResult?.isError) throw abortResult.error;
385381
});
386382

387383
test("should throw correct error for Messages whose content is not a Notification if there are recipients in deletion", async () => {
388384
await client2.transport.identityDeletionProcesses.initiateIdentityDeletionProcess();
389385
await syncUntilHasEvent(client1, PeerToBeDeletedEvent, (e) => e.data.id === relationshipIdToClient2);
390-
await client1.eventBus.waitForRunningEventHandlers();
391-
392-
await client5.transport.identityDeletionProcesses.initiateIdentityDeletionProcess();
393-
await syncUntilHasEvent(client1, PeerToBeDeletedEvent, (e) => e.data.id === relationshipIdToClient5);
394-
await client1.eventBus.waitForRunningEventHandlers();
395386

396-
const result = await sendMessageToMultipleRecipients(client1.transport, [client2.address, client5.address]);
387+
const result = await client1.transport.messages.sendMessage({
388+
recipients: [client2.address],
389+
content: {
390+
"@type": "ArbitraryMessageContent",
391+
value: "aString"
392+
}
393+
});
397394
expect(result).toBeAnError(/.*/, "error.runtime.messages.peerIsInDeletion");
398395
expect(result.error.message).toBe(
399-
`The Message cannot be sent as the recipient(s) with the following address(es) being in deletion: '${client2.address.toString()}', '${client5.address.toString()}'. However, please note that Messages whose content is a Notification can be sent to recipients in deletion.`
396+
`The Message cannot be sent as the recipient(s) with the following address(es) being in deletion: '${client2.address.toString()}'. However, please note that Messages whose content is a Notification can be sent to recipients in deletion.`
400397
);
401398
});
402399

packages/runtime/test/transport/relationshipTemplates.test.ts

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,11 @@ describe("RelationshipTemplates query", () => {
277277
maxNumberOfAllocations: 1,
278278
expiresAt: DateTime.utc().plus({ minutes: 10 }).toString(),
279279
content: emptyRelationshipTemplateContent,
280-
forIdentity: runtimeServices1.address
280+
forIdentity: runtimeServices1.address,
281+
passwordProtection: {
282+
password: "1234",
283+
passwordIsPin: true
284+
}
281285
})
282286
).value;
283287
const conditions = new QueryParamConditions<GetRelationshipTemplatesQuery>(template, runtimeServices1.transport)
@@ -287,7 +291,28 @@ describe("RelationshipTemplates query", () => {
287291
.addStringSet("createdBy")
288292
.addStringSet("createdByDevice")
289293
.addNumberSet("maxNumberOfAllocations")
290-
.addStringSet("forIdentity");
294+
.addStringSet("forIdentity")
295+
.addSingleCondition({
296+
expectedResult: true,
297+
key: "passwordProtection",
298+
value: ""
299+
})
300+
.addSingleCondition({
301+
expectedResult: false,
302+
key: "passwordProtection",
303+
value: "!"
304+
})
305+
.addStringSet("passwordProtection.password")
306+
.addSingleCondition({
307+
expectedResult: true,
308+
key: "passwordProtection.passwordIsPin",
309+
value: "true"
310+
})
311+
.addSingleCondition({
312+
expectedResult: false,
313+
key: "passwordProtection.passwordIsPin",
314+
value: "!"
315+
});
291316

292317
await conditions.executeTests((c, q) => c.relationshipTemplates.getRelationshipTemplates({ query: q }));
293318
});
@@ -297,15 +322,29 @@ describe("RelationshipTemplates query", () => {
297322
await runtimeServices1.transport.relationshipTemplates.createOwnRelationshipTemplate({
298323
maxNumberOfAllocations: 1,
299324
expiresAt: DateTime.utc().plus({ minutes: 10 }).toString(),
300-
content: emptyRelationshipTemplateContent
325+
content: emptyRelationshipTemplateContent,
326+
passwordProtection: {
327+
password: "password"
328+
}
301329
})
302330
).value;
303331
const conditions = new QueryParamConditions<GetRelationshipTemplatesQuery>(template, runtimeServices1.transport)
304332
.addDateSet("createdAt")
305333
.addDateSet("expiresAt")
306334
.addStringSet("createdBy")
307335
.addStringSet("createdByDevice")
308-
.addNumberSet("maxNumberOfAllocations");
336+
.addNumberSet("maxNumberOfAllocations")
337+
.addStringSet("passwordProtection.password")
338+
.addSingleCondition({
339+
expectedResult: false,
340+
key: "passwordProtection.passwordIsPin",
341+
value: "true"
342+
})
343+
.addSingleCondition({
344+
expectedResult: true,
345+
key: "passwordProtection.passwordIsPin",
346+
value: "!"
347+
});
309348
await conditions.executeTests((c, q) => c.relationshipTemplates.getRelationshipTemplates({ query: q, ownerRestriction: OwnerRestriction.Own }));
310349
});
311350

@@ -323,7 +362,17 @@ describe("RelationshipTemplates query", () => {
323362
.addDateSet("expiresAt")
324363
.addStringSet("createdBy")
325364
.addStringSet("createdByDevice")
326-
.addNumberSet("maxNumberOfAllocations");
365+
.addNumberSet("maxNumberOfAllocations")
366+
.addSingleCondition({
367+
expectedResult: false,
368+
key: "passwordProtection",
369+
value: ""
370+
})
371+
.addSingleCondition({
372+
expectedResult: true,
373+
key: "passwordProtection",
374+
value: "!"
375+
});
327376

328377
await conditions.executeTests((c, q) => c.relationshipTemplates.getRelationshipTemplates({ query: q, ownerRestriction: OwnerRestriction.Peer }));
329378
});

packages/transport/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,10 @@
7272
"@js-soft/ts-utils": "^2.3.3",
7373
"@nmshd/core-types": "*",
7474
"@nmshd/crypto": "2.1.0",
75-
"axios": "^1.7.8",
75+
"axios": "^1.7.9",
7676
"fast-json-patch": "^3.1.1",
7777
"form-data": "^4.0.1",
78-
"https-proxy-agent": "^7.0.5",
78+
"https-proxy-agent": "^7.0.6",
7979
"json-stringify-safe": "^5.0.1",
8080
"lodash": "^4.17.21",
8181
"luxon": "^3.5.0",
@@ -96,6 +96,7 @@
9696
"@types/uuid": "^10.0.0",
9797
"correlation-id": "^5.2.0",
9898
"expect": "^29.7.0",
99+
"testcontainers": "^10.14.0",
99100
"ts-mockito": "^2.6.1"
100101
},
101102
"publishConfig": {

packages/transport/src/modules/accounts/IdentityDeletionProcessController.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ export class IdentityDeletionProcessController extends TransportController {
7474
return identityDeletionProcess;
7575
}
7676

77-
public async initiateIdentityDeletionProcess(): Promise<IdentityDeletionProcess> {
78-
const identityDeletionProcessResponse = await this.identityDeletionProcessClient.initiateIdentityDeletionProcess();
77+
public async initiateIdentityDeletionProcess(lengthOfGracePeriodInDays?: number): Promise<IdentityDeletionProcess> {
78+
const identityDeletionProcessResponse = await this.identityDeletionProcessClient.initiateIdentityDeletionProcess({ lengthOfGracePeriodInDays });
7979

8080
const identityDeletionProcess = this.createIdentityDeletionProcessFromBackboneResponse(identityDeletionProcessResponse);
8181

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export interface BackbonePostIdentityDeletionProcessRequest {
2+
lengthOfGracePeriodInDays?: number;
3+
}

packages/transport/src/modules/accounts/backbone/IdentityDeletionProcessClient.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import { RESTClientAuthenticate, RESTClientLogDirective } from "../../../core";
22
import { ClientResult } from "../../../core/backbone/ClientResult";
33
import { BackboneIdentityDeletionProcess } from "./BackboneIdentityDeletionProcess";
4+
import { BackbonePostIdentityDeletionProcessRequest } from "./BackbonePostIdentityDeletionProcess";
45

56
export class IdentityDeletionProcessClient extends RESTClientAuthenticate {
67
protected override _logDirective = RESTClientLogDirective.LogResponse;
78

8-
public async initiateIdentityDeletionProcess(): Promise<ClientResult<BackboneIdentityDeletionProcess>> {
9-
return await this.post<BackboneIdentityDeletionProcess>("/api/v1/Identities/Self/DeletionProcesses", {});
9+
public async initiateIdentityDeletionProcess(value: BackbonePostIdentityDeletionProcessRequest): Promise<ClientResult<BackboneIdentityDeletionProcess>> {
10+
return await this.post<BackboneIdentityDeletionProcess>("/api/v1/Identities/Self/DeletionProcesses", value);
1011
}
1112

1213
public async getIdentityDeletionProcess(identityDeletionProcessId: string): Promise<ClientResult<BackboneIdentityDeletionProcess>> {

0 commit comments

Comments
 (0)