From de47525d7c84d8802a29e2c590d365fd3d69772a Mon Sep 17 00:00:00 2001 From: giorgoslytos Date: Mon, 19 Feb 2024 17:29:46 +0200 Subject: [PATCH] feat: Addition of Application Account page --- src/account/Fallback.tsx | 3 + src/account/kcContext/KcContext.ts | 67 ++++++++++- src/account/kcContext/kcContextMocks.ts | 2 +- src/account/pages/Applications.tsx | 138 ++++++++++++++++++++++ src/bin/keycloakify/generateFtl/pageId.ts | 2 +- 5 files changed, 209 insertions(+), 3 deletions(-) create mode 100644 src/account/pages/Applications.tsx diff --git a/src/account/Fallback.tsx b/src/account/Fallback.tsx index 8ef67146..03e07d49 100644 --- a/src/account/Fallback.tsx +++ b/src/account/Fallback.tsx @@ -8,6 +8,7 @@ const Password = lazy(() => import("keycloakify/account/pages/Password")); const Account = lazy(() => import("keycloakify/account/pages/Account")); const Sessions = lazy(() => import("keycloakify/account/pages/Sessions")); const Totp = lazy(() => import("keycloakify/account/pages/Totp")); +const Applications = lazy(() => import("keycloakify/account/pages/Applications")); export default function Fallback(props: PageProps) { const { kcContext, ...rest } = props; @@ -24,6 +25,8 @@ export default function Fallback(props: PageProps) { return ; case "totp.ftl": return ; + case "applications.ftl": + return ; } assert>(false); })()} diff --git a/src/account/kcContext/KcContext.ts b/src/account/kcContext/KcContext.ts index 1cce3b2c..ad6cedce 100644 --- a/src/account/kcContext/KcContext.ts +++ b/src/account/kcContext/KcContext.ts @@ -3,7 +3,7 @@ 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; +export type KcContext = KcContext.Password | KcContext.Account | KcContext.Sessions | KcContext.Totp | KcContext.Applications; export declare namespace KcContext { export type Common = { @@ -180,6 +180,71 @@ export declare namespace KcContext { }; stateChecker: string; }; + + export type Applications = Common & { + pageId: "applications.ftl"; + features: { + log: boolean; + identityFederation: boolean; + authorization: boolean; + passwordUpdateSupported: boolean; + }; + stateChecker: string; + applications: { + applications: { + realmRolesAvailable: { name: string; description: string }[]; + resourceRolesAvailable: Record< + string, + { + roleName: string; + roleDescription: string; + clientName: string; + clientId: string; + }[] + >; + additionalGrants: string[]; + 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; + consentRequired: boolean; + notBefore: string; + rolesStream: Record; + protocol: string; + dynamicScope: boolean; + directAccessGrantsEnabled: boolean; + name: string; + serviceAccountsEnabled: boolean; + frontchannelLogout: boolean; + nodeReRegistrationTimeout: string; + implicitFlowEnabled: boolean; + baseUrl: string; + webOrigins: string[]; + realm: Record; + }; + }[]; + }; + }; } { diff --git a/src/account/kcContext/kcContextMocks.ts b/src/account/kcContext/kcContextMocks.ts index 6f52d8d3..1afd18f3 100644 --- a/src/account/kcContext/kcContextMocks.ts +++ b/src/account/kcContext/kcContextMocks.ts @@ -198,7 +198,7 @@ export const kcContextMocks: KcContext[] = [ } ] }, - "stateChecker": "" + "stateChecker": "g6WB1FaYnKotTkiy7ZrlxvFztSqS0U8jvHsOOOb2z4g" }), id({ ...kcContextCommonMock, diff --git a/src/account/pages/Applications.tsx b/src/account/pages/Applications.tsx new file mode 100644 index 00000000..c1a51da4 --- /dev/null +++ b/src/account/pages/Applications.tsx @@ -0,0 +1,138 @@ +import { clsx } from "keycloakify/tools/clsx"; +import type { PageProps } from "keycloakify/account/pages/PageProps"; +import { useGetClassName } from "keycloakify/account/lib/useGetClassName"; +import type { KcContext } from "../kcContext"; +import type { I18n } from "../i18n"; + +function isArrayWithEmptyObject(variable: any): boolean { + return Array.isArray(variable) && variable.length === 1 && typeof variable[0] === "object" && Object.keys(variable[0]).length === 0; +} + +export default function Applications(props: PageProps, I18n>) { + const { kcContext, i18n, doUseDefaultCss, classes, Template } = props; + + const { getClassName } = useGetClassName({ + doUseDefaultCss, + classes + }); + + const { + url, + applications: { applications }, + stateChecker + } = kcContext; + + const { msg, advancedMsg } = i18n; + + return ( + + ); +} diff --git a/src/bin/keycloakify/generateFtl/pageId.ts b/src/bin/keycloakify/generateFtl/pageId.ts index 3688198c..3188198f 100644 --- a/src/bin/keycloakify/generateFtl/pageId.ts +++ b/src/bin/keycloakify/generateFtl/pageId.ts @@ -27,7 +27,7 @@ export const loginThemePageIds = [ "saml-post-form.ftl" ] as const; -export const accountThemePageIds = ["password.ftl", "account.ftl", "sessions.ftl", "totp.ftl"] as const; +export const accountThemePageIds = ["password.ftl", "account.ftl", "sessions.ftl", "totp.ftl", "applications.ftl"] as const; export type LoginThemePageId = (typeof loginThemePageIds)[number]; export type AccountThemePageId = (typeof accountThemePageIds)[number];