diff --git a/packages/runtime/src/useCases/common/Schemas.ts b/packages/runtime/src/useCases/common/Schemas.ts index 5fa6ec0c5..d7bd4fb08 100644 --- a/packages/runtime/src/useCases/common/Schemas.ts +++ b/packages/runtime/src/useCases/common/Schemas.ts @@ -22772,6 +22772,26 @@ export const GetRelationshipTemplatesRequest: any = { } } ] + }, + "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..e273b4e11 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,8 @@ export interface GetRelationshipTemplatesQuery { createdByDevice?: string | string[]; maxNumberOfAllocations?: string | string[]; forIdentity?: string | string[]; + "passwordProtection.password"?: string | string[]; + "passwordProtection.passwordIsPin"?: "true" | "!"; } export interface GetRelationshipTemplatesRequest { @@ -37,7 +39,9 @@ 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)}.password`]: true, + [`${nameof((r) => r.passwordProtection)}.passwordIsPin`]: true }, alias: { [nameof((r) => r.isOwn)]: nameof((r) => r.isOwn), @@ -51,6 +55,23 @@ export class GetRelationshipTemplatesUseCase extends UseCase t.maxNumberOfAllocations )}`, [nameof((r) => r.forIdentity)]: `${nameof((r) => r.cache)}.${nameof((t) => t.forIdentity)}` + }, + 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)}`] = { + $in: ["pw", undefined] + }; + } + } } }); diff --git a/packages/runtime/test/transport/relationshipTemplates.test.ts b/packages/runtime/test/transport/relationshipTemplates.test.ts index d46560234..4e58f61bd 100644 --- a/packages/runtime/test/transport/relationshipTemplates.test.ts +++ b/packages/runtime/test/transport/relationshipTemplates.test.ts @@ -1,7 +1,7 @@ import { RelationshipTemplateContent, RelationshipTemplateContentJSON } from "@nmshd/content"; import { DateTime } from "luxon"; import { GetRelationshipTemplatesQuery, OwnerRestriction } from "../../src"; -import { emptyRelationshipTemplateContent, QueryParamConditions, RuntimeServiceProvider, TestRuntimeServices } from "../lib"; +import { createTemplate, emptyRelationshipTemplateContent, QueryParamConditions, RuntimeServiceProvider, TestRuntimeServices } from "../lib"; const serviceProvider = new RuntimeServiceProvider(); let runtimeServices1: TestRuntimeServices; @@ -327,4 +327,54 @@ describe("RelationshipTemplates query", () => { await conditions.executeTests((c, q) => c.relationshipTemplates.getRelationshipTemplates({ query: q, ownerRestriction: OwnerRestriction.Peer })); }); + + test("password query for a template protected with a password that's not a PIN", async () => { + const passwordProtectedTemplate = await createTemplate(runtimeServices1.transport, undefined, { password: "password" }); + + const conditions = new QueryParamConditions(passwordProtectedTemplate, runtimeServices1.transport).addStringSet( + "passwordProtection.password" + ); + await conditions.executeTests((c, q) => c.relationshipTemplates.getRelationshipTemplates({ query: q })); + }); + + test("password query for a template protected with a PIN", async () => { + const pinProtectedTemplate = await createTemplate(runtimeServices1.transport, undefined, { password: "1234", passwordIsPin: true }); + + const conditions = new QueryParamConditions(pinProtectedTemplate, runtimeServices1.transport).addStringSet("passwordProtection.password"); + await conditions.executeTests((c, q) => c.relationshipTemplates.getRelationshipTemplates({ query: q })); + }); + + test("passwordIsPin query", async () => { + const passwordProtectedTemplate = await createTemplate(runtimeServices1.transport, undefined, { password: "password" }); + + const pinProtectedTemplate = await createTemplate(runtimeServices1.transport, undefined, { password: "1234", passwordIsPin: true }); + + const unprotectedTemplate = await createTemplate(runtimeServices1.transport); + + const templatesWithoutPin = ( + await runtimeServices1.transport.relationshipTemplates.getRelationshipTemplates({ + query: { + "passwordProtection.passwordIsPin": "!" + } + }) + ).value; + const idsOfTemplatesWithoutPin = templatesWithoutPin.map((t) => t.id); + + expect(idsOfTemplatesWithoutPin).toContain(passwordProtectedTemplate.id); + expect(idsOfTemplatesWithoutPin).not.toContain(pinProtectedTemplate.id); + expect(idsOfTemplatesWithoutPin).toContain(unprotectedTemplate.id); + + const templatesWithPin = ( + await runtimeServices1.transport.relationshipTemplates.getRelationshipTemplates({ + query: { + "passwordProtection.passwordIsPin": "true" + } + }) + ).value; + const idsOfTemplatesWithPin = templatesWithPin.map((t) => t.id); + + expect(idsOfTemplatesWithPin).not.toContain(passwordProtectedTemplate.id); + expect(idsOfTemplatesWithPin).toContain(pinProtectedTemplate.id); + expect(idsOfTemplatesWithPin).not.toContain(unprotectedTemplate.id); + }); });