mirror of
https://github.com/pocket-id/pocket-id.git
synced 2026-02-16 11:21:12 +00:00
Co-authored-by: Kyle Mendell <kmendell@ofkm.us> Co-authored-by: Kyle Mendell <kmendell@outlook.com> Co-authored-by: Elias Schneider <login@eliasschneider.com>
This commit is contained in:
283
frontend/package-lock.json
generated
283
frontend/package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "pocket-id-frontend",
|
"name": "pocket-id-frontend",
|
||||||
"version": "0.45.0",
|
"version": "0.46.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "pocket-id-frontend",
|
"name": "pocket-id-frontend",
|
||||||
"version": "0.45.0",
|
"version": "0.46.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@simplewebauthn/browser": "^13.1.0",
|
"@simplewebauthn/browser": "^13.1.0",
|
||||||
"@tailwindcss/vite": "^4.0.0",
|
"@tailwindcss/vite": "^4.0.0",
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
"jose": "^5.9.6",
|
"jose": "^5.9.6",
|
||||||
"lucide-svelte": "^0.487.0",
|
"lucide-svelte": "^0.487.0",
|
||||||
"mode-watcher": "^0.5.1",
|
"mode-watcher": "^0.5.1",
|
||||||
|
"qrcode": "^1.5.4",
|
||||||
"svelte-sonner": "^0.3.28",
|
"svelte-sonner": "^0.3.28",
|
||||||
"sveltekit-superforms": "^2.23.1",
|
"sveltekit-superforms": "^2.23.1",
|
||||||
"tailwind-merge": "^2.6.0",
|
"tailwind-merge": "^2.6.0",
|
||||||
@@ -35,6 +36,7 @@
|
|||||||
"@sveltejs/vite-plugin-svelte": "^5.0.3",
|
"@sveltejs/vite-plugin-svelte": "^5.0.3",
|
||||||
"@types/eslint": "^9.6.1",
|
"@types/eslint": "^9.6.1",
|
||||||
"@types/node": "^22.10.10",
|
"@types/node": "^22.10.10",
|
||||||
|
"@types/qrcode": "^1.5.5",
|
||||||
"bits-ui": "^0.22.0",
|
"bits-ui": "^0.22.0",
|
||||||
"cmdk-sv": "^0.0.19",
|
"cmdk-sv": "^0.0.19",
|
||||||
"eslint": "^9.19.0",
|
"eslint": "^9.19.0",
|
||||||
@@ -1725,6 +1727,15 @@
|
|||||||
"undici-types": "~6.20.0"
|
"undici-types": "~6.20.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/qrcode": {
|
||||||
|
"version": "1.5.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/qrcode/-/qrcode-1.5.5.tgz",
|
||||||
|
"integrity": "sha512-CdfBi/e3Qk+3Z/fXYShipBT13OJ2fDO2Q2w5CIP5anLTLIndQG9z6P1cnm+8zCWSpm5dnxMFd/uREtb0EXuQzg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/resolve": {
|
"node_modules/@types/resolve": {
|
||||||
"version": "1.20.2",
|
"version": "1.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
|
||||||
@@ -2036,11 +2047,19 @@
|
|||||||
"url": "https://github.com/sponsors/epoberezkin"
|
"url": "https://github.com/sponsors/epoberezkin"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ansi-regex": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ansi-styles": {
|
"node_modules/ansi-styles": {
|
||||||
"version": "4.3.0",
|
"version": "4.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"color-convert": "^2.0.1"
|
"color-convert": "^2.0.1"
|
||||||
},
|
},
|
||||||
@@ -2237,6 +2256,17 @@
|
|||||||
"validator": "^13.9.0"
|
"validator": "^13.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cliui": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"string-width": "^4.2.0",
|
||||||
|
"strip-ansi": "^6.0.0",
|
||||||
|
"wrap-ansi": "^6.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/clsx": {
|
"node_modules/clsx": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
||||||
@@ -2296,7 +2326,6 @@
|
|||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"color-name": "~1.1.4"
|
"color-name": "~1.1.4"
|
||||||
},
|
},
|
||||||
@@ -2307,8 +2336,7 @@
|
|||||||
"node_modules/color-name": {
|
"node_modules/color-name": {
|
||||||
"version": "1.1.4",
|
"version": "1.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/combined-stream": {
|
"node_modules/combined-stream": {
|
||||||
"version": "1.0.8",
|
"version": "1.0.8",
|
||||||
@@ -2439,6 +2467,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/decamelize": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/dedent": {
|
"node_modules/dedent": {
|
||||||
"version": "1.5.1",
|
"version": "1.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz",
|
||||||
@@ -2501,6 +2538,12 @@
|
|||||||
"resolved": "https://registry.npmjs.org/devalue/-/devalue-5.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/devalue/-/devalue-5.1.1.tgz",
|
||||||
"integrity": "sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw=="
|
"integrity": "sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/dijkstrajs": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/dlv": {
|
"node_modules/dlv": {
|
||||||
"version": "1.1.3",
|
"version": "1.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
|
||||||
@@ -2516,6 +2559,12 @@
|
|||||||
"fast-check": "^3.23.1"
|
"fast-check": "^3.23.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/emoji-regex": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||||
|
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/enhanced-resolve": {
|
"node_modules/enhanced-resolve": {
|
||||||
"version": "5.18.0",
|
"version": "5.18.0",
|
||||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.0.tgz",
|
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.0.tgz",
|
||||||
@@ -3080,6 +3129,15 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/get-caller-file": {
|
||||||
|
"version": "2.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
||||||
|
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": "6.* || 8.* || >= 10.*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/glob-parent": {
|
"node_modules/glob-parent": {
|
||||||
"version": "6.0.2",
|
"version": "6.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
|
||||||
@@ -3223,6 +3281,15 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/is-fullwidth-code-point": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/is-glob": {
|
"node_modules/is-glob": {
|
||||||
"version": "4.0.3",
|
"version": "4.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||||
@@ -3858,6 +3925,15 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/p-try": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/parent-module": {
|
"node_modules/parent-module": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
||||||
@@ -3874,7 +3950,6 @@
|
|||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||||
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
|
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
@@ -3941,6 +4016,15 @@
|
|||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/pngjs": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.13.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/postcss": {
|
"node_modules/postcss": {
|
||||||
"version": "8.5.3",
|
"version": "8.5.3",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz",
|
||||||
@@ -4227,6 +4311,22 @@
|
|||||||
],
|
],
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
"node_modules/qrcode": {
|
||||||
|
"version": "1.5.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz",
|
||||||
|
"integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==",
|
||||||
|
"dependencies": {
|
||||||
|
"dijkstrajs": "^1.0.1",
|
||||||
|
"pngjs": "^5.0.0",
|
||||||
|
"yargs": "^15.3.1"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"qrcode": "bin/qrcode"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.13.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/queue-microtask": {
|
"node_modules/queue-microtask": {
|
||||||
"version": "1.2.3",
|
"version": "1.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
||||||
@@ -4276,6 +4376,21 @@
|
|||||||
"node": ">=0.10"
|
"node": ">=0.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/require-directory": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/require-main-filename": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
"node_modules/resolve": {
|
"node_modules/resolve": {
|
||||||
"version": "1.22.10",
|
"version": "1.22.10",
|
||||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
|
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
|
||||||
@@ -4398,6 +4513,12 @@
|
|||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/set-blocking": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
"node_modules/set-cookie-parser": {
|
"node_modules/set-cookie-parser": {
|
||||||
"version": "2.7.1",
|
"version": "2.7.1",
|
||||||
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
|
||||||
@@ -4476,6 +4597,32 @@
|
|||||||
"kysely": "*"
|
"kysely": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/string-width": {
|
||||||
|
"version": "4.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||||
|
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"emoji-regex": "^8.0.0",
|
||||||
|
"is-fullwidth-code-point": "^3.0.0",
|
||||||
|
"strip-ansi": "^6.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/strip-ansi": {
|
||||||
|
"version": "6.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||||
|
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-regex": "^5.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/strip-json-comments": {
|
"node_modules/strip-json-comments": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
|
||||||
@@ -5128,6 +5275,12 @@
|
|||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/which-module": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
"node_modules/word-wrap": {
|
"node_modules/word-wrap": {
|
||||||
"version": "1.2.5",
|
"version": "1.2.5",
|
||||||
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
|
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
|
||||||
@@ -5137,6 +5290,26 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/wrap-ansi": {
|
||||||
|
"version": "6.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
|
||||||
|
"integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-styles": "^4.0.0",
|
||||||
|
"string-width": "^4.1.0",
|
||||||
|
"strip-ansi": "^6.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/y18n": {
|
||||||
|
"version": "4.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
|
||||||
|
"integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
"node_modules/yaml": {
|
"node_modules/yaml": {
|
||||||
"version": "2.7.0",
|
"version": "2.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz",
|
||||||
@@ -5150,6 +5323,102 @@
|
|||||||
"node": ">= 14"
|
"node": ">= 14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/yargs": {
|
||||||
|
"version": "15.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
|
||||||
|
"integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"cliui": "^6.0.0",
|
||||||
|
"decamelize": "^1.2.0",
|
||||||
|
"find-up": "^4.1.0",
|
||||||
|
"get-caller-file": "^2.0.1",
|
||||||
|
"require-directory": "^2.1.1",
|
||||||
|
"require-main-filename": "^2.0.0",
|
||||||
|
"set-blocking": "^2.0.0",
|
||||||
|
"string-width": "^4.2.0",
|
||||||
|
"which-module": "^2.0.0",
|
||||||
|
"y18n": "^4.0.0",
|
||||||
|
"yargs-parser": "^18.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/yargs-parser": {
|
||||||
|
"version": "18.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
|
||||||
|
"integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"camelcase": "^5.0.0",
|
||||||
|
"decamelize": "^1.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/yargs-parser/node_modules/camelcase": {
|
||||||
|
"version": "5.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
|
||||||
|
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/yargs/node_modules/find-up": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"locate-path": "^5.0.0",
|
||||||
|
"path-exists": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/yargs/node_modules/locate-path": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"p-locate": "^4.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/yargs/node_modules/p-limit": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"p-try": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/yargs/node_modules/p-locate": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"p-limit": "^2.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/yocto-queue": {
|
"node_modules/yocto-queue": {
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
"jose": "^5.9.6",
|
"jose": "^5.9.6",
|
||||||
"lucide-svelte": "^0.487.0",
|
"lucide-svelte": "^0.487.0",
|
||||||
"mode-watcher": "^0.5.1",
|
"mode-watcher": "^0.5.1",
|
||||||
|
"qrcode": "^1.5.4",
|
||||||
"svelte-sonner": "^0.3.28",
|
"svelte-sonner": "^0.3.28",
|
||||||
"sveltekit-superforms": "^2.23.1",
|
"sveltekit-superforms": "^2.23.1",
|
||||||
"tailwind-merge": "^2.6.0",
|
"tailwind-merge": "^2.6.0",
|
||||||
@@ -40,6 +41,7 @@
|
|||||||
"@sveltejs/vite-plugin-svelte": "^5.0.3",
|
"@sveltejs/vite-plugin-svelte": "^5.0.3",
|
||||||
"@types/eslint": "^9.6.1",
|
"@types/eslint": "^9.6.1",
|
||||||
"@types/node": "^22.10.10",
|
"@types/node": "^22.10.10",
|
||||||
|
"@types/qrcode": "^1.5.5",
|
||||||
"bits-ui": "^0.22.0",
|
"bits-ui": "^0.22.0",
|
||||||
"cmdk-sv": "^0.0.19",
|
"cmdk-sv": "^0.0.19",
|
||||||
"eslint": "^9.19.0",
|
"eslint": "^9.19.0",
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { page } from '$app/state';
|
import { page } from '$app/state';
|
||||||
|
import CopyToClipboard from '$lib/components/copy-to-clipboard.svelte';
|
||||||
|
import Qrcode from '$lib/components/qrcode/qrcode.svelte';
|
||||||
import { Button } from '$lib/components/ui/button';
|
import { Button } from '$lib/components/ui/button';
|
||||||
import * as Dialog from '$lib/components/ui/dialog';
|
import * as Dialog from '$lib/components/ui/dialog';
|
||||||
import Input from '$lib/components/ui/input/input.svelte';
|
|
||||||
import Label from '$lib/components/ui/label/label.svelte';
|
import Label from '$lib/components/ui/label/label.svelte';
|
||||||
import * as Select from '$lib/components/ui/select/index.js';
|
import * as Select from '$lib/components/ui/select/index.js';
|
||||||
|
import { Separator } from '$lib/components/ui/separator';
|
||||||
import { m } from '$lib/paraglide/messages';
|
import { m } from '$lib/paraglide/messages';
|
||||||
import UserService from '$lib/services/user-service';
|
import UserService from '$lib/services/user-service';
|
||||||
import { axiosErrorToast } from '$lib/utils/error-util';
|
import { axiosErrorToast } from '$lib/utils/error-util';
|
||||||
|
import { mode } from 'mode-watcher';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
userId = $bindable()
|
userId = $bindable()
|
||||||
@@ -18,6 +21,7 @@
|
|||||||
const userService = new UserService();
|
const userService = new UserService();
|
||||||
|
|
||||||
let oneTimeLink: string | null = $state(null);
|
let oneTimeLink: string | null = $state(null);
|
||||||
|
let code: string | null = $state(null);
|
||||||
let selectedExpiration: keyof typeof availableExpirations = $state(m.one_hour());
|
let selectedExpiration: keyof typeof availableExpirations = $state(m.one_hour());
|
||||||
|
|
||||||
let availableExpirations = {
|
let availableExpirations = {
|
||||||
@@ -31,8 +35,8 @@
|
|||||||
async function createOneTimeAccessToken() {
|
async function createOneTimeAccessToken() {
|
||||||
try {
|
try {
|
||||||
const expiration = new Date(Date.now() + availableExpirations[selectedExpiration] * 1000);
|
const expiration = new Date(Date.now() + availableExpirations[selectedExpiration] * 1000);
|
||||||
const token = await userService.createOneTimeAccessToken(expiration, userId!);
|
code = await userService.createOneTimeAccessToken(expiration, userId!);
|
||||||
oneTimeLink = `${page.url.origin}/lc/${token}`;
|
oneTimeLink = `${page.url.origin}/lc/${code}`;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
axiosErrorToast(e);
|
axiosErrorToast(e);
|
||||||
}
|
}
|
||||||
@@ -41,6 +45,7 @@
|
|||||||
function onOpenChange(open: boolean) {
|
function onOpenChange(open: boolean) {
|
||||||
if (!open) {
|
if (!open) {
|
||||||
oneTimeLink = null;
|
oneTimeLink = null;
|
||||||
|
code = null;
|
||||||
userId = null;
|
userId = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -54,6 +59,7 @@
|
|||||||
>{m.create_a_login_code_to_sign_in_without_a_passkey_once()}</Dialog.Description
|
>{m.create_a_login_code_to_sign_in_without_a_passkey_once()}</Dialog.Description
|
||||||
>
|
>
|
||||||
</Dialog.Header>
|
</Dialog.Header>
|
||||||
|
|
||||||
{#if oneTimeLink === null}
|
{#if oneTimeLink === null}
|
||||||
<div>
|
<div>
|
||||||
<Label for="expiration">{m.expiration()}</Label>
|
<Label for="expiration">{m.expiration()}</Label>
|
||||||
@@ -65,7 +71,7 @@
|
|||||||
onSelectedChange={(v) =>
|
onSelectedChange={(v) =>
|
||||||
(selectedExpiration = v!.value as keyof typeof availableExpirations)}
|
(selectedExpiration = v!.value as keyof typeof availableExpirations)}
|
||||||
>
|
>
|
||||||
<Select.Trigger class="h-9 ">
|
<Select.Trigger class="h-9 w-full">
|
||||||
<Select.Value>{selectedExpiration}</Select.Value>
|
<Select.Value>{selectedExpiration}</Select.Value>
|
||||||
</Select.Trigger>
|
</Select.Trigger>
|
||||||
<Select.Content>
|
<Select.Content>
|
||||||
@@ -75,12 +81,36 @@
|
|||||||
</Select.Content>
|
</Select.Content>
|
||||||
</Select.Root>
|
</Select.Root>
|
||||||
</div>
|
</div>
|
||||||
<Button onclick={() => createOneTimeAccessToken()} disabled={!selectedExpiration}>
|
<Button
|
||||||
|
onclick={() => createOneTimeAccessToken()}
|
||||||
|
disabled={!selectedExpiration}
|
||||||
|
class="mt-2 w-full"
|
||||||
|
>
|
||||||
{m.generate_code()}
|
{m.generate_code()}
|
||||||
</Button>
|
</Button>
|
||||||
{:else}
|
{:else}
|
||||||
<Label for="login-code" class="sr-only">{m.login_code()}</Label>
|
<div class="flex flex-col items-center gap-2">
|
||||||
<Input id="login-code" value={oneTimeLink} readonly />
|
<CopyToClipboard value={code!}>
|
||||||
|
<p class="text-3xl font-semibold">{code}</p>
|
||||||
|
</CopyToClipboard>
|
||||||
|
|
||||||
|
<div class="text-muted-foreground my-2 flex items-center justify-center gap-3">
|
||||||
|
<Separator />
|
||||||
|
<p class="text-nowrap text-xs">{m.or_visit()}</p>
|
||||||
|
<Separator />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Qrcode
|
||||||
|
class="mb-2"
|
||||||
|
value={oneTimeLink}
|
||||||
|
size={180}
|
||||||
|
color={$mode === 'dark' ? '#FFFFFF' : '#000000'}
|
||||||
|
backgroundColor={$mode === 'dark' ? '#000000' : '#FFFFFF'}
|
||||||
|
/>
|
||||||
|
<CopyToClipboard value={oneTimeLink!}>
|
||||||
|
<p data-testId="login-code-link">{oneTimeLink!}</p>
|
||||||
|
</CopyToClipboard>
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</Dialog.Content>
|
</Dialog.Content>
|
||||||
</Dialog.Root>
|
</Dialog.Root>
|
||||||
|
|||||||
42
frontend/src/lib/components/qrcode/qrcode.svelte
Normal file
42
frontend/src/lib/components/qrcode/qrcode.svelte
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { cn } from '$lib/utils/style';
|
||||||
|
import QRCode from 'qrcode';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
|
|
||||||
|
let canvasEl: HTMLCanvasElement | null;
|
||||||
|
let {
|
||||||
|
value,
|
||||||
|
size = 200,
|
||||||
|
color = '#000000',
|
||||||
|
backgroundColor = '#FFFFFF',
|
||||||
|
...restProps
|
||||||
|
}: HTMLAttributes<HTMLCanvasElement> & {
|
||||||
|
value: string | null;
|
||||||
|
size?: number;
|
||||||
|
color?: string;
|
||||||
|
backgroundColor?: string;
|
||||||
|
} = $props();
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
if (value && canvasEl) {
|
||||||
|
// Convert "transparent" to a valid value for the QR code library
|
||||||
|
const lightColor = backgroundColor === 'transparent' ? '#00000000' : backgroundColor;
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
width: size,
|
||||||
|
margin: 0,
|
||||||
|
color: {
|
||||||
|
dark: color,
|
||||||
|
light: lightColor
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
QRCode.toCanvas(canvasEl, value, options).catch((error: Error) => {
|
||||||
|
console.error('Error generating QR Code:', error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<canvas {...restProps} bind:this={canvasEl} class={cn('rounded-lg', restProps.class)}></canvas>
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { page } from '$app/state';
|
import { page } from '$app/state';
|
||||||
import CopyToClipboard from '$lib/components/copy-to-clipboard.svelte';
|
import CopyToClipboard from '$lib/components/copy-to-clipboard.svelte';
|
||||||
|
import Qrcode from '$lib/components/qrcode/qrcode.svelte';
|
||||||
import * as Dialog from '$lib/components/ui/dialog';
|
import * as Dialog from '$lib/components/ui/dialog';
|
||||||
import { Separator } from '$lib/components/ui/separator';
|
import { Separator } from '$lib/components/ui/separator';
|
||||||
import { m } from '$lib/paraglide/messages';
|
import { m } from '$lib/paraglide/messages';
|
||||||
import UserService from '$lib/services/user-service';
|
import UserService from '$lib/services/user-service';
|
||||||
import { axiosErrorToast } from '$lib/utils/error-util';
|
import { axiosErrorToast } from '$lib/utils/error-util';
|
||||||
|
import { mode } from 'mode-watcher';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
show = $bindable()
|
show = $bindable()
|
||||||
@@ -16,13 +18,17 @@
|
|||||||
const userService = new UserService();
|
const userService = new UserService();
|
||||||
|
|
||||||
let code: string | null = $state(null);
|
let code: string | null = $state(null);
|
||||||
|
let loginCodeLink: string | null = $state(null);
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
if (show) {
|
if (show) {
|
||||||
const expiration = new Date(Date.now() + 15 * 60 * 1000);
|
const expiration = new Date(Date.now() + 15 * 60 * 1000);
|
||||||
userService
|
userService
|
||||||
.createOneTimeAccessToken(expiration, 'me')
|
.createOneTimeAccessToken(expiration, 'me')
|
||||||
.then((c) => (code = c))
|
.then((c) => {
|
||||||
|
code = c;
|
||||||
|
loginCodeLink = page.url.origin + '/lc/' + code;
|
||||||
|
})
|
||||||
.catch((e) => axiosErrorToast(e));
|
.catch((e) => axiosErrorToast(e));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -48,16 +54,22 @@
|
|||||||
<CopyToClipboard value={code!}>
|
<CopyToClipboard value={code!}>
|
||||||
<p class="text-3xl font-semibold">{code}</p>
|
<p class="text-3xl font-semibold">{code}</p>
|
||||||
</CopyToClipboard>
|
</CopyToClipboard>
|
||||||
<div class="text-muted-foreground flex items-center justify-center gap-3">
|
<div class="text-muted-foreground my-2 flex items-center justify-center gap-3">
|
||||||
<Separator />
|
<Separator />
|
||||||
<p class="text-nowrap text-xs">{m.or_visit()}</p>
|
<p class="text-nowrap text-xs">{m.or_visit()}</p>
|
||||||
<Separator />
|
<Separator />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
|
||||||
<CopyToClipboard value={page.url.origin + '/lc/' + code!}>
|
<Qrcode
|
||||||
<p data-testId="login-code-link">{page.url.origin + '/lc/' + code!}</p>
|
class="mb-2"
|
||||||
|
value={loginCodeLink}
|
||||||
|
size={180}
|
||||||
|
color={$mode === 'dark' ? '#FFFFFF' : '#000000'}
|
||||||
|
backgroundColor={$mode === 'dark' ? '#000000' : '#FFFFFF'}
|
||||||
|
/>
|
||||||
|
<CopyToClipboard value={loginCodeLink!}>
|
||||||
|
<p data-testId="login-code-link">{loginCodeLink!}</p>
|
||||||
</CopyToClipboard>
|
</CopyToClipboard>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</Dialog.Content>
|
</Dialog.Content>
|
||||||
</Dialog.Root>
|
</Dialog.Root>
|
||||||
|
|||||||
@@ -3,14 +3,13 @@
|
|||||||
import { openConfirmDialog } from '$lib/components/confirm-dialog/';
|
import { openConfirmDialog } from '$lib/components/confirm-dialog/';
|
||||||
import { Button } from '$lib/components/ui/button';
|
import { Button } from '$lib/components/ui/button';
|
||||||
import * as Table from '$lib/components/ui/table';
|
import * as Table from '$lib/components/ui/table';
|
||||||
|
import { m } from '$lib/paraglide/messages';
|
||||||
import OIDCService from '$lib/services/oidc-service';
|
import OIDCService from '$lib/services/oidc-service';
|
||||||
import type { OidcClient } from '$lib/types/oidc.type';
|
import type { OidcClient } from '$lib/types/oidc.type';
|
||||||
import type { Paginated, SearchPaginationSortRequest } from '$lib/types/pagination.type';
|
import type { Paginated, SearchPaginationSortRequest } from '$lib/types/pagination.type';
|
||||||
import { axiosErrorToast } from '$lib/utils/error-util';
|
import { axiosErrorToast } from '$lib/utils/error-util';
|
||||||
import { LucidePencil, LucideTrash } from 'lucide-svelte';
|
import { LucidePencil, LucideTrash } from 'lucide-svelte';
|
||||||
import { toast } from 'svelte-sonner';
|
import { toast } from 'svelte-sonner';
|
||||||
import OneTimeLinkModal from './client-secret.svelte';
|
|
||||||
import { m } from '$lib/paraglide/messages';
|
|
||||||
|
|
||||||
let {
|
let {
|
||||||
clients = $bindable(),
|
clients = $bindable(),
|
||||||
@@ -20,8 +19,6 @@
|
|||||||
requestOptions: SearchPaginationSortRequest;
|
requestOptions: SearchPaginationSortRequest;
|
||||||
} = $props();
|
} = $props();
|
||||||
|
|
||||||
let oneTimeLink = $state<string | null>(null);
|
|
||||||
|
|
||||||
const oidcService = new OIDCService();
|
const oidcService = new OIDCService();
|
||||||
|
|
||||||
async function deleteClient(client: OidcClient) {
|
async function deleteClient(client: OidcClient) {
|
||||||
@@ -86,5 +83,3 @@
|
|||||||
</Table.Cell>
|
</Table.Cell>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
</AdvancedTable>
|
</AdvancedTable>
|
||||||
|
|
||||||
<OneTimeLinkModal {oneTimeLink} />
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import test, { expect } from '@playwright/test';
|
import test, { expect } from '@playwright/test';
|
||||||
import { users } from './data';
|
import { users } from './data';
|
||||||
|
import authUtil from './utils/auth.util';
|
||||||
import { cleanupBackend } from './utils/cleanup.util';
|
import { cleanupBackend } from './utils/cleanup.util';
|
||||||
import passkeyUtil from './utils/passkey.util';
|
import passkeyUtil from './utils/passkey.util';
|
||||||
import authUtil from './utils/auth.util';
|
|
||||||
|
|
||||||
test.beforeEach(cleanupBackend);
|
test.beforeEach(cleanupBackend);
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { cleanupBackend } from './utils/cleanup.util';
|
|||||||
|
|
||||||
test.describe('API Key Management', () => {
|
test.describe('API Key Management', () => {
|
||||||
test.beforeEach(async ({ page }) => {
|
test.beforeEach(async ({ page }) => {
|
||||||
await cleanupBackend()
|
await cleanupBackend();
|
||||||
await page.goto('/settings/admin/api-keys');
|
await page.goto('/settings/admin/api-keys');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -50,11 +50,13 @@ test('Create user fails with already taken username', async ({ page }) => {
|
|||||||
await expect(page.getByRole('status')).toHaveText('Username is already in use');
|
await expect(page.getByRole('status')).toHaveText('Username is already in use');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Create one time access token', async ({ page }) => {
|
test('Create one time access token', async ({ page, context }) => {
|
||||||
await page.goto('/settings/admin/users');
|
await page.goto('/settings/admin/users');
|
||||||
|
|
||||||
await page
|
await page
|
||||||
.getByRole('row', { name: `${users.craig.firstname} ${users.craig.lastname}` })
|
.getByRole('row', {
|
||||||
|
name: `${users.craig.firstname} ${users.craig.lastname}`
|
||||||
|
})
|
||||||
.getByRole('button')
|
.getByRole('button')
|
||||||
.click();
|
.click();
|
||||||
|
|
||||||
@@ -64,16 +66,20 @@ test('Create one time access token', async ({ page }) => {
|
|||||||
await page.getByRole('option', { name: '12 hours' }).click();
|
await page.getByRole('option', { name: '12 hours' }).click();
|
||||||
await page.getByRole('button', { name: 'Generate Code' }).click();
|
await page.getByRole('button', { name: 'Generate Code' }).click();
|
||||||
|
|
||||||
await expect(page.getByRole('textbox', { name: 'Login Code' })).toHaveValue(
|
const link = await page.getByTestId('login-code-link').textContent();
|
||||||
/http:\/\/localhost\/lc\/.*/
|
await context.clearCookies();
|
||||||
);
|
|
||||||
|
await page.goto(link!);
|
||||||
|
await page.waitForURL('/settings/account');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Delete user', async ({ page }) => {
|
test('Delete user', async ({ page }) => {
|
||||||
await page.goto('/settings/admin/users');
|
await page.goto('/settings/admin/users');
|
||||||
|
|
||||||
await page
|
await page
|
||||||
.getByRole('row', { name: `${users.craig.firstname} ${users.craig.lastname}` })
|
.getByRole('row', {
|
||||||
|
name: `${users.craig.firstname} ${users.craig.lastname}`
|
||||||
|
})
|
||||||
.getByRole('button')
|
.getByRole('button')
|
||||||
.click();
|
.click();
|
||||||
await page.getByRole('menuitem', { name: 'Delete' }).click();
|
await page.getByRole('menuitem', { name: 'Delete' }).click();
|
||||||
@@ -81,7 +87,9 @@ test('Delete user', async ({ page }) => {
|
|||||||
|
|
||||||
await expect(page.getByRole('status')).toHaveText('User deleted successfully');
|
await expect(page.getByRole('status')).toHaveText('User deleted successfully');
|
||||||
await expect(
|
await expect(
|
||||||
page.getByRole('row', { name: `${users.craig.firstname} ${users.craig.lastname}` })
|
page.getByRole('row', {
|
||||||
|
name: `${users.craig.firstname} ${users.craig.lastname}`
|
||||||
|
})
|
||||||
).not.toBeVisible();
|
).not.toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user