diff --git a/package-lock.json b/package-lock.json index 280de6ee..54a59cd0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@cheqd/credential-service", - "version": "2.15.0-develop.3", + "version": "2.15.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@cheqd/credential-service", - "version": "2.15.0-develop.3", + "version": "2.15.0", "license": "Apache-2.0", "dependencies": { "@cheqd/did-provider-cheqd": "^3.6.14", @@ -53,7 +53,7 @@ "sqlite3": "^5.1.7", "swagger-ui-express": "^5.0.0", "typeorm": "^0.3.19", - "uint8arrays": "^4.0.10", + "uint8arrays": "^5.0.1", "uri-js": "^4.4.1" }, "devDependencies": { @@ -5462,7 +5462,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", - "devOptional": true + "optional": true }, "node_modules/@graphql-typed-document-node/core": { "version": "3.2.0", @@ -7239,7 +7239,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", - "devOptional": true, + "optional": true, "dependencies": { "@gar/promisify": "^1.0.1", "semver": "^7.3.5" @@ -7250,7 +7250,7 @@ "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", "deprecated": "This functionality has been moved to @npmcli/fs", - "devOptional": true, + "optional": true, "dependencies": { "mkdirp": "^1.0.4", "rimraf": "^3.0.2" @@ -9668,7 +9668,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "devOptional": true, + "optional": true, "engines": { "node": ">= 6" } @@ -13015,7 +13015,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "devOptional": true + "optional": true }, "node_modules/abort-controller": { "version": "3.0.0", @@ -13143,7 +13143,7 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", - "devOptional": true, + "optional": true, "dependencies": { "humanize-ms": "^1.2.1" }, @@ -13345,7 +13345,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "devOptional": true + "optional": true }, "node_modules/arch": { "version": "2.2.0", @@ -13370,7 +13370,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "devOptional": true, + "optional": true, "dependencies": { "delegates": "^1.0.0", "readable-stream": "^3.6.0" @@ -13383,7 +13383,7 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "devOptional": true, + "optional": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -14295,7 +14295,8 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", "integrity": "sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==", - "devOptional": true + "optional": true, + "peer": true }, "node_modules/bytes": { "version": "3.1.2", @@ -14309,7 +14310,7 @@ "version": "15.3.0", "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", - "devOptional": true, + "optional": true, "dependencies": { "@npmcli/fs": "^1.0.0", "@npmcli/move-file": "^1.0.1", @@ -14800,7 +14801,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "devOptional": true, + "optional": true, "bin": { "color-support": "bin.js" } @@ -15040,7 +15041,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "devOptional": true + "optional": true }, "node_modules/content-disposition": { "version": "0.5.4", @@ -15908,7 +15909,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "devOptional": true + "optional": true }, "node_modules/denodeify": { "version": "1.2.1", @@ -16494,7 +16495,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "devOptional": true, + "optional": true, "engines": { "node": ">=6" } @@ -18073,7 +18074,7 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "devOptional": true, + "optional": true, "dependencies": { "aproba": "^1.0.3 || ^2.0.0", "color-support": "^1.1.3", @@ -18478,7 +18479,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "devOptional": true + "optional": true }, "node_modules/hash-base": { "version": "3.1.0", @@ -18613,7 +18614,8 @@ "version": "3.0.8", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz", "integrity": "sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==", - "devOptional": true, + "optional": true, + "peer": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -18631,7 +18633,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "devOptional": true + "optional": true }, "node_modules/http-errors": { "version": "2.0.0", @@ -18700,7 +18702,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "devOptional": true, + "optional": true, "dependencies": { "ms": "^2.0.0" } @@ -18862,7 +18864,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "devOptional": true + "optional": true }, "node_modules/inflight": { "version": "1.0.6", @@ -19505,7 +19507,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "devOptional": true + "optional": true }, "node_modules/is-number": { "version": "7.0.0", @@ -22374,7 +22376,7 @@ "version": "9.1.0", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", - "devOptional": true, + "optional": true, "dependencies": { "agentkeepalive": "^4.1.3", "cacache": "^15.2.0", @@ -22401,7 +22403,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "devOptional": true, + "optional": true, "dependencies": { "debug": "4" }, @@ -22413,7 +22415,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "devOptional": true, + "optional": true, "dependencies": { "@tootallnate/once": "1", "agent-base": "6", @@ -22427,7 +22429,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "devOptional": true, + "optional": true, "dependencies": { "agent-base": "6", "debug": "4" @@ -23236,7 +23238,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "devOptional": true, + "optional": true, "dependencies": { "minipass": "^3.0.0" }, @@ -23248,7 +23250,7 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", - "devOptional": true, + "optional": true, "dependencies": { "minipass": "^3.1.0", "minipass-sized": "^1.0.3", @@ -23265,7 +23267,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "devOptional": true, + "optional": true, "dependencies": { "minipass": "^3.0.0" }, @@ -23277,7 +23279,7 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "devOptional": true, + "optional": true, "dependencies": { "minipass": "^3.0.0" }, @@ -23289,7 +23291,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "devOptional": true, + "optional": true, "dependencies": { "minipass": "^3.0.0" }, @@ -23737,7 +23739,7 @@ "version": "8.4.1", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", - "devOptional": true, + "optional": true, "dependencies": { "env-paths": "^2.2.0", "glob": "^7.1.4", @@ -23826,7 +23828,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "devOptional": true, + "optional": true, "dependencies": { "abbrev": "1" }, @@ -24056,7 +24058,8 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-7.0.0.tgz", "integrity": "sha512-xXxr8y5U0kl8dVkz2oK7yZjPBvqM2fwaO5l3Yg13p03v8+E3qQcD0JNhHzjL1vyGgxcKkD0cco+NLR72iuPk3g==", - "devOptional": true, + "optional": true, + "peer": true, "dependencies": { "hosted-git-info": "^3.0.2", "osenv": "^0.1.5", @@ -24068,7 +24071,8 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "devOptional": true, + "optional": true, + "peer": true, "bin": { "semver": "bin/semver" } @@ -26896,7 +26900,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "devOptional": true, + "optional": true, "dependencies": { "are-we-there-yet": "^3.0.0", "console-control-strings": "^1.1.0", @@ -27169,7 +27173,8 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==", - "devOptional": true, + "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -27178,7 +27183,8 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "devOptional": true, + "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -27187,7 +27193,8 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "devOptional": true, + "optional": true, + "peer": true, "dependencies": { "os-homedir": "^1.0.0", "os-tmpdir": "^1.0.0" @@ -27302,7 +27309,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "devOptional": true, + "optional": true, "dependencies": { "aggregate-error": "^3.0.0" }, @@ -28488,13 +28495,13 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", - "devOptional": true + "optional": true }, "node_modules/promise-retry": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "devOptional": true, + "optional": true, "dependencies": { "err-code": "^2.0.2", "retry": "^0.12.0" @@ -28507,7 +28514,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "devOptional": true + "optional": true }, "node_modules/prompts": { "version": "2.4.2", @@ -28672,7 +28679,8 @@ "version": "0.11.0", "resolved": "https://registry.npmjs.org/qrcode-terminal/-/qrcode-terminal-0.11.0.tgz", "integrity": "sha512-Uu7ii+FQy4Qf82G4xu7ShHhjhGahEpCWc3x8UavY3CTcWV+ufmmCtwkr7ZKsX42jdL0kr1B5FKUeqJvAn51jzQ==", - "devOptional": true, + "optional": true, + "peer": true, "bin": { "qrcode-terminal": "bin/qrcode-terminal.js" } @@ -29689,7 +29697,7 @@ "version": "0.12.0", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "devOptional": true, + "optional": true, "engines": { "node": ">= 4" } @@ -30778,7 +30786,7 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "devOptional": true, + "optional": true, "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" @@ -30788,7 +30796,7 @@ "version": "2.7.1", "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", - "devOptional": true, + "optional": true, "dependencies": { "ip": "^2.0.0", "smart-buffer": "^4.2.0" @@ -30802,7 +30810,7 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", - "devOptional": true, + "optional": true, "dependencies": { "agent-base": "^6.0.2", "debug": "^4.3.3", @@ -30816,7 +30824,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "devOptional": true, + "optional": true, "dependencies": { "debug": "4" }, @@ -30828,7 +30836,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", - "devOptional": true + "optional": true }, "node_modules/sonic-boom": { "version": "2.8.0", @@ -30980,7 +30988,7 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", - "devOptional": true, + "optional": true, "dependencies": { "minipass": "^3.1.1" }, @@ -32638,7 +32646,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "devOptional": true, + "optional": true, "dependencies": { "unique-slug": "^2.0.0" } @@ -32647,7 +32655,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "devOptional": true, + "optional": true, "dependencies": { "imurmurhash": "^0.1.4" } @@ -32961,7 +32969,8 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", "integrity": "sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw==", - "devOptional": true, + "optional": true, + "peer": true, "dependencies": { "builtins": "^1.0.3" } @@ -33202,7 +33211,7 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "devOptional": true, + "optional": true, "dependencies": { "string-width": "^1.0.2 || 2 || 3 || 4" } @@ -33262,7 +33271,8 @@ "version": "2.4.3", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", - "devOptional": true, + "optional": true, + "peer": true, "dependencies": { "graceful-fs": "^4.1.11", "imurmurhash": "^0.1.4", diff --git a/package.json b/package.json index 8d34d58a..e18e527e 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,7 @@ "sqlite3": "^5.1.7", "swagger-ui-express": "^5.0.0", "typeorm": "^0.3.19", - "uint8arrays": "^4.0.10", + "uint8arrays": "^5.0.1", "uri-js": "^4.4.1" }, "devDependencies": { diff --git a/src/app.ts b/src/app.ts index 882b7cf0..6bd5d553 100644 --- a/src/app.ts +++ b/src/app.ts @@ -160,7 +160,7 @@ class App { // Keys API app.post('/key/create', new KeyController().createKey); - app.post('/key/import', KeyController.importKeyValidator, new KeyController().importKey); + app.post('/key/import', KeyController.keyImportValidator, new KeyController().importKey); app.get('/key/read/:kid', new KeyController().getKey); // DIDs API diff --git a/src/controllers/account.ts b/src/controllers/account.ts index 77c5b901..739e4943 100644 --- a/src/controllers/account.ts +++ b/src/controllers/account.ts @@ -13,6 +13,13 @@ import type { CustomerEntity } from '../database/entities/customer.entity.js'; import type { UserEntity } from '../database/entities/user.entity.js'; import type { PaymentAccountEntity } from '../database/entities/payment.account.entity.js'; import { IdentityServiceStrategySetup } from '../services/identity/index.js'; +import type { + QueryCustomerResponseBody, + QueryIdTokenResponseBody, + UnsuccessfulQueryCustomerResponseBody, + UnsuccessfulQueryIdTokenResponseBody, +} from '../types/customer.js'; +import type { UnsuccessfulResponseBody } from '../types/shared.js'; import { check, validationResult } from 'express-validator'; export class AccountController { @@ -49,10 +56,10 @@ export class AccountController { try { if (!response.locals.customer) { // It's not ok, seems like there no any customer assigned to the user yet - // But it's not an expectede behaviour cause it should be done on bootstrap phase of after migration + // But it's not an expected behaviour cause it should be done on bootstrap phase of after migration return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ error: 'Bad state cause there is no customer assigned to the user yet. Please contact administrator.', - }); + } satisfies UnsuccessfulQueryCustomerResponseBody); } const paymentAccount = await PaymentAccountService.instance.find({ customer: response.locals.customer }); const result = { @@ -63,13 +70,13 @@ export class AccountController { paymentAccount: { address: paymentAccount[0].address, }, - }; + } satisfies QueryCustomerResponseBody; return response.status(StatusCodes.OK).json(result); } catch (error) { return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ error: `Internal error: ${(error as Error)?.message || error}`, - }); + } satisfies UnsuccessfulQueryCustomerResponseBody); } } @@ -99,10 +106,11 @@ export class AccountController { if (!request.user || !request.session.idToken) { return response.status(StatusCodes.BAD_REQUEST).json({ error: 'Seems like authorisation process was corrupted. Please contact administrator.', - }); + } satisfies UnsuccessfulQueryIdTokenResponseBody); } const identityStrategySetup = new IdentityServiceStrategySetup(response.locals.customer.customerId); + try { // Get the API key for the customer let apiKey = await identityStrategySetup.agent.getAPIKey(response.locals.customer, response.locals.user); @@ -119,11 +127,11 @@ export class AccountController { } return response.status(StatusCodes.OK).json({ idToken: apiKey?.apiKey, - }); + } satisfies QueryIdTokenResponseBody); } catch (error) { return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ error: `Internal error: ${(error as Error)?.message || error}`, - }); + } satisfies UnsuccessfulQueryIdTokenResponseBody); } } @@ -156,7 +164,7 @@ export class AccountController { if (!request.body.user || !request.body.user.id || !request.body.user.primaryEmail) { return response.status(StatusCodes.BAD_REQUEST).json({ error: 'User id is not specified or primaryEmail is not set', - }); + } satisfies UnsuccessfulResponseBody); } const logToUserId = request.body.user.id; const logToUserEmail = request.body.user.primaryEmail; @@ -164,7 +172,7 @@ export class AccountController { if (!defaultRole) { return response.status(StatusCodes.BAD_REQUEST).json({ error: 'Default role is not set on Credential Service side', - }); + } satisfies UnsuccessfulResponseBody); } // 2. Check if such row exists in the DB user = await UserService.instance.get(logToUserId); @@ -179,14 +187,14 @@ export class AccountController { if (!customer) { return response.status(StatusCodes.BAD_REQUEST).json({ error: 'User is not found in db: Customer was not created', - }); + } satisfies UnsuccessfulResponseBody); } // 2.2. Create user user = await UserService.instance.create(logToUserId, customer, defaultRole); if (!user) { return response.status(StatusCodes.BAD_REQUEST).json({ error: 'User is not found in db: User was not created', - }); + } satisfies UnsuccessfulResponseBody); } } // 3. If yes - check that there is customer associated with such user @@ -197,7 +205,7 @@ export class AccountController { if (!customer) { return response.status(StatusCodes.BAD_REQUEST).json({ error: 'User exists in db: Customer was not created', - }); + } satisfies UnsuccessfulResponseBody); } // 3.1.2. Assign customer to the user user.customer = customer; @@ -216,7 +224,7 @@ export class AccountController { if (!key) { return response.status(StatusCodes.BAD_REQUEST).json({ error: 'PaymentAccount is not found in db: Key was not created', - }); + } satisfies UnsuccessfulResponseBody); } paymentAccount = (await PaymentAccountService.instance.create( CheqdNetwork.Testnet, @@ -227,7 +235,7 @@ export class AccountController { if (!paymentAccount) { return response.status(StatusCodes.BAD_REQUEST).json({ error: 'PaymentAccount is not found in db: Payment account was not created', - }); + } satisfies UnsuccessfulResponseBody); } } else { paymentAccount = accounts[0]; @@ -238,7 +246,7 @@ export class AccountController { if (_r.status !== StatusCodes.OK) { return response.status(StatusCodes.BAD_GATEWAY).json({ error: _r.error, - }); + } satisfies UnsuccessfulResponseBody); } // 5. Assign default role on LogTo // 5.1 Get user's roles @@ -246,7 +254,7 @@ export class AccountController { if (roles.status !== StatusCodes.OK) { return response.status(StatusCodes.BAD_GATEWAY).json({ error: roles.error, - }); + } satisfies UnsuccessfulResponseBody); } // 5.2 If list of roles is empty and the user is not suspended - assign default role @@ -255,7 +263,7 @@ export class AccountController { if (_r.status !== StatusCodes.OK) { return response.status(StatusCodes.BAD_GATEWAY).json({ error: _r.error, - }); + } satisfies UnsuccessfulResponseBody); } } @@ -276,7 +284,7 @@ export class AccountController { if (_r.status !== 200) { return response.status(_r.status).json({ error: _r.error, - }); + } satisfies UnsuccessfulResponseBody); } } @@ -290,7 +298,7 @@ export class AccountController { if (resp.status !== StatusCodes.OK) { return response.status(StatusCodes.BAD_GATEWAY).json({ error: resp.error, - }); + } satisfies UnsuccessfulResponseBody); } } } diff --git a/src/controllers/credential-status.ts b/src/controllers/credential-status.ts index 9e3c410f..c36117fc 100644 --- a/src/controllers/credential-status.ts +++ b/src/controllers/credential-status.ts @@ -3,7 +3,7 @@ import { check, validationResult, query } from './validator/index.js'; import { fromString } from 'uint8arrays'; import { StatusCodes } from 'http-status-codes'; import { IdentityServiceStrategySetup } from '../services/identity/index.js'; -import type { ITrackOperation } from '../types/shared.js'; +import type { ITrackOperation, ValidationErrorResponseBody } from '../types/shared.js'; import type { CheckStatusListSuccessfulResponseBody, FeePaymentOptions } from '../types/credential-status.js'; import { DefaultStatusAction, @@ -496,7 +496,9 @@ export class CredentialStatusController { // handle error if (!result.isEmpty()) { - return response.status(StatusCodes.BAD_REQUEST).json({ error: result.array().pop()?.msg }); + return response.status(StatusCodes.BAD_REQUEST).json({ + error: result.array().pop()?.msg, + } satisfies ValidationErrorResponseBody); } // collect request parameters - case: body @@ -627,7 +629,9 @@ export class CredentialStatusController { // handle error if (!result.isEmpty()) { - return response.status(StatusCodes.BAD_REQUEST).json({ error: result.array().pop()?.msg }); + return response.status(StatusCodes.BAD_REQUEST).json({ + error: result.array().pop()?.msg, + } satisfies ValidationErrorResponseBody); } // collect request parameters - case: body @@ -761,7 +765,9 @@ export class CredentialStatusController { // handle error if (!result.isEmpty()) { - return response.status(StatusCodes.BAD_REQUEST).json({ error: result.array().pop()?.msg }); + return response.status(StatusCodes.BAD_REQUEST).json({ + error: result.array().pop()?.msg, + } satisfies ValidationErrorResponseBody); } // collect request parameters - case: body @@ -792,9 +798,10 @@ export class CredentialStatusController { } // handle generic error - return response - .status(StatusCodes.BAD_REQUEST) - .json({ updated: false, error: `update: error: ${unencrypted.error}` }); + return response.status(StatusCodes.BAD_REQUEST).json({ + updated: false, + error: `update: error: ${unencrypted.error}`, + } satisfies UpdateUnencryptedStatusListUnsuccessfulResponseBody); } // validate unencrypted @@ -940,7 +947,9 @@ export class CredentialStatusController { // handle error if (!result.isEmpty()) { - return response.status(StatusCodes.BAD_REQUEST).json({ error: result.array().pop()?.msg }); + return response.status(StatusCodes.BAD_REQUEST).json({ + error: result.array().pop()?.msg, + } satisfies ValidationErrorResponseBody); } // collect request parameters - case: body @@ -1140,7 +1149,9 @@ export class CredentialStatusController { // handle error if (!result.isEmpty()) { - return response.status(StatusCodes.BAD_REQUEST).json({ error: result.array()[0].msg }); + return response.status(StatusCodes.BAD_REQUEST).json({ + error: result.array()[0].msg, + } satisfies ValidationErrorResponseBody); } // collect request parameters - case: body @@ -1302,7 +1313,9 @@ export class CredentialStatusController { // handle error if (!result.isEmpty()) { - return response.status(StatusCodes.BAD_REQUEST).json({ error: result.array().pop()?.msg }); + return response.status(StatusCodes.BAD_REQUEST).json({ + error: result.array().pop()?.msg, + } satisfies ValidationErrorResponseBody); } // collect request parameters - case: query diff --git a/src/controllers/credentials.ts b/src/controllers/credentials.ts index 852879f9..fae796a3 100644 --- a/src/controllers/credentials.ts +++ b/src/controllers/credentials.ts @@ -6,11 +6,32 @@ import { check, validationResult, query } from './validator/index.js'; import { Credentials } from '../services/credentials.js'; import { IdentityServiceStrategySetup } from '../services/identity/index.js'; -import type { ITrackOperation } from '../types/shared.js'; +import type { ITrackOperation, ValidationErrorResponseBody } from '../types/shared.js'; import { Cheqd } from '@cheqd/did-provider-cheqd'; import { OPERATION_CATEGORY_NAME_CREDENTIAL } from '../types/constants.js'; import { CheqdW3CVerifiableCredential } from '../services/w3c-credential.js'; import { isCredentialIssuerDidDeactivated } from '../services/helpers.js'; +import type { + IssueCredentialRequestBody, + IssueCredentialResponseBody, + RevokeCredentialRequestBody, + RevokeCredentialRequestQuery, + RevokeCredentialResponseBody, + SuspendCredentialRequestBody, + SuspendCredentialRequestQuery, + SuspendCredentialResponseBody, + UnsuccesfulIssueCredentialResponseBody, + UnsuccesfulRevokeCredentialResponseBody, + UnsuccesfulSuspendCredentialResponseBody, + UnsuccesfulUnsuspendCredentialResponseBody, + UnsuccesfulVerifyCredentialResponseBody, + UnsuspendCredentialRequestBody, + UnsuspendCredentialRequestQuery, + UnsuspendCredentialResponseBody, + VerifyCredentialRequestBody, + VerifyCredentialRequestQuery, + VerifyCredentialResponseBody, +} from '../types/credential.js'; import { VeridaDIDValidator } from './validator/did.js'; export class CredentialController { @@ -44,7 +65,24 @@ export class CredentialController { .withMessage('W3c verifiable credential was not provided') .isW3CCheqdCredential() .bail(), - query('verifyStatus').optional().isBoolean().withMessage('verifyStatus should be a boolean value').bail(), + query('verifyStatus') + .optional() + .isBoolean() + .withMessage('verifyStatus should be a boolean value') + .toBoolean() + .bail(), + query('fetchRemoteContexts') + .optional() + .isBoolean() + .withMessage('fetchRemoteContexts should be a boolean value') + .toBoolean() + .bail(), + query('allowDeactivatedDid') + .optional() + .isBoolean() + .withMessage('allowDeactivatedDid should be a boolean value') + .toBoolean() + .bail(), query('policies').optional().isObject().withMessage('Verification policies should be an object').bail(), ]; public static revokeValidator = [ @@ -53,7 +91,7 @@ export class CredentialController { .withMessage('W3c verifiable credential was not provided') .isW3CCheqdCredential() .bail(), - query('publish').optional().isBoolean().withMessage('publish should be a boolean value').bail(), + query('publish').optional().isBoolean().withMessage('publish should be a boolean value').toBoolean().bail(), ]; public static suspendValidator = [ check('credential') @@ -62,7 +100,7 @@ export class CredentialController { .bail() .isW3CCheqdCredential() .bail(), - query('publish').optional().isBoolean().withMessage('publish should be a boolean value').bail(), + query('publish').optional().isBoolean().withMessage('publish should be a boolean value').toBoolean().bail(), ]; public static reinstateValidator = [ @@ -71,7 +109,7 @@ export class CredentialController { .withMessage('W3c verifiable credential was not provided') .isW3CCheqdCredential() .bail(), - query('publish').optional().isBoolean().withMessage('publish should be a boolean value').bail(), + query('publish').optional().isBoolean().withMessage('publish should be a boolean value').toBoolean().bail(), ]; /** @@ -109,15 +147,20 @@ export class CredentialController { const result = validationResult(request); // handle error if (!result.isEmpty()) { - return response.status(StatusCodes.BAD_REQUEST).json({ error: result.array().pop()?.msg }); + return response.status(StatusCodes.BAD_REQUEST).json({ + error: result.array().pop()?.msg, + } satisfies ValidationErrorResponseBody); } + // Get request body + const requestBody = request.body as IssueCredentialRequestBody; + // Handles string input instead of an array - if (typeof request.body.type === 'string') { - request.body.type = [request.body.type]; + if (typeof requestBody.type === 'string') { + requestBody.type = [requestBody.type]; } - if (typeof request.body['@context'] === 'string') { - request.body['@context'] = [request.body['@context']]; + if (typeof requestBody['@context'] === 'string') { + requestBody['@context'] = [requestBody['@context']]; } // Get strategy e.g. postgres or local @@ -125,27 +168,29 @@ export class CredentialController { try { // resolve issuer DID-Document - const resolvedResult = await identityServiceStrategySetup.agent.resolve(request.body.issuerDid); + const resolvedResult = await identityServiceStrategySetup.agent.resolve(requestBody.issuerDid); // check if DID-Document is resolved const body = await resolvedResult.json(); if (!body?.didDocument) { - return response.status(resolvedResult.status).send({ body }); + return response.status(StatusCodes.BAD_REQUEST).send({ + error: `DID ${requestBody.issuerDid} is not resolved because of error from resolver: ${body.didResolutionMetadata.error}.`, + } satisfies UnsuccesfulIssueCredentialResponseBody); } if (body.didDocumentMetadata.deactivated) { return response.status(StatusCodes.BAD_REQUEST).send({ - error: `${request.body.issuerDid} is deactivated`, - }); + error: `${requestBody.issuerDid} is deactivated`, + } satisfies UnsuccesfulIssueCredentialResponseBody); } // issue credential const credential: VerifiableCredential = await Credentials.instance.issue_credential( - request.body, + requestBody, response.locals.customer ); - return response.status(StatusCodes.OK).json(credential); + return response.status(StatusCodes.OK).json(credential satisfies IssueCredentialResponseBody); } catch (error) { return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ error: `Internal error: ${(error as Error)?.message || error}`, - }); + } satisfies UnsuccesfulIssueCredentialResponseBody); } } @@ -204,12 +249,16 @@ export class CredentialController { const result = validationResult(request); // handle error if (!result.isEmpty()) { - return response.status(StatusCodes.BAD_REQUEST).json({ error: result.array().pop()?.msg }); + return response.status(StatusCodes.BAD_REQUEST).json({ + error: result.array().pop()?.msg, + } satisfies ValidationErrorResponseBody); } + // Get params from request - const { credential, policies } = request.body; - const verifyStatus = request.query.verifyStatus === 'true'; - const allowDeactivatedDid = request.query.allowDeactivatedDid === 'true'; + const { credential, policies } = request.body as VerifyCredentialRequestBody; + const { verifyStatus, allowDeactivatedDid } = request.query as VerifyCredentialRequestQuery; + + // Create credential object const cheqdCredential = new CheqdW3CVerifiableCredential(credential); // Get strategy e.g. postgres or local const identityServiceStrategySetup = new IdentityServiceStrategySetup(); @@ -218,7 +267,7 @@ export class CredentialController { if (!allowDeactivatedDid && (await isCredentialIssuerDidDeactivated(cheqdCredential))) { return response.status(StatusCodes.BAD_REQUEST).json({ error: `Credential issuer DID is deactivated`, - }); + } satisfies UnsuccesfulVerifyCredentialResponseBody); } const verifyResult = await identityServiceStrategySetup.agent.verifyCredential( @@ -229,17 +278,18 @@ export class CredentialController { }, response.locals.customer ); + if (verifyResult.error) { return response.status(StatusCodes.BAD_REQUEST).json({ verified: verifyResult.verified, - error: verifyResult.error.message, - }); + error: `verify: ${verifyResult.error.message}`, + } satisfies UnsuccesfulVerifyCredentialResponseBody); } - return response.status(StatusCodes.OK).json(verifyResult); + return response.status(StatusCodes.OK).json(verifyResult satisfies VerifyCredentialResponseBody); } catch (error) { return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ error: `Internal error: ${(error as Error)?.message || error}`, - }); + } satisfies UnsuccesfulVerifyCredentialResponseBody); } } @@ -287,22 +337,25 @@ export class CredentialController { const result = validationResult(request); // handle error if (!result.isEmpty()) { - return response.status(StatusCodes.BAD_REQUEST).json({ error: result.array().pop()?.msg }); + return response.status(StatusCodes.BAD_REQUEST).json({ + error: result.array().pop()?.msg, + } satisfies UnsuccesfulRevokeCredentialResponseBody); } // Get publish flag - const publish = request.query.publish === 'false' ? false : true; + const { publish } = request.query as RevokeCredentialRequestQuery; // Get symmetric key - const symmetricKey = request.body.symmetricKey as string; + const { credential, symmetricKey } = request.body as RevokeCredentialRequestBody; // Get strategy e.g. postgres or local const identityServiceStrategySetup = new IdentityServiceStrategySetup(response.locals.customer.customerId); try { const result = await identityServiceStrategySetup.agent.revokeCredentials( - request.body.credential, - publish, + credential, + publish as boolean, response.locals.customer, - symmetricKey + symmetricKey as string ); + // Track operation if revocation was successful and publish is true // Otherwise the StatusList2021 publisher should manually publish the resource // and it will be tracked there @@ -341,11 +394,11 @@ export class CredentialController { } } // Return Ok response - return response.status(StatusCodes.OK).json(result); + return response.status(StatusCodes.OK).json(result satisfies RevokeCredentialResponseBody); } catch (error) { return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ error: `Internal error: ${(error as Error)?.message || error}`, - }); + } satisfies UnsuccesfulRevokeCredentialResponseBody); } } @@ -391,22 +444,25 @@ export class CredentialController { const result = validationResult(request); // handle error if (!result.isEmpty()) { - return response.status(StatusCodes.BAD_REQUEST).json({ error: result.array().pop()?.msg }); + return response.status(StatusCodes.BAD_REQUEST).json({ + error: result.array().pop()?.msg, + } satisfies UnsuccesfulSuspendCredentialResponseBody); } // Get publish flag - const publish = request.query.publish === 'false' ? false : true; + const { publish } = request.query as SuspendCredentialRequestQuery; // Get symmetric key - const symmetricKey = request.body.symmetricKey as string; + const { credential, symmetricKey } = request.body as SuspendCredentialRequestBody; + // Get strategy e.g. postgres or local const identityServiceStrategySetup = new IdentityServiceStrategySetup(response.locals.customer.customerId); try { const result = await identityServiceStrategySetup.agent.suspendCredentials( - request.body.credential, - publish, + credential, + publish as boolean, response.locals.customer, - symmetricKey + symmetricKey as string ); // Track operation if suspension was successful and publish is true @@ -447,11 +503,11 @@ export class CredentialController { } } - return response.status(StatusCodes.OK).json(result); + return response.status(StatusCodes.OK).json(result satisfies SuspendCredentialResponseBody); } catch (error) { return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ error: `Internal error: ${(error as Error)?.message || error}`, - }); + } satisfies UnsuccesfulSuspendCredentialResponseBody); } } @@ -497,22 +553,25 @@ export class CredentialController { const result = validationResult(request); // handle error if (!result.isEmpty()) { - return response.status(StatusCodes.BAD_REQUEST).json({ error: result.array().pop()?.msg }); + return response.status(StatusCodes.BAD_REQUEST).json({ + error: result.array().pop()?.msg, + } satisfies UnsuccesfulUnsuspendCredentialResponseBody); } // Get publish flag - const publish = request.query.publish === 'false' ? false : true; + const { publish } = request.query as UnsuspendCredentialRequestQuery; // Get symmetric key - const symmetricKey = request.body.symmetricKey as string; + const { credential, symmetricKey } = request.body as UnsuspendCredentialRequestBody; // Get strategy e.g. postgres or local const identityServiceStrategySetup = new IdentityServiceStrategySetup(response.locals.customer.customerId); try { const result = await identityServiceStrategySetup.agent.reinstateCredentials( - request.body.credential, - publish, + credential, + publish as boolean, response.locals.customer, - symmetricKey + symmetricKey as string ); + // Track operation if the process of reinstantiating was successful and publish is true // Otherwise the StatusList2021 publisher should manually publish the resource // and it will be tracked there @@ -551,11 +610,11 @@ export class CredentialController { } } // Return Ok response - return response.status(StatusCodes.OK).json(result); + return response.status(StatusCodes.OK).json(result satisfies UnsuspendCredentialResponseBody); } catch (error) { return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ error: `Internal error: ${(error as Error)?.message || error}`, - }); + } satisfies UnsuccesfulUnsuspendCredentialResponseBody); } } } diff --git a/src/controllers/did.ts b/src/controllers/did.ts index f0cfea28..3305922c 100644 --- a/src/controllers/did.ts +++ b/src/controllers/did.ts @@ -5,7 +5,6 @@ import { DIDDocument, MethodSpecificIdAlgo, Service, - VerificationMethod, VerificationMethods, createDidVerificationMethod, } from '@cheqd/sdk'; @@ -14,14 +13,32 @@ import { IdentityServiceStrategySetup } from '../services/identity/index.js'; import { decryptPrivateKey, generateDidDoc, getQueryParams } from '../helpers/helpers.js'; import { bases } from 'multiformats/basics'; import { base64ToBytes } from 'did-jwt'; -import type { CreateDidRequestBody, KeyImportRequest } from '../types/did.js'; - +import type { + CreateDidRequestBody, + CreateDidResponseBody, + DeactivateDidResponseBody, + ListDidsResponseBody, + QueryDidResponseBody, + ResolveDidResponseBody, + UnsuccessfulCreateDidResponseBody, + UnsuccessfulDeactivateDidResponseBody, + UnsuccessfulGetDidResponseBody, + UnsuccessfulResolveDidResponseBody, + UnsuccessfulUpdateDidResponseBody, + UpdateDidResponseBody, + UpdateDidRequestBody, + ImportDidRequestBody, + DeactivateDIDRequestParams, + GetDIDRequestParams, + ResolveDIDRequestParams, +} from '../types/did.js'; import { check, validationResult, param } from './validator/index.js'; import type { IKey, RequireOnly } from '@veramo/core'; import { extractPublicKeyHex } from '@veramo/utils'; +import type { ValidationErrorResponseBody } from '../types/shared.js'; +import type { KeyImport } from '../types/key.js'; export class DIDController { - // ToDo: improve validation in a "bail" fashion public static createDIDValidator = [ check('didDocument').optional().isObject().withMessage('Should be JSON object').bail().isDIDDocument(), check('verificationMethodType') @@ -88,14 +105,16 @@ export class DIDController { .withMessage('Keys should be an array of KeyImportRequest objects used in the DID-VerificationMethod') .custom((value) => { return value.every( - (item: KeyImportRequest) => + (item: KeyImport) => item.privateKeyHex && typeof item.encrypted === 'boolean' && - (item.encrypted === true ? item.ivHex && item.salt : true) + (item.encrypted === true ? item.ivHex && item.salt : true) && + typeof item.type === 'string' && + (item.type === 'Ed25519' || item.type === 'Secp256k1') ); }) .withMessage( - 'KeyImportRequest object is invalid, privateKeyHex is required, Property ivHex, salt is required when encrypted is set to true' + 'KeyImportRequest object is invalid, privateKeyHex is required, Property ivHex, salt is required when encrypted is set to true, property type should be Ed25519 or Secp256k1' ) .bail(), ]; @@ -148,7 +167,9 @@ export class DIDController { // handle error if (!result.isEmpty()) { - return response.status(StatusCodes.BAD_REQUEST).json({ error: result.array().pop()?.msg }); + return response.status(StatusCodes.BAD_REQUEST).json({ + error: result.array().pop()?.msg, + } satisfies ValidationErrorResponseBody); } // handle request params @@ -182,7 +203,7 @@ export class DIDController { } else { return response.status(StatusCodes.BAD_REQUEST).json({ error: 'Provide options section to create a DID', - }); + } satisfies UnsuccessfulCreateDidResponseBody); } } else if (verificationMethodType) { const publicKeyHex = @@ -219,7 +240,7 @@ export class DIDController { } catch (e) { return response.status(StatusCodes.BAD_REQUEST).json({ error: 'Provide the correct service section to create a DID', - }); + } satisfies UnsuccessfulCreateDidResponseBody); } } else { didDocument.service = [ @@ -234,7 +255,7 @@ export class DIDController { } else { return response.status(StatusCodes.BAD_REQUEST).json({ error: 'Provide a DID Document or the VerificationMethodType to create a DID', - }); + } satisfies UnsuccessfulCreateDidResponseBody); } const did = await new IdentityServiceStrategySetup(response.locals.customer.customerId).agent.createDid( @@ -242,11 +263,11 @@ export class DIDController { didDocument, response.locals.customer ); - return response.status(StatusCodes.OK).json(did); + return response.status(StatusCodes.OK).json(did satisfies CreateDidResponseBody); } catch (error) { return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ error: `Internal error: ${(error as Error)?.message || error}`, - }); + } satisfies UnsuccessfulCreateDidResponseBody); } } @@ -286,32 +307,27 @@ export class DIDController { // handle error if (!result.isEmpty()) { - return response.status(StatusCodes.BAD_REQUEST).json({ error: result.array().pop()?.msg }); + return response.status(StatusCodes.BAD_REQUEST).json({ + error: result.array().pop()?.msg, + } satisfies ValidationErrorResponseBody); } // handle request params - const { did, service, verificationMethod, authentication } = request.body as { - did: string; - service: Service[]; - verificationMethod: VerificationMethod[]; - authentication: string[]; - }; - let updatedDocument: DIDDocument; + const { did, service, verificationMethod, authentication } = request.body as UpdateDidRequestBody; + // Get the didDocument from the request if it's placed there + let updatedDocument: DIDDocument | undefined = request.body.didDocument; // Get strategy e.g. postgres or local const identityServiceStrategySetup = new IdentityServiceStrategySetup(response.locals.customer.customerId); try { - if (request.body.didDocument) { - // Just pass the didDocument from the user as is - updatedDocument = request.body.didDocument; - } else if (did && (service || verificationMethod || authentication)) { + if (!updatedDocument && did && (service || verificationMethod || authentication)) { // Resolve DID const resolvedResult = await identityServiceStrategySetup.agent.resolveDid(did); // Check output that DID is not deactivated or exist if (!resolvedResult?.didDocument || resolvedResult.didDocumentMetadata.deactivated) { return response.status(StatusCodes.BAD_REQUEST).send({ error: `${did} is either Deactivated or Not found`, - }); + } satisfies UnsuccessfulUpdateDidResponseBody); } // Fill up the DID Document with updated sections const resolvedDocument = resolvedResult.didDocument; @@ -331,18 +347,18 @@ export class DIDController { } else { return response.status(StatusCodes.BAD_REQUEST).json({ error: 'Provide a DID Document or atleast one field to update', - }); + } satisfies UnsuccessfulUpdateDidResponseBody); } const result = await identityServiceStrategySetup.agent.updateDid( updatedDocument, response.locals.customer ); - return response.status(StatusCodes.OK).json(result); + return response.status(StatusCodes.OK).json(result satisfies UpdateDidResponseBody); } catch (error) { return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ error: `Internal error: ${(error as Error)?.message || error}`, - }); + } satisfies UnsuccessfulUpdateDidResponseBody); } } @@ -394,12 +410,17 @@ export class DIDController { // handle error if (!result.isEmpty()) { - return response.status(StatusCodes.BAD_REQUEST).json({ error: result.array().pop()?.msg }); + return response.status(StatusCodes.BAD_REQUEST).json({ + error: result.array().pop()?.msg, + } satisfies ValidationErrorResponseBody); } try { - const { did, controllerKeyId, keys } = request.body; + // Get the params from body + const { did, controllerKeyId, keys } = request.body as ImportDidRequestBody; + // Resolve the didDocument from the ledger const { didDocument } = await new IdentityServiceStrategySetup().agent.resolveDid(did); + // Check if the didDocument is valid if (!didDocument || !didDocument.verificationMethod || didDocument.verificationMethod.length === 0) { return response.status(StatusCodes.BAD_REQUEST).json({ error: `Invalid request: Invalid did document for ${did}`, @@ -416,7 +437,7 @@ export class DIDController { // import keys keysToImport.push( ...(await Promise.all( - keys.map(async (key: any) => { + keys.map(async (key: KeyImport) => { const { type, encrypted, ivHex, salt } = key; let { privateKeyHex } = key; if (encrypted) { @@ -491,30 +512,28 @@ export class DIDController { // handle error if (!result.isEmpty()) { - return response.status(StatusCodes.BAD_REQUEST).json({ error: result.array().pop()?.msg }); + return response.status(StatusCodes.BAD_REQUEST).json({ + error: result.array().pop()?.msg, + } satisfies ValidationErrorResponseBody); } + // Extract did from request params + const { did } = request.params as DeactivateDIDRequestParams; + // Get strategy e.g. postgres or local const identityServiceStrategySetup = new IdentityServiceStrategySetup(response.locals.customer.customerId); try { // Deactivate DID - const deactivated = await identityServiceStrategySetup.agent.deactivateDid( - request.params.did, - response.locals.customer - ); - - if (!deactivated) { - return response.status(StatusCodes.BAD_REQUEST).json({ deactivated: false }); - } + await identityServiceStrategySetup.agent.deactivateDid(did, response.locals.customer); // Send the deactivated DID as result const result = await identityServiceStrategySetup.agent.resolveDid(request.params.did); - return response.status(StatusCodes.OK).json(result); + return response.status(StatusCodes.OK).json(result satisfies DeactivateDidResponseBody); } catch (error) { return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ error: `Internal error: ${(error as Error)?.message || error}`, - }); + } satisfies UnsuccessfulDeactivateDidResponseBody); } } @@ -543,18 +562,23 @@ export class DIDController { * $ref: '#/components/schemas/InternalError' */ public async getDids(request: Request, response: Response) { + // Extract did from params + const { did } = request.params as GetDIDRequestParams; // Get strategy e.g. postgres or local const identityServiceStrategySetup = new IdentityServiceStrategySetup(response.locals.customer.customerId); + try { - const did = request.params.did + const didDocument = did ? await identityServiceStrategySetup.agent.resolveDid(request.params.did) : await identityServiceStrategySetup.agent.listDids(response.locals.customer); - return response.status(StatusCodes.OK).json(did); + return response + .status(StatusCodes.OK) + .json(didDocument satisfies ListDidsResponseBody | QueryDidResponseBody); } catch (error) { return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ error: `Internal error: ${(error as Error)?.message || error}`, - }); + } satisfies UnsuccessfulGetDidResponseBody); } } @@ -631,9 +655,11 @@ export class DIDController { public async resolveDidUrl(request: Request, response: Response) { // Get strategy e.g. postgres or local const identityServiceStrategySetup = new IdentityServiceStrategySetup(); + // Extract did from params + const { did } = request.params as ResolveDIDRequestParams; try { let res: globalThis.Response; - if (request.params.did) { + if (did) { res = await identityServiceStrategySetup.agent.resolve( request.params.did + getQueryParams(request.query) ); @@ -641,16 +667,19 @@ export class DIDController { const contentType = res.headers.get('Content-Type') || 'application/octet-stream'; const body = new TextDecoder().decode(await res.arrayBuffer()); - return response.setHeader('Content-Type', contentType).status(res.status).send(body); + return response + .setHeader('Content-Type', contentType) + .status(res.status) + .send(body satisfies ResolveDidResponseBody); } else { return response.status(StatusCodes.BAD_REQUEST).json({ error: 'The DIDUrl parameter is empty.', - }); + } satisfies UnsuccessfulResolveDidResponseBody); } } catch (error) { return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ error: `Internal error: ${(error as Error)?.message || error}`, - }); + } satisfies UnsuccessfulResolveDidResponseBody); } } } diff --git a/src/controllers/key.ts b/src/controllers/key.ts index 03af7394..9c0b26e8 100644 --- a/src/controllers/key.ts +++ b/src/controllers/key.ts @@ -3,19 +3,39 @@ import { StatusCodes } from 'http-status-codes'; import { IdentityServiceStrategySetup } from '../services/identity/index.js'; import { decryptPrivateKey } from '../helpers/helpers.js'; import { toString } from 'uint8arrays'; -import { check } from 'express-validator'; +import type { + CreateKeyResponseBody, + GetKeyRequestBody, + ImportKeyRequestBody, + ImportKeyResponseBody, + QueryKeyResponseBody, + UnsuccessfulCreateKeyResponseBody, + UnsuccessfulImportKeyResponseBody, + UnsuccessfulQueryKeyResponseBody, +} from '../types/key.js'; +import { check } from './validator/index.js'; +// ToDo: Make the format of /key/create and /key/read the same +// ToDo: Add valdiation for /key/import export class KeyController { - public static importKeyValidator = [ - check('privateKeyHex').isString().withMessage('privateKeyHex is required').bail(), + public static keyImportValidator = [ + check('privateKeyHex') + .exists() + .withMessage('Private key was not provided') + .isHexadecimal() + .withMessage('Private key should be a hexadecimal string') + .bail(), check('encrypted') .isBoolean() .withMessage('encrypted is required') .custom((value, { req }) => (value === true ? req.body.ivHex && req.body.salt : true)) .withMessage('Property ivHex, salt is required when encrypted is set to true') .bail(), + check('ivHex').optional().isHexadecimal().withMessage('ivHex should be a hexadecimal string').bail(), + check('salt').optional().isHexadecimal().withMessage('salt should be a hexadecimal string').bail(), + check('type').optional().isString().withMessage('type should be a string').bail(), + check('alias').optional().isString().withMessage('alias should be a string').bail(), ]; - /** * @openapi * @@ -55,11 +75,11 @@ export class KeyController { const identityServiceStrategySetup = new IdentityServiceStrategySetup(response.locals.customer.customerId); try { const key = await identityServiceStrategySetup.agent.createKey('Ed25519', response.locals.customer); - return response.status(StatusCodes.OK).json(key); + return response.status(StatusCodes.OK).json(key satisfies CreateKeyResponseBody); } catch (error) { return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ - error: `${error}`, - }); + error: `Internal error: ${(error as Error)?.message || error}`, + } satisfies UnsuccessfulCreateKeyResponseBody); } } @@ -106,29 +126,33 @@ export class KeyController { * error: Internal Error */ public async importKey(request: Request, response: Response) { + // Get parameters requeired for key importing + const { type, encrypted, ivHex, salt, alias, privateKeyHex } = request.body as ImportKeyRequestBody; + // Get strategy e.g. postgres or local + const identityServiceStrategySetup = new IdentityServiceStrategySetup(response.locals.customer.customerId); + let decryptedPrivateKeyHex = privateKeyHex; + try { - const { type, encrypted, ivHex, salt, alias } = request.body; - let { privateKeyHex } = request.body; if (encrypted) { if (ivHex && salt) { - privateKeyHex = toString(await decryptPrivateKey(privateKeyHex, ivHex, salt), 'hex'); + decryptedPrivateKeyHex = toString(await decryptPrivateKey(privateKeyHex, ivHex, salt), 'hex'); } else { return response.status(StatusCodes.BAD_REQUEST).json({ error: `Invalid request: Property ivHex, salt is required when encrypted is set to true`, - }); + } satisfies UnsuccessfulImportKeyResponseBody); } } - const key = await new IdentityServiceStrategySetup(response.locals.customer.customerId).agent.importKey( + const key = await identityServiceStrategySetup.agent.importKey( type || 'Ed25519', - privateKeyHex, + decryptedPrivateKeyHex, response.locals.customer, alias ); - return response.status(StatusCodes.OK).json(key); + return response.status(StatusCodes.OK).json(key satisfies ImportKeyResponseBody); } catch (error) { return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ error: `Internal error: ${(error as Error)?.message || error}`, - }); + } satisfies UnsuccessfulImportKeyResponseBody); } } @@ -174,20 +198,21 @@ export class KeyController { * error: Internal Error */ public async getKey(request: Request, response: Response) { + const { kid } = request.params as GetKeyRequestBody; // Get strategy e.g. postgres or local const identityServiceStrategySetup = new IdentityServiceStrategySetup(response.locals.customer.customerId); try { - const key = await identityServiceStrategySetup.agent.getKey(request.params.kid, response.locals.customer); + const key = await identityServiceStrategySetup.agent.getKey(kid, response.locals.customer); if (key) { - return response.status(StatusCodes.OK).json(key); + return response.status(StatusCodes.OK).json(key satisfies QueryKeyResponseBody); } return response.status(StatusCodes.NOT_FOUND).json({ - error: `Key with kid: ${request.params.kid} not found`, - }); + error: `Key with kid: ${kid} not found`, + } satisfies UnsuccessfulQueryKeyResponseBody); } catch (error) { return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ error: `${error}`, - }); + } satisfies UnsuccessfulQueryKeyResponseBody); } } } diff --git a/src/controllers/presentation.ts b/src/controllers/presentation.ts index c333bd2b..5a73309f 100644 --- a/src/controllers/presentation.ts +++ b/src/controllers/presentation.ts @@ -4,8 +4,17 @@ import { StatusCodes } from 'http-status-codes'; import { check, validationResult, query } from './validator/index.js'; import { IdentityServiceStrategySetup } from '../services/identity/index.js'; import { CheqdW3CVerifiablePresentation } from '../services/w3c-presentation.js'; -import type { VerifyPresentationResponseBody } from '../types/presentation.js'; +import type { + CreatePresentationRequestBody, + CreatePresentationResponseBody, + UnsuccessfulCreatePresentationResponseBody, + UnsuccessfulVerifyCredentialResponseBody, + VerifyPresentationRequestBody, + VerifyPresentationResponseBody, + VerifyPresentationResponseQuery, +} from '../types/presentation.js'; import { isIssuerDidDeactivated } from '../services/helpers.js'; +import type { ValidationErrorResponseBody } from '../types/shared.js'; export class PresentationController { public static presentationCreateValidator = [ @@ -27,8 +36,30 @@ export class PresentationController { .bail(), check('verifierDid').optional().isDID().bail(), check('policies').optional().isObject().withMessage('Verification policies should be an object').bail(), - check('makeFeePayment').optional().isBoolean().withMessage('makeFeePayment: should be a boolean').bail(), - query('verifyStatus').optional().isBoolean().withMessage('verifyStatus should be a boolean value').bail(), + check('makeFeePayment') + .optional() + .isBoolean() + .withMessage('makeFeePayment: should be a boolean') + .toBoolean() + .bail(), + query('verifyStatus') + .optional() + .isBoolean() + .withMessage('verifyStatus should be a boolean value') + .toBoolean() + .bail(), + query('allowDeactivatedDid') + .optional() + .isBoolean() + .withMessage('allowDeactivatedDid should be a boolean value') + .toBoolean() + .bail(), + query('fetchRemoteContexts') + .optional() + .isBoolean() + .withMessage('fetchRemoteContexts should be a boolean value') + .toBoolean() + .bail(), ]; /** @@ -63,12 +94,16 @@ export class PresentationController { */ public async createPresentation(request: Request, response: Response) { + // Validate request const result = validationResult(request); + // Handle validation error if (!result.isEmpty()) { - return response.status(StatusCodes.BAD_REQUEST).json({ error: result.array()[0].msg }); + return response.status(StatusCodes.BAD_REQUEST).json({ + error: result.array()[0].msg, + } satisfies ValidationErrorResponseBody); } - const { credentials, holderDid, verifierDid } = request.body; + const { credentials, holderDid, verifierDid } = request.body as CreatePresentationRequestBody; try { const result = await new IdentityServiceStrategySetup( @@ -85,15 +120,14 @@ export class PresentationController { ); if (result.error) { return response.status(StatusCodes.BAD_REQUEST).json({ - presentation: result.presentation, error: result.error, - }); + } satisfies UnsuccessfulCreatePresentationResponseBody); } - return response.status(StatusCodes.OK).json(result); + return response.status(StatusCodes.OK).json(result satisfies CreatePresentationResponseBody); } catch (error) { return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ error: `Internal error: ${(error as Error)?.message || error}`, - }); + } satisfies UnsuccessfulCreatePresentationResponseBody); } } @@ -149,12 +183,15 @@ export class PresentationController { public async verifyPresentation(request: Request, response: Response) { const result = validationResult(request); if (!result.isEmpty()) { - return response.status(StatusCodes.BAD_REQUEST).json({ error: result.array()[0].msg }); + return response.status(StatusCodes.BAD_REQUEST).json({ + error: result.array()[0].msg, + } satisfies UnsuccessfulVerifyCredentialResponseBody); } - const { presentation, verifierDid, policies, makeFeePayment } = request.body; - const verifyStatus = request.query.verifyStatus === 'true'; - const allowDeactivatedDid = request.query.allowDeactivatedDid === 'true'; + // Extract request parameters from body + const { presentation, verifierDid, policies, makeFeePayment } = request.body as VerifyPresentationRequestBody; + // Extract request parameters from query + const { verifyStatus, allowDeactivatedDid } = request.query as VerifyPresentationResponseQuery; // Get strategy e.g. postgres or local const identityServiceStrategySetup = new IdentityServiceStrategySetup(response.locals.customer.customerId); @@ -166,7 +203,7 @@ export class PresentationController { if (setResult.error) { return response.status(setResult.status).send({ error: setResult.error, - }); + } satisfies UnsuccessfulVerifyCredentialResponseBody); } if (cheqdPresentation.isPaymentNeeded()) { const feePaymentResult = await cheqdPresentation.makeFeePayment( @@ -175,9 +212,8 @@ export class PresentationController { ); if (feePaymentResult.error) { return response.status(StatusCodes.BAD_REQUEST).json({ - checked: false, error: `verify: payment: error: ${feePaymentResult.error}`, - }); + } satisfies UnsuccessfulVerifyCredentialResponseBody); } } } @@ -186,8 +222,9 @@ export class PresentationController { if (!allowDeactivatedDid && (await isIssuerDidDeactivated(cheqdPresentation))) { return response.status(StatusCodes.BAD_REQUEST).json({ error: `Credential issuer DID is deactivated`, - }); + } satisfies UnsuccessfulVerifyCredentialResponseBody); } + // verify presentation const result = await identityServiceStrategySetup.agent.verifyPresentation( cheqdPresentation, { @@ -197,40 +234,39 @@ export class PresentationController { }, response.locals.customer ); + // handle errors if (result.error) { return response.status(StatusCodes.BAD_REQUEST).json({ verified: result.verified, - error: result.error.message, - }); + error: `verify: ${result.error.message}`, + } satisfies UnsuccessfulVerifyCredentialResponseBody); } - return response.status(StatusCodes.OK).json(result); + return response.status(StatusCodes.OK).json(result satisfies VerifyPresentationResponseBody); } catch (error) { // define error const errorRef = error as Record; // handle doesn't meet condition if (errorRef?.errorCode === 'NodeAccessControlConditionsReturnedNotAuthorized') return response.status(StatusCodes.UNAUTHORIZED).json({ - verified: false, error: `check: error: ${ errorRef?.message ? 'unauthorised: decryption conditions are not met' : (error as Record).toString() }`, - } satisfies VerifyPresentationResponseBody); + } satisfies UnsuccessfulVerifyCredentialResponseBody); // handle incorrect access control conditions if (errorRef?.errorCode === 'incorrect_access_control_conditions') return response.status(StatusCodes.BAD_REQUEST).json({ - verified: false, error: `check: error: ${ errorRef?.message ? 'incorrect access control conditions' : (error as Record).toString() }`, - } satisfies VerifyPresentationResponseBody); + } satisfies UnsuccessfulVerifyCredentialResponseBody); // catch all other unhandled errors return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ error: `Internal error: ${(error as Error)?.message || error}`, - }); + } satisfies UnsuccessfulVerifyCredentialResponseBody); } } } diff --git a/src/controllers/resource.ts b/src/controllers/resource.ts index 4f06862a..4fb80fa5 100644 --- a/src/controllers/resource.ts +++ b/src/controllers/resource.ts @@ -6,9 +6,17 @@ import { StatusCodes } from 'http-status-codes'; import { IdentityServiceStrategySetup } from '../services/identity/index.js'; import { getQueryParams } from '../helpers/helpers.js'; import { DIDMetadataDereferencingResult, DefaultResolverUrl } from '@cheqd/did-provider-cheqd'; -import type { ITrackOperation } from '../types/shared.js'; +import type { ITrackOperation, ValidationErrorResponseBody } from '../types/shared.js'; import { OPERATION_CATEGORY_NAME_RESOURCE } from '../types/constants.js'; import { check, validationResult, param, query } from './validator/index.js'; +import type { + CreateResourceRequestBody, + CreateResourceResponseBody, + QueryResourceResponseBody, + SearchResourceRequestParams, + UnsuccessfulCreateResourceResponseBody, + UnsuccessfulQueryResourceResponseBody, +} from '../types/resource.js'; export class ResourceController { public static createResourceValidator = [ @@ -137,11 +145,16 @@ export class ResourceController { // handle error if (!result.isEmpty()) { - return response.status(StatusCodes.BAD_REQUEST).json({ error: result.array().pop()?.msg }); + return response.status(StatusCodes.BAD_REQUEST).json({ + error: result.array().pop()?.msg, + } satisfies ValidationErrorResponseBody); } + // Extract the did from the request const { did } = request.params; - const { data, encoding, name, type, alsoKnownAs, version, network } = request.body; + // Extract the resource parameters from the request + const { data, encoding, name, type, alsoKnownAs, version, network } = request.body as CreateResourceRequestBody; + // Get strategy e.g. postgres or local const identityServiceStrategySetup = new IdentityServiceStrategySetup(response.locals.customer.customerId); let resourcePayload: Partial = {}; @@ -151,7 +164,7 @@ export class ResourceController { if (!didDocument || !didDocumentMetadata || didDocumentMetadata.deactivated) { return response.status(StatusCodes.BAD_REQUEST).send({ error: `${did} is a either Deactivated or Not found`, - }); + } satisfies UnsuccessfulCreateResourceResponseBody); } resourcePayload = { @@ -201,16 +214,16 @@ export class ResourceController { return response.status(StatusCodes.CREATED).json({ resource, - }); + } satisfies CreateResourceResponseBody); } else { return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ error: 'Error creating resource', - }); + } satisfies UnsuccessfulCreateResourceResponseBody); } } catch (error) { return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ error: `${error}`, - }); + } satisfies UnsuccessfulCreateResourceResponseBody); } } @@ -293,30 +306,34 @@ export class ResourceController { // handle error if (!result.isEmpty()) { - return response.status(StatusCodes.BAD_REQUEST).json({ error: result.array().pop()?.msg }); + return response.status(StatusCodes.BAD_REQUEST).json({ + error: result.array().pop()?.msg, + } satisfies ValidationErrorResponseBody); } + const { did } = request.params as SearchResourceRequestParams; // Get strategy e.g. postgres or local const identityServiceStrategySetup = new IdentityServiceStrategySetup(); try { let res: globalThis.Response; - if (request.params.did) { - res = await identityServiceStrategySetup.agent.resolve( - request.params.did + getQueryParams(request.query) - ); + if (did) { + res = await identityServiceStrategySetup.agent.resolve(did + getQueryParams(request.query)); const contentType = res.headers.get('Content-Type') || 'application/octet-stream'; const body = new TextDecoder().decode(await res.arrayBuffer()); - return response.setHeader('Content-Type', contentType).status(res.status).send(body); + return response + .setHeader('Content-Type', contentType) + .status(res.status) + .send(body satisfies QueryResourceResponseBody); } else { return response.status(StatusCodes.BAD_REQUEST).json({ error: 'The DID parameter is empty.', - }); + } satisfies UnsuccessfulQueryResourceResponseBody); } } catch (error) { return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ error: `${error}`, - }); + } satisfies UnsuccessfulQueryResourceResponseBody); } } } diff --git a/src/controllers/validator/index.ts b/src/controllers/validator/index.ts index 2dd7d178..1fa5beef 100644 --- a/src/controllers/validator/index.ts +++ b/src/controllers/validator/index.ts @@ -1,5 +1,5 @@ import { ExpressValidator } from 'express-validator'; -import { DIDValidator, KeyDIDValidator } from './did.js'; +import { DIDValidator, KeyDIDValidator, VeridaDIDValidator } from './did.js'; import { DIDDocumentValidator } from './did-document.js'; import type { Validatable } from './validator.js'; import type { Service, VerificationMethod } from 'did-resolver'; @@ -85,4 +85,12 @@ export const { check, validationResult, query, param } = new ExpressValidator({ } return true; }, + + isVeridaDID: (value: Validatable) => { + const res = new VeridaDIDValidator().validate(value); + if (!res.valid) { + throw new Error(res.error); + } + return true; + }, }); diff --git a/src/middleware/authentication.ts b/src/middleware/authentication.ts index d48f62f6..3322c7fd 100644 --- a/src/middleware/authentication.ts +++ b/src/middleware/authentication.ts @@ -157,7 +157,7 @@ export class Authentication { }); } customer = user.customer; - } + } if (_resp.data.customerId !== '' && !customer) { customer = await CustomerService.instance.get(_resp.data.customerId); if (!customer) { @@ -169,7 +169,7 @@ export class Authentication { if (!customer && !user && !this.isBootstrapping(request)) { return response.status(StatusCodes.UNAUTHORIZED).json({ error: `Looks like customer and user are not found in the system or they are not registered yet. Please contact administrator.`, - }) + }); } response.locals.customer = customer; response.locals.user = user; diff --git a/src/services/identity/abstract.ts b/src/services/identity/abstract.ts index 4ef972b8..996ef5df 100644 --- a/src/services/identity/abstract.ts +++ b/src/services/identity/abstract.ts @@ -11,6 +11,7 @@ import type { PresentationPayload, VerifiableCredential, VerifiablePresentation, + W3CVerifiableCredential, } from '@veramo/core'; import type { ResourcePayload, @@ -25,7 +26,7 @@ import type { TransactionResult, } from '@cheqd/did-provider-cheqd'; import type { ITrackOperation, ITrackResult, VeramoAgent } from '../../types/shared'; -import type { VerificationOptions } from '../../types/credential'; +import type { VerificationOptions } from '../../types/shared'; import type { FeePaymentOptions } from '../../types/credential-status'; import type { CredentialRequest } from '../../types/credential'; import type { CheckStatusListOptions } from '../../types/credential-status'; @@ -159,7 +160,7 @@ export abstract class AbstractIdentityService implements IIdentityService { throw new Error(`Not supported`); } revokeCredentials( - credential: VerifiableCredential | VerifiableCredential[], + credential: W3CVerifiableCredential | W3CVerifiableCredential[], publish: boolean, customer: CustomerEntity, symmetricKey: string @@ -167,7 +168,7 @@ export abstract class AbstractIdentityService implements IIdentityService { throw new Error(`Not supported`); } suspendCredentials( - credential: VerifiableCredential | VerifiableCredential[], + credential: W3CVerifiableCredential | W3CVerifiableCredential[], publish: boolean, customer: CustomerEntity, symmetricKey: string @@ -175,7 +176,7 @@ export abstract class AbstractIdentityService implements IIdentityService { throw new Error(`Not supported`); } reinstateCredentials( - credential: VerifiableCredential | VerifiableCredential[], + credential: W3CVerifiableCredential | W3CVerifiableCredential[], publish: boolean, customer: CustomerEntity, symmetricKey: string diff --git a/src/services/identity/agent.ts b/src/services/identity/agent.ts index b23306fa..e848577c 100644 --- a/src/services/identity/agent.ts +++ b/src/services/identity/agent.ts @@ -16,6 +16,7 @@ import { TAgent, VerifiableCredential, VerifiablePresentation, + W3CVerifiableCredential, } from '@veramo/core'; import { KeyManager } from '@veramo/key-manager'; import { DIDStore, KeyStore } from '@veramo/data-store'; @@ -52,7 +53,7 @@ import type { CheqdNetwork } from '@cheqd/sdk'; import { getDidKeyResolver as KeyDidResolver } from '@veramo/did-provider-key'; import { Resolver, ResolverRegistry } from 'did-resolver'; import { DefaultDidUrlPattern, CreateAgentRequest, VeramoAgent } from '../../types/shared.js'; -import type { VerificationOptions } from '../../types/credential.js'; +import type { VerificationOptions } from '../../types/shared.js'; import type { FeePaymentOptions } from '../../types/credential-status.js'; import type { CredentialRequest } from '../../types/credential.js'; import { DefaultStatusActions } from '../../types/credential-status.js'; @@ -204,11 +205,19 @@ export class Veramo { async deactivateDid(agent: VeramoAgent, did: string): Promise { try { const [kms] = await agent.keyManagerGetKeyManagementSystems(); - const didDocument = (await this.resolveDid(agent, did)).didDocument; + const didResolutionResult = await this.resolveDid(agent, did); + const didDocument = didResolutionResult.didDocument; + const didMetadata = didResolutionResult.didDocumentMetadata; if (!didDocument) { throw new Error('DID document not found'); } + + // check if DID is already deactivated. If yes - just return true + if (didMetadata.deactivated) { + return true; + } + const result = await agent.cheqdDeactivateIdentifier({ kms, document: didDocument, @@ -557,7 +566,7 @@ export class Veramo { async revokeCredentials( agent: VeramoAgent, - credentials: VerifiableCredential | VerifiableCredential[], + credentials: W3CVerifiableCredential | W3CVerifiableCredential[], publish = true, symmetricKey = '' ) { @@ -579,7 +588,7 @@ export class Veramo { async suspendCredentials( agent: VeramoAgent, - credentials: VerifiableCredential | VerifiableCredential[], + credentials: W3CVerifiableCredential | W3CVerifiableCredential[], publish = true, symmetricKey = '' ) { @@ -597,7 +606,7 @@ export class Veramo { async unsuspendCredentials( agent: VeramoAgent, - credentials: VerifiableCredential | VerifiableCredential[], + credentials: W3CVerifiableCredential | W3CVerifiableCredential[], publish = true, symmetricKey = '' ) { diff --git a/src/services/identity/default.ts b/src/services/identity/default.ts index a4c1455b..855f5b55 100644 --- a/src/services/identity/default.ts +++ b/src/services/identity/default.ts @@ -2,7 +2,7 @@ import type { DIDResolutionResult } from 'did-resolver'; import { AbstractIdentityService } from './abstract.js'; import type { IVerifyResult, VerifiableCredential, VerifiablePresentation } from '@veramo/core'; -import type { VerificationOptions } from '../../types/credential.js'; +import type { VerificationOptions } from '../../types/shared.js'; import type { FeePaymentOptions } from '../../types/credential-status.js'; import type { CheckStatusListOptions } from '../../types/credential-status.js'; import type { SearchStatusListResult } from '../../types/credential-status.js'; diff --git a/src/services/identity/index.ts b/src/services/identity/index.ts index ffbbfae2..28a35776 100644 --- a/src/services/identity/index.ts +++ b/src/services/identity/index.ts @@ -16,6 +16,7 @@ import type { TAgent, VerifiableCredential, VerifiablePresentation, + W3CVerifiableCredential, } from '@veramo/core'; import type { ResourcePayload, @@ -30,7 +31,7 @@ import type { TransactionResult, } from '@cheqd/did-provider-cheqd'; import type { ITrackOperation, ITrackResult, VeramoAgent } from '../../types/shared.js'; -import type { VerificationOptions } from '../../types/credential.js'; +import type { VerificationOptions } from '../../types/shared.js'; import type { FeePaymentOptions } from '../../types/credential-status.js'; import type { CredentialRequest } from '../../types/credential.js'; import type { CheckStatusListOptions } from '../../types/credential-status.js'; @@ -146,19 +147,19 @@ export interface IIdentityService { customer?: CustomerEntity ): Promise; revokeCredentials( - credential: VerifiableCredential | VerifiableCredential[], + credential: W3CVerifiableCredential | W3CVerifiableCredential[], publish: boolean, customer: CustomerEntity, symmetricKey: string ): Promise; suspendCredentials( - credential: VerifiableCredential | VerifiableCredential[], + credential: W3CVerifiableCredential | W3CVerifiableCredential[], publish: boolean, customer: CustomerEntity, symmetricKey: string ): Promise; reinstateCredentials( - credential: VerifiableCredential | VerifiableCredential[], + credential: W3CVerifiableCredential | W3CVerifiableCredential[], publish: boolean, customer: CustomerEntity, symmetricKey: string diff --git a/src/services/identity/local.ts b/src/services/identity/local.ts index fa9f9f97..e757b7f9 100644 --- a/src/services/identity/local.ts +++ b/src/services/identity/local.ts @@ -1,5 +1,11 @@ import * as dotenv from 'dotenv'; -import type { IIdentifier, CredentialPayload, VerifiableCredential, IVerifyResult } from '@veramo/core'; +import type { + IIdentifier, + CredentialPayload, + VerifiableCredential, + IVerifyResult, + W3CVerifiableCredential, +} from '@veramo/core'; import { MemoryPrivateKeyStore } from '@veramo/key-manager'; import { KeyManagementSystem } from '@veramo/kms-local'; import { @@ -16,7 +22,7 @@ import { LitNetworks, } from '@cheqd/did-provider-cheqd'; import { CheqdNetwork } from '@cheqd/sdk'; -import type { VerificationOptions } from '../../types/credential.js'; +import type { VerificationOptions } from '../../types/shared.js'; import type { FeePaymentOptions } from '../../types/credential-status.js'; import type { CredentialRequest } from '../../types/credential.js'; import type { CheckStatusListOptions } from '../../types/credential-status.js'; @@ -227,15 +233,15 @@ export class LocalIdentityService extends DefaultIdentityService { return await Veramo.instance.remunerateStatusList2021(this.initAgent(), feePaymentOptions); } - async revokeCredentials(credentials: VerifiableCredential | VerifiableCredential[], publish: boolean) { + async revokeCredentials(credentials: W3CVerifiableCredential | W3CVerifiableCredential[], publish: boolean) { return await Veramo.instance.revokeCredentials(this.initAgent(), credentials, publish); } - async suspendCredentials(credentials: VerifiableCredential | VerifiableCredential[], publish: boolean) { + async suspendCredentials(credentials: W3CVerifiableCredential | W3CVerifiableCredential[], publish: boolean) { return await Veramo.instance.suspendCredentials(this.initAgent(), credentials, publish); } - async reinstateCredentials(credentials: VerifiableCredential | VerifiableCredential[], publish: boolean) { + async reinstateCredentials(credentials: W3CVerifiableCredential | W3CVerifiableCredential[], publish: boolean) { return await Veramo.instance.unsuspendCredentials(this.initAgent(), credentials, publish); } } diff --git a/src/services/identity/postgres.ts b/src/services/identity/postgres.ts index e57ac051..b07cc692 100644 --- a/src/services/identity/postgres.ts +++ b/src/services/identity/postgres.ts @@ -7,6 +7,7 @@ import type { PresentationPayload, VerifiableCredential, VerifiablePresentation, + W3CVerifiableCredential, } from '@veramo/core'; import type { AbstractPrivateKeyStore } from '@veramo/key-manager'; import { KeyManagementSystem, SecretBox } from '@veramo/kms-local'; @@ -24,7 +25,7 @@ import { type TransactionResult, } from '@cheqd/did-provider-cheqd'; import { DefaultDidUrlPattern, VeramoAgent, ITrackResult, ITrackOperation } from '../../types/shared.js'; -import type { VerificationOptions } from '../../types/credential.js'; +import type { VerificationOptions } from '../../types/shared.js'; import type { FeePaymentOptions } from '../../types/credential-status.js'; import type { CredentialRequest } from '../../types/credential.js'; import type { CheckStatusListOptions } from '../../types/credential-status.js'; @@ -443,7 +444,7 @@ export class PostgresIdentityService extends DefaultIdentityService { } async revokeCredentials( - credentials: VerifiableCredential | VerifiableCredential[], + credentials: W3CVerifiableCredential | W3CVerifiableCredential[], publish: boolean, customer: CustomerEntity, symmetricKey: string @@ -454,7 +455,7 @@ export class PostgresIdentityService extends DefaultIdentityService { } async suspendCredentials( - credentials: VerifiableCredential | VerifiableCredential[], + credentials: W3CVerifiableCredential | W3CVerifiableCredential[], publish: boolean, customer: CustomerEntity, symmetricKey: string @@ -465,7 +466,7 @@ export class PostgresIdentityService extends DefaultIdentityService { } async reinstateCredentials( - credentials: VerifiableCredential | VerifiableCredential[], + credentials: W3CVerifiableCredential | W3CVerifiableCredential[], publish: boolean, customer: CustomerEntity, symmetricKey: string @@ -476,7 +477,7 @@ export class PostgresIdentityService extends DefaultIdentityService { } private async validateCredentialAccess( - credentials: VerifiableCredential | VerifiableCredential[], + credentials: W3CVerifiableCredential | W3CVerifiableCredential[], customer: CustomerEntity ) { credentials = Array.isArray(credentials) ? credentials : [credentials]; diff --git a/src/types/credential.ts b/src/types/credential.ts index abd166a6..104c7011 100644 --- a/src/types/credential.ts +++ b/src/types/credential.ts @@ -1,5 +1,15 @@ -import type { VerificationPolicies } from '@veramo/core'; +import type { IVerifyResult, VerifiableCredential, VerificationPolicies, W3CVerifiableCredential } from '@veramo/core'; import type { StatusOptions } from './credential-status.js'; +import type { UnsuccessfulResponseBody } from './shared.js'; +import type { + BulkRevocationResult, + BulkSuspensionResult, + BulkUnsuspensionResult, + RevocationResult, + SuspensionResult, + UnsuspensionResult, +} from '@cheqd/did-provider-cheqd'; +import type { VerificationOptions } from './shared.js'; export interface CredentialRequest { subjectDid: string; @@ -14,10 +24,70 @@ export interface CredentialRequest { credentialName?: string; credentialSummary?: string; } -export interface VerificationOptions { - fetchRemoteContexts?: boolean; - policies?: VerificationPolicies; - domain?: string; - verifyStatus?: boolean; -} + +export type VerificationPoliciesRequest = { + policies: VerificationPolicies; +}; + +export type PubslishRequest = { + publish?: boolean; +}; + +export type SymmetricKeyRequest = { + symmetricKey?: string; +}; + +export type CredentialRequestBody = { credential: W3CVerifiableCredential } & SymmetricKeyRequest; + export type DateType = string | Date; + +// Request bodies and queries + +export type IssueCredentialRequestBody = CredentialRequest; + +export type VerifyCredentialRequestBody = { credential: W3CVerifiableCredential } & VerificationPoliciesRequest; + +export type VerifyCredentialRequestQuery = VerificationOptions; + +export type RevokeCredentialRequestBody = CredentialRequestBody; + +export type RevokeCredentialRequestQuery = PubslishRequest; + +export type SuspendCredentialRequestBody = CredentialRequestBody; + +export type SuspendCredentialRequestQuery = PubslishRequest; + +export type UnsuspendCredentialRequestBody = CredentialRequestBody; + +export type UnsuspendCredentialRequestQuery = PubslishRequest; + +// Response bodies +// Positive + +export type IssueCredentialResponseBody = VerifiableCredential; + +export type VerifyCredentialResponseBody = IVerifyResult; + +export type RevokeCredentialResponseBody = RevocationResult | BulkRevocationResult; + +export type SuspendCredentialResponseBody = SuspensionResult | BulkSuspensionResult; + +export type UnsuspendCredentialResponseBody = UnsuspensionResult | BulkUnsuspensionResult; + +// Negative + +export type UnsuccesfulIssueCredentialResponseBody = UnsuccessfulResponseBody; + +export type UnsuccesfulRevokeredentialResponseBody = UnsuccessfulResponseBody; + +export type UnsuccesfulReinstateCredentialResponseBody = UnsuccessfulResponseBody; + +export type UnsuccesfulVerifyCredentialResponseBody = UnsuccessfulResponseBody | VerifyCredentialResponseBody; + +export type UnsuccesfulRevokeCredentialResponseBody = Pick | UnsuccessfulResponseBody; + +export type UnsuccesfulSuspendCredentialResponseBody = Pick | UnsuccessfulResponseBody; + +export type UnsuccesfulUnsuspendCredentialResponseBody = + | Pick + | UnsuccessfulResponseBody; diff --git a/src/types/customer.ts b/src/types/customer.ts new file mode 100644 index 00000000..53ae4404 --- /dev/null +++ b/src/types/customer.ts @@ -0,0 +1,23 @@ +import type { UnsuccessfulQueryResponseBody } from './shared.js'; + +// Positive + +export type QueryCustomerResponseBody = { + customer: { + customerId: string; + name: string; + }; + paymentAccount: { + address: string; + }; +}; + +export type QueryIdTokenResponseBody = { + idToken: string; +}; + +//Negative + +export type UnsuccessfulQueryCustomerResponseBody = UnsuccessfulQueryResponseBody; + +export type UnsuccessfulQueryIdTokenResponseBody = UnsuccessfulQueryResponseBody; diff --git a/src/types/did.ts b/src/types/did.ts index e22010c4..9d94b7e1 100644 --- a/src/types/did.ts +++ b/src/types/did.ts @@ -1,5 +1,21 @@ import type { CheqdNetwork, MethodSpecificIdAlgo, Service, VerificationMethods } from '@cheqd/sdk'; -import type { DIDDocument } from 'did-resolver'; +import type { DIDDocument, DIDResolutionResult, VerificationMethod } from 'did-resolver'; +import type { UnsuccessfulQueryResponseBody, UnsuccessfulResponseBody } from './shared.js'; +import type { IIdentifier } from '@veramo/core'; +import type { KeyImport } from './key.js'; + +// Interfaces +export interface DidImportRequest { + did: string; + keys: KeyImport[]; + controllerKeyId?: string; +} + +// Requests + +export type DIDRequest = { + did: string; +}; export type CreateDidRequestBody = { didDocument?: DIDDocument; @@ -15,14 +31,45 @@ export type CreateDidRequestBody = { }; }; -export interface KeyImportRequest { - privateKeyHex: string; - encrypted: boolean; - ivHex: string | undefined; - salt: string | undefined; -} - -export interface DidImportRequest { +export type UpdateDidRequestBody = { did: string; - keys: KeyImportRequest[]; -} + service: Service[]; + verificationMethod: VerificationMethod[]; + authentication: string[]; + didDocument?: DIDDocument; +}; + +export type ImportDidRequestBody = DidImportRequest; + +export type DeactivateDIDRequestParams = DIDRequest; + +export type GetDIDRequestParams = DIDRequest; + +export type ResolveDIDRequestParams = DIDRequest; + +// Responses +//Positive + +export type CreateDidResponseBody = IIdentifier; + +export type UpdateDidResponseBody = IIdentifier; + +export type DeactivateDidResponseBody = DIDResolutionResult; + +export type ListDidsResponseBody = string[]; + +export type QueryDidResponseBody = DIDResolutionResult; + +export type ResolveDidResponseBody = any; + +// Negative + +export type UnsuccessfulCreateDidResponseBody = UnsuccessfulResponseBody; + +export type UnsuccessfulUpdateDidResponseBody = UnsuccessfulResponseBody; + +export type UnsuccessfulDeactivateDidResponseBody = UnsuccessfulResponseBody | { deactivated: boolean }; + +export type UnsuccessfulGetDidResponseBody = UnsuccessfulQueryResponseBody; + +export type UnsuccessfulResolveDidResponseBody = UnsuccessfulQueryResponseBody; diff --git a/src/types/key.ts b/src/types/key.ts new file mode 100644 index 00000000..eecdd8e3 --- /dev/null +++ b/src/types/key.ts @@ -0,0 +1,37 @@ +import type { ManagedKeyInfo } from '@veramo/core'; +import type { KeyEntity } from '../database/entities/key.entity.js'; +import type { UnsuccessfulQueryResponseBody, UnsuccessfulResponseBody } from './shared.js'; + +// Interfaces + +export interface KeyImport { + privateKeyHex: string; + encrypted: boolean; + ivHex: string | undefined; + salt: string | undefined; + alias?: string; + type: 'Ed25519' | 'Secp256k1'; +} + +// Requests +export type ImportKeyRequestBody = KeyImport; + +export type GetKeyRequestBody = { + kid: string; +}; + +// Positive + +export type CreateKeyResponseBody = KeyEntity; + +export type ImportKeyResponseBody = KeyEntity; + +export type QueryKeyResponseBody = ManagedKeyInfo; + +//Negative + +export type UnsuccessfulCreateKeyResponseBody = UnsuccessfulResponseBody; + +export type UnsuccessfulImportKeyResponseBody = UnsuccessfulResponseBody; + +export type UnsuccessfulQueryKeyResponseBody = UnsuccessfulQueryResponseBody; diff --git a/src/types/presentation.ts b/src/types/presentation.ts index 0eff329b..5edb15ed 100644 --- a/src/types/presentation.ts +++ b/src/types/presentation.ts @@ -1,4 +1,36 @@ -export type VerifyPresentationResponseBody = { - verified: false; - error: string; +import type { + IVerifyResult, + VerifiablePresentation, + VerificationPolicies, + W3CVerifiableCredential, + W3CVerifiablePresentation, +} from '@veramo/core'; +import type { UnsuccessfulResponseBody, VerificationOptions } from './shared.js'; + +// Requests +export type CreatePresentationRequestBody = { + credentials: W3CVerifiableCredential[]; + holderDid: string; + verifierDid: string; }; + +export type VerifyPresentationRequestBody = { + presentation: W3CVerifiablePresentation; + verifierDid: string; + policies: VerificationPolicies; + makeFeePayment: boolean; +}; + +// Positive + +export type CreatePresentationResponseBody = VerifiablePresentation; + +export type VerifyPresentationResponseQuery = VerificationOptions; + +export type VerifyPresentationResponseBody = IVerifyResult; + +// Negative + +export type UnsuccessfulVerifyCredentialResponseBody = UnsuccessfulResponseBody | VerifyPresentationResponseBody; + +export type UnsuccessfulCreatePresentationResponseBody = UnsuccessfulResponseBody; diff --git a/src/types/resource.ts b/src/types/resource.ts new file mode 100644 index 00000000..04a191f0 --- /dev/null +++ b/src/types/resource.ts @@ -0,0 +1,33 @@ +import type { LinkedResourceMetadataResolutionResult } from '@cheqd/did-provider-cheqd/build/types'; +import type { UnsuccessfulQueryResponseBody, UnsuccessfulResponseBody } from './shared.js'; +import type { DIDRequest } from './did.js'; +import type { CheqdNetwork } from '@cheqd/sdk'; +import type { AlternativeUri } from '@cheqd/ts-proto/cheqd/resource/v2/resource.js'; +import type { SupportedEncodings } from 'uint8arrays'; + +// Requests +export type CreateResourceRequestParams = DIDRequest; + +export type CreateResourceRequestBody = { + data: string; + encoding: SupportedEncodings; + name: string; + type: string; + network: CheqdNetwork.Mainnet | CheqdNetwork.Testnet; + alsoKnownAs?: AlternativeUri[]; + version?: string; +}; + +export type SearchResourceRequestParams = DIDRequest; + +// Positive + +export type CreateResourceResponseBody = { resource: LinkedResourceMetadataResolutionResult }; + +export type QueryResourceResponseBody = any; + +// Negative + +export type UnsuccessfulCreateResourceResponseBody = UnsuccessfulResponseBody; + +export type UnsuccessfulQueryResourceResponseBody = UnsuccessfulQueryResponseBody; diff --git a/src/types/shared.ts b/src/types/shared.ts index 312a3eec..6150c3cb 100644 --- a/src/types/shared.ts +++ b/src/types/shared.ts @@ -6,6 +6,7 @@ import type { ICredentialIssuer, ICredentialVerifier, TAgent, + VerificationPolicies, } from '@veramo/core'; import type { ICheqd, CheqdDIDProvider, LinkedResourceMetadataResolutionResult } from '@cheqd/did-provider-cheqd'; import type { ICredentialIssuerLD } from '@veramo/credential-ld'; @@ -94,10 +95,14 @@ export interface IErrorResponse { message: string; } -export type UnsuccessfulQueryResponseBody = { +export type UnsuccessfulResponseBody = { error: string; }; +export type UnsuccessfulQueryResponseBody = UnsuccessfulResponseBody; + +export type ValidationErrorResponseBody = UnsuccessfulResponseBody; + export class CommonReturn implements IReturn { returnOk(data = {}): ICommonErrorResponse { return { @@ -115,3 +120,10 @@ export class CommonReturn implements IReturn { }; } } +export interface VerificationOptions { + fetchRemoteContexts?: boolean; + domain?: string; + verifyStatus?: boolean; + policies?: VerificationPolicies; + allowDeactivatedDid?: boolean; +}