diff --git a/package-lock.json b/package-lock.json index a8f88924d..78d27f349 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ }, "devDependencies": { "@babel/core": "7.18.10", + "@formatjs/cli-lib": "6.3.3", "@ory/client": "1.2.10", "@ory/integrations": "1.1.5", "@playwright/experimental-ct-react": "1.38.0", @@ -3847,6 +3848,141 @@ "integrity": "sha512-ou3elfqG/hZsbmF4bxeJhPHIf3G2pm0ujc39hYEZrfVqt7Vk/Zji6CXc3W0pmYM8BW1g40U+akTl9DKZhFhInQ==", "dev": true }, + "node_modules/@formatjs/cli-lib": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/@formatjs/cli-lib/-/cli-lib-6.3.3.tgz", + "integrity": "sha512-qQwrsghvp3Bg5rxP8xRNk2iloIvgClLhaBD30J4fxM6LucyGvYa5aTVNOy2lgqUKoGT51QjxFuzZxhx4YZdiqQ==", + "dev": true, + "dependencies": { + "@formatjs/icu-messageformat-parser": "2.7.3", + "@formatjs/ts-transformer": "3.13.9", + "@types/estree": "^1.0.0", + "@types/fs-extra": "^9.0.1", + "@types/json-stable-stringify": "^1.0.32", + "@types/node": "14 || 16 || 17", + "chalk": "^4.0.0", + "commander": "8", + "fast-glob": "^3.2.7", + "fs-extra": "10", + "json-stable-stringify": "^1.0.1", + "loud-rejection": "^2.2.0", + "tslib": "^2.4.0", + "typescript": "5" + }, + "engines": { + "node": ">= 16" + }, + "peerDependencies": { + "@vue/compiler-core": "^3.3.4", + "vue": "^3.3.4" + }, + "peerDependenciesMeta": { + "@vue/compiler-core": { + "optional": true + }, + "vue": { + "optional": true + } + } + }, + "node_modules/@formatjs/cli-lib/node_modules/@formatjs/ecma402-abstract": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.18.0.tgz", + "integrity": "sha512-PEVLoa3zBevWSCZzPIM/lvPCi8P5l4G+NXQMc/CjEiaCWgyHieUoo0nM7Bs0n/NbuQ6JpXEolivQ9pKSBHaDlA==", + "dev": true, + "dependencies": { + "@formatjs/intl-localematcher": "0.5.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@formatjs/cli-lib/node_modules/@formatjs/icu-messageformat-parser": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.7.3.tgz", + "integrity": "sha512-X/jy10V9S/vW+qlplqhMUxR8wErQ0mmIYSq4mrjpjDl9mbuGcCILcI1SUYkL5nlM4PJqpc0KOS0bFkkJNPxYRw==", + "dev": true, + "dependencies": { + "@formatjs/ecma402-abstract": "1.18.0", + "@formatjs/icu-skeleton-parser": "1.7.0", + "tslib": "^2.4.0" + } + }, + "node_modules/@formatjs/cli-lib/node_modules/@formatjs/icu-skeleton-parser": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.7.0.tgz", + "integrity": "sha512-Cfdo/fgbZzpN/jlN/ptQVe0lRHora+8ezrEeg2RfrNjyp+YStwBy7cqDY8k5/z2LzXg6O0AdzAV91XS0zIWv+A==", + "dev": true, + "dependencies": { + "@formatjs/ecma402-abstract": "1.18.0", + "tslib": "^2.4.0" + } + }, + "node_modules/@formatjs/cli-lib/node_modules/@formatjs/intl-localematcher": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.5.2.tgz", + "integrity": "sha512-txaaE2fiBMagLrR4jYhxzFO6wEdEG4TPMqrzBAcbr4HFUYzH/YC+lg6OIzKCHm8WgDdyQevxbAAV1OgcXctuGw==", + "dev": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@formatjs/cli-lib/node_modules/@formatjs/ts-transformer": { + "version": "3.13.9", + "resolved": "https://registry.npmjs.org/@formatjs/ts-transformer/-/ts-transformer-3.13.9.tgz", + "integrity": "sha512-J3kmCHOwkc0Tru0ZnBHPVDIwHCcaNh/zB8ZU4VQFBH2jhaOku0drym/hjz+f9/PCKLutd3Q7alUi2+Z2VpBIng==", + "dev": true, + "dependencies": { + "@formatjs/icu-messageformat-parser": "2.7.3", + "@types/json-stable-stringify": "^1.0.32", + "@types/node": "14 || 16 || 17", + "chalk": "^4.0.0", + "json-stable-stringify": "^1.0.1", + "tslib": "^2.4.0", + "typescript": "5" + }, + "peerDependencies": { + "ts-jest": ">=27" + }, + "peerDependenciesMeta": { + "ts-jest": { + "optional": true + } + } + }, + "node_modules/@formatjs/cli-lib/node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, + "node_modules/@formatjs/cli-lib/node_modules/@types/node": { + "version": "17.0.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", + "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==", + "dev": true + }, + "node_modules/@formatjs/cli-lib/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/@formatjs/cli-lib/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/@formatjs/ecma402-abstract": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.17.0.tgz", @@ -11309,6 +11445,15 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/fs-extra": { + "version": "9.0.13", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", + "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/glob": { "version": "7.2.0", "dev": true, @@ -14434,6 +14579,18 @@ "version": "3.1.1", "license": "MIT" }, + "node_modules/currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha512-/fITjgjGU50vjQ4FH6eUoYu+iUoUKIXws2hL15JJpIR+BbTxaXQsMuuyjtNh2WqsSBS5nsaZHFsFecyw5CCAng==", + "dev": true, + "dependencies": { + "array-find-index": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "license": "BSD-2-Clause" @@ -20019,6 +20176,19 @@ "loose-envify": "cli.js" } }, + "node_modules/loud-rejection": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-2.2.0.tgz", + "integrity": "sha512-S0FayMXku80toa5sZ6Ro4C+s+EtFDCsyJNG/AzFMfX3AxD5Si4dZsgzm/kKnbOxHl5Cv8jBlno8+3XYIh2pNjQ==", + "dev": true, + "dependencies": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/lru-cache": { "version": "5.1.1", "dev": true, diff --git a/package.json b/package.json index 5687fd21f..58d9aeb33 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "homepage": "https://github.com/ory/elements#readme", "devDependencies": { "@babel/core": "7.18.10", + "@formatjs/cli-lib": "6.3.3", "@ory/client": "1.2.10", "@ory/integrations": "1.1.5", "@playwright/experimental-ct-react": "1.38.0", diff --git a/src/locales/de.json b/src/locales/de.json index 8b2f9f02b..b2c94c778 100644 --- a/src/locales/de.json +++ b/src/locales/de.json @@ -157,6 +157,7 @@ "settings.navigation-profile": "Profil", "settings.navigation-totp": "Zwei-Faktor App", "settings.navigation-webauthn": "Sicherheitsschlüssel", + "settings.navigation-passkey": "Passkeys", "settings.subtitle-instructions": "Hier können Sie Einstellungen zu Ihrem Konto vornehmen. Für manche Einstellungen müssen Sie Ihre Identität erneut bestätigen.", "settings.title": "Kontoeinstellungen", "settings.title-lookup-secret": "Manage 2FA Backup Recovery Codes", @@ -166,6 +167,7 @@ "settings.title-profile": "Profil Einstellungen", "settings.title-totp": "Zwei-Faktor TOTP App", "settings.title-webauthn": "Sicherheitsschlüssel verwalten", + "settings.title-passkey": "Passkeys verwalten", "verification.registration-button": "Registrieren", "verification.registration-label": "Sie haben noch kein Konto?", "verification.title": "Verifizieren Sie ihr Konto" diff --git a/src/locales/en.json b/src/locales/en.json index 9c522544f..ee5b6f7ef 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -157,6 +157,7 @@ "settings.navigation-profile": "Profile", "settings.navigation-totp": "Authenticator App", "settings.navigation-webauthn": "Hardware Tokens", + "settings.navigation-passkey": "Passkeys", "settings.subtitle-instructions": "Here you can manage settings related to your account. Keep in mind that certain actions require you to re-authenticate.", "settings.title": "Account Settings", "settings.title-lookup-secret": "Manage 2FA Backup Recovery Codes", @@ -166,6 +167,7 @@ "settings.title-profile": "Profile Settings", "settings.title-totp": "Manage 2FA TOTP Authenticator App", "settings.title-webauthn": "Manage Hardware Tokens", + "settings.title-passkey": "Manage Passkeys", "verification.registration-button": "Sign up", "verification.registration-label": "Don't have an account?", "verification.title": "Verify your account" diff --git a/src/locales/es.json b/src/locales/es.json index 2975f3861..49e313248 100644 --- a/src/locales/es.json +++ b/src/locales/es.json @@ -157,6 +157,7 @@ "settings.navigation-profile": "Perfil", "settings.navigation-totp": "Aplicación Autenticadora", "settings.navigation-webauthn": "Tokens de Hardware", + "settings.navigation-passkey": "Passkeys", "settings.subtitle-instructions": "Aquí puede gestionar las configuraciones relacionadas con su cuenta. Tenga en cuenta que ciertas acciones requieren que vuelva a autenticarse.", "settings.title": "Configuraciones de la Cuenta", "settings.title-lookup-secret": "Gestionar Códigos de Recuperación de Respaldo de 2FA", @@ -166,6 +167,7 @@ "settings.title-profile": "Configuraciones del Perfil", "settings.title-totp": "Gestionar Aplicación Autenticadora de 2FA", "settings.title-webauthn": "Gestionar Tokens de Hardware", + "settings.title-passkey": "Gestionar Passkeys", "verification.registration-button": "Registrarse", "verification.registration-label": "¿No tiene una cuenta?", "verification.title": "Verificar su cuenta" diff --git a/src/locales/fr.json b/src/locales/fr.json index c796445dc..6c8fd1e34 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -157,6 +157,7 @@ "settings.navigation-profile": "Profil", "settings.navigation-totp": "Application d'authentification TOTP", "settings.navigation-webauthn": "Tokens matériels", + "settings.navigation-passkey": "Passkeys", "settings.subtitle-instructions": "Ici, vous pouvez gérer les paramètres liés à votre compte. Gardez à l'esprit que certaines actions nécessitent une nouvelle authentification.", "settings.title": "Paramètres du compte", "settings.title-lookup-secret": "Gérer les codes de récupération 2FA", @@ -166,6 +167,7 @@ "settings.title-profile": "Paramètres de profil", "settings.title-totp": "Gérer l'application d'authentification TOTP 2FA", "settings.title-webauthn": "Gérer les tokens matériels", + "settings.title-passkey": "Gérer les Passkeys", "verification.registration-button": "S'inscrire", "verification.registration-label": "Vous n'avez pas de compte ?", "verification.title": "Vérifiez votre compte" diff --git a/src/locales/nl.json b/src/locales/nl.json index 2aaaee0ca..f0a7e6c4e 100644 --- a/src/locales/nl.json +++ b/src/locales/nl.json @@ -157,6 +157,7 @@ "settings.navigation-profile": "Profiel", "settings.navigation-totp": "Authenticator App", "settings.navigation-webauthn": "Hardware Tokens", + "settings.navigation-passkey": "Passkeys", "settings.subtitle-instructions": "Hier kun je instellingen beheren die verband houden met je account. Houd er rekening mee dat bepaalde acties vereisen dat je opnieuw wordt geauthenticeerd.", "settings.title": "Accountinstellingen", "settings.title-lookup-secret": "Beheer 2FA Backup Herstelcodes", @@ -166,6 +167,7 @@ "settings.title-profile": "Profielinstellingen", "settings.title-totp": "Beheer 2FA TOTP Authenticator App", "settings.title-webauthn": "Beheer Hardware Tokens", + "settings.title-passkey": "Beheer Passkeys", "verification.registration-button": "Registreren", "verification.registration-label": "Heb je nog geen account?", "verification.title": "Verifieer je account" diff --git a/src/locales/pt.json b/src/locales/pt.json index 790a22eff..0a621d91e 100644 --- a/src/locales/pt.json +++ b/src/locales/pt.json @@ -157,6 +157,7 @@ "settings.navigation-profile": "Perfil", "settings.navigation-totp": "Aplicação Autenticador 2FA", "settings.navigation-webauthn": "Tokens de Hardware", + "settings.navigation-passkey": "Passkeys", "settings.subtitle-instructions": "Aqui pode gerar configurações relacionadas com a sua conta. Lembre-se de que certas ações exigem que efetue novamente login.", "settings.title": "Configurações da Conta", "settings.title-lookup-secret": "Gerar Códigos de Recuperação de Backup de 2FA", @@ -166,6 +167,7 @@ "settings.title-profile": "Configurações de Perfil", "settings.title-totp": "Gerar Aplicação Autenticador 2FA", "settings.title-webauthn": "Gerar Tokens de Hardware", + "settings.title-passkey": "Gerar Passkeys", "verification.registration-button": "Registar", "verification.registration-label": "Não tem uma conta?", "verification.title": "Verifique a sua conta" diff --git a/src/locales/se.json b/src/locales/se.json index 020f96640..094c328a9 100644 --- a/src/locales/se.json +++ b/src/locales/se.json @@ -157,6 +157,7 @@ "settings.navigation-profile": "Profil", "settings.navigation-totp": "Autentiserings App", "settings.navigation-webauthn": "Hårdvaru Tokens", + "settings.navigation-passkey": "Passkeys", "settings.subtitle-instructions": "Här kan du hantera inställningar relaterade till ditt konto. Tänk på att vissa åtgärder kräver att du autentiseras på nytt.", "settings.title": "Kontoinställningar", "settings.title-lookup-secret": "Hantera 2FA backup-återställningskoder", @@ -166,6 +167,7 @@ "settings.title-profile": "Profilinställningar", "settings.title-totp": "Hantera 2FA TOTP Autentiserings App", "settings.title-webauthn": "Hantera Hårdvaru Tokens", + "settings.title-passkey": "Hantera Passkeys", "verification.registration-button": "Skapa konto", "verification.registration-label": "Har du inget konto?", "verification.title": "Verifiera ditt konto" diff --git a/src/markup-components/components.ts b/src/markup-components/components.ts index cc8ca5b8f..f188adfed 100644 --- a/src/markup-components/components.ts +++ b/src/markup-components/components.ts @@ -58,6 +58,8 @@ import { UserSettingsScreenProps, WebAuthnSettingsProps, WebAuthnSettingsSection as webAuthnSettingsSection, + PasskeySettingsSection as passkeySettingsSection, + PasskeySettingsProps, } from "../react-components" import { ComponentWrapper, Context } from "./component-wrapper" @@ -191,6 +193,13 @@ export const WebAuthnSettingsSection = ( return ComponentWrapper(webAuthnSettingsSection, props, context) } +export const PasskeySettingsSection = ( + props: PasskeySettingsProps, + context: Context = {}, +) => { + return ComponentWrapper(passkeySettingsSection, props, context) +} + export const OIDCSettingsSection = ( props: OIDCSettingsProps, context: Context = {}, diff --git a/src/react-components/ory/helpers/node.tsx b/src/react-components/ory/helpers/node.tsx index 53ade5a7d..8456c9c53 100644 --- a/src/react-components/ory/helpers/node.tsx +++ b/src/react-components/ory/helpers/node.tsx @@ -1,4 +1,4 @@ -import { UiNode, UiText } from "@ory/client" +import { UiNode, UiNodeAttributes, UiText } from "@ory/client" import { isUiNodeAnchorAttributes, isUiNodeImageAttributes, @@ -106,37 +106,37 @@ export const uiTextToFormattedMessage = ( // context might provide an array of objects instead of a single object // for example when looking up a recovery code /* - * - { - "text": { - "id": 1050015, - "text": "3r9noma8, tv14n5tu, ...", - "type": "info", - "context": { - "secrets": [ + * { + "text": { + "id": 1050015, + "text": "3r9noma8, tv14n5tu, ...", + "type": "info", "context": { - "secret": "3r9noma8" - }, - "id": 1050009, - "text": "3r9noma8", - "type": "info" + "secrets": [ + { + "context": { + "secret": "3r9noma8" + }, + "id": 1050009, + "text": "3r9noma8", + "type": "info" + }, + { + "context": { + "secret": "tv14n5tu" + }, + "id": 1050009, + "text": "tv14n5tu", + "type": "info" + }, + ] + } }, - { - "context": { - "secret": "tv14n5tu" - }, - "id": 1050009, - "text": "tv14n5tu", - "type": "info" - }, - ] - } - }, - "id": "lookup_secret_codes", - "node_type": "text" - } - */ + "id": "lookup_secret_codes", + "node_type": "text" + } + */ if (Array.isArray(value)) { return { ...accumulator, @@ -182,6 +182,18 @@ export const uiTextToFormattedMessage = ( ) } +function dataAttributes(attrs: UiNodeAttributes): Record { + return Object.entries(attrs).reduce( + (accumulator, [key, value]) => { + if (key.startsWith("data-")) { + accumulator[key] = value + } + return accumulator + }, + {} as Record, + ) +} + export const Node = ({ node, className, @@ -205,6 +217,7 @@ export const Node = ({ header={formatMessage(node.meta.label)} width={node.attributes.width} height={node.attributes.height} + {...dataAttributes(node.attributes)} /> ) } else if (isUiNodeTextAttributes(node.attributes)) { @@ -307,6 +320,7 @@ export const Node = ({ disabled={attrs.disabled} {...(buttonSocialOverrideProps && buttonSocialOverrideProps)} {...submit} + {...dataAttributes(attrs)} /> ) : (