Repository: nmshd/connector-tui
Pull request #59: Add support for passwordLocationIndicator
Author: login: jkoenig134
Created: 2025-04-30T05:53:27Z | Merged: 2025-04-30T08:53:27Z



Diff:
diff --git a/package-lock.json b/package-lock.json
index 8d740fb..ccda7b6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,16 +1,16 @@
 {
   "name": "@nmshd/connector-tui",
-  "version": "2.9.1",
+  "version": "2.10.0",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "@nmshd/connector-tui",
-      "version": "2.9.1",
+      "version": "2.10.0",
       "license": "MIT",
       "dependencies": {
-        "@nmshd/connector-sdk": "^6.23.0",
-        "axios": "^1.8.4",
+        "@nmshd/connector-sdk": "^6.24.0",
+        "axios": "^1.9.0",
         "chalk": "^5.4.1",
         "dotenv": "^16.5.0",
         "luxon": "^3.6.1",
@@ -27,7 +27,7 @@
         "@js-soft/eslint-config-ts": "^1.6.14",
         "@js-soft/license-check": "^1.0.9",
         "@types/luxon": "^3.6.2",
-        "@types/node": "^22.14.1",
+        "@types/node": "^22.15.3",
         "@types/prompts": "^2.4.9",
         "@types/qrcode-terminal": "^0.12.2",
         "@types/yargs": "^17.0.33",
@@ -223,34 +223,34 @@
       }
     },
     "node_modules/@nmshd/connector-sdk": {
-      "version": "6.23.0",
-      "resolved": "https://registry.npmjs.org/@nmshd/connector-sdk/-/connector-sdk-6.23.0.tgz",
-      "integrity": "sha512-gBxqqKm2lwJbqcWQB6P/0O0R4N9dcDqOWr3pyEwcoPzHebrLzWCCOouWoYcfJM5kM4ECY8rjEWx4EtGje986hg==",
+      "version": "6.24.0",
+      "resolved": "https://registry.npmjs.org/@nmshd/connector-sdk/-/connector-sdk-6.24.0.tgz",
+      "integrity": "sha512-81e8BUk+RsJesG0dWixhEMrhyKJzKodkQac7F3UTg8k4qAZhPWo9CWsF0s1ksex8j5jRi8lJOw0PKxKw8lwdYQ==",
       "license": "MIT",
       "dependencies": {
-        "@nmshd/content": "6.38.0",
-        "axios": "^1.8.4",
+        "@nmshd/content": "6.42.1",
+        "axios": "^1.9.0",
         "form-data": "^4.0.2",
         "qs": "^6.14.0"
       }
     },
     "node_modules/@nmshd/content": {
-      "version": "6.38.0",
-      "resolved": "https://registry.npmjs.org/@nmshd/content/-/content-6.38.0.tgz",
-      "integrity": "sha512-CkuucfsVdTSDuW0gDkMBmI0APflnFnBIogCIpQBlUbV829OP5qpqXrtuvWlE5DF9ukcVmeUKFJ45poi7K1a3jA==",
+      "version": "6.42.1",
+      "resolved": "https://registry.npmjs.org/@nmshd/content/-/content-6.42.1.tgz",
+      "integrity": "sha512-vBPm52Q3e6JtyxNvQlTmC47Ey7QCIapSYbYTE3bBFaEVMjm+/q/x1spWdyfYCHhc43ADPPrim7KEzvTu5X7XpQ==",
       "license": "MIT",
       "dependencies": {
         "@js-soft/ts-serval": "2.0.12",
-        "@nmshd/core-types": "6.38.0",
+        "@nmshd/core-types": "6.42.1",
         "@nmshd/iql": "^1.0.2",
         "luxon": "^3.6.1",
         "ts-simple-nameof": "^1.3.1"
       }
     },
     "node_modules/@nmshd/core-types": {
-      "version": "6.38.0",
-      "resolved": "https://registry.npmjs.org/@nmshd/core-types/-/core-types-6.38.0.tgz",
-      "integrity": "sha512-3WuFvB1kIEPVGU0sWmtj0Apo1GWl0WOliBETL7tE6pv7q2JUJo7cCX0dzHJmZVVNerRqaxyrJI39rPAshGIAYA==",
+      "version": "6.42.1",
+      "resolved": "https://registry.npmjs.org/@nmshd/core-types/-/core-types-6.42.1.tgz",
+      "integrity": "sha512-/BWGLvqkidUUcpvZLSBUQ0jT9mo2SFR6bIjWsqy+1NeoSpZ4zrBlXBvtwiZUEXzz3PR1BNp8d3OG4wh3y0SWxg==",
       "license": "MIT",
       "dependencies": {
         "@js-soft/logging-abstractions": "^1.0.1",
@@ -343,9 +343,9 @@
       "license": "MIT"
     },
     "node_modules/@types/node": {
-      "version": "22.14.1",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.1.tgz",
-      "integrity": "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==",
+      "version": "22.15.3",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.3.tgz",
+      "integrity": "sha512-lX7HFZeHf4QG/J7tBZqrCAXwz9J5RD56Y6MpP0eJkka8p+K0RY/yBTW7CYFJ4VGCclxqOLKmiGP5juQc6MKgcw==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -717,9 +717,10 @@
       "license": "MIT"
     },
     "node_modules/axios": {
-      "version": "1.8.4",
-      "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz",
-      "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==",
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz",
+      "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==",
+      "license": "MIT",
       "dependencies": {
         "follow-redirects": "^1.15.6",
         "form-data": "^4.0.0",
diff --git a/package.json b/package.json
index d7e2666..742e768 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@nmshd/connector-tui",
-  "version": "2.9.1",
+  "version": "2.10.0",
   "repository": "github:nmshd/connector-tui",
   "license": "MIT",
   "author": "j&s-soft AG",
@@ -29,8 +29,8 @@
     "watch": "node --watch --import 'data:text/javascript,import { register } from \"node:module\"; import { pathToFileURL } from \"node:url\"; register(\"ts-node/esm\", pathToFileURL(\"./\"));' src/run.ts"
   },
   "dependencies": {
-    "@nmshd/connector-sdk": "^6.23.0",
-    "axios": "^1.8.4",
+    "@nmshd/connector-sdk": "^6.24.0",
+    "axios": "^1.9.0",
     "chalk": "^5.4.1",
     "dotenv": "^16.5.0",
     "luxon": "^3.6.1",
@@ -42,7 +42,7 @@
     "@js-soft/eslint-config-ts": "^1.6.14",
     "@js-soft/license-check": "^1.0.9",
     "@types/luxon": "^3.6.2",
-    "@types/node": "^22.14.1",
+    "@types/node": "^22.15.3",
     "@types/prompts": "^2.4.9",
     "@types/qrcode-terminal": "^0.12.2",
     "@types/yargs": "^17.0.33",
diff --git a/src/mixins/AddShareRequestByTemplate.ts b/src/mixins/AddShareRequestByTemplate.ts
index 16f42ce..3e020ee 100644
--- a/src/mixins/AddShareRequestByTemplate.ts
+++ b/src/mixins/AddShareRequestByTemplate.ts
@@ -127,7 +127,7 @@ export function AddShareRequestByTemplate<TBase extends ConnectorTUIBaseConstruc
       return createAttributeResponse.result
     }
 
-    private async createPasswordProtection(): Promise<{ password: string; passwordIsPin?: true } | undefined> {
+    private async createPasswordProtection(): Promise<{ password: string; passwordIsPin?: true; passwordLocationIndicator?: string | number } | undefined> {
       const result = await prompts({
         message: "What kind of password protection do you want to use?",
         type: "select",
@@ -152,7 +152,8 @@ export function AddShareRequestByTemplate<TBase extends ConnectorTUIBaseConstruc
           name: "password",
         })
 
-        return { password: password.password }
+        const passwordLocationIndicator = await this.selectPasswordLocationIndicator()
+        return { password: password.password, passwordLocationIndicator }
       }
 
       const password = await prompts({
@@ -167,14 +168,52 @@ export function AddShareRequestByTemplate<TBase extends ConnectorTUIBaseConstruc
         name: "password",
       })
 
-      return { password: password.password, passwordIsPin: true }
+      const passwordLocationIndicator = await this.selectPasswordLocationIndicator()
+      return { password: password.password, passwordIsPin: true, passwordLocationIndicator }
+    }
+
+    private async selectPasswordLocationIndicator(): Promise<string | number | undefined> {
+      const result = await prompts({
+        message: "Where can the user find the password?",
+        type: "select",
+        name: "passwordLocationIndicator",
+        choices: [
+          { title: "None", value: "None", selected: true },
+          { title: "Custom (Number between 50 and 99)", value: "Custom" },
+          { title: "Self", value: "Self" },
+          { title: "Letter", value: "Letter" },
+          { title: "RegistrationLetter", value: "RegistrationLetter" },
+          { title: "Email", value: "Email" },
+          { title: "SMS", value: "SMS" },
+          { title: "Website", value: "Website" },
+        ],
+      })
+
+      if (result.passwordLocationIndicator === "None") return
+      if (result.passwordLocationIndicator !== "Custom") return result.passwordLocationIndicator
+
+      const customLocation = await prompts({
+        message: "Enter a number between 50 and 99",
+        type: "number",
+        validate: (value) => {
+          if (value < 50 || value > 99) return "Number must be between 50 and 99"
+          return true
+        },
+        name: "passwordLocationIndicator",
+      })
+
+      return customLocation.passwordLocationIndicator
     }
 
     private async createQRCodeForRelationshipTemplate(
       onNewRelationship: RequestJSON,
       onExistingRelationship: RequestJSON,
       name: string,
-      passwordProtection?: { password: string; passwordIsPin?: true }
+      passwordProtection?: {
+        password: string
+        passwordIsPin?: true
+        passwordLocationIndicator?: string | number
+      }
     ) {
       const content: RelationshipTemplateContentJSON = {
         "@type": "RelationshipTemplateContent",


Reviews:
user: login: Milena-Czierlinski
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-30T07:45:10Z
user: login: jkoenig134
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-30T07:49:47Z
user: login: github-advanced-security[bot]
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-30T07:50:55Z
user: login: jkoenig134
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-30T07:54:08Z
user: login: Milena-Czierlinski
state: APPROVED
author_association: MEMBER
submitted_at: 2025-04-30T08:49:08Z

Review comments:
diff_hunk: @@ -167,14 +168,51 @@ export function AddShareRequestByTemplate<TBase extends ConnectorTUIBaseConstruc
         name: "password",
       })
 
-      return { password: password.password, passwordIsPin: true }
+      const passwordLocationIndicator = await this.selectPasswordLocationIndicator()
+      return { password: password.password, passwordIsPin: true, passwordLocationIndicator }
+    }
+
+    private async selectPasswordLocationIndicator(): Promise<string | number | undefined> {
+      const result = await prompts({
+        message: "Where can the user find the password?",
+        type: "select",
+        name: "passwordLocationIndicator",
+        choices: [
+          { title: "None", value: undefined, selected: true },
path: src/mixins/AddShareRequestByTemplate.ts
user: login: Milena-Czierlinski
body: Here 0 is passed instead of undefined. Nevertheless, the runtime should not allow to create such a RelationshipTemplate.  I'll take care of that...
created_at: 2025-04-30T07:45:10Z
author_association: MEMBER
diff_hunk: @@ -167,14 +168,51 @@ export function AddShareRequestByTemplate<TBase extends ConnectorTUIBaseConstruc
         name: "password",
       })
 
-      return { password: password.password, passwordIsPin: true }
+      const passwordLocationIndicator = await this.selectPasswordLocationIndicator()
+      return { password: password.password, passwordIsPin: true, passwordLocationIndicator }
+    }
+
+    private async selectPasswordLocationIndicator(): Promise<string | number | undefined> {
+      const result = await prompts({
+        message: "Where can the user find the password?",
+        type: "select",
+        name: "passwordLocationIndicator",
+        choices: [
+          { title: "None", value: undefined, selected: true },
path: src/mixins/AddShareRequestByTemplate.ts
user: login: jkoenig134
body: fixed!
created_at: 2025-04-30T07:49:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -167,14 +168,53 @@
         name: "password",
       })
 
-      return { password: password.password, passwordIsPin: true }
+      const passwordLocationIndicator = await this.selectPasswordLocationIndicator()
+      console.log(passwordLocationIndicator)
path: src/mixins/AddShareRequestByTemplate.ts
user: login: github-advanced-security[bot]
body: ## Clear-text logging of sensitive information

This logs sensitive data returned by [an access to passwordLocationIndicator](1) as clear text.

[Show more details](https://github.com/nmshd/connector-tui/security/code-scanning/1)
created_at: 2025-04-30T07:50:55Z
author_association: NONE
diff_hunk: @@ -167,14 +168,53 @@
         name: "password",
       })
 
-      return { password: password.password, passwordIsPin: true }
+      const passwordLocationIndicator = await this.selectPasswordLocationIndicator()
+      console.log(passwordLocationIndicator)
path: src/mixins/AddShareRequestByTemplate.ts
user: login: jkoenig134
body: lol, stop crying.
created_at: 2025-04-30T07:54:08Z
author_association: CONTRIBUTOR

PR comments:
user: login: Milena-Czierlinski
created_at: 2025-04-30T07:37:08Z
body: If I scan the QR Code of a password protected RelationshipTemplate without passwordLocationIndicator, the text for a RecoveryKit is shown. We should check if this is an error here or in the app. @jkoenig134 
author_association: MEMBER
user: login: Milena-Czierlinski
created_at: 2025-04-30T07:39:09Z
body: > If I scan the QR Code of a password protected RelationshipTemplate without passwordLocationIndicator, the text for a RecoveryKit is shown. We should check if this is an error here or in the app. @jkoenig134

It's a problem here, 0 is passed instead of undefined.
author_association: MEMBER
user: login: jkoenig134
created_at: 2025-04-30T07:39:35Z
body: > > If I scan the QR Code of a password protected RelationshipTemplate without passwordLocationIndicator, the text for a RecoveryKit is shown. We should check if this is an error here or in the app. @jkoenig134
> 
> It's a problem here, 0 is passed instead of undefined.

ehhhhhm, what? But the runtime should not allow 0
author_association: CONTRIBUTOR
user: login: Milena-Czierlinski
created_at: 2025-04-30T07:39:58Z
body: I'll look into it. 
author_association: MEMBER