From 7071817f1ff2126a74bf3d784e2ffdc22a0096df Mon Sep 17 00:00:00 2001 From: Magnus Kuhn <127854942+Magnus-Kuhn@users.noreply.github.com> Date: Mon, 9 Dec 2024 16:24:40 +0100 Subject: [PATCH] Query RelationshipTemplates for password protection (#353) * feat: query templates * fix: use custom query * test: cleanup tests * fix: !true accepts undefined * refactor: naming * feat: !true to ! * chore: build schemas * test: use queryconditions * test: naming * test: move password query into existing tests * feat/refactor: passwordProtection, passwordIsPin query * feat: restrict passwordIsPin query * refactor: name values * test: add passwordProtection query tests --------- Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- .../runtime/src/useCases/common/Schemas.ts | 27 +++++++++ .../GetRelationshipTemplates.ts | 28 ++++++++- .../transport/relationshipTemplates.test.ts | 59 +++++++++++++++++-- 3 files changed, 106 insertions(+), 8 deletions(-) diff --git a/packages/runtime/src/useCases/common/Schemas.ts b/packages/runtime/src/useCases/common/Schemas.ts index 5fa6ec0c5..b7b04468e 100644 --- a/packages/runtime/src/useCases/common/Schemas.ts +++ b/packages/runtime/src/useCases/common/Schemas.ts @@ -22772,6 +22772,33 @@ export const GetRelationshipTemplatesRequest: any = { } } ] + }, + "passwordProtection": { + "type": "string", + "enum": [ + "", + "!" + ] + }, + "passwordProtection.password": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + }, + "passwordProtection.passwordIsPin": { + "type": "string", + "enum": [ + "true", + "!" + ] } }, "additionalProperties": false diff --git a/packages/runtime/src/useCases/transport/relationshipTemplates/GetRelationshipTemplates.ts b/packages/runtime/src/useCases/transport/relationshipTemplates/GetRelationshipTemplates.ts index 30700b485..354df7960 100644 --- a/packages/runtime/src/useCases/transport/relationshipTemplates/GetRelationshipTemplates.ts +++ b/packages/runtime/src/useCases/transport/relationshipTemplates/GetRelationshipTemplates.ts @@ -1,6 +1,6 @@ import { QueryTranslator } from "@js-soft/docdb-querytranslator"; import { Result } from "@js-soft/ts-utils"; -import { CachedRelationshipTemplate, RelationshipTemplate, RelationshipTemplateController } from "@nmshd/transport"; +import { CachedRelationshipTemplate, PasswordProtection, RelationshipTemplate, RelationshipTemplateController } from "@nmshd/transport"; import { Inject } from "@nmshd/typescript-ioc"; import { nameof } from "ts-simple-nameof"; import { RelationshipTemplateDTO } from "../../../types"; @@ -15,6 +15,9 @@ export interface GetRelationshipTemplatesQuery { createdByDevice?: string | string[]; maxNumberOfAllocations?: string | string[]; forIdentity?: string | string[]; + passwordProtection?: "" | "!"; + "passwordProtection.password"?: string | string[]; + "passwordProtection.passwordIsPin"?: "true" | "!"; } export interface GetRelationshipTemplatesRequest { @@ -37,7 +40,10 @@ export class GetRelationshipTemplatesUseCase extends UseCase((r) => r.createdBy)]: true, [nameof((r) => r.createdByDevice)]: true, [nameof((r) => r.maxNumberOfAllocations)]: true, - [nameof((r) => r.forIdentity)]: true + [nameof((r) => r.forIdentity)]: true, + [nameof((r) => r.passwordProtection)]: true, + [`${nameof((r) => r.passwordProtection)}.password`]: true, + [`${nameof((r) => r.passwordProtection)}.passwordIsPin`]: true }, alias: { [nameof((r) => r.isOwn)]: nameof((r) => r.isOwn), @@ -50,7 +56,23 @@ export class GetRelationshipTemplatesUseCase extends UseCase((r) => r.maxNumberOfAllocations)]: `${nameof((r) => r.cache)}.${nameof( (t) => t.maxNumberOfAllocations )}`, - [nameof((r) => r.forIdentity)]: `${nameof((r) => r.cache)}.${nameof((t) => t.forIdentity)}` + [nameof((r) => r.forIdentity)]: `${nameof((r) => r.cache)}.${nameof((t) => t.forIdentity)}`, + [nameof((r) => r.passwordProtection)]: nameof((r) => r.passwordProtection) + }, + custom: { + [`${nameof((r) => r.passwordProtection)}.password`]: (query: any, input: string) => { + query[`${nameof((t) => t.passwordProtection)}.${nameof((t) => t.password)}`] = input; + }, + [`${nameof((t) => t.passwordProtection)}.passwordIsPin`]: (query: any, input: string) => { + if (input === "true") { + query[`${nameof((t) => t.passwordProtection)}.${nameof((t) => t.passwordType)}`] = { + $regex: "^pin" + }; + } + if (input === "!") { + query[`${nameof((t) => t.passwordProtection)}.${nameof((t) => t.passwordType)}`] = "pw"; + } + } } }); diff --git a/packages/runtime/test/transport/relationshipTemplates.test.ts b/packages/runtime/test/transport/relationshipTemplates.test.ts index d46560234..b89ed1d8e 100644 --- a/packages/runtime/test/transport/relationshipTemplates.test.ts +++ b/packages/runtime/test/transport/relationshipTemplates.test.ts @@ -277,7 +277,11 @@ describe("RelationshipTemplates query", () => { maxNumberOfAllocations: 1, expiresAt: DateTime.utc().plus({ minutes: 10 }).toString(), content: emptyRelationshipTemplateContent, - forIdentity: runtimeServices1.address + forIdentity: runtimeServices1.address, + passwordProtection: { + password: "1234", + passwordIsPin: true + } }) ).value; const conditions = new QueryParamConditions(template, runtimeServices1.transport) @@ -287,7 +291,28 @@ describe("RelationshipTemplates query", () => { .addStringSet("createdBy") .addStringSet("createdByDevice") .addNumberSet("maxNumberOfAllocations") - .addStringSet("forIdentity"); + .addStringSet("forIdentity") + .addSingleCondition({ + expectedResult: true, + key: "passwordProtection", + value: "" + }) + .addSingleCondition({ + expectedResult: false, + key: "passwordProtection", + value: "!" + }) + .addStringSet("passwordProtection.password") + .addSingleCondition({ + expectedResult: true, + key: "passwordProtection.passwordIsPin", + value: "true" + }) + .addSingleCondition({ + expectedResult: false, + key: "passwordProtection.passwordIsPin", + value: "!" + }); await conditions.executeTests((c, q) => c.relationshipTemplates.getRelationshipTemplates({ query: q })); }); @@ -297,7 +322,10 @@ describe("RelationshipTemplates query", () => { await runtimeServices1.transport.relationshipTemplates.createOwnRelationshipTemplate({ maxNumberOfAllocations: 1, expiresAt: DateTime.utc().plus({ minutes: 10 }).toString(), - content: emptyRelationshipTemplateContent + content: emptyRelationshipTemplateContent, + passwordProtection: { + password: "password" + } }) ).value; const conditions = new QueryParamConditions(template, runtimeServices1.transport) @@ -305,7 +333,18 @@ describe("RelationshipTemplates query", () => { .addDateSet("expiresAt") .addStringSet("createdBy") .addStringSet("createdByDevice") - .addNumberSet("maxNumberOfAllocations"); + .addNumberSet("maxNumberOfAllocations") + .addStringSet("passwordProtection.password") + .addSingleCondition({ + expectedResult: false, + key: "passwordProtection.passwordIsPin", + value: "true" + }) + .addSingleCondition({ + expectedResult: true, + key: "passwordProtection.passwordIsPin", + value: "!" + }); await conditions.executeTests((c, q) => c.relationshipTemplates.getRelationshipTemplates({ query: q, ownerRestriction: OwnerRestriction.Own })); }); @@ -323,7 +362,17 @@ describe("RelationshipTemplates query", () => { .addDateSet("expiresAt") .addStringSet("createdBy") .addStringSet("createdByDevice") - .addNumberSet("maxNumberOfAllocations"); + .addNumberSet("maxNumberOfAllocations") + .addSingleCondition({ + expectedResult: false, + key: "passwordProtection", + value: "" + }) + .addSingleCondition({ + expectedResult: true, + key: "passwordProtection", + value: "!" + }); await conditions.executeTests((c, q) => c.relationshipTemplates.getRelationshipTemplates({ query: q, ownerRestriction: OwnerRestriction.Peer })); });