From 586b28af1cff43252786ad6c6ad6c4e3cd90225c Mon Sep 17 00:00:00 2001 From: giorgoslytos Date: Thu, 16 May 2024 12:53:31 +0300 Subject: [PATCH 1/8] fix: Correction of types on KcContext for account pages --- src/account/kcContext/KcContext.ts | 96 +++++++++++++------------ src/account/kcContext/kcContextMocks.ts | 17 +---- 2 files changed, 53 insertions(+), 60 deletions(-) diff --git a/src/account/kcContext/KcContext.ts b/src/account/kcContext/KcContext.ts index f65a0a7f..9748cd2e 100644 --- a/src/account/kcContext/KcContext.ts +++ b/src/account/kcContext/KcContext.ts @@ -91,15 +91,6 @@ export declare namespace KcContext { username?: string; }; properties: Record; - sessions: { - sessions: { - ipAddress: string; - started?: any; - lastAccess?: any; - expires?: any; - clients: string[]; - }[]; - }; }; export type Password = Common & { @@ -126,11 +117,12 @@ export declare namespace KcContext { pageId: "sessions.ftl"; sessions: { sessions: { - ipAddress: string; - started?: any; - lastAccess?: any; - expires?: any; + expires: string; clients: string[]; + ipAddress: string; + started: string; + lastAccess: string; + id: string; }[]; }; stateChecker: string; @@ -193,12 +185,21 @@ export declare namespace KcContext { stateChecker: string; applications: { applications: { - realmRolesAvailable: { name: string; description: string }[]; + realmRolesAvailable: { + name: string; + description: string; + compositesStream?: Record; + clientRole?: boolean; + composite?: boolean; + id?: string; + containerId?: string; + attributes?: Record; + }[]; resourceRolesAvailable: Record< string, { roleName: string; - roleDescription: string; + roleDescription?: string; clientName: string; clientId: string; }[] @@ -207,41 +208,44 @@ export declare namespace KcContext { clientScopesGranted: string[]; effectiveUrl?: string; client: { - consentScreenText: string; - surrogateAuthRequired: boolean; - bearerOnly: boolean; - id: string; - protocolMappersStream: Record; - includeInTokenScope: boolean; - redirectUris: string[]; - fullScopeAllowed: boolean; - registeredNodes: Record; - enabled: boolean; - clientAuthenticatorType: string; - realmScopeMappingsStream: Record; - scopeMappingsStream: Record; - displayOnConsentScreen: boolean; - clientId: string; - rootUrl: string; - authenticationFlowBindingOverrides: Record; - standardFlowEnabled: boolean; - attributes: Record; - publicClient: boolean; alwaysDisplayInConsole: boolean; + attributes: Record; + authenticationFlowBindingOverrides: Record; + baseUrl?: string; + bearerOnly: boolean; + clientAuthenticatorType: string; + clientId: string; consentRequired: boolean; - notBefore: string; - rolesStream: Record; - protocol: string; - dynamicScope: boolean; + consentScreenText: string; + description: string; directAccessGrantsEnabled: boolean; - name: string; - serviceAccountsEnabled: boolean; + displayOnConsentScreen: boolean; + dynamicScope: boolean; + enabled: boolean; frontchannelLogout: boolean; - nodeReRegistrationTimeout: string; + fullScopeAllowed: boolean; + id: string; implicitFlowEnabled: boolean; - baseUrl: string; - webOrigins: string[]; + includeInTokenScope: boolean; + managementUrl: string; + name?: string; + nodeReRegistrationTimeout: string; + notBefore: string; + protocol: string; + protocolMappersStream: Record; + publicClient: boolean; realm: Record; + realmScopeMappingsStream: Record; + redirectUris: string[]; + registeredNodes: Record; + rolesStream: Record; + rootUrl?: string; + scopeMappingsStream: Record; + secret: string; + serviceAccountsEnabled: boolean; + standardFlowEnabled: boolean; + surrogateAuthRequired: boolean; + webOrigins: string[]; }; }[]; }; @@ -254,8 +258,8 @@ export declare namespace KcContext { date: string | number | Date; event: string; ipAddress: string; - client: any; - details: any[]; + client: string; + details: { value: string; key: string }[]; }[]; }; }; diff --git a/src/account/kcContext/kcContextMocks.ts b/src/account/kcContext/kcContextMocks.ts index 383d94c2..c774b44a 100644 --- a/src/account/kcContext/kcContextMocks.ts +++ b/src/account/kcContext/kcContextMocks.ts @@ -156,17 +156,6 @@ export const kcContextCommonMock: KcContext.Common = { "css/account.css img/icon-sidebar-active.png img/logo.png resources-common/node_modules/patternfly/dist/css/patternfly.min.css resources-common/node_modules/patternfly/dist/css/patternfly-additions.min.css resources-common/node_modules/patternfly/dist/css/patternfly-additions.min.css", "kcButtonClass": "btn", "kcButtonDefaultClass": "btn-default" - }, - "sessions": { - "sessions": [ - { - "ipAddress": "127.0.0.1", - "started": new Date().toString(), - "lastAccess": new Date().toString(), - "expires": new Date().toString(), - "clients": ["Chrome", "Firefox"] - } - ] } }; @@ -200,12 +189,12 @@ export const kcContextMocks: KcContext[] = [ "sessions": { "sessions": [ { - ...kcContextCommonMock.sessions, "ipAddress": "127.0.0.1", "started": new Date().toString(), "lastAccess": new Date().toString(), "expires": new Date().toString(), - "clients": ["Chrome", "Firefox"] + "clients": ["Chrome", "Firefox"], + "id": "f8951177-817d-4a70-9c02-86d3c170fe51" } ] }, @@ -246,7 +235,7 @@ export const kcContextMocks: KcContext[] = [ "event": "login", "ipAddress": "172.17.0.1", "client": "security-admin-console", - "details": ["auth_method = openid-connect, username = admin"] + "details": [{ key: "openid-connect", value: "admin" }] } ] } From def2d8b75b70439766af3b25dd7dffa8ac677e97 Mon Sep 17 00:00:00 2001 From: giorgoslytos Date: Thu, 16 May 2024 14:05:28 +0300 Subject: [PATCH 2/8] fix: Correction of Application page --- src/account/pages/Applications.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/account/pages/Applications.tsx b/src/account/pages/Applications.tsx index d1b82906..051fb2d1 100644 --- a/src/account/pages/Applications.tsx +++ b/src/account/pages/Applications.tsx @@ -61,10 +61,10 @@ export default function Applications(props: PageProps {!isArrayWithEmptyObject(application.realmRolesAvailable) && - application.realmRolesAvailable.map(role => ( + application.realmRolesAvailable.map((role, index) => ( {role.description ? advancedMsg(role.description) : advancedMsg(role.name)} - {role !== application.realmRolesAvailable[application.realmRolesAvailable.length - 1] && ", "} + {index < application.realmRolesAvailable.length - 1 && ", "} ))} {!isArrayWithEmptyObject(application.realmRolesAvailable) && application.resourceRolesAvailable && ", "} From fd538e95ca886500375f3d39cf477084d9e4b02f Mon Sep 17 00:00:00 2001 From: giorgoslytos Date: Thu, 16 May 2024 14:05:58 +0300 Subject: [PATCH 3/8] fix: Correction of import of useGetClassName --- src/account/pages/Log.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/account/pages/Log.tsx b/src/account/pages/Log.tsx index 392873f5..cbec31dd 100644 --- a/src/account/pages/Log.tsx +++ b/src/account/pages/Log.tsx @@ -2,7 +2,7 @@ import type { PageProps } from "keycloakify/account/pages/PageProps"; import type { KcContext } from "../kcContext"; import type { I18n } from "../i18n"; import { Key } from "react"; -import { useGetClassName } from "../lib/useGetClassName"; +import { useGetClassName } from "keycloakify/account/lib/useGetClassName"; export default function Log(props: PageProps, I18n>) { const { kcContext, i18n, doUseDefaultCss, classes, Template } = props; From fb4acc62c4bdbb8aeb54462525de89bdd2f509ff Mon Sep 17 00:00:00 2001 From: giorgoslytos Date: Thu, 16 May 2024 17:09:03 +0300 Subject: [PATCH 4/8] fix: Addition of prop logoutUrl --- src/account/kcContext/KcContext.ts | 1 + src/account/kcContext/kcContextMocks.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/src/account/kcContext/KcContext.ts b/src/account/kcContext/KcContext.ts index 9748cd2e..19ca1a6f 100644 --- a/src/account/kcContext/KcContext.ts +++ b/src/account/kcContext/KcContext.ts @@ -27,6 +27,7 @@ export declare namespace KcContext { sessionsUrl: string; applicationsUrl: string; logUrl: string; + logoutUrl: string; resourceUrl: string; resourcesCommonPath: string; resourcesPath: string; diff --git a/src/account/kcContext/kcContextMocks.ts b/src/account/kcContext/kcContextMocks.ts index c774b44a..69d0a8d4 100644 --- a/src/account/kcContext/kcContextMocks.ts +++ b/src/account/kcContext/kcContextMocks.ts @@ -17,6 +17,7 @@ export const kcContextCommonMock: KcContext.Common = { "resourceUrl": "#", "accountUrl": "#", "applicationsUrl": "#", + "logoutUrl": "#", "getLogoutUrl": () => "#", "logUrl": "#", "passwordUrl": "#", From 19ba0873f525cd42a0d23e1c351f210ead631956 Mon Sep 17 00:00:00 2001 From: giorgoslytos Date: Thu, 16 May 2024 17:11:45 +0300 Subject: [PATCH 5/8] fix: Prune --- src/account/pages/Sessions.tsx | 3 --- src/account/pages/Totp.tsx | 41 +++++++++++++++++----------------- 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/src/account/pages/Sessions.tsx b/src/account/pages/Sessions.tsx index 1bb46355..b97338a2 100644 --- a/src/account/pages/Sessions.tsx +++ b/src/account/pages/Sessions.tsx @@ -12,12 +12,9 @@ export default function Sessions(props: PageProps
diff --git a/src/account/pages/Totp.tsx b/src/account/pages/Totp.tsx index 838d0bf7..201d11d6 100644 --- a/src/account/pages/Totp.tsx +++ b/src/account/pages/Totp.tsx @@ -7,6 +7,7 @@ import { MessageKey } from "keycloakify/account/i18n/i18n"; export default function Totp(props: PageProps, I18n>) { const { kcContext, i18n, doUseDefaultCss, Template, classes } = props; + const { getClassName } = useGetClassName({ doUseDefaultCss, classes @@ -78,7 +79,7 @@ export default function Totp(props: PageProps{msg("totpStep1")}

    - {totp.supportedApplications.map(app => ( + {totp.supportedApplications?.map(app => (
  • {msg(app as MessageKey)}
  • ))}
@@ -99,28 +100,26 @@ export default function Totp(props: PageProps
  • {msg("totpManualStep3")}

    -

    -

      -
    • - {msg("totpType")}: {msg(`totp.${totp.policy.type}`)} +
        +
      • + {msg("totpType")}: {msg(`totp.${totp.policy.type}`)} +
      • +
      • + {msg("totpAlgorithm")}: {algToKeyUriAlg?.[totp.policy.algorithm] ?? totp.policy.algorithm} +
      • +
      • + {msg("totpDigits")}: {totp.policy.digits} +
      • + {totp.policy.type === "totp" ? ( +
      • + {msg("totpInterval")}: {totp.policy.period}
      • -
      • - {msg("totpAlgorithm")}: {algToKeyUriAlg?.[totp.policy.algorithm] ?? totp.policy.algorithm} + ) : ( +
      • + {msg("totpCounter")}: {totp.policy.initialCounter}
      • -
      • - {msg("totpDigits")}: {totp.policy.digits} -
      • - {totp.policy.type === "totp" ? ( -
      • - {msg("totpInterval")}: {totp.policy.period} -
      • - ) : ( -
      • - {msg("totpCounter")}: {totp.policy.initialCounter} -
      • - )} -
      -

      + )} +
  • ) : ( From 346e3df0092282737deecf7b7a795e37f2472d55 Mon Sep 17 00:00:00 2001 From: giorgoslytos Date: Fri, 17 May 2024 12:14:47 +0300 Subject: [PATCH 6/8] feat: Addition of FederatedIdentity Account Page --- src/account/Fallback.tsx | 3 + src/account/kcContext/KcContext.ts | 23 +++++++- src/account/kcContext/kcContextMocks.ts | 16 +++++ src/account/pages/FederatedIdentity.tsx | 58 +++++++++++++++++++ src/bin/keycloakify/generateFtl/pageId.ts | 10 +++- .../pages/FederatedIdentity.stories.tsx | 34 +++++++++++ 6 files changed, 142 insertions(+), 2 deletions(-) create mode 100644 src/account/pages/FederatedIdentity.tsx create mode 100644 stories/account/pages/FederatedIdentity.stories.tsx diff --git a/src/account/Fallback.tsx b/src/account/Fallback.tsx index 8fe62daf..d19f3227 100644 --- a/src/account/Fallback.tsx +++ b/src/account/Fallback.tsx @@ -3,6 +3,7 @@ import type { PageProps } from "keycloakify/account/pages/PageProps"; import type { I18n } from "keycloakify/account/i18n"; import type { KcContext } from "./kcContext"; import { assert, type Equals } from "tsafe/assert"; +import FederatedIdentity from "./pages/FederatedIdentity"; const Password = lazy(() => import("keycloakify/account/pages/Password")); const Account = lazy(() => import("keycloakify/account/pages/Account")); @@ -30,6 +31,8 @@ export default function Fallback(props: PageProps) { return ; case "log.ftl": return ; + case "federatedIdentity.ftl": + return ; } assert>(false); })()} diff --git a/src/account/kcContext/KcContext.ts b/src/account/kcContext/KcContext.ts index 19ca1a6f..9b32c0cf 100644 --- a/src/account/kcContext/KcContext.ts +++ b/src/account/kcContext/KcContext.ts @@ -3,7 +3,14 @@ import { assert } from "tsafe/assert"; import type { Equals } from "tsafe"; import { type ThemeType } from "keycloakify/bin/constants"; -export type KcContext = KcContext.Password | KcContext.Account | KcContext.Sessions | KcContext.Totp | KcContext.Applications | KcContext.Log; +export type KcContext = + | KcContext.Password + | KcContext.Account + | KcContext.Sessions + | KcContext.Totp + | KcContext.Applications + | KcContext.Log + | KcContext.FederatedIdentity; export declare namespace KcContext { export type Common = { @@ -264,6 +271,20 @@ export declare namespace KcContext { }[]; }; }; + + export type FederatedIdentity = Common & { + pageId: "federatedIdentity.ftl"; + stateChecker: string; + federatedIdentity: { + identities: { + providerId: string; + displayName: string; + userName: string; + connected: boolean; + }[]; + removeLinkPossible: boolean; + }; + }; } { diff --git a/src/account/kcContext/kcContextMocks.ts b/src/account/kcContext/kcContextMocks.ts index 69d0a8d4..1053b367 100644 --- a/src/account/kcContext/kcContextMocks.ts +++ b/src/account/kcContext/kcContextMocks.ts @@ -240,5 +240,21 @@ export const kcContextMocks: KcContext[] = [ } ] } + }), + id({ + ...kcContextCommonMock, + "stateChecker": "", + "pageId": "federatedIdentity.ftl", + "federatedIdentity": { + "identities": [ + { + "providerId": "keycloak-oidc", + "displayName": "keycloak-oidc", + "userName": "John", + "connected": true + } + ], + "removeLinkPossible": true + } }) ]; diff --git a/src/account/pages/FederatedIdentity.tsx b/src/account/pages/FederatedIdentity.tsx new file mode 100644 index 00000000..91833952 --- /dev/null +++ b/src/account/pages/FederatedIdentity.tsx @@ -0,0 +1,58 @@ +import { PageProps } from "keycloakify/account"; +import { I18n } from "keycloakify/account/i18n"; +import { KcContext } from "keycloakify/account/kcContext"; + +export default function FederatedIdentity(props: PageProps, I18n>) { + const { kcContext, i18n, doUseDefaultCss, classes, Template } = props; + + const { url, federatedIdentity, stateChecker } = kcContext; + const { msg } = i18n; + return ( + + ); +} diff --git a/src/bin/keycloakify/generateFtl/pageId.ts b/src/bin/keycloakify/generateFtl/pageId.ts index e0dce92c..cd1083c8 100644 --- a/src/bin/keycloakify/generateFtl/pageId.ts +++ b/src/bin/keycloakify/generateFtl/pageId.ts @@ -27,7 +27,15 @@ export const loginThemePageIds = [ "saml-post-form.ftl" ] as const; -export const accountThemePageIds = ["password.ftl", "account.ftl", "sessions.ftl", "totp.ftl", "applications.ftl", "log.ftl"] as const; +export const accountThemePageIds = [ + "password.ftl", + "account.ftl", + "sessions.ftl", + "totp.ftl", + "applications.ftl", + "log.ftl", + "federatedIdentity.ftl" +] as const; export type LoginThemePageId = (typeof loginThemePageIds)[number]; export type AccountThemePageId = (typeof accountThemePageIds)[number]; diff --git a/stories/account/pages/FederatedIdentity.stories.tsx b/stories/account/pages/FederatedIdentity.stories.tsx new file mode 100644 index 00000000..ab9d782c --- /dev/null +++ b/stories/account/pages/FederatedIdentity.stories.tsx @@ -0,0 +1,34 @@ +import React from "react"; +import { Meta } from "@storybook/react"; +import { createPageStory } from "../createPageStory"; + +const pageId = "federatedIdentity.ftl"; + +const { PageStory } = createPageStory({ pageId }); + +const meta = { + title: "account/FederatedIdentity", + component: PageStory +} satisfies Meta; + +export default meta; + +export const Default = () => ; + +export const NotConnected = () => ( + +); From e533e127bffa559a49aa4ccc5a1e91fa4c776a6d Mon Sep 17 00:00:00 2001 From: giorgoslytos Date: Fri, 17 May 2024 12:16:36 +0300 Subject: [PATCH 7/8] feat: Addition of stories for account pages that were missing them --- .../account/pages/Authenticator.stories.tsx | 173 +++++++++ stories/account/pages/Log.stories.tsx | 354 ++++++++++++++++++ 2 files changed, 527 insertions(+) create mode 100644 stories/account/pages/Authenticator.stories.tsx create mode 100644 stories/account/pages/Log.stories.tsx diff --git a/stories/account/pages/Authenticator.stories.tsx b/stories/account/pages/Authenticator.stories.tsx new file mode 100644 index 00000000..2f229056 --- /dev/null +++ b/stories/account/pages/Authenticator.stories.tsx @@ -0,0 +1,173 @@ +import React from "react"; +import { Meta } from "@storybook/react"; +import { createPageStory } from "../createPageStory"; + +const { PageStory } = createPageStory({ + pageId: "totp.ftl" +}); + +const meta = { + title: "account/Authenticator", + component: PageStory +} satisfies Meta; +export default meta; + +export const Default = () => ( + +); + +export const WithTotpEnabled = () => ( + +); + +export const WithManualMode = () => ( + +); + +export const MoreThanOneTotpProviders = () => ( + +); diff --git a/stories/account/pages/Log.stories.tsx b/stories/account/pages/Log.stories.tsx new file mode 100644 index 00000000..8e1fdfe5 --- /dev/null +++ b/stories/account/pages/Log.stories.tsx @@ -0,0 +1,354 @@ +import React from "react"; +import { Meta } from "@storybook/react"; +import { createPageStory } from "../createPageStory"; + +const pageId = "log.ftl"; + +const { PageStory } = createPageStory({ + pageId +}); + +const meta = { + title: "account/Log", + component: PageStory +} satisfies Meta; + +export default meta; + +export const Default = () => ( + +); From a664195625e2aed7e50f8c380f5e659a2aba6835 Mon Sep 17 00:00:00 2001 From: giorgoslytos Date: Fri, 17 May 2024 12:17:17 +0300 Subject: [PATCH 8/8] fix: Use of 'Meta' from storybook instead of 'ComponentMeta' --- stories/account/pages/Account.stories.tsx | 25 ++++----- stories/account/pages/Pasword.stories.tsx | 18 ++----- stories/account/pages/Sessions.stories.tsx | 59 ++++++++++++++++------ stories/account/pages/Totp.stories.tsx | 18 ++----- 4 files changed, 64 insertions(+), 56 deletions(-) diff --git a/stories/account/pages/Account.stories.tsx b/stories/account/pages/Account.stories.tsx index 64f1d8ca..5e197369 100644 --- a/stories/account/pages/Account.stories.tsx +++ b/stories/account/pages/Account.stories.tsx @@ -1,24 +1,19 @@ import React from "react"; -import type { ComponentMeta } from "@storybook/react"; +import { Meta, StoryObj } from "@storybook/react"; import { createPageStory } from "../createPageStory"; const pageId = "account.ftl"; const { PageStory } = createPageStory({ pageId }); -const meta: ComponentMeta = { - title: `account/${pageId}`, - component: PageStory, - parameters: { - viewMode: "story", - previewTabs: { - "storybook/docs/panel": { - hidden: true - } - } - } -}; - +const meta = { + title: "account/Account", + component: PageStory +} satisfies Meta; export default meta; -export const Default = () => ; +type Story = StoryObj; + +export const Default: Story = { + render: () => +}; diff --git a/stories/account/pages/Pasword.stories.tsx b/stories/account/pages/Pasword.stories.tsx index 637a0c03..e385fcfa 100644 --- a/stories/account/pages/Pasword.stories.tsx +++ b/stories/account/pages/Pasword.stories.tsx @@ -1,23 +1,15 @@ import React from "react"; -import type { ComponentMeta } from "@storybook/react"; +import { Meta } from "@storybook/react"; import { createPageStory } from "../createPageStory"; const pageId = "password.ftl"; const { PageStory } = createPageStory({ pageId }); -const meta: ComponentMeta = { - title: `account/${pageId}`, - component: PageStory, - parameters: { - viewMode: "story", - previewTabs: { - "storybook/docs/panel": { - hidden: true - } - } - } -}; +const meta = { + title: "account/Password", + component: PageStory +} satisfies Meta; export default meta; diff --git a/stories/account/pages/Sessions.stories.tsx b/stories/account/pages/Sessions.stories.tsx index 250c53b0..462a2c98 100644 --- a/stories/account/pages/Sessions.stories.tsx +++ b/stories/account/pages/Sessions.stories.tsx @@ -1,26 +1,55 @@ import React from "react"; -import type { ComponentMeta } from "@storybook/react"; +import { Meta } from "@storybook/react"; import { createPageStory } from "../createPageStory"; const pageId = "sessions.ftl"; const { PageStory } = createPageStory({ pageId }); -const meta: ComponentMeta = { - title: `account/${pageId}`, - component: PageStory, - parameters: { - viewMode: "story", - previewTabs: { - "storybook/docs/panel": { - hidden: true - } - } - } -}; +const meta = { + title: "account/Sessions", + component: PageStory +} satisfies Meta; export default meta; -export const Default = () => ; +export const Default = () => ( + +); -export const WithMessage = () => ; +export const WithError = () => ( + +); diff --git a/stories/account/pages/Totp.stories.tsx b/stories/account/pages/Totp.stories.tsx index 265d76a6..c6e9f4ad 100644 --- a/stories/account/pages/Totp.stories.tsx +++ b/stories/account/pages/Totp.stories.tsx @@ -1,23 +1,15 @@ import React from "react"; -import type { ComponentMeta } from "@storybook/react"; +import { Meta } from "@storybook/react"; import { createPageStory } from "../createPageStory"; const pageId = "totp.ftl"; const { PageStory } = createPageStory({ pageId }); -const meta: ComponentMeta = { - title: `account/${pageId}`, - component: PageStory, - parameters: { - viewMode: "story", - previewTabs: { - "storybook/docs/panel": { - hidden: true - } - } - } -}; +const meta = { + title: "account/Authenticator", + component: PageStory +} satisfies Meta; export default meta;