From c9d7fc1b6ed5a0721095cef6d856462876ac5d26 Mon Sep 17 00:00:00 2001
From: Nima Shkouhfar
Date: Sun, 29 Sep 2024 04:35:02 -0400
Subject: [PATCH 01/77] Changes: - First draft of test coverage improvement for
storybooks - code's page html rendering issue fixed
---
src/login/pages/Code.tsx | 10 +-
stories/login/pages/Code.stories.tsx | 39 ++++++
.../pages/DeleteAccountConfirm.stories.tsx | 30 ++++
.../login/pages/DeleteCredential.stories.tsx | 10 ++
stories/login/pages/Error.stories.tsx | 35 +++++
.../pages/FrontchannelLogout.stories.tsx | 11 ++
.../pages/IdpReviewUserProfile.stories.tsx | 44 ++++++
stories/login/pages/Info.stories.tsx | 39 ++++++
stories/login/pages/Login.stories.tsx | 128 ++++++++++++++++++
.../login/pages/LoginConfigTotp.stories.tsx | 21 +++
.../login/pages/LoginIdpLinkEmail.stories.tsx | 46 +++++++
stories/login/pages/Register.stories.tsx | 62 +++++++++
stories/login/pages/Terms.stories.tsx | 29 ++++
13 files changed, 503 insertions(+), 1 deletion(-)
diff --git a/src/login/pages/Code.tsx b/src/login/pages/Code.tsx
index 576a2ccd..4bca62f6 100644
--- a/src/login/pages/Code.tsx
+++ b/src/login/pages/Code.tsx
@@ -2,6 +2,7 @@ import { getKcClsx } from "keycloakify/login/lib/kcClsx";
import type { PageProps } from "keycloakify/login/pages/PageProps";
import type { KcContext } from "../KcContext";
import type { I18n } from "../i18n";
+import { kcSanitize } from "keycloakify/lib/kcSanitize";
export default function Code(props: PageProps, I18n>) {
const { kcContext, i18n, doUseDefaultCss, Template, classes } = props;
@@ -30,7 +31,14 @@ export default function Code(props: PageProps
>
) : (
- {code.error}
+ code.error && (
+
+ )
)}
diff --git a/stories/login/pages/Code.stories.tsx b/stories/login/pages/Code.stories.tsx
index 0fcdf87f..b93125bf 100644
--- a/stories/login/pages/Code.stories.tsx
+++ b/stories/login/pages/Code.stories.tsx
@@ -16,3 +16,42 @@ type Story = StoryObj;
export const Default: Story = {
render: () =>
};
+export const WithErrorCode: Story = {
+ render: () => (
+
+ )
+};
+export const WithFrenchLanguage: Story = {
+ render: () => (
+
+ )
+};
+export const WithHtmlErrorMessage: Story = {
+ render: () => (
+ Try again"
+ }
+ }}
+ />
+ )
+};
diff --git a/stories/login/pages/DeleteAccountConfirm.stories.tsx b/stories/login/pages/DeleteAccountConfirm.stories.tsx
index 501fa0c4..0d865dfe 100644
--- a/stories/login/pages/DeleteAccountConfirm.stories.tsx
+++ b/stories/login/pages/DeleteAccountConfirm.stories.tsx
@@ -16,3 +16,33 @@ type Story = StoryObj;
export const Default: Story = {
render: () =>
};
+export const WithAIAFlow: Story = {
+ render: () => (
+
+ )
+};
+export const WithoutAIAFlow: Story = {
+ render: () => (
+
+ )
+};
+export const WithCustomButtonStyle: Story = {
+ render: () => (
+
+ )
+};
diff --git a/stories/login/pages/DeleteCredential.stories.tsx b/stories/login/pages/DeleteCredential.stories.tsx
index 7b211a52..38619d5b 100644
--- a/stories/login/pages/DeleteCredential.stories.tsx
+++ b/stories/login/pages/DeleteCredential.stories.tsx
@@ -16,3 +16,13 @@ type Story = StoryObj;
export const Default: Story = {
render: () =>
};
+export const WithCustomCredentialLabel: Story = {
+ render: () => (
+
+ )
+};
diff --git a/stories/login/pages/Error.stories.tsx b/stories/login/pages/Error.stories.tsx
index 7b12410e..e64ea3f8 100644
--- a/stories/login/pages/Error.stories.tsx
+++ b/stories/login/pages/Error.stories.tsx
@@ -26,3 +26,38 @@ export const WithAnotherMessage: Story = {
/>
)
};
+
+export const WithHtmlErrorMessage: Story = {
+ render: () => (
+ Error: Something went wrong. Go back"
+ }
+ }}
+ />
+ )
+};
+export const FrenchError: Story = {
+ render: () => (
+
+ )
+};
+export const WithSkipLink: Story = {
+ render: () => (
+
+ )
+};
diff --git a/stories/login/pages/FrontchannelLogout.stories.tsx b/stories/login/pages/FrontchannelLogout.stories.tsx
index 9dacf0b0..cdef7c2c 100644
--- a/stories/login/pages/FrontchannelLogout.stories.tsx
+++ b/stories/login/pages/FrontchannelLogout.stories.tsx
@@ -16,3 +16,14 @@ type Story = StoryObj;
export const Default: Story = {
render: () =>
};
+export const WithoutRedirectUrl: Story = {
+ render: () => (
+
+ )
+};
diff --git a/stories/login/pages/IdpReviewUserProfile.stories.tsx b/stories/login/pages/IdpReviewUserProfile.stories.tsx
index 6778e77d..93eb5b30 100644
--- a/stories/login/pages/IdpReviewUserProfile.stories.tsx
+++ b/stories/login/pages/IdpReviewUserProfile.stories.tsx
@@ -16,3 +16,47 @@ type Story = StoryObj;
export const Default: Story = {
render: () =>
};
+export const WithFormValidationErrors: Story = {
+ render: () => (
+ ["email", "firstName"].includes(fieldName),
+ get: (fieldName: string) => {
+ if (fieldName === "email") return "Invalid email format.";
+ if (fieldName === "firstName") return "First name is required.";
+ }
+ }
+ }}
+ />
+ )
+};
+export const WithReadOnlyFields: Story = {
+ render: () => (
+
+ )
+};
+export const WithPrefilledFormFields: Story = {
+ render: () => (
+
+ )
+};
diff --git a/stories/login/pages/Info.stories.tsx b/stories/login/pages/Info.stories.tsx
index 195061f3..81884dce 100644
--- a/stories/login/pages/Info.stories.tsx
+++ b/stories/login/pages/Info.stories.tsx
@@ -55,3 +55,42 @@ export const WithRequiredActions: Story = {
/>
)
};
+export const WithPageRedirect: Story = {
+ render: () => (
+
+ )
+};
+export const WithoutClientBaseUrl: Story = {
+ render: () => (
+
+ )
+};
+export const WithMessageHeader: Story = {
+ render: () => (
+
+ )
+};
+export const WithAdvancedMessage: Story = {
+ render: () => (
+ important information." }
+ }}
+ />
+ )
+};
diff --git a/stories/login/pages/Login.stories.tsx b/stories/login/pages/Login.stories.tsx
index 075d1f98..a3743adb 100644
--- a/stories/login/pages/Login.stories.tsx
+++ b/stories/login/pages/Login.stories.tsx
@@ -231,3 +231,131 @@ export const WithErrorMessage: Story = {
/>
)
};
+
+export const WithOneSocialProvider: Story = {
+ render: args => (
+
+ )
+};
+
+export const WithTwoSocialProviders: Story = {
+ render: args => (
+
+ )
+};
+export const WithNoSocialProviders: Story = {
+ render: args => (
+
+ )
+};
+export const WithMoreThanTwoSocialProviders: Story = {
+ render: args => (
+
+ )
+};
+export const WithSocialProvidersAndWithoutRememberMe: Story = {
+ render: args => (
+
+ )
+};
diff --git a/stories/login/pages/LoginConfigTotp.stories.tsx b/stories/login/pages/LoginConfigTotp.stories.tsx
index 5d38df9b..743d38c2 100644
--- a/stories/login/pages/LoginConfigTotp.stories.tsx
+++ b/stories/login/pages/LoginConfigTotp.stories.tsx
@@ -41,3 +41,24 @@ export const WithError: Story = {
/>
)
};
+export const WithAppInitiatedAction: Story = {
+ render: () => (
+
+ )
+};
+
+export const WithPreFilledUserLabel: Story = {
+ render: () => (
+
+ )
+};
diff --git a/stories/login/pages/LoginIdpLinkEmail.stories.tsx b/stories/login/pages/LoginIdpLinkEmail.stories.tsx
index a58ae2d3..e855eed5 100644
--- a/stories/login/pages/LoginIdpLinkEmail.stories.tsx
+++ b/stories/login/pages/LoginIdpLinkEmail.stories.tsx
@@ -16,3 +16,49 @@ type Story = StoryObj;
export const Default: Story = {
render: () =>
};
+export const WithIdpAlias: Story = {
+ render: () => (
+
+ )
+};
+export const WithoutIdpAlias: Story = {
+ render: () => (
+
+ )
+};
+
+export const WithCustomRealmDisplayName: Story = {
+ render: () => (
+
+ )
+};
diff --git a/stories/login/pages/Register.stories.tsx b/stories/login/pages/Register.stories.tsx
index 0a8c395f..11e0a8a7 100644
--- a/stories/login/pages/Register.stories.tsx
+++ b/stories/login/pages/Register.stories.tsx
@@ -185,3 +185,65 @@ export const WithTermsAcceptance: Story = {
/>
)
};
+export const WithTermsNotAccepted: Story = {
+ render: args => (
+ fieldName === "termsAccepted",
+ get: (fieldName: string) => (fieldName === "termsAccepted" ? "You must accept the terms." : undefined)
+ }
+ }}
+ />
+ )
+};
+export const WithFieldErrors: Story = {
+ render: () => (
+ ["username", "email"].includes(fieldName),
+ get: fieldName => {
+ if (fieldName === "username") return "Username is required.";
+ if (fieldName === "email") return "Invalid email format.";
+ }
+ }
+ }}
+ />
+ )
+};
+export const WithReadOnlyFields: Story = {
+ render: () => (
+
+ )
+};
+export const WithAutoGeneratedUsername: Story = {
+ render: () => (
+
+ )
+};
diff --git a/stories/login/pages/Terms.stories.tsx b/stories/login/pages/Terms.stories.tsx
index f5837b07..631fe685 100644
--- a/stories/login/pages/Terms.stories.tsx
+++ b/stories/login/pages/Terms.stories.tsx
@@ -45,3 +45,32 @@ export const French: Story = {
/>
)
};
+export const WithErrorMessage: Story = {
+ render: () => (
+ true,
+ get: () => "An error occurred while processing your request."
+ }
+ }}
+ />
+ )
+};
+
+export const Spanish: Story = {
+ render: () => (
+ Mis tΓ©rminos en EspaΓ±ol
"
+ }
+ }
+ }}
+ />
+ )
+};
From da3023cf5e7ddfa70df33d4d0f888fb3bfdcdf8d Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Mon, 30 Sep 2024 00:31:27 +0200
Subject: [PATCH 02/77] Refactor: Make ClassKey importable without having react
as a dependency
---
src/account/TemplateProps.ts | 16 +----
src/account/lib/kcClsx.ts | 18 ++++-
src/login/TemplateProps.ts | 127 +---------------------------------
src/login/lib/kcClsx.ts | 129 ++++++++++++++++++++++++++++++++++-
4 files changed, 145 insertions(+), 145 deletions(-)
diff --git a/src/account/TemplateProps.ts b/src/account/TemplateProps.ts
index 0e5196d2..d8f26cbd 100644
--- a/src/account/TemplateProps.ts
+++ b/src/account/TemplateProps.ts
@@ -1,4 +1,5 @@
import type { ReactNode } from "react";
+import type { ClassKey } from "keycloakify/account/lib/kcClsx";
export type TemplateProps = {
kcContext: KcContext;
@@ -10,17 +11,4 @@ export type TemplateProps = {
active: string;
};
-export type ClassKey =
- | "kcHtmlClass"
- | "kcBodyClass"
- | "kcButtonClass"
- | "kcButtonPrimaryClass"
- | "kcButtonLargeClass"
- | "kcButtonDefaultClass"
- | "kcContentWrapperClass"
- | "kcFormClass"
- | "kcFormGroupClass"
- | "kcInputWrapperClass"
- | "kcLabelClass"
- | "kcInputClass"
- | "kcInputErrorMessageClass";
+export type { ClassKey };
diff --git a/src/account/lib/kcClsx.ts b/src/account/lib/kcClsx.ts
index 330e0c4f..33df4515 100644
--- a/src/account/lib/kcClsx.ts
+++ b/src/account/lib/kcClsx.ts
@@ -1,5 +1,19 @@
import { createGetKcClsx } from "keycloakify/lib/getKcClsx";
-import type { ClassKey } from "keycloakify/account/TemplateProps";
+
+export type ClassKey =
+ | "kcHtmlClass"
+ | "kcBodyClass"
+ | "kcButtonClass"
+ | "kcButtonPrimaryClass"
+ | "kcButtonLargeClass"
+ | "kcButtonDefaultClass"
+ | "kcContentWrapperClass"
+ | "kcFormClass"
+ | "kcFormGroupClass"
+ | "kcInputWrapperClass"
+ | "kcLabelClass"
+ | "kcInputClass"
+ | "kcInputErrorMessageClass";
export const { getKcClsx } = createGetKcClsx({
defaultClasses: {
@@ -20,6 +34,4 @@ export const { getKcClsx } = createGetKcClsx({
}
});
-export type { ClassKey };
-
export type KcClsx = ReturnType["kcClsx"];
diff --git a/src/login/TemplateProps.ts b/src/login/TemplateProps.ts
index 0e3b2895..b3b8f7c6 100644
--- a/src/login/TemplateProps.ts
+++ b/src/login/TemplateProps.ts
@@ -1,4 +1,5 @@
import type { ReactNode } from "react";
+import type { ClassKey } from "keycloakify/login/lib/kcClsx";
export type TemplateProps = {
kcContext: KcContext;
@@ -18,128 +19,4 @@ export type TemplateProps = {
bodyClassName?: string;
};
-export type ClassKey =
- | "kcBodyClass"
- | "kcHeaderWrapperClass"
- | "kcLocaleWrapperClass"
- | "kcInfoAreaWrapperClass"
- | "kcFormButtonsWrapperClass"
- | "kcFormOptionsWrapperClass"
- | "kcCheckboxInputClass"
- | "kcLocaleDropDownClass"
- | "kcLocaleListItemClass"
- | "kcContentWrapperClass"
- | "kcLogoIdP-facebook"
- | "kcAuthenticatorOTPClass"
- | "kcLogoIdP-bitbucket"
- | "kcAuthenticatorWebAuthnClass"
- | "kcWebAuthnDefaultIcon"
- | "kcLogoIdP-stackoverflow"
- | "kcSelectAuthListItemClass"
- | "kcLogoIdP-microsoft"
- | "kcLoginOTPListItemHeaderClass"
- | "kcLocaleItemClass"
- | "kcLoginOTPListItemIconBodyClass"
- | "kcInputHelperTextAfterClass"
- | "kcFormClass"
- | "kcSelectAuthListClass"
- | "kcInputClassRadioCheckboxLabelDisabled"
- | "kcSelectAuthListItemIconClass"
- | "kcRecoveryCodesWarning"
- | "kcFormSettingClass"
- | "kcWebAuthnBLE"
- | "kcInputWrapperClass"
- | "kcSelectAuthListItemArrowIconClass"
- | "kcFeedbackAreaClass"
- | "kcFormPasswordVisibilityButtonClass"
- | "kcLogoIdP-google"
- | "kcCheckLabelClass"
- | "kcSelectAuthListItemFillClass"
- | "kcAuthenticatorDefaultClass"
- | "kcLogoIdP-gitlab"
- | "kcFormAreaClass"
- | "kcFormButtonsClass"
- | "kcInputClassRadioLabel"
- | "kcAuthenticatorWebAuthnPasswordlessClass"
- | "kcSelectAuthListItemHeadingClass"
- | "kcInfoAreaClass"
- | "kcLogoLink"
- | "kcContainerClass"
- | "kcSelectAuthListItemTitle"
- | "kcHtmlClass"
- | "kcLoginOTPListItemTitleClass"
- | "kcLogoIdP-openshift-v4"
- | "kcWebAuthnUnknownIcon"
- | "kcFormSocialAccountNameClass"
- | "kcLogoIdP-openshift-v3"
- | "kcLoginOTPListInputClass"
- | "kcWebAuthnUSB"
- | "kcInputClassRadio"
- | "kcWebAuthnKeyIcon"
- | "kcFeedbackInfoIcon"
- | "kcCommonLogoIdP"
- | "kcRecoveryCodesActions"
- | "kcFormGroupHeader"
- | "kcFormSocialAccountSectionClass"
- | "kcLogoIdP-instagram"
- | "kcAlertClass"
- | "kcHeaderClass"
- | "kcLabelWrapperClass"
- | "kcFormPasswordVisibilityIconShow"
- | "kcFormSocialAccountLinkClass"
- | "kcLocaleMainClass"
- | "kcInputGroup"
- | "kcTextareaClass"
- | "kcButtonBlockClass"
- | "kcButtonClass"
- | "kcWebAuthnNFC"
- | "kcLocaleClass"
- | "kcInputClassCheckboxInput"
- | "kcFeedbackErrorIcon"
- | "kcInputLargeClass"
- | "kcInputErrorMessageClass"
- | "kcRecoveryCodesList"
- | "kcFormSocialAccountListClass"
- | "kcAlertTitleClass"
- | "kcAuthenticatorPasswordClass"
- | "kcCheckInputClass"
- | "kcLogoIdP-linkedin"
- | "kcLogoIdP-twitter"
- | "kcFeedbackWarningIcon"
- | "kcResetFlowIcon"
- | "kcSelectAuthListItemIconPropertyClass"
- | "kcFeedbackSuccessIcon"
- | "kcLoginOTPListClass"
- | "kcSrOnlyClass"
- | "kcFormSocialAccountListGridClass"
- | "kcButtonDefaultClass"
- | "kcFormGroupErrorClass"
- | "kcSelectAuthListItemDescriptionClass"
- | "kcSelectAuthListItemBodyClass"
- | "kcWebAuthnInternal"
- | "kcSelectAuthListItemArrowClass"
- | "kcCheckClass"
- | "kcContentClass"
- | "kcLogoClass"
- | "kcLoginOTPListItemIconClass"
- | "kcLoginClass"
- | "kcSignUpClass"
- | "kcButtonLargeClass"
- | "kcFormCardClass"
- | "kcLocaleListClass"
- | "kcInputClass"
- | "kcFormGroupClass"
- | "kcLogoIdP-paypal"
- | "kcInputClassCheckbox"
- | "kcRecoveryCodesConfirmation"
- | "kcFormPasswordVisibilityIconHide"
- | "kcInputClassRadioInput"
- | "kcFormSocialAccountListButtonClass"
- | "kcInputClassCheckboxLabel"
- | "kcFormOptionsClass"
- | "kcFormHeaderClass"
- | "kcFormSocialAccountGridItem"
- | "kcButtonPrimaryClass"
- | "kcInputHelperTextBeforeClass"
- | "kcLogoIdP-github"
- | "kcLabelClass";
+export type { ClassKey };
diff --git a/src/login/lib/kcClsx.ts b/src/login/lib/kcClsx.ts
index a140671f..9198f778 100644
--- a/src/login/lib/kcClsx.ts
+++ b/src/login/lib/kcClsx.ts
@@ -1,5 +1,130 @@
import { createGetKcClsx } from "keycloakify/lib/getKcClsx";
-import type { ClassKey } from "keycloakify/login/TemplateProps";
+
+export type ClassKey =
+ | "kcBodyClass"
+ | "kcHeaderWrapperClass"
+ | "kcLocaleWrapperClass"
+ | "kcInfoAreaWrapperClass"
+ | "kcFormButtonsWrapperClass"
+ | "kcFormOptionsWrapperClass"
+ | "kcCheckboxInputClass"
+ | "kcLocaleDropDownClass"
+ | "kcLocaleListItemClass"
+ | "kcContentWrapperClass"
+ | "kcLogoIdP-facebook"
+ | "kcAuthenticatorOTPClass"
+ | "kcLogoIdP-bitbucket"
+ | "kcAuthenticatorWebAuthnClass"
+ | "kcWebAuthnDefaultIcon"
+ | "kcLogoIdP-stackoverflow"
+ | "kcSelectAuthListItemClass"
+ | "kcLogoIdP-microsoft"
+ | "kcLoginOTPListItemHeaderClass"
+ | "kcLocaleItemClass"
+ | "kcLoginOTPListItemIconBodyClass"
+ | "kcInputHelperTextAfterClass"
+ | "kcFormClass"
+ | "kcSelectAuthListClass"
+ | "kcInputClassRadioCheckboxLabelDisabled"
+ | "kcSelectAuthListItemIconClass"
+ | "kcRecoveryCodesWarning"
+ | "kcFormSettingClass"
+ | "kcWebAuthnBLE"
+ | "kcInputWrapperClass"
+ | "kcSelectAuthListItemArrowIconClass"
+ | "kcFeedbackAreaClass"
+ | "kcFormPasswordVisibilityButtonClass"
+ | "kcLogoIdP-google"
+ | "kcCheckLabelClass"
+ | "kcSelectAuthListItemFillClass"
+ | "kcAuthenticatorDefaultClass"
+ | "kcLogoIdP-gitlab"
+ | "kcFormAreaClass"
+ | "kcFormButtonsClass"
+ | "kcInputClassRadioLabel"
+ | "kcAuthenticatorWebAuthnPasswordlessClass"
+ | "kcSelectAuthListItemHeadingClass"
+ | "kcInfoAreaClass"
+ | "kcLogoLink"
+ | "kcContainerClass"
+ | "kcSelectAuthListItemTitle"
+ | "kcHtmlClass"
+ | "kcLoginOTPListItemTitleClass"
+ | "kcLogoIdP-openshift-v4"
+ | "kcWebAuthnUnknownIcon"
+ | "kcFormSocialAccountNameClass"
+ | "kcLogoIdP-openshift-v3"
+ | "kcLoginOTPListInputClass"
+ | "kcWebAuthnUSB"
+ | "kcInputClassRadio"
+ | "kcWebAuthnKeyIcon"
+ | "kcFeedbackInfoIcon"
+ | "kcCommonLogoIdP"
+ | "kcRecoveryCodesActions"
+ | "kcFormGroupHeader"
+ | "kcFormSocialAccountSectionClass"
+ | "kcLogoIdP-instagram"
+ | "kcAlertClass"
+ | "kcHeaderClass"
+ | "kcLabelWrapperClass"
+ | "kcFormPasswordVisibilityIconShow"
+ | "kcFormSocialAccountLinkClass"
+ | "kcLocaleMainClass"
+ | "kcInputGroup"
+ | "kcTextareaClass"
+ | "kcButtonBlockClass"
+ | "kcButtonClass"
+ | "kcWebAuthnNFC"
+ | "kcLocaleClass"
+ | "kcInputClassCheckboxInput"
+ | "kcFeedbackErrorIcon"
+ | "kcInputLargeClass"
+ | "kcInputErrorMessageClass"
+ | "kcRecoveryCodesList"
+ | "kcFormSocialAccountListClass"
+ | "kcAlertTitleClass"
+ | "kcAuthenticatorPasswordClass"
+ | "kcCheckInputClass"
+ | "kcLogoIdP-linkedin"
+ | "kcLogoIdP-twitter"
+ | "kcFeedbackWarningIcon"
+ | "kcResetFlowIcon"
+ | "kcSelectAuthListItemIconPropertyClass"
+ | "kcFeedbackSuccessIcon"
+ | "kcLoginOTPListClass"
+ | "kcSrOnlyClass"
+ | "kcFormSocialAccountListGridClass"
+ | "kcButtonDefaultClass"
+ | "kcFormGroupErrorClass"
+ | "kcSelectAuthListItemDescriptionClass"
+ | "kcSelectAuthListItemBodyClass"
+ | "kcWebAuthnInternal"
+ | "kcSelectAuthListItemArrowClass"
+ | "kcCheckClass"
+ | "kcContentClass"
+ | "kcLogoClass"
+ | "kcLoginOTPListItemIconClass"
+ | "kcLoginClass"
+ | "kcSignUpClass"
+ | "kcButtonLargeClass"
+ | "kcFormCardClass"
+ | "kcLocaleListClass"
+ | "kcInputClass"
+ | "kcFormGroupClass"
+ | "kcLogoIdP-paypal"
+ | "kcInputClassCheckbox"
+ | "kcRecoveryCodesConfirmation"
+ | "kcFormPasswordVisibilityIconHide"
+ | "kcInputClassRadioInput"
+ | "kcFormSocialAccountListButtonClass"
+ | "kcInputClassCheckboxLabel"
+ | "kcFormOptionsClass"
+ | "kcFormHeaderClass"
+ | "kcFormSocialAccountGridItem"
+ | "kcButtonPrimaryClass"
+ | "kcInputHelperTextBeforeClass"
+ | "kcLogoIdP-github"
+ | "kcLabelClass";
export const { getKcClsx } = createGetKcClsx({
defaultClasses: {
@@ -138,6 +263,4 @@ export const { getKcClsx } = createGetKcClsx({
}
});
-export type { ClassKey };
-
export type KcClsx = ReturnType["kcClsx"];
From a0c95207cfed164215072b369ad00233cd9ea891 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Mon, 30 Sep 2024 01:10:45 +0200
Subject: [PATCH 03/77] Bump version
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 42f474a3..f28b02d8 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "keycloakify",
- "version": "11.2.0",
+ "version": "11.2.1",
"description": "Framework to create custom Keycloak UIs",
"repository": {
"type": "git",
From 8cacb21f1baf4086cde20975b4938b9816a80bde Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Mon, 30 Sep 2024 01:22:37 +0200
Subject: [PATCH 04/77] Remove unessesary reference to react specific construct
in KcContext
---
src/login/KcContext/KcContext.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/login/KcContext/KcContext.ts b/src/login/KcContext/KcContext.ts
index 4b9c91e6..14d1169f 100644
--- a/src/login/KcContext/KcContext.ts
+++ b/src/login/KcContext/KcContext.ts
@@ -2,7 +2,7 @@ import type { ThemeType, LoginThemePageId } from "keycloakify/bin/shared/constan
import type { ValueOf } from "keycloakify/tools/ValueOf";
import { assert } from "tsafe/assert";
import type { Equals } from "tsafe";
-import type { ClassKey } from "keycloakify/login/TemplateProps";
+import type { ClassKey } from "keycloakify/login/lib/kcClsx";
export type ExtendKcContext<
KcContextExtension extends { properties?: Record },
From 47ca811878cbec21662229b0c638d7b0f0c4be7b Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Mon, 30 Sep 2024 01:22:49 +0200
Subject: [PATCH 05/77] Bump version
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index f28b02d8..ef9b65d9 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "keycloakify",
- "version": "11.2.1",
+ "version": "11.2.2",
"description": "Framework to create custom Keycloak UIs",
"repository": {
"type": "git",
From 9f8a36fe9361ba81d792c1e2b97a97a641872b4c Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Mon, 30 Sep 2024 11:48:57 +0200
Subject: [PATCH 06/77] Fix allegated vulnerability
---
.../keycloakify/generateFtl/kcContextDeclarationTemplate.ftl | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/bin/keycloakify/generateFtl/kcContextDeclarationTemplate.ftl b/src/bin/keycloakify/generateFtl/kcContextDeclarationTemplate.ftl
index 6b74955f..5cfc2755 100644
--- a/src/bin/keycloakify/generateFtl/kcContextDeclarationTemplate.ftl
+++ b/src/bin/keycloakify/generateFtl/kcContextDeclarationTemplate.ftl
@@ -166,7 +166,7 @@ function decodeHtmlEntities(htmlStr){
areSamePath(path, []) &&
["login-idp-link-confirm.ftl", "login-idp-link-email.ftl" ]?seq_contains(xKeycloakify.pageId)
) || (
- ["masterAdminClient", "delegateForUpdate", "defaultRole"]?seq_contains(key) &&
+ ["masterAdminClient", "delegateForUpdate", "defaultRole", "smtpConfig"]?seq_contains(key) &&
areSamePath(path, ["realm"])
) || (
xKeycloakify.pageId == "error.ftl" &&
From d7103b1ad914eea6821f478e9a4b0bd2699505dd Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Mon, 30 Sep 2024 11:49:33 +0200
Subject: [PATCH 07/77] Bump version
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index ef9b65d9..880782d1 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "keycloakify",
- "version": "11.2.2",
+ "version": "11.2.3",
"description": "Framework to create custom Keycloak UIs",
"repository": {
"type": "git",
From 2ea5e34e81b554024ed470b87fa366ab2ad773c0 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Mon, 30 Sep 2024 17:57:41 +0200
Subject: [PATCH 08/77] update ci
---
.github/workflows/ci.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 9fca0a23..6ec87504 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -112,7 +112,7 @@ jobs:
registry-url: https://registry.npmjs.org/
- uses: bahmutov/npm-install@v1
- run: npm run build
- - run: npx -y -p denoify@1.6.12 enable_short_npm_import_path
+ - run: npx -y -p denoify@1.6.13 enable_short_npm_import_path
env:
DRY_RUN: "0"
- uses: garronej/ts-ci@v2.1.2
From 302fe8d7cde5529d84f7d6ff6736d854feeeed7c Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Mon, 30 Sep 2024 18:10:09 +0200
Subject: [PATCH 09/77] Update tsafe (provide ESM distribution)
---
package.json | 2 +-
yarn.lock | 5 +++++
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 880782d1..4b2ad41f 100644
--- a/package.json
+++ b/package.json
@@ -62,7 +62,7 @@
],
"homepage": "https://www.keycloakify.dev",
"dependencies": {
- "tsafe": "^1.6.6"
+ "tsafe": "^1.7.4"
},
"devDependencies": {
"@babel/core": "^7.24.5",
diff --git a/yarn.lock b/yarn.lock
index abab9a2c..d05e77af 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -12579,6 +12579,11 @@ tsafe@^1.6.6:
resolved "https://registry.yarnpkg.com/tsafe/-/tsafe-1.6.6.tgz#fd93e64d6eb13ef83ed1650669cc24bad4f5df9f"
integrity sha512-gzkapsdbMNwBnTIjgO758GujLCj031IgHK/PKr2mrmkCSJMhSOR5FeOuSxKLMUoYc0vAA4RGEYYbjt/v6afD3g==
+tsafe@^1.7.4:
+ version "1.7.4"
+ resolved "https://registry.yarnpkg.com/tsafe/-/tsafe-1.7.4.tgz#7dd288b1a1be8d9c25e84ab8dd8a7df6094168d7"
+ integrity sha512-4BrLklZMJ14dEtA+CkhY9OtID3al4+/GJhaeocWPtUuoZPr4SJkaqoPemyFgkLC1Y3LRNXF9zxa94SwssRGMaQ==
+
tsc-alias@^1.8.10:
version "1.8.10"
resolved "https://registry.yarnpkg.com/tsc-alias/-/tsc-alias-1.8.10.tgz#279f9bf0dd8bc10fb27820393d4881db5a303938"
From 6716fcb88102cb1ee7d13eb3a2fa7e5d4c6594f4 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Mon, 30 Sep 2024 18:10:26 +0200
Subject: [PATCH 10/77] Bump version
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 4b2ad41f..2aac84f8 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "keycloakify",
- "version": "11.2.3",
+ "version": "11.2.4",
"description": "Framework to create custom Keycloak UIs",
"repository": {
"type": "git",
From 77952337c594e396b277a1057dfc8bf62cda0c92 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Tue, 1 Oct 2024 11:52:40 +0200
Subject: [PATCH 11/77] Avoid modifying BASE_URL for App context
---
src/vite-plugin/vite-plugin.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/vite-plugin/vite-plugin.ts b/src/vite-plugin/vite-plugin.ts
index 1ccfaf89..f22cb62a 100644
--- a/src/vite-plugin/vite-plugin.ts
+++ b/src/vite-plugin/vite-plugin.ts
@@ -166,7 +166,7 @@ export function keycloakify(params: keycloakify.Params) {
[
`(`,
`(window.kcContext === undefined || import.meta.env.MODE === "development")?`,
- `"${urlPathname ?? "/"}":`,
+ `import.meta.env.BASE_URL:`,
`(window.kcContext["x-keycloakify"].resourcesPath + "/${WELL_KNOWN_DIRECTORY_BASE_NAME.DIST}/")`,
`)`
].join("")
From 1177d6770ceb44e859955e1a32bf561cb96da10d Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Tue, 1 Oct 2024 11:59:39 +0200
Subject: [PATCH 12/77] Bump version
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 2aac84f8..760e7453 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "keycloakify",
- "version": "11.2.4",
+ "version": "11.2.5",
"description": "Framework to create custom Keycloak UIs",
"repository": {
"type": "git",
From 2e10ec80734c5ab7097518d23d00363c92b1500c Mon Sep 17 00:00:00 2001
From: "allcontributors[bot]"
<46447321+allcontributors[bot]@users.noreply.github.com>
Date: Wed, 2 Oct 2024 08:59:48 +0000
Subject: [PATCH 13/77] docs: update README.md [skip ci]
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index ddc36c80..82e44eba 100644
--- a/README.md
+++ b/README.md
@@ -134,6 +134,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
 Omid β οΈ π» |
+  Katharina Eiserfey π» β οΈ π |
From c21d072231ca0e5fe272ff861507caa5873ad8e7 Mon Sep 17 00:00:00 2001
From: "allcontributors[bot]"
<46447321+allcontributors[bot]@users.noreply.github.com>
Date: Wed, 2 Oct 2024 08:59:49 +0000
Subject: [PATCH 14/77] docs: update .all-contributorsrc [skip ci]
---
.all-contributorsrc | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/.all-contributorsrc b/.all-contributorsrc
index 864f118b..b6496bfb 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -269,6 +269,17 @@
"test",
"code"
]
+ },
+ {
+ "login": "kathari00",
+ "name": "Katharina Eiserfey",
+ "avatar_url": "https://avatars.githubusercontent.com/u/42547712?v=4",
+ "profile": "https://github.com/kathari00",
+ "contributions": [
+ "code",
+ "test",
+ "doc"
+ ]
}
],
"contributorsPerLine": 7,
From 939e3ca7ea8f6c542983451972c24968bd790aa0 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Wed, 2 Oct 2024 11:02:25 +0200
Subject: [PATCH 15/77] Put Kathi as first contributor
---
README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 82e44eba..50c221ce 100644
--- a/README.md
+++ b/README.md
@@ -97,13 +97,13 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
From 153a99d63ff0b9c7fdb72c60864b186b37c5a38b Mon Sep 17 00:00:00 2001
From: "allcontributors[bot]"
<46447321+allcontributors[bot]@users.noreply.github.com>
Date: Wed, 2 Oct 2024 09:05:34 +0000
Subject: [PATCH 16/77] docs: update README.md [skip ci]
---
README.md | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 50c221ce..78872df3 100644
--- a/README.md
+++ b/README.md
@@ -97,13 +97,13 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
From 8c8d2fd6a8b0861b9ee74b6865a21ff3ad2c205d Mon Sep 17 00:00:00 2001
From: "allcontributors[bot]"
<46447321+allcontributors[bot]@users.noreply.github.com>
Date: Wed, 2 Oct 2024 09:05:35 +0000
Subject: [PATCH 17/77] docs: update .all-contributorsrc [skip ci]
---
.all-contributorsrc | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/.all-contributorsrc b/.all-contributorsrc
index b6496bfb..fdede216 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -280,6 +280,16 @@
"test",
"doc"
]
+ },
+ {
+ "login": "luca-peruzzo",
+ "name": "Luca Peruzzo",
+ "avatar_url": "https://avatars.githubusercontent.com/u/69015314?v=4",
+ "profile": "https://github.com/luca-peruzzo",
+ "contributions": [
+ "code",
+ "test"
+ ]
}
],
"contributorsPerLine": 7,
From 09abc73068c8b66ed86d434bca9ca5c2c5eff8bd Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Wed, 2 Oct 2024 13:42:38 +0200
Subject: [PATCH 18/77] Update tsafe
---
package.json | 2 +-
yarn.lock | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/package.json b/package.json
index 760e7453..14a5622b 100644
--- a/package.json
+++ b/package.json
@@ -62,7 +62,7 @@
],
"homepage": "https://www.keycloakify.dev",
"dependencies": {
- "tsafe": "^1.7.4"
+ "tsafe": "^1.7.5"
},
"devDependencies": {
"@babel/core": "^7.24.5",
diff --git a/yarn.lock b/yarn.lock
index d05e77af..c8b469f3 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -12579,10 +12579,10 @@ tsafe@^1.6.6:
resolved "https://registry.yarnpkg.com/tsafe/-/tsafe-1.6.6.tgz#fd93e64d6eb13ef83ed1650669cc24bad4f5df9f"
integrity sha512-gzkapsdbMNwBnTIjgO758GujLCj031IgHK/PKr2mrmkCSJMhSOR5FeOuSxKLMUoYc0vAA4RGEYYbjt/v6afD3g==
-tsafe@^1.7.4:
- version "1.7.4"
- resolved "https://registry.yarnpkg.com/tsafe/-/tsafe-1.7.4.tgz#7dd288b1a1be8d9c25e84ab8dd8a7df6094168d7"
- integrity sha512-4BrLklZMJ14dEtA+CkhY9OtID3al4+/GJhaeocWPtUuoZPr4SJkaqoPemyFgkLC1Y3LRNXF9zxa94SwssRGMaQ==
+tsafe@^1.7.5:
+ version "1.7.5"
+ resolved "https://registry.yarnpkg.com/tsafe/-/tsafe-1.7.5.tgz#0d3a31202b5ef87c7ba997e66e03fd80801278ef"
+ integrity sha512-tbNyyBSbwfbilFfiuXkSOj82a6++ovgANwcoqBAcO9/REPoZMEQoE8kWPeO0dy5A2D/2Lajr8Ohue5T0ifIvLQ==
tsc-alias@^1.8.10:
version "1.8.10"
From ce3135c83be2b6d2cbc4a97313c6b84b0780353b Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Wed, 2 Oct 2024 13:44:22 +0200
Subject: [PATCH 19/77] Bump version
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 14a5622b..e6c02daa 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "keycloakify",
- "version": "11.2.5",
+ "version": "11.2.6",
"description": "Framework to create custom Keycloak UIs",
"repository": {
"type": "git",
From 80eaa77acc26a5196e487bb81ce9136d42331653 Mon Sep 17 00:00:00 2001
From: johanjk
Date: Wed, 2 Oct 2024 16:16:16 +0200
Subject: [PATCH 20/77] ['select-radiobuttons'/'multiselect-checkboxes'] fixed
'inputOptionLabels'
---
src/login/UserProfileFormFields.tsx | 38 ++++++++++++------------
stories/login/pages/Register.stories.tsx | 32 ++++++++++++++++++++
2 files changed, 51 insertions(+), 19 deletions(-)
diff --git a/src/login/UserProfileFormFields.tsx b/src/login/UserProfileFormFields.tsx
index 445bda6f..93a99ad7 100644
--- a/src/login/UserProfileFormFields.tsx
+++ b/src/login/UserProfileFormFields.tsx
@@ -434,9 +434,7 @@ function AddRemoveButtonsMultiValuedAttribute(props: {
}
function InputTagSelects(props: InputFieldByTypeProps) {
- const { attribute, dispatchFormAction, kcClsx, valueOrValues } = props;
-
- const { advancedMsg } = props.i18n;
+ const { attribute, dispatchFormAction, kcClsx, i18n, valueOrValues } = props;
const { classDiv, classInput, classLabel, inputType } = (() => {
const { inputType } = attribute.annotations;
@@ -533,7 +531,7 @@ function InputTagSelects(props: InputFieldByTypeProps) {
htmlFor={`${attribute.name}-${option}`}
className={`${classLabel}${attribute.readOnly ? ` ${kcClsx("kcInputClassRadioCheckboxLabelDisabled")}` : ""}`}
>
- {advancedMsg(option)}
+ {inputLabel(i18n, attribute, option)}
))}
@@ -580,8 +578,6 @@ function TextareaTag(props: InputFieldByTypeProps) {
function SelectTag(props: InputFieldByTypeProps) {
const { attribute, dispatchFormAction, kcClsx, displayableErrors, i18n, valueOrValues } = props;
- const { advancedMsgStr } = i18n;
-
const isMultiple = attribute.annotations.inputType === "multiselect";
return (
@@ -645,22 +641,26 @@ function SelectTag(props: InputFieldByTypeProps) {
return options.map(option => (
));
})()}
);
}
+
+function inputLabel(i18n: I18n, attribute: Attribute, option: string) {
+ const { advancedMsg } = i18n;
+
+ if (attribute.annotations.inputOptionLabels !== undefined) {
+ const { inputOptionLabels } = attribute.annotations;
+
+ return advancedMsg(inputOptionLabels[option] ?? option);
+ }
+
+ if (attribute.annotations.inputOptionLabelsI18nPrefix !== undefined) {
+ return advancedMsg(`${attribute.annotations.inputOptionLabelsI18nPrefix}.${option}`);
+ }
+
+ return option;
+}
diff --git a/stories/login/pages/Register.stories.tsx b/stories/login/pages/Register.stories.tsx
index 0a8c395f..f25568cc 100644
--- a/stories/login/pages/Register.stories.tsx
+++ b/stories/login/pages/Register.stories.tsx
@@ -115,6 +115,38 @@ export const WithFavoritePet: Story = {
)
};
+
+export const WithNewsletter: Story = {
+ render: () => (
+
+ )
+};
+
+
export const WithEmailAsUsername: Story = {
render: () => (
Date: Wed, 2 Oct 2024 23:36:58 +0200
Subject: [PATCH 21/77] Bump version
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index e6c02daa..ff7fbe2a 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "keycloakify",
- "version": "11.2.6",
+ "version": "11.2.8",
"description": "Framework to create custom Keycloak UIs",
"repository": {
"type": "git",
From dd217e8a469a625f1cd66a1fdca719ee9882d72e Mon Sep 17 00:00:00 2001
From: pnzrr <93841792+pnzrr@users.noreply.github.com>
Date: Thu, 3 Oct 2024 21:04:02 -0600
Subject: [PATCH 22/77] Fix link in CONTRIBUTING.md
---
CONTRIBUTING.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 733042ec..25b079a7 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,3 +1,3 @@
Looking to contribute? Thank you! PR are more than welcome.
-Please refers to [this documentation page](https://docs.keycloakify.dev/contributing) that will help you get started.
+Please refers to [this documentation page](https://docs.keycloakify.dev/faq-and-help/contributing) that will help you get started.
From 39ad1eb8d13717c063133110fbd90c0bb88c8e38 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Fri, 4 Oct 2024 12:17:08 +0200
Subject: [PATCH 23/77] Update version target range
---
.../getKeycloakVersionRangeForJar.ts | 4 +-
src/bin/shared/KeycloakVersionRange.ts | 2 +-
src/bin/shared/buildContext.ts | 36 +-
src/bin/start-keycloak/myrealm-realm-26.json | 2400 +++++++++++++++++
4 files changed, 2431 insertions(+), 11 deletions(-)
create mode 100644 src/bin/start-keycloak/myrealm-realm-26.json
diff --git a/src/bin/keycloakify/buildJars/getKeycloakVersionRangeForJar.ts b/src/bin/keycloakify/buildJars/getKeycloakVersionRangeForJar.ts
index 3999ce8f..6c301223 100644
--- a/src/bin/keycloakify/buildJars/getKeycloakVersionRangeForJar.ts
+++ b/src/bin/keycloakify/buildJars/getKeycloakVersionRangeForJar.ts
@@ -75,9 +75,9 @@ export function getKeycloakVersionRangeForJar(params: {
}
switch (keycloakThemeAdditionalInfoExtensionVersion) {
case null:
- return "21-and-below";
+ return "all-other-versions";
case "1.1.5":
- return "22-and-above";
+ return "22-to-25";
}
assert>(
false
diff --git a/src/bin/shared/KeycloakVersionRange.ts b/src/bin/shared/KeycloakVersionRange.ts
index 2827d34e..1e118ea1 100644
--- a/src/bin/shared/KeycloakVersionRange.ts
+++ b/src/bin/shared/KeycloakVersionRange.ts
@@ -3,7 +3,7 @@ export type KeycloakVersionRange =
| KeycloakVersionRange.WithoutAccountV1Theme;
export namespace KeycloakVersionRange {
- export type WithoutAccountV1Theme = "21-and-below" | "22-and-above";
+ export type WithoutAccountV1Theme = "22-to-25" | "all-other-versions";
export type WithAccountV1Theme = "21-and-below" | "23" | "24" | "25-and-above";
}
diff --git a/src/bin/shared/buildContext.ts b/src/bin/shared/buildContext.ts
index b4a998b7..852bd1fd 100644
--- a/src/bin/shared/buildContext.ts
+++ b/src/bin/shared/buildContext.ts
@@ -25,6 +25,7 @@ import { type ThemeType } from "./constants";
import { id } from "tsafe/id";
import chalk from "chalk";
import { getProxyFetchOptions, type ProxyFetchOptions } from "../tools/fetchProxyOptions";
+import { is } from "tsafe/is";
export type BuildContext = {
themeVersion: string;
@@ -297,8 +298,8 @@ export function getBuildContext(params: {
]),
keycloakVersionTargets: z
.object({
- "21-and-below": z.union([z.boolean(), z.string()]),
- "22-and-above": z.union([z.boolean(), z.string()])
+ "22-to-25": z.union([z.boolean(), z.string()]),
+ "all-other-versions": z.union([z.boolean(), z.string()])
})
.optional()
});
@@ -779,11 +780,14 @@ export function getBuildContext(params: {
return keycloakVersionRange;
} else {
const keycloakVersionRange = (() => {
- if (buildForKeycloakMajorVersionNumber <= 21) {
- return "21-and-below" as const;
+ if (
+ buildForKeycloakMajorVersionNumber <= 21 ||
+ buildForKeycloakMajorVersionNumber >= 26
+ ) {
+ return "all-other-versions" as const;
}
- return "22-and-above" as const;
+ return "22-to-25" as const;
})();
assert<
@@ -801,6 +805,12 @@ export function getBuildContext(params: {
use_custom_jar_basename: {
const { keycloakVersionTargets } = buildOptions;
+ assert(
+ is>(
+ keycloakVersionTargets
+ )
+ );
+
if (keycloakVersionTargets === undefined) {
break use_custom_jar_basename;
}
@@ -861,8 +871,8 @@ export function getBuildContext(params: {
}
} else {
for (const keycloakVersionRange of [
- "21-and-below",
- "22-and-above"
+ "22-to-25",
+ "all-other-versions"
] as const) {
assert<
Equals<
@@ -888,7 +898,17 @@ export function getBuildContext(params: {
const jarTargets: BuildContext["jarTargets"] = [];
for (const [keycloakVersionRange, jarNameOrBoolean] of objectEntries(
- buildOptions.keycloakVersionTargets
+ (() => {
+ const { keycloakVersionTargets } = buildOptions;
+
+ assert(
+ is>(
+ keycloakVersionTargets
+ )
+ );
+
+ return keycloakVersionTargets;
+ })()
)) {
if (jarNameOrBoolean === false) {
continue;
diff --git a/src/bin/start-keycloak/myrealm-realm-26.json b/src/bin/start-keycloak/myrealm-realm-26.json
new file mode 100644
index 00000000..21b95023
--- /dev/null
+++ b/src/bin/start-keycloak/myrealm-realm-26.json
@@ -0,0 +1,2400 @@
+{
+ "id": "5d0dd960-0478-4ca6-b64a-810a3f6f4071",
+ "realm": "myrealm",
+ "notBefore": 0,
+ "defaultSignatureAlgorithm": "RS256",
+ "revokeRefreshToken": false,
+ "refreshTokenMaxReuse": 0,
+ "accessTokenLifespan": 300,
+ "accessTokenLifespanForImplicitFlow": 900,
+ "ssoSessionIdleTimeout": 1800,
+ "ssoSessionMaxLifespan": 36000,
+ "ssoSessionIdleTimeoutRememberMe": 0,
+ "ssoSessionMaxLifespanRememberMe": 0,
+ "offlineSessionIdleTimeout": 2592000,
+ "offlineSessionMaxLifespanEnabled": false,
+ "offlineSessionMaxLifespan": 5184000,
+ "clientSessionIdleTimeout": 0,
+ "clientSessionMaxLifespan": 0,
+ "clientOfflineSessionIdleTimeout": 0,
+ "clientOfflineSessionMaxLifespan": 0,
+ "accessCodeLifespan": 60,
+ "accessCodeLifespanUserAction": 300,
+ "accessCodeLifespanLogin": 1800,
+ "actionTokenGeneratedByAdminLifespan": 43200,
+ "actionTokenGeneratedByUserLifespan": 300,
+ "oauth2DeviceCodeLifespan": 600,
+ "oauth2DevicePollingInterval": 5,
+ "enabled": true,
+ "sslRequired": "external",
+ "registrationAllowed": true,
+ "registrationEmailAsUsername": false,
+ "rememberMe": true,
+ "verifyEmail": false,
+ "loginWithEmailAllowed": true,
+ "duplicateEmailsAllowed": false,
+ "resetPasswordAllowed": true,
+ "editUsernameAllowed": false,
+ "bruteForceProtected": false,
+ "permanentLockout": false,
+ "maxTemporaryLockouts": 0,
+ "maxFailureWaitSeconds": 900,
+ "minimumQuickLoginWaitSeconds": 60,
+ "waitIncrementSeconds": 60,
+ "quickLoginCheckMilliSeconds": 1000,
+ "maxDeltaTimeSeconds": 43200,
+ "failureFactor": 30,
+ "roles": {
+ "realm": [
+ {
+ "id": "cc4b5045-3bff-4aa7-889e-1492630c3002",
+ "name": "uma_authorization",
+ "description": "${role_uma_authorization}",
+ "composite": false,
+ "clientRole": false,
+ "containerId": "5d0dd960-0478-4ca6-b64a-810a3f6f4071",
+ "attributes": {}
+ },
+ {
+ "id": "e92017b2-18a0-49cd-956c-fad64f16b26b",
+ "name": "default-roles-myrealm",
+ "description": "${role_default-roles}",
+ "composite": true,
+ "composites": {
+ "realm": ["offline_access", "uma_authorization"],
+ "client": {
+ "account": ["delete-account", "manage-account", "view-profile"]
+ }
+ },
+ "clientRole": false,
+ "containerId": "5d0dd960-0478-4ca6-b64a-810a3f6f4071",
+ "attributes": {}
+ },
+ {
+ "id": "e8616113-e302-4abe-bd5c-d51f8221046b",
+ "name": "offline_access",
+ "description": "${role_offline-access}",
+ "composite": false,
+ "clientRole": false,
+ "containerId": "5d0dd960-0478-4ca6-b64a-810a3f6f4071",
+ "attributes": {}
+ }
+ ],
+ "client": {
+ "myclient": [],
+ "realm-management": [
+ {
+ "id": "b27b272d-d153-4ae7-9fe7-fd96582f057d",
+ "name": "manage-events",
+ "description": "${role_manage-events}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "e05cc68c-5e53-4796-ae3a-a1bfbf5c51bb",
+ "attributes": {}
+ },
+ {
+ "id": "40fdfec8-f1b9-4c2b-81c5-a775bc047840",
+ "name": "manage-users",
+ "description": "${role_manage-users}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "e05cc68c-5e53-4796-ae3a-a1bfbf5c51bb",
+ "attributes": {}
+ },
+ {
+ "id": "5f446f9a-d008-4067-8325-f4658a32d964",
+ "name": "view-authorization",
+ "description": "${role_view-authorization}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "e05cc68c-5e53-4796-ae3a-a1bfbf5c51bb",
+ "attributes": {}
+ },
+ {
+ "id": "82bf956d-1fd1-4d20-a5a9-62b3e77e9d88",
+ "name": "create-client",
+ "description": "${role_create-client}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "e05cc68c-5e53-4796-ae3a-a1bfbf5c51bb",
+ "attributes": {}
+ },
+ {
+ "id": "b41e1ce8-d63f-4cf4-9966-e6c9eab5da11",
+ "name": "manage-clients",
+ "description": "${role_manage-clients}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "e05cc68c-5e53-4796-ae3a-a1bfbf5c51bb",
+ "attributes": {}
+ },
+ {
+ "id": "3198743d-fdfa-4a9c-a229-5fb979847ec2",
+ "name": "view-users",
+ "description": "${role_view-users}",
+ "composite": true,
+ "composites": {
+ "client": {
+ "realm-management": ["query-users", "query-groups"]
+ }
+ },
+ "clientRole": true,
+ "containerId": "e05cc68c-5e53-4796-ae3a-a1bfbf5c51bb",
+ "attributes": {}
+ },
+ {
+ "id": "e83c21cb-c84c-4824-9f7d-ce3574921800",
+ "name": "query-users",
+ "description": "${role_query-users}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "e05cc68c-5e53-4796-ae3a-a1bfbf5c51bb",
+ "attributes": {}
+ },
+ {
+ "id": "3f6e2e81-e40d-40ff-a5f3-12ba2614fba5",
+ "name": "query-groups",
+ "description": "${role_query-groups}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "e05cc68c-5e53-4796-ae3a-a1bfbf5c51bb",
+ "attributes": {}
+ },
+ {
+ "id": "63111288-7f3d-4570-838f-48405d70e212",
+ "name": "view-realm",
+ "description": "${role_view-realm}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "e05cc68c-5e53-4796-ae3a-a1bfbf5c51bb",
+ "attributes": {}
+ },
+ {
+ "id": "a7f8f8ad-057b-485e-abfa-8a98e5e0c4ea",
+ "name": "manage-realm",
+ "description": "${role_manage-realm}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "e05cc68c-5e53-4796-ae3a-a1bfbf5c51bb",
+ "attributes": {}
+ },
+ {
+ "id": "7783b160-2f1a-48c9-89fb-623a29f26c9a",
+ "name": "query-realms",
+ "description": "${role_query-realms}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "e05cc68c-5e53-4796-ae3a-a1bfbf5c51bb",
+ "attributes": {}
+ },
+ {
+ "id": "b8b5341f-f44f-40a2-9ba4-e2d621b11b2f",
+ "name": "impersonation",
+ "description": "${role_impersonation}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "e05cc68c-5e53-4796-ae3a-a1bfbf5c51bb",
+ "attributes": {}
+ },
+ {
+ "id": "6b9d72e9-949f-4897-b11a-c8aa9252f3f2",
+ "name": "query-clients",
+ "description": "${role_query-clients}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "e05cc68c-5e53-4796-ae3a-a1bfbf5c51bb",
+ "attributes": {}
+ },
+ {
+ "id": "bfa94ba9-1d70-4259-b928-906e8bb815b2",
+ "name": "view-events",
+ "description": "${role_view-events}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "e05cc68c-5e53-4796-ae3a-a1bfbf5c51bb",
+ "attributes": {}
+ },
+ {
+ "id": "96bb9322-5c1f-48f0-aa05-65521c77e742",
+ "name": "realm-admin",
+ "description": "${role_realm-admin}",
+ "composite": true,
+ "composites": {
+ "client": {
+ "realm-management": [
+ "manage-users",
+ "view-authorization",
+ "manage-events",
+ "create-client",
+ "view-users",
+ "manage-clients",
+ "query-users",
+ "query-groups",
+ "view-realm",
+ "manage-realm",
+ "query-realms",
+ "query-clients",
+ "impersonation",
+ "view-events",
+ "manage-authorization",
+ "manage-identity-providers",
+ "view-identity-providers",
+ "view-clients"
+ ]
+ }
+ },
+ "clientRole": true,
+ "containerId": "e05cc68c-5e53-4796-ae3a-a1bfbf5c51bb",
+ "attributes": {}
+ },
+ {
+ "id": "6e0ca5ce-f5db-4580-90e5-27c35804fc34",
+ "name": "manage-authorization",
+ "description": "${role_manage-authorization}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "e05cc68c-5e53-4796-ae3a-a1bfbf5c51bb",
+ "attributes": {}
+ },
+ {
+ "id": "7499eb46-cf4a-4813-9bf9-42b1bbcadc0d",
+ "name": "manage-identity-providers",
+ "description": "${role_manage-identity-providers}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "e05cc68c-5e53-4796-ae3a-a1bfbf5c51bb",
+ "attributes": {}
+ },
+ {
+ "id": "fcc99ef9-347d-4c21-b25c-8229e906a1a3",
+ "name": "view-clients",
+ "description": "${role_view-clients}",
+ "composite": true,
+ "composites": {
+ "client": {
+ "realm-management": ["query-clients"]
+ }
+ },
+ "clientRole": true,
+ "containerId": "e05cc68c-5e53-4796-ae3a-a1bfbf5c51bb",
+ "attributes": {}
+ },
+ {
+ "id": "7b024069-57d8-4368-9942-8790507c156d",
+ "name": "view-identity-providers",
+ "description": "${role_view-identity-providers}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "e05cc68c-5e53-4796-ae3a-a1bfbf5c51bb",
+ "attributes": {}
+ }
+ ],
+ "security-admin-console": [],
+ "admin-cli": [],
+ "account-console": [],
+ "broker": [
+ {
+ "id": "3050eb8a-9a47-4a27-aece-be2e60fc7f73",
+ "name": "read-token",
+ "description": "${role_read-token}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "f5e032da-c8ab-48c2-959c-8466ad1e6a09",
+ "attributes": {}
+ }
+ ],
+ "account": [
+ {
+ "id": "d554d15b-d098-47a0-bdd5-d656b20f5643",
+ "name": "delete-account",
+ "description": "${role_delete-account}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "7221ef76-9d96-49ad-88a6-9f72eeeb0aa7",
+ "attributes": {}
+ },
+ {
+ "id": "aaf4946d-2cd4-43ba-ad7d-86be56b9ad2c",
+ "name": "view-applications",
+ "description": "${role_view-applications}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "7221ef76-9d96-49ad-88a6-9f72eeeb0aa7",
+ "attributes": {}
+ },
+ {
+ "id": "b417b187-18b7-41fa-9537-3313cf9b8ed4",
+ "name": "manage-account",
+ "description": "${role_manage-account}",
+ "composite": true,
+ "composites": {
+ "client": {
+ "account": ["manage-account-links"]
+ }
+ },
+ "clientRole": true,
+ "containerId": "7221ef76-9d96-49ad-88a6-9f72eeeb0aa7",
+ "attributes": {}
+ },
+ {
+ "id": "8bb5480d-83a3-4ea2-8e91-237b8870acec",
+ "name": "view-consent",
+ "description": "${role_view-consent}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "7221ef76-9d96-49ad-88a6-9f72eeeb0aa7",
+ "attributes": {}
+ },
+ {
+ "id": "e341c1b8-eaf7-467d-9986-d3f2356a60b9",
+ "name": "view-profile",
+ "description": "${role_view-profile}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "7221ef76-9d96-49ad-88a6-9f72eeeb0aa7",
+ "attributes": {}
+ },
+ {
+ "id": "98ccac20-3906-436f-8dc3-ae8d8ae25cbc",
+ "name": "view-groups",
+ "description": "${role_view-groups}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "7221ef76-9d96-49ad-88a6-9f72eeeb0aa7",
+ "attributes": {}
+ },
+ {
+ "id": "adfba539-826f-4fa7-86f5-8c1287152ed6",
+ "name": "manage-account-links",
+ "description": "${role_manage-account-links}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "7221ef76-9d96-49ad-88a6-9f72eeeb0aa7",
+ "attributes": {}
+ },
+ {
+ "id": "2516ab58-490c-444c-9e7d-0dd8b87a69f0",
+ "name": "manage-consent",
+ "description": "${role_manage-consent}",
+ "composite": true,
+ "composites": {
+ "client": {
+ "account": ["view-consent"]
+ }
+ },
+ "clientRole": true,
+ "containerId": "7221ef76-9d96-49ad-88a6-9f72eeeb0aa7",
+ "attributes": {}
+ }
+ ]
+ }
+ },
+ "groups": [],
+ "defaultRole": {
+ "id": "e92017b2-18a0-49cd-956c-fad64f16b26b",
+ "name": "default-roles-myrealm",
+ "description": "${role_default-roles}",
+ "composite": true,
+ "clientRole": false,
+ "containerId": "5d0dd960-0478-4ca6-b64a-810a3f6f4071"
+ },
+ "requiredCredentials": ["password"],
+ "otpPolicyType": "totp",
+ "otpPolicyAlgorithm": "HmacSHA1",
+ "otpPolicyInitialCounter": 0,
+ "otpPolicyDigits": 6,
+ "otpPolicyLookAheadWindow": 1,
+ "otpPolicyPeriod": 30,
+ "otpPolicyCodeReusable": false,
+ "otpSupportedApplications": [
+ "totpAppFreeOTPName",
+ "totpAppGoogleName",
+ "totpAppMicrosoftAuthenticatorName"
+ ],
+ "localizationTexts": {
+ "de": {
+ "profile.attributes.favourite_pet": ""
+ },
+ "no": {
+ "profile.attributes.favourite_pet": ""
+ },
+ "fi": {
+ "profile.attributes.favourite_pet": ""
+ },
+ "ru": {
+ "profile.attributes.favourite_pet": ""
+ },
+ "pt": {
+ "profile.attributes.favourite_pet": ""
+ },
+ "lt": {
+ "profile.attributes.favourite_pet": ""
+ },
+ "lv": {
+ "profile.attributes.favourite_pet": ""
+ },
+ "fr": {
+ "profile.attributes.favourite_pet": "Animal de compagnie prΓ©fΓ©rΓ©",
+ "profile.attributes.favourite_pet.cat": "Chat",
+ "profile.attributes.favourite_pet.dog": "Chien",
+ "profile.attributes.favourite_pet.bird": "Oiseau"
+ },
+ "hu": {
+ "profile.attributes.favourite_pet": ""
+ },
+ "zh-CN": {
+ "profile.attributes.favourite_pet": ""
+ },
+ "uk": {
+ "profile.attributes.favourite_pet": ""
+ },
+ "sk": {
+ "profile.attributes.favourite_pet": ""
+ },
+ "ca": {
+ "profile.attributes.favourite_pet": ""
+ },
+ "sv": {
+ "profile.attributes.favourite_pet": ""
+ },
+ "zh-TW": {
+ "profile.attributes.favourite_pet": ""
+ },
+ "pt-BR": {
+ "profile.attributes.favourite_pet": ""
+ },
+ "en": {
+ "profile.attributes.favourite_pet": "Favourite Pet",
+ "profile.attributes.favourite_pet.cat": "Cat",
+ "profile.attributes.favourite_pet.dog": "Dog",
+ "profile.attributes.favourite_pet.bird": "Bird"
+ },
+ "it": {
+ "profile.attributes.favourite_pet": ""
+ },
+ "es": {
+ "profile.attributes.favourite_pet": "Mascota favorita",
+ "profile.attributes.favourite_pet.cat": "Gato",
+ "profile.attributes.favourite_pet.dog": "Perro",
+ "profile.attributes.favourite_pet.bird": "PΓ‘jaro"
+ },
+ "cs": {
+ "profile.attributes.favourite_pet": ""
+ },
+ "ar": {
+ "profile.attributes.favourite_pet": ""
+ },
+ "th": {
+ "profile.attributes.favourite_pet": ""
+ },
+ "ja": {
+ "profile.attributes.favourite_pet": ""
+ },
+ "fa": {
+ "profile.attributes.favourite_pet": ""
+ },
+ "pl": {
+ "profile.attributes.favourite_pet": ""
+ },
+ "da": {
+ "profile.attributes.favourite_pet": ""
+ },
+ "nl": {
+ "profile.attributes.favourite_pet": ""
+ },
+ "tr": {
+ "profile.attributes.favourite_pet": ""
+ }
+ },
+ "webAuthnPolicyRpEntityName": "keycloak",
+ "webAuthnPolicySignatureAlgorithms": ["ES256"],
+ "webAuthnPolicyRpId": "",
+ "webAuthnPolicyAttestationConveyancePreference": "not specified",
+ "webAuthnPolicyAuthenticatorAttachment": "not specified",
+ "webAuthnPolicyRequireResidentKey": "not specified",
+ "webAuthnPolicyUserVerificationRequirement": "not specified",
+ "webAuthnPolicyCreateTimeout": 0,
+ "webAuthnPolicyAvoidSameAuthenticatorRegister": false,
+ "webAuthnPolicyAcceptableAaguids": [],
+ "webAuthnPolicyExtraOrigins": [],
+ "webAuthnPolicyPasswordlessRpEntityName": "keycloak",
+ "webAuthnPolicyPasswordlessSignatureAlgorithms": ["ES256"],
+ "webAuthnPolicyPasswordlessRpId": "",
+ "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified",
+ "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified",
+ "webAuthnPolicyPasswordlessRequireResidentKey": "not specified",
+ "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified",
+ "webAuthnPolicyPasswordlessCreateTimeout": 0,
+ "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false,
+ "webAuthnPolicyPasswordlessAcceptableAaguids": [],
+ "webAuthnPolicyPasswordlessExtraOrigins": [],
+ "users": [
+ {
+ "id": "d93e1772-4916-4243-850f-a6d9b2615716",
+ "username": "testuser",
+ "firstName": "Test",
+ "lastName": "User",
+ "email": "testuser@gmail.com",
+ "emailVerified": true,
+ "attributes": {
+ "additional_emails": ["test.user@protonmail.com", "testuser@hotmail.com"],
+ "gender": ["prefer_not_to_say"],
+ "favorite_pet": ["cats"],
+ "favourite_pet": ["cat"],
+ "bio": ["Hello I'm Test User and I do not exist."],
+ "phone_number": ["1111111111"],
+ "locale": ["en"],
+ "favorite_media": ["movies", "series"]
+ },
+ "createdTimestamp": 1716183898408,
+ "enabled": true,
+ "totp": false,
+ "credentials": [
+ {
+ "id": "576982e2-6fb3-4752-8724-5ff390ea8301",
+ "type": "password",
+ "userLabel": "My password",
+ "createdDate": 1716183916529,
+ "secretData": "{\"value\":\"9hwJ989FAr0UgT0MfffNYSI6Zf/3qT/y17DTUcwbiEM=\",\"salt\":\"C3ZnHzgPd+0Lemw4olCOgA==\",\"additionalParameters\":{}}",
+ "credentialData": "{\"hashIterations\":5,\"algorithm\":\"argon2\",\"additionalParameters\":{\"hashLength\":[\"32\"],\"memory\":[\"7168\"],\"type\":[\"id\"],\"version\":[\"1.3\"],\"parallelism\":[\"1\"]}}"
+ }
+ ],
+ "disableableCredentialTypes": [],
+ "requiredActions": [],
+ "realmRoles": ["default-roles-myrealm"],
+ "notBefore": 0,
+ "groups": []
+ }
+ ],
+ "scopeMappings": [
+ {
+ "clientScope": "offline_access",
+ "roles": ["offline_access"]
+ }
+ ],
+ "clientScopeMappings": {
+ "account": [
+ {
+ "client": "account-console",
+ "roles": ["manage-account", "view-groups"]
+ }
+ ]
+ },
+ "clients": [
+ {
+ "id": "7221ef76-9d96-49ad-88a6-9f72eeeb0aa7",
+ "clientId": "account",
+ "name": "${client_account}",
+ "rootUrl": "${authBaseUrl}",
+ "baseUrl": "/realms/myrealm/account/",
+ "surrogateAuthRequired": false,
+ "enabled": true,
+ "alwaysDisplayInConsole": false,
+ "clientAuthenticatorType": "client-secret",
+ "redirectUris": ["/realms/myrealm/account/*"],
+ "webOrigins": [],
+ "notBefore": 0,
+ "bearerOnly": false,
+ "consentRequired": false,
+ "standardFlowEnabled": true,
+ "implicitFlowEnabled": false,
+ "directAccessGrantsEnabled": false,
+ "serviceAccountsEnabled": false,
+ "publicClient": true,
+ "frontchannelLogout": false,
+ "protocol": "openid-connect",
+ "attributes": {
+ "post.logout.redirect.uris": "+"
+ },
+ "authenticationFlowBindingOverrides": {},
+ "fullScopeAllowed": false,
+ "nodeReRegistrationTimeout": 0,
+ "defaultClientScopes": [
+ "web-origins",
+ "acr",
+ "profile",
+ "roles",
+ "basic",
+ "email"
+ ],
+ "optionalClientScopes": [
+ "address",
+ "phone",
+ "offline_access",
+ "microprofile-jwt"
+ ]
+ },
+ {
+ "id": "d8f14dc4-5f0f-4a1d-8c0b-cfe78ee55cb3",
+ "clientId": "account-console",
+ "name": "${client_account-console}",
+ "rootUrl": "${authBaseUrl}",
+ "baseUrl": "/realms/myrealm/account/",
+ "surrogateAuthRequired": false,
+ "enabled": true,
+ "alwaysDisplayInConsole": false,
+ "clientAuthenticatorType": "client-secret",
+ "redirectUris": ["/realms/myrealm/account/*"],
+ "webOrigins": [],
+ "notBefore": 0,
+ "bearerOnly": false,
+ "consentRequired": false,
+ "standardFlowEnabled": true,
+ "implicitFlowEnabled": false,
+ "directAccessGrantsEnabled": false,
+ "serviceAccountsEnabled": false,
+ "publicClient": true,
+ "frontchannelLogout": false,
+ "protocol": "openid-connect",
+ "attributes": {
+ "post.logout.redirect.uris": "+",
+ "pkce.code.challenge.method": "S256"
+ },
+ "authenticationFlowBindingOverrides": {},
+ "fullScopeAllowed": false,
+ "nodeReRegistrationTimeout": 0,
+ "protocolMappers": [
+ {
+ "id": "08d7bc08-2ff3-44ea-9d65-fa1c4ca35646",
+ "name": "audience resolve",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-audience-resolve-mapper",
+ "consentRequired": false,
+ "config": {}
+ }
+ ],
+ "defaultClientScopes": [
+ "web-origins",
+ "acr",
+ "profile",
+ "roles",
+ "basic",
+ "email"
+ ],
+ "optionalClientScopes": [
+ "address",
+ "phone",
+ "offline_access",
+ "microprofile-jwt"
+ ]
+ },
+ {
+ "id": "953c597f-faef-4abc-88dc-4fbc9501170c",
+ "clientId": "admin-cli",
+ "name": "${client_admin-cli}",
+ "surrogateAuthRequired": false,
+ "enabled": true,
+ "alwaysDisplayInConsole": false,
+ "clientAuthenticatorType": "client-secret",
+ "redirectUris": [],
+ "webOrigins": [],
+ "notBefore": 0,
+ "bearerOnly": false,
+ "consentRequired": false,
+ "standardFlowEnabled": false,
+ "implicitFlowEnabled": false,
+ "directAccessGrantsEnabled": true,
+ "serviceAccountsEnabled": false,
+ "publicClient": true,
+ "frontchannelLogout": false,
+ "protocol": "openid-connect",
+ "attributes": {
+ "post.logout.redirect.uris": "+"
+ },
+ "authenticationFlowBindingOverrides": {},
+ "fullScopeAllowed": false,
+ "nodeReRegistrationTimeout": 0,
+ "defaultClientScopes": [
+ "web-origins",
+ "acr",
+ "profile",
+ "roles",
+ "basic",
+ "email"
+ ],
+ "optionalClientScopes": [
+ "address",
+ "phone",
+ "offline_access",
+ "microprofile-jwt"
+ ]
+ },
+ {
+ "id": "f5e032da-c8ab-48c2-959c-8466ad1e6a09",
+ "clientId": "broker",
+ "name": "${client_broker}",
+ "surrogateAuthRequired": false,
+ "enabled": true,
+ "alwaysDisplayInConsole": false,
+ "clientAuthenticatorType": "client-secret",
+ "redirectUris": [],
+ "webOrigins": [],
+ "notBefore": 0,
+ "bearerOnly": true,
+ "consentRequired": false,
+ "standardFlowEnabled": true,
+ "implicitFlowEnabled": false,
+ "directAccessGrantsEnabled": false,
+ "serviceAccountsEnabled": false,
+ "publicClient": false,
+ "frontchannelLogout": false,
+ "protocol": "openid-connect",
+ "attributes": {
+ "post.logout.redirect.uris": "+"
+ },
+ "authenticationFlowBindingOverrides": {},
+ "fullScopeAllowed": false,
+ "nodeReRegistrationTimeout": 0,
+ "defaultClientScopes": [
+ "web-origins",
+ "acr",
+ "profile",
+ "roles",
+ "basic",
+ "email"
+ ],
+ "optionalClientScopes": [
+ "address",
+ "phone",
+ "offline_access",
+ "microprofile-jwt"
+ ]
+ },
+ {
+ "id": "8fba88fa-61e9-45a4-893d-ab102973ebf6",
+ "clientId": "myclient",
+ "name": "",
+ "description": "",
+ "rootUrl": "https://my-theme.keycloakify.dev",
+ "adminUrl": "https://my-theme.keycloakify.dev",
+ "baseUrl": "https://my-theme.keycloakify.dev",
+ "surrogateAuthRequired": false,
+ "enabled": true,
+ "alwaysDisplayInConsole": false,
+ "clientAuthenticatorType": "client-secret",
+ "redirectUris": [
+ "https://my-theme.keycloakify.dev/*",
+ "http://localhost*",
+ "http://127.0.0.1*"
+ ],
+ "webOrigins": ["*"],
+ "notBefore": 0,
+ "bearerOnly": false,
+ "consentRequired": false,
+ "standardFlowEnabled": true,
+ "implicitFlowEnabled": false,
+ "directAccessGrantsEnabled": true,
+ "serviceAccountsEnabled": false,
+ "publicClient": true,
+ "frontchannelLogout": true,
+ "protocol": "openid-connect",
+ "attributes": {
+ "oidc.ciba.grant.enabled": "false",
+ "backchannel.logout.session.required": "true",
+ "login_theme": "keycloakify-starter",
+ "post.logout.redirect.uris": "https://my-theme.keycloakify.dev/*##http://localhost*##http://127.0.0.1*",
+ "oauth2.device.authorization.grant.enabled": "false",
+ "display.on.consent.screen": "false",
+ "backchannel.logout.revoke.offline.tokens": "false"
+ },
+ "authenticationFlowBindingOverrides": {},
+ "fullScopeAllowed": true,
+ "nodeReRegistrationTimeout": -1,
+ "protocolMappers": [
+ {
+ "id": "91a196c1-f93c-48a5-aced-b8d60fb09b62",
+ "name": "Favourite Pet",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "favourite_pet",
+ "id.token.claim": "true",
+ "lightweight.claim": "false",
+ "access.token.claim": "true",
+ "claim.name": "favourite_pet",
+ "jsonType.label": "String"
+ }
+ }
+ ],
+ "defaultClientScopes": [
+ "web-origins",
+ "acr",
+ "profile",
+ "roles",
+ "basic",
+ "email"
+ ],
+ "optionalClientScopes": [
+ "address",
+ "phone",
+ "offline_access",
+ "microprofile-jwt"
+ ]
+ },
+ {
+ "id": "e05cc68c-5e53-4796-ae3a-a1bfbf5c51bb",
+ "clientId": "realm-management",
+ "name": "${client_realm-management}",
+ "surrogateAuthRequired": false,
+ "enabled": true,
+ "alwaysDisplayInConsole": false,
+ "clientAuthenticatorType": "client-secret",
+ "redirectUris": [],
+ "webOrigins": [],
+ "notBefore": 0,
+ "bearerOnly": true,
+ "consentRequired": false,
+ "standardFlowEnabled": true,
+ "implicitFlowEnabled": false,
+ "directAccessGrantsEnabled": false,
+ "serviceAccountsEnabled": false,
+ "publicClient": false,
+ "frontchannelLogout": false,
+ "protocol": "openid-connect",
+ "attributes": {
+ "post.logout.redirect.uris": "+"
+ },
+ "authenticationFlowBindingOverrides": {},
+ "fullScopeAllowed": false,
+ "nodeReRegistrationTimeout": 0,
+ "defaultClientScopes": [
+ "web-origins",
+ "acr",
+ "profile",
+ "roles",
+ "basic",
+ "email"
+ ],
+ "optionalClientScopes": [
+ "address",
+ "phone",
+ "offline_access",
+ "microprofile-jwt"
+ ]
+ },
+ {
+ "id": "fce8a109-6f32-4814-9a20-2ff2435d2da6",
+ "clientId": "security-admin-console",
+ "name": "${client_security-admin-console}",
+ "rootUrl": "${authAdminUrl}",
+ "baseUrl": "/admin/myrealm/console/",
+ "surrogateAuthRequired": false,
+ "enabled": true,
+ "alwaysDisplayInConsole": false,
+ "clientAuthenticatorType": "client-secret",
+ "redirectUris": ["/admin/myrealm/console/*"],
+ "webOrigins": ["+"],
+ "notBefore": 0,
+ "bearerOnly": false,
+ "consentRequired": false,
+ "standardFlowEnabled": true,
+ "implicitFlowEnabled": false,
+ "directAccessGrantsEnabled": false,
+ "serviceAccountsEnabled": false,
+ "publicClient": true,
+ "frontchannelLogout": false,
+ "protocol": "openid-connect",
+ "attributes": {
+ "post.logout.redirect.uris": "+",
+ "pkce.code.challenge.method": "S256"
+ },
+ "authenticationFlowBindingOverrides": {},
+ "fullScopeAllowed": false,
+ "nodeReRegistrationTimeout": 0,
+ "protocolMappers": [
+ {
+ "id": "52192d19-0406-41b7-b995-b099bdbaa448",
+ "name": "locale",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "locale",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "locale",
+ "jsonType.label": "String"
+ }
+ }
+ ],
+ "defaultClientScopes": [
+ "web-origins",
+ "acr",
+ "profile",
+ "roles",
+ "basic",
+ "email"
+ ],
+ "optionalClientScopes": [
+ "address",
+ "phone",
+ "offline_access",
+ "microprofile-jwt"
+ ]
+ }
+ ],
+ "clientScopes": [
+ {
+ "id": "6a955b1e-f0e2-49fa-b3c9-bd59ed1fcd4f",
+ "name": "web-origins",
+ "description": "OpenID Connect scope for add allowed web origins to the access token",
+ "protocol": "openid-connect",
+ "attributes": {
+ "include.in.token.scope": "false",
+ "consent.screen.text": "",
+ "display.on.consent.screen": "false"
+ },
+ "protocolMappers": [
+ {
+ "id": "3a392f70-ed70-424a-b60b-82db32b83df8",
+ "name": "allowed web origins",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-allowed-origins-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "access.token.claim": "true"
+ }
+ }
+ ]
+ },
+ {
+ "id": "9cda058d-9935-4c8b-844d-c163d10f7c3c",
+ "name": "address",
+ "description": "OpenID Connect built-in scope: address",
+ "protocol": "openid-connect",
+ "attributes": {
+ "include.in.token.scope": "true",
+ "consent.screen.text": "${addressScopeConsentText}",
+ "display.on.consent.screen": "true"
+ },
+ "protocolMappers": [
+ {
+ "id": "a053d8ec-b267-4e5a-a424-3b14bef9cd15",
+ "name": "address",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-address-mapper",
+ "consentRequired": false,
+ "config": {
+ "user.attribute.formatted": "formatted",
+ "user.attribute.country": "country",
+ "introspection.token.claim": "true",
+ "user.attribute.postal_code": "postal_code",
+ "userinfo.token.claim": "true",
+ "user.attribute.street": "street",
+ "id.token.claim": "true",
+ "user.attribute.region": "region",
+ "access.token.claim": "true",
+ "user.attribute.locality": "locality"
+ }
+ }
+ ]
+ },
+ {
+ "id": "6225f4c7-ad5c-42ea-b7d4-5bb4e7c77459",
+ "name": "phone",
+ "description": "OpenID Connect built-in scope: phone",
+ "protocol": "openid-connect",
+ "attributes": {
+ "include.in.token.scope": "true",
+ "consent.screen.text": "${phoneScopeConsentText}",
+ "display.on.consent.screen": "true"
+ },
+ "protocolMappers": [
+ {
+ "id": "5052be82-243f-41b0-a214-4f01935180e5",
+ "name": "phone number",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "phoneNumber",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "phone_number",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "4d31d278-e6ef-4b8b-97cb-4da9626d0e93",
+ "name": "phone number verified",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "phoneNumberVerified",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "phone_number_verified",
+ "jsonType.label": "boolean"
+ }
+ }
+ ]
+ },
+ {
+ "id": "9357440c-6200-41a1-a447-0ec97895763e",
+ "name": "basic",
+ "description": "OpenID Connect scope for add all basic claims to the token",
+ "protocol": "openid-connect",
+ "attributes": {
+ "include.in.token.scope": "false",
+ "display.on.consent.screen": "false"
+ },
+ "protocolMappers": [
+ {
+ "id": "bf9cb6c6-71a4-4bf9-8c60-ed58adcc2258",
+ "name": "auth_time",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usersessionmodel-note-mapper",
+ "consentRequired": false,
+ "config": {
+ "user.session.note": "AUTH_TIME",
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "auth_time",
+ "jsonType.label": "long"
+ }
+ },
+ {
+ "id": "679c8292-1abb-4d96-bacc-671303765f9b",
+ "name": "sub",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-sub-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "access.token.claim": "true"
+ }
+ }
+ ]
+ },
+ {
+ "id": "0ec225e7-253b-4a01-85e1-68daf3df3eba",
+ "name": "role_list",
+ "description": "SAML role list",
+ "protocol": "saml",
+ "attributes": {
+ "consent.screen.text": "${samlRoleListScopeConsentText}",
+ "display.on.consent.screen": "true"
+ },
+ "protocolMappers": [
+ {
+ "id": "a55cf74e-ce68-4ebd-9c24-dc3fd6a9cfa5",
+ "name": "role list",
+ "protocol": "saml",
+ "protocolMapper": "saml-role-list-mapper",
+ "consentRequired": false,
+ "config": {
+ "single": "false",
+ "attribute.nameformat": "Basic",
+ "attribute.name": "Role"
+ }
+ }
+ ]
+ },
+ {
+ "id": "e2f1dd86-00a2-4374-b888-7211f748c58d",
+ "name": "offline_access",
+ "description": "OpenID Connect built-in scope: offline_access",
+ "protocol": "openid-connect",
+ "attributes": {
+ "consent.screen.text": "${offlineAccessScopeConsentText}",
+ "display.on.consent.screen": "true"
+ }
+ },
+ {
+ "id": "e86456b8-0663-448e-ad16-7d520d0c448e",
+ "name": "profile",
+ "description": "OpenID Connect built-in scope: profile",
+ "protocol": "openid-connect",
+ "attributes": {
+ "include.in.token.scope": "true",
+ "consent.screen.text": "${profileScopeConsentText}",
+ "display.on.consent.screen": "true"
+ },
+ "protocolMappers": [
+ {
+ "id": "569c799d-79f2-4b2b-a1ec-3661e3d8d433",
+ "name": "gender",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "gender",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "gender",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "2d01eb48-77c3-4c83-a864-755699cb7e7c",
+ "name": "updated at",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "updatedAt",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "updated_at",
+ "jsonType.label": "long"
+ }
+ },
+ {
+ "id": "a9700270-006f-4a85-8458-f39644659029",
+ "name": "locale",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "locale",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "locale",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "3a7bca96-0839-4d1e-b37d-6e624f37facb",
+ "name": "profile",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "profile",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "profile",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "2a41be1c-872a-4b3e-9051-71ebd5d140c1",
+ "name": "website",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "website",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "website",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "9fe5e57d-ee79-4b8b-9ab2-345093a1fdbf",
+ "name": "full name",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-full-name-mapper",
+ "consentRequired": false,
+ "config": {
+ "id.token.claim": "true",
+ "introspection.token.claim": "true",
+ "access.token.claim": "true",
+ "userinfo.token.claim": "true"
+ }
+ },
+ {
+ "id": "bda9e4e7-4de0-455d-bace-4e94b1dab5ad",
+ "name": "nickname",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "nickname",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "nickname",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "312a0b4d-46b8-42e0-b162-e5869b317b36",
+ "name": "zoneinfo",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "zoneinfo",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "zoneinfo",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "4f8ac9bc-e32d-4ebb-bb85-b9a94a459aa1",
+ "name": "username",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "username",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "preferred_username",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "bebdf0c7-6f0f-4b08-a327-50af837c82b9",
+ "name": "family name",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "lastName",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "family_name",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "d96d9686-f4e0-479a-9855-cfc526a35294",
+ "name": "middle name",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "middleName",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "middle_name",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "66ad8239-e1df-4f9d-9cb7-d35f23f95f37",
+ "name": "given name",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "firstName",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "given_name",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "ece8245b-16ae-4322-bc78-f8d5f671640a",
+ "name": "picture",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "picture",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "picture",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "384cf049-0fed-47e2-8b11-06cf6c03465d",
+ "name": "birthdate",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "birthdate",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "birthdate",
+ "jsonType.label": "String"
+ }
+ }
+ ]
+ },
+ {
+ "id": "49e85de9-edd1-4a9e-a2b0-e9c663d4dd9a",
+ "name": "email",
+ "description": "OpenID Connect built-in scope: email",
+ "protocol": "openid-connect",
+ "attributes": {
+ "include.in.token.scope": "true",
+ "consent.screen.text": "${emailScopeConsentText}",
+ "display.on.consent.screen": "true"
+ },
+ "protocolMappers": [
+ {
+ "id": "d458e6fc-b414-4b45-b9e1-99342d7d2bba",
+ "name": "email",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "email",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "email",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "2b73ce63-0443-46dc-b35c-1148edb976ab",
+ "name": "email verified",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-property-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "emailVerified",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "email_verified",
+ "jsonType.label": "boolean"
+ }
+ }
+ ]
+ },
+ {
+ "id": "71303f6d-348a-4892-9d6f-dc9a2d2e4b14",
+ "name": "microprofile-jwt",
+ "description": "Microprofile - JWT built-in scope",
+ "protocol": "openid-connect",
+ "attributes": {
+ "include.in.token.scope": "true",
+ "display.on.consent.screen": "false"
+ },
+ "protocolMappers": [
+ {
+ "id": "498cbff6-a650-4a09-8192-5defaa50f33b",
+ "name": "upn",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "username",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "upn",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "eb8585bc-ca30-410e-9f92-0d63665f5ed6",
+ "name": "groups",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-realm-role-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "multivalued": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "foo",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "groups",
+ "jsonType.label": "String"
+ }
+ }
+ ]
+ },
+ {
+ "id": "62b8c264-2c10-48c6-803f-b7606a89e0d9",
+ "name": "roles",
+ "description": "OpenID Connect scope for add user roles to the access token",
+ "protocol": "openid-connect",
+ "attributes": {
+ "include.in.token.scope": "false",
+ "consent.screen.text": "${rolesScopeConsentText}",
+ "display.on.consent.screen": "true"
+ },
+ "protocolMappers": [
+ {
+ "id": "0c18ca55-df63-4071-81f9-43f5d077c015",
+ "name": "realm roles",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-realm-role-mapper",
+ "consentRequired": false,
+ "config": {
+ "user.attribute": "foo",
+ "introspection.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "realm_access.roles",
+ "jsonType.label": "String",
+ "multivalued": "true"
+ }
+ },
+ {
+ "id": "6de6510d-d7f3-4289-a10f-4c21289313a4",
+ "name": "audience resolve",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-audience-resolve-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "access.token.claim": "true"
+ }
+ },
+ {
+ "id": "a5851eb2-bfc5-4a0a-8a49-92f4fc8c5041",
+ "name": "client roles",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-client-role-mapper",
+ "consentRequired": false,
+ "config": {
+ "user.attribute": "foo",
+ "introspection.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "resource_access.${client_id}.roles",
+ "jsonType.label": "String",
+ "multivalued": "true"
+ }
+ }
+ ]
+ },
+ {
+ "id": "bfc69775-83af-4816-82fd-d1c42687fb5e",
+ "name": "acr",
+ "description": "OpenID Connect scope for add acr (authentication context class reference) to the token",
+ "protocol": "openid-connect",
+ "attributes": {
+ "include.in.token.scope": "false",
+ "display.on.consent.screen": "false"
+ },
+ "protocolMappers": [
+ {
+ "id": "8e2027d5-32dd-4a87-a7ec-00e5316c5617",
+ "name": "acr loa level",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-acr-mapper",
+ "consentRequired": false,
+ "config": {
+ "id.token.claim": "true",
+ "introspection.token.claim": "true",
+ "access.token.claim": "true",
+ "userinfo.token.claim": "true"
+ }
+ }
+ ]
+ }
+ ],
+ "defaultDefaultClientScopes": [
+ "role_list",
+ "profile",
+ "email",
+ "roles",
+ "web-origins",
+ "acr",
+ "basic"
+ ],
+ "defaultOptionalClientScopes": [
+ "offline_access",
+ "address",
+ "phone",
+ "microprofile-jwt"
+ ],
+ "browserSecurityHeaders": {
+ "contentSecurityPolicyReportOnly": "",
+ "xContentTypeOptions": "nosniff",
+ "referrerPolicy": "no-referrer",
+ "xRobotsTag": "none",
+ "xFrameOptions": "SAMEORIGIN",
+ "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';",
+ "xXSSProtection": "1; mode=block",
+ "strictTransportSecurity": "max-age=31536000; includeSubDomains"
+ },
+ "smtpServer": {},
+ "loginTheme": "keycloakify-starter",
+ "accountTheme": "keycloakify-starter",
+ "adminTheme": "",
+ "emailTheme": "",
+ "eventsEnabled": false,
+ "eventsListeners": ["jboss-logging"],
+ "enabledEventTypes": [],
+ "adminEventsEnabled": false,
+ "adminEventsDetailsEnabled": false,
+ "identityProviders": [],
+ "identityProviderMappers": [],
+ "components": {
+ "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [
+ {
+ "id": "67526992-f0ce-42ff-a0fb-af267192ff70",
+ "name": "Allowed Client Scopes",
+ "providerId": "allowed-client-templates",
+ "subType": "authenticated",
+ "subComponents": {},
+ "config": {
+ "allow-default-scopes": ["true"]
+ }
+ },
+ {
+ "id": "64a2f718-da10-45d9-a75a-69c156a7ccd8",
+ "name": "Allowed Protocol Mapper Types",
+ "providerId": "allowed-protocol-mappers",
+ "subType": "authenticated",
+ "subComponents": {},
+ "config": {
+ "allowed-protocol-mapper-types": [
+ "oidc-full-name-mapper",
+ "oidc-usermodel-attribute-mapper",
+ "oidc-address-mapper",
+ "saml-user-attribute-mapper",
+ "oidc-usermodel-property-mapper",
+ "saml-user-property-mapper",
+ "saml-role-list-mapper",
+ "oidc-sha256-pairwise-sub-mapper"
+ ]
+ }
+ },
+ {
+ "id": "4d3e104f-6fdf-45eb-b756-5fef6840fbed",
+ "name": "Consent Required",
+ "providerId": "consent-required",
+ "subType": "anonymous",
+ "subComponents": {},
+ "config": {}
+ },
+ {
+ "id": "c647e85f-6700-4d66-84f2-4a869e467735",
+ "name": "Max Clients Limit",
+ "providerId": "max-clients",
+ "subType": "anonymous",
+ "subComponents": {},
+ "config": {
+ "max-clients": ["200"]
+ }
+ },
+ {
+ "id": "51f41974-f7e5-4e7d-b486-5bd652a98e93",
+ "name": "Allowed Protocol Mapper Types",
+ "providerId": "allowed-protocol-mappers",
+ "subType": "anonymous",
+ "subComponents": {},
+ "config": {
+ "allowed-protocol-mapper-types": [
+ "oidc-sha256-pairwise-sub-mapper",
+ "oidc-usermodel-property-mapper",
+ "oidc-address-mapper",
+ "oidc-usermodel-attribute-mapper",
+ "oidc-full-name-mapper",
+ "saml-user-attribute-mapper",
+ "saml-user-property-mapper",
+ "saml-role-list-mapper"
+ ]
+ }
+ },
+ {
+ "id": "8f7d6ece-e956-4e48-95ab-5ab72b2b7c9a",
+ "name": "Allowed Client Scopes",
+ "providerId": "allowed-client-templates",
+ "subType": "anonymous",
+ "subComponents": {},
+ "config": {
+ "allow-default-scopes": ["true"]
+ }
+ },
+ {
+ "id": "e60b1167-cdee-4173-be99-3dad6a536b4a",
+ "name": "Trusted Hosts",
+ "providerId": "trusted-hosts",
+ "subType": "anonymous",
+ "subComponents": {},
+ "config": {
+ "host-sending-registration-request-must-match": ["true"],
+ "client-uris-must-match": ["true"]
+ }
+ },
+ {
+ "id": "5ba8b893-ab01-430b-9092-32646a50a662",
+ "name": "Full Scope Disabled",
+ "providerId": "scope",
+ "subType": "anonymous",
+ "subComponents": {},
+ "config": {}
+ }
+ ],
+ "org.keycloak.userprofile.UserProfileProvider": [
+ {
+ "id": "237022c6-9443-46b3-902e-210e14c3c9a8",
+ "providerId": "declarative-user-profile",
+ "subComponents": {},
+ "config": {
+ "kc.user.profile.config": [
+ "{\"attributes\":[{\"name\":\"username\",\"displayName\":\"${username}\",\"validations\":{\"length\":{\"min\":3,\"max\":255},\"username-prohibited-characters\":{},\"up-username-not-idn-homograph\":{}},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"email\",\"displayName\":\"${email}\",\"validations\":{\"email\":{},\"length\":{\"max\":255}},\"required\":{\"roles\":[\"user\"]},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"firstName\",\"displayName\":\"${firstName}\",\"validations\":{\"length\":{\"max\":255},\"person-name-prohibited-characters\":{}},\"required\":{\"roles\":[\"user\"]},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"lastName\",\"displayName\":\"${lastName}\",\"validations\":{\"length\":{\"max\":255},\"person-name-prohibited-characters\":{}},\"required\":{\"roles\":[\"user\"]},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"favourite_pet\",\"displayName\":\"${profile.attributes.favourite_pet}\",\"validations\":{\"options\":{\"options\":[\"cat\",\"dog\",\"bird\"]}},\"annotations\":{\"inputType\":\"select\",\"inputOptionLabelsI18nPrefix\":\"profile.attributes.favourite_pet\"},\"required\":{\"roles\":[\"admin\",\"user\"]},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false}],\"groups\":[{\"name\":\"user-metadata\",\"displayHeader\":\"User metadata\",\"displayDescription\":\"Attributes, which refer to user metadata\"}]}"
+ ]
+ }
+ }
+ ],
+ "org.keycloak.keys.KeyProvider": [
+ {
+ "id": "5f3c1765-8810-419f-9c18-4a2db0e874e7",
+ "name": "rsa-generated",
+ "providerId": "rsa-generated",
+ "subComponents": {},
+ "config": {
+ "privateKey": [
+ "MIIEowIBAAKCAQEAsYUWzVfZMd6ywpBmLJYeF1U9Mgd/z3xWvl1Yq76oRPPfpcqQitN+cktWqu0hPerCVSl2ltwXDMrUwFzswG9MiM9hb+BLEld7kYiYkcFNt3lCtmmeRQEae7JwWimzeNV96Qlz0tHY8f9Zh0ffPDsLTN1HGAeRJJhI7mNQm6qCJNMCfVA/O5SWumsIn2XLnSMiQ05AACVHOLUq6rAZ2zCCaYmXTmJkuSOb8e26V303P6l63DSe5HSNXDdI00tjfFFf37q870zhvfsotrjjx0RMijy9Kjj8OZF+pFHpDRaGEi8tpQxZDnCTofTieB/Vp3QP+aTlvAyD3Q1ZnJxGQCLygwIDAQABAoIBABUJ9XMJGNQzamiVwuOWN7ht4UP8ezYvgdEA8NaLUO0PIYVIKyD7l4OwkHPPM9PfRACM2qG0MZp8sCyg4WxIeepy+D979oRqJYUmNRLSipqWlASuItRXIPjiY99uYXdjh2R8Os5pvCD+MZxPX9KHGuaVXmzSJMO7YAAPeYkMHcLYTp/U0c65Ztaaz1zz1FeyvpjkLr9SHiMcIN51zFmhvT1tcRIqy4zidisjrTSUr/KPVxeJtrEfyhTGk3z41yJf5YbeaxaMjJR5x0WXzt1fWVmA/V1bWa2Zlj9d8AxDReA1p7Lpstz34PRoCMj9bmFguI2+RTw6K0D++Jydfxmh8vUCgYEA5Zwk2r3TFO3i3V70LOn6CLzn15yLeuSIJ9p2os70jQOmFMCreLdcUbCaiUe7UV/IIVftbcxhFm9zECXZXX0wubcmHZqyptlbuAn1de4QkLJixXo1A7ZQXBEZk22WN2naXHQF5oK6lh/VSLcZBajTsyvBm5JWXrd8djjG06MugA8CgYEAxexKI5IwcLhpMDV9UPQb/+lDWHVqCT2xwYxnZ85y+5gmrOyyT7mIChz3DFYiaw4CHJWmBkIDBaiDgLEgQk4QXWzYshXawShBHnv1h08bVMMw98Ivec7ZRkV+/ET30YRwC2Uyk4bm4HpwVV5GCFhC4aAvRcCA1CIJk3MwcOwksk0CgYEAqxyaOomMbOR7VQ4WWgJkW26sOHppV8RH06tzDhG9HfnCI2USZHwBSL+b6wKSDiqbMn4cat8M23NjBH2wZ4OMdFqRBS7sRHtnZtfFHYW0wqCuCwzvxTxw1qvHq57Xe6RfHtc4LnjuJELE59PLyfPvEG9jcVS1GREUp+XYBpBtbvECgYAMhWBDU9JAr0noRNoCrw6+Z9Fc3UCyCPcf2XQJOyRHCl8X/XliVchna2GtpB1VTHORv13bc32hdAGtuIbj6vBaGLK0wXEvWw6TkR/9SWHfQOHuKpi6Sf2w1mCsMOjElm5IKkTC1Hvyo4xLukUP7hV9FJcpAH6l7OlSLK1Z13aS2QKBgB6w4gvmVEQruHV5+K60OatuFojr+kxJwmzCb5uKOULUFezT2pA3p3l6IWxGL2XtM+LD0SiZE3KZJUzf+LatYlBU9ek4F1krkVNUTRZpzUa0oADbymCL1chM4oPIs7sISQlFIH2wOSZt6Blvcw0E0wfjd9Gv/LHxcMnlRb1t1sLk"
+ ],
+ "keyUse": ["SIG"],
+ "certificate": [
+ "MIICnTCCAYUCBgGQBsyplzANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdteXJlYWxtMB4XDTI0MDYxMTEwMTQ1NFoXDTM0MDYxMTEwMTYzNFowEjEQMA4GA1UEAwwHbXlyZWFsbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALGFFs1X2THessKQZiyWHhdVPTIHf898Vr5dWKu+qETz36XKkIrTfnJLVqrtIT3qwlUpdpbcFwzK1MBc7MBvTIjPYW/gSxJXe5GImJHBTbd5QrZpnkUBGnuycFops3jVfekJc9LR2PH/WYdH3zw7C0zdRxgHkSSYSO5jUJuqgiTTAn1QPzuUlrprCJ9ly50jIkNOQAAlRzi1KuqwGdswgmmJl05iZLkjm/Htuld9Nz+petw0nuR0jVw3SNNLY3xRX9+6vO9M4b37KLa448dETIo8vSo4/DmRfqRR6Q0WhhIvLaUMWQ5wk6H04ngf1ad0D/mk5bwMg90NWZycRkAi8oMCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAVS+gJshIFX6cmBGI8UaOOI/9+XFb4Gi+DHaHVWVVHTd14MoqNK1bmmyTHbGIZbvK8UqgJ9+FhJX1ejx17d4KBzkZI3tYvPnVacHvaw1CIUMZ1Ini6u+UGUTnIlnQzCG0pcTKjOZXf3ih1B2CKdwyC7XeXyEJHicAIG7XfzYfYd9DYHvA+h6hrXaQcNJMW7WFNbtb3fJhtlv5P1Iw+ZEGdj15ukMI0bg2OEQA0F3jIw6QZpigSAGuai3HOY6OgoPO82d7TyTYlNhuwyutWr9izl6QMc2R7BmRfW9XQj4ICR2VWJiL9nqz+SOyqnjQiOObuw8Vywb8c36R1Ym1aaGjOw=="
+ ],
+ "priority": ["100"]
+ }
+ },
+ {
+ "id": "e586f825-a25a-4833-a38e-4c6484ad17fd",
+ "name": "rsa-enc-generated",
+ "providerId": "rsa-enc-generated",
+ "subComponents": {},
+ "config": {
+ "privateKey": [
+ "MIIEogIBAAKCAQEAkQtefHy82e8d5dVWN00LnGI5YmBOTKh0tgqayVRjqLH6u3NfgJVVIe0tFnxa7Wka/ySHrn1KSsW52czZ4uPXLUo4sXBkQxyyFXeZiWN8H+9WiUQ+0hefZF4es5ZPhY2VpeMK9XAnphC362LFLVycXulkpJcQ+4DjI99To4LLyJmjQvsVaJ7amoVJ5xd62eUv+D7f2+jwuaTwjGE3+MWZADXjVxsUY1qJuGLGKnLkNNxJNMDhvnKYw+aa3Z4V90fQVyjN1Volgw3DdA59o4wrWEy+2xHc6j2ESi8+cM60fWzZU9sp2XkyJoCnV7nmwk7pZkDy3zvAkeOWzrr3OWeR3wIDAQABAoIBACWMcet8R0+L7YuATQ+H7IeRjhV/pQWHXp9541RXem1DlgtM9N5Oynk78z4s90Uavphqlo1/deohgdl2hLmODjh1THPzCqGtHhUcnyzICmwiA58JgdHVt7e9/eiz8uY6HxGQ01dyr3D4RwSyzyTNItYXSayqRwU0+phgykA8LhFCAQM/UkRXDf6UCFKBhDyE7VPBaDv0xyxNb7dKtE7C6Qo5t5D40xCfQ8ni8OcD5RvshQq5xOWcw7igxAhlmXCu1fuO2CDiSiqXLMENs4NlwilQ3caMXAIzUiblaKwCrrK2noBoitx6vuOR2tKmIZSlTyDAG4vLQQtOHk53hBoupGECgYEAx4jSmLM9uUzNwNY1zfs8iNswxbU3YibNe2Q+IFmOQofvTaq1jBBxdPWX5ifIbuTvOAA33pmJRh+BtWzOBBQC7Z4i9mdfvyWB6s8t9nnTnWIY5Hj+hV5gaqae59MjdudsORR887fxzPIeAwwaETfKaZnYpC6zLaE3BXwhIcjlFTcCgYEAuhcKf16JkEYNIwanVHpUXjFxwAThAogHWZAngRokmai67Iulx+rSUhhtOIXtmjj/EaObsrqo5yCKAVZ5EbPTOajdd9RtFzH6q3bRjRdp8o8ZVx4c1vMNaOnLbvK4YzJlKSZN9N7m255Mg+/ea3veKVZsSVHDMnuYmH8GjncjPJkCgYAOIUlQmPjZA3BapJDA2nbJ9kO47IFUiQzqHQotPkpNudSfemRK2+s87htoqA6Qk9PA8nsCX3sSJS8JSwA317bxXs55Bo8IOT6/AxbtKmlq7sR2gX78sNdBFjWQkyoixHasgB/tHmyYJ9kqPBQoffvuiH+H+OqlY5JC6CxseQ6H9wKBgF69Hj4MDjLiRwve9k9+2/b8azHcCgX05PEG/+WtPpbwHQIScnseJKdhAjH1lSqf+9OqHLlYaGcK3Nejg42spEvFmcLI5iUZ78lde3++PNUdX0RH81zHbrtL06MPdSojXPcfJi8VUCjdJY1CEFVeQZOACS8mrh7EZ8KzYM4k/055AoGAYqjBv3WS8ul7kAsjpZKpIw1QZZaTjBSmLpjB6X8InF+Zihjgm80Dd4RMFnMnEawhFBvnpklvyw5Ce6NSwcC137kN3NVpJypykkXuYkimg7OxgJjR7YFdbQWJWlc+1eB81WTHcEOHVI/DmeV2yVJcv6kA2iC+3/JA0VoJxvrRBKc="
+ ],
+ "keyUse": ["ENC"],
+ "certificate": [
+ "MIICnTCCAYUCBgGQBsyq0jANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdteXJlYWxtMB4XDTI0MDYxMTEwMTQ1NFoXDTM0MDYxMTEwMTYzNFowEjEQMA4GA1UEAwwHbXlyZWFsbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJELXnx8vNnvHeXVVjdNC5xiOWJgTkyodLYKmslUY6ix+rtzX4CVVSHtLRZ8Wu1pGv8kh659SkrFudnM2eLj1y1KOLFwZEMcshV3mYljfB/vVolEPtIXn2ReHrOWT4WNlaXjCvVwJ6YQt+tixS1cnF7pZKSXEPuA4yPfU6OCy8iZo0L7FWie2pqFSecXetnlL/g+39vo8Lmk8IxhN/jFmQA141cbFGNaibhixipy5DTcSTTA4b5ymMPmmt2eFfdH0FcozdVaJYMNw3QOfaOMK1hMvtsR3Oo9hEovPnDOtH1s2VPbKdl5MiaAp1e55sJO6WZA8t87wJHjls669zlnkd8CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAD9wQ+CJ0FRgls3JrUzxwHLgrJ3Yo4+mDFpSe1rh2XYK5FEIWDWSqxaXI3p0cOZq75RZmI2xV8oaiJMUz9WMZkbNe/KtGRzHY1N9AZooicGIsnFu1t++b8taFxxpvKWZgnbOum2PZlfcNiXL0QeMv0wwhfn9zKA9W1DRcqYGbIamoyVlumvbNyIjqXJKwGYIOW6GNt7v3wJl5AJw8qAU/O/DQwWwmzcnFGNRxRxAwI7we8EiQ5JlG0Wi+nyAQn74o3RhNr3zsY0ndmFx9bFV4BBo2AiYGozCDOCCG5HvrmoDbrm//wmGRv0tCwueBzWHL2mhtbZ6sGWmMWfiTJ2HPpg=="
+ ],
+ "priority": ["100"],
+ "algorithm": ["RSA-OAEP"]
+ }
+ },
+ {
+ "id": "d85dae25-3728-46a0-980b-46171ba50cdd",
+ "name": "aes-generated",
+ "providerId": "aes-generated",
+ "subComponents": {},
+ "config": {
+ "kid": ["1c1d0c8a-6f0b-48a9-a66f-488489137d85"],
+ "secret": ["N4wzheVYYBWxFn9VGWTPQQ"],
+ "priority": ["100"]
+ }
+ },
+ {
+ "id": "8c3bb039-6f5b-4bdc-9faa-e0f6038d9e6b",
+ "name": "hmac-generated-hs512",
+ "providerId": "hmac-generated",
+ "subComponents": {},
+ "config": {
+ "kid": ["ce43821c-6cfd-4ea9-a29a-a724a37e6955"],
+ "secret": [
+ "j_8WeQHYt5R6coay0IOUeu9hGvCoJsgnENSoYm0gDlDx6IHOg-f6p17QIaesNmgrzXtJDRpYMhSjpTMHOnHCHLxwUM4eVg9TcszffndB850Yj3PHPeCc5aoHcpYzWN9NDZZ02nBYA04nfbkdlLXiGlpS3I3e502e4DX3rFtbFZ0"
+ ],
+ "priority": ["100"],
+ "algorithm": ["HS512"]
+ }
+ }
+ ]
+ },
+ "internationalizationEnabled": true,
+ "supportedLocales": ["en", "fr", "es"],
+ "defaultLocale": "en",
+ "authenticationFlows": [
+ {
+ "id": "0e1abbbe-40e3-4754-9fe2-8a7d1f82354e",
+ "alias": "Account verification options",
+ "description": "Method with which to verity the existing account",
+ "providerId": "basic-flow",
+ "topLevel": false,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "idp-email-verification",
+ "authenticatorFlow": false,
+ "requirement": "ALTERNATIVE",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticatorFlow": true,
+ "requirement": "ALTERNATIVE",
+ "priority": 20,
+ "autheticatorFlow": true,
+ "flowAlias": "Verify Existing Account by Re-authentication",
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "f279cc4d-ebed-4390-a5d4-0cbb6dd662ae",
+ "alias": "Browser - Conditional OTP",
+ "description": "Flow to determine if the OTP is required for the authentication",
+ "providerId": "basic-flow",
+ "topLevel": false,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "conditional-user-configured",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticator": "auth-otp-form",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 20,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "6926f455-0fd0-4ac6-9fc1-333b86c4150f",
+ "alias": "Direct Grant - Conditional OTP",
+ "description": "Flow to determine if the OTP is required for the authentication",
+ "providerId": "basic-flow",
+ "topLevel": false,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "conditional-user-configured",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticator": "direct-grant-validate-otp",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 20,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "b11840e7-21ec-4200-bf3c-c7853646a908",
+ "alias": "First broker login - Conditional OTP",
+ "description": "Flow to determine if the OTP is required for the authentication",
+ "providerId": "basic-flow",
+ "topLevel": false,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "conditional-user-configured",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticator": "auth-otp-form",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 20,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "615b4d0e-e71e-4c96-aed3-b03b34b61808",
+ "alias": "Handle Existing Account",
+ "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider",
+ "providerId": "basic-flow",
+ "topLevel": false,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "idp-confirm-link",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticatorFlow": true,
+ "requirement": "REQUIRED",
+ "priority": 20,
+ "autheticatorFlow": true,
+ "flowAlias": "Account verification options",
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "36958ec5-62d7-4d51-8b30-7a6709476aec",
+ "alias": "Reset - Conditional OTP",
+ "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.",
+ "providerId": "basic-flow",
+ "topLevel": false,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "conditional-user-configured",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticator": "reset-otp",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 20,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "aa4a7ac2-ec63-48ea-a70f-b3f18992b99a",
+ "alias": "User creation or linking",
+ "description": "Flow for the existing/non-existing user alternatives",
+ "providerId": "basic-flow",
+ "topLevel": false,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticatorConfig": "create unique user config",
+ "authenticator": "idp-create-user-if-unique",
+ "authenticatorFlow": false,
+ "requirement": "ALTERNATIVE",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticatorFlow": true,
+ "requirement": "ALTERNATIVE",
+ "priority": 20,
+ "autheticatorFlow": true,
+ "flowAlias": "Handle Existing Account",
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "dafdfc68-72eb-49b2-a8f4-495ee25fba21",
+ "alias": "Verify Existing Account by Re-authentication",
+ "description": "Reauthentication of existing account",
+ "providerId": "basic-flow",
+ "topLevel": false,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "idp-username-password-form",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticatorFlow": true,
+ "requirement": "CONDITIONAL",
+ "priority": 20,
+ "autheticatorFlow": true,
+ "flowAlias": "First broker login - Conditional OTP",
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "6a39b6db-c81e-4de4-92a8-a9e504593f2e",
+ "alias": "browser",
+ "description": "browser based authentication",
+ "providerId": "basic-flow",
+ "topLevel": true,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "auth-cookie",
+ "authenticatorFlow": false,
+ "requirement": "ALTERNATIVE",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticator": "auth-spnego",
+ "authenticatorFlow": false,
+ "requirement": "DISABLED",
+ "priority": 20,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticator": "identity-provider-redirector",
+ "authenticatorFlow": false,
+ "requirement": "ALTERNATIVE",
+ "priority": 25,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticatorFlow": true,
+ "requirement": "ALTERNATIVE",
+ "priority": 30,
+ "autheticatorFlow": true,
+ "flowAlias": "forms",
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "6fa840df-bc04-4045-9e33-8901d183b165",
+ "alias": "clients",
+ "description": "Base authentication for clients",
+ "providerId": "client-flow",
+ "topLevel": true,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "client-secret",
+ "authenticatorFlow": false,
+ "requirement": "ALTERNATIVE",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticator": "client-jwt",
+ "authenticatorFlow": false,
+ "requirement": "ALTERNATIVE",
+ "priority": 20,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticator": "client-secret-jwt",
+ "authenticatorFlow": false,
+ "requirement": "ALTERNATIVE",
+ "priority": 30,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticator": "client-x509",
+ "authenticatorFlow": false,
+ "requirement": "ALTERNATIVE",
+ "priority": 40,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "4aa24ca0-ad09-4f30-806b-4c699724d731",
+ "alias": "direct grant",
+ "description": "OpenID Connect Resource Owner Grant",
+ "providerId": "basic-flow",
+ "topLevel": true,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "direct-grant-validate-username",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticator": "direct-grant-validate-password",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 20,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticatorFlow": true,
+ "requirement": "CONDITIONAL",
+ "priority": 30,
+ "autheticatorFlow": true,
+ "flowAlias": "Direct Grant - Conditional OTP",
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "0a914ba4-f662-4b85-af64-74738a222b7f",
+ "alias": "docker auth",
+ "description": "Used by Docker clients to authenticate against the IDP",
+ "providerId": "basic-flow",
+ "topLevel": true,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "docker-http-basic-authenticator",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "9b40f15f-b690-4fe2-9fe8-07e77d965297",
+ "alias": "first broker login",
+ "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account",
+ "providerId": "basic-flow",
+ "topLevel": true,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticatorConfig": "review profile config",
+ "authenticator": "idp-review-profile",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticatorFlow": true,
+ "requirement": "REQUIRED",
+ "priority": 20,
+ "autheticatorFlow": true,
+ "flowAlias": "User creation or linking",
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "c8a9848f-8dd8-4e13-b521-0a537d92ec36",
+ "alias": "forms",
+ "description": "Username, password, otp and other auth forms.",
+ "providerId": "basic-flow",
+ "topLevel": false,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "auth-username-password-form",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticatorFlow": true,
+ "requirement": "CONDITIONAL",
+ "priority": 20,
+ "autheticatorFlow": true,
+ "flowAlias": "Browser - Conditional OTP",
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "603957f8-b0a5-4885-aafd-e2757e431954",
+ "alias": "registration",
+ "description": "registration flow",
+ "providerId": "basic-flow",
+ "topLevel": true,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "registration-page-form",
+ "authenticatorFlow": true,
+ "requirement": "REQUIRED",
+ "priority": 10,
+ "autheticatorFlow": true,
+ "flowAlias": "registration form",
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "f41632f9-7fad-427d-ae7a-78ac9b1f51d0",
+ "alias": "registration form",
+ "description": "registration form",
+ "providerId": "form-flow",
+ "topLevel": false,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "registration-user-creation",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 20,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticator": "registration-password-action",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 50,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticator": "registration-recaptcha-action",
+ "authenticatorFlow": false,
+ "requirement": "DISABLED",
+ "priority": 60,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticator": "registration-terms-and-conditions",
+ "authenticatorFlow": false,
+ "requirement": "DISABLED",
+ "priority": 70,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "27a133ca-e05e-4c93-a3b7-ffe14b4e62ec",
+ "alias": "reset credentials",
+ "description": "Reset credentials for a user if they forgot their password or something",
+ "providerId": "basic-flow",
+ "topLevel": true,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "reset-credentials-choose-user",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticator": "reset-credential-email",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 20,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticator": "reset-password",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 30,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ },
+ {
+ "authenticatorFlow": true,
+ "requirement": "CONDITIONAL",
+ "priority": 40,
+ "autheticatorFlow": true,
+ "flowAlias": "Reset - Conditional OTP",
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "06cd7382-4944-4499-94dc-9908544e291b",
+ "alias": "saml ecp",
+ "description": "SAML ECP Profile Authentication Flow",
+ "providerId": "basic-flow",
+ "topLevel": true,
+ "builtIn": true,
+ "authenticationExecutions": [
+ {
+ "authenticator": "http-basic-authenticator",
+ "authenticatorFlow": false,
+ "requirement": "REQUIRED",
+ "priority": 10,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ }
+ ]
+ }
+ ],
+ "authenticatorConfig": [
+ {
+ "id": "5f953def-6f7c-430f-a33f-440ec2d2dddd",
+ "alias": "create unique user config",
+ "config": {
+ "require.password.update.after.registration": "false"
+ }
+ },
+ {
+ "id": "b3dad9a1-5b82-4e91-a250-157a45694e24",
+ "alias": "review profile config",
+ "config": {
+ "update.profile.on.first.login": "missing"
+ }
+ }
+ ],
+ "requiredActions": [
+ {
+ "alias": "CONFIGURE_TOTP",
+ "name": "Configure OTP",
+ "providerId": "CONFIGURE_TOTP",
+ "enabled": true,
+ "defaultAction": false,
+ "priority": 10,
+ "config": {}
+ },
+ {
+ "alias": "TERMS_AND_CONDITIONS",
+ "name": "Terms and Conditions",
+ "providerId": "TERMS_AND_CONDITIONS",
+ "enabled": true,
+ "defaultAction": true,
+ "priority": 20,
+ "config": {}
+ },
+ {
+ "alias": "UPDATE_PASSWORD",
+ "name": "Update Password",
+ "providerId": "UPDATE_PASSWORD",
+ "enabled": true,
+ "defaultAction": false,
+ "priority": 30,
+ "config": {}
+ },
+ {
+ "alias": "UPDATE_PROFILE",
+ "name": "Update Profile",
+ "providerId": "UPDATE_PROFILE",
+ "enabled": true,
+ "defaultAction": false,
+ "priority": 40,
+ "config": {}
+ },
+ {
+ "alias": "VERIFY_EMAIL",
+ "name": "Verify Email",
+ "providerId": "VERIFY_EMAIL",
+ "enabled": true,
+ "defaultAction": false,
+ "priority": 50,
+ "config": {}
+ },
+ {
+ "alias": "delete_account",
+ "name": "Delete Account",
+ "providerId": "delete_account",
+ "enabled": true,
+ "defaultAction": false,
+ "priority": 60,
+ "config": {}
+ },
+ {
+ "alias": "webauthn-register",
+ "name": "Webauthn Register",
+ "providerId": "webauthn-register",
+ "enabled": true,
+ "defaultAction": false,
+ "priority": 70,
+ "config": {}
+ },
+ {
+ "alias": "webauthn-register-passwordless",
+ "name": "Webauthn Register Passwordless",
+ "providerId": "webauthn-register-passwordless",
+ "enabled": true,
+ "defaultAction": false,
+ "priority": 80,
+ "config": {}
+ },
+ {
+ "alias": "VERIFY_PROFILE",
+ "name": "Verify Profile",
+ "providerId": "VERIFY_PROFILE",
+ "enabled": true,
+ "defaultAction": false,
+ "priority": 90,
+ "config": {}
+ },
+ {
+ "alias": "delete_credential",
+ "name": "Delete Credential",
+ "providerId": "delete_credential",
+ "enabled": true,
+ "defaultAction": false,
+ "priority": 100,
+ "config": {}
+ },
+ {
+ "alias": "update_user_locale",
+ "name": "Update User Locale",
+ "providerId": "update_user_locale",
+ "enabled": true,
+ "defaultAction": false,
+ "priority": 1000,
+ "config": {}
+ }
+ ],
+ "browserFlow": "browser",
+ "registrationFlow": "registration",
+ "directGrantFlow": "direct grant",
+ "resetCredentialsFlow": "reset credentials",
+ "clientAuthenticationFlow": "clients",
+ "dockerAuthenticationFlow": "docker auth",
+ "firstBrokerLoginFlow": "first broker login",
+ "attributes": {
+ "cibaBackchannelTokenDeliveryMode": "poll",
+ "cibaAuthRequestedUserHint": "login_hint",
+ "clientOfflineSessionMaxLifespan": "0",
+ "oauth2DevicePollingInterval": "5",
+ "clientSessionIdleTimeout": "0",
+ "clientOfflineSessionIdleTimeout": "0",
+ "cibaInterval": "5",
+ "realmReusableOtpCode": "false",
+ "cibaExpiresIn": "120",
+ "oauth2DeviceCodeLifespan": "600",
+ "parRequestUriLifespan": "60",
+ "clientSessionMaxLifespan": "0",
+ "organizationsEnabled": "false"
+ },
+ "keycloakVersion": "25.0.0",
+ "userManagedAccessAllowed": false,
+ "organizationsEnabled": false,
+ "clientProfiles": {
+ "profiles": []
+ },
+ "clientPolicies": {
+ "policies": []
+ }
+}
From cfdad8d71d5a373eb470efc642a25bb4d40b7da5 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Fri, 4 Oct 2024 12:17:54 +0200
Subject: [PATCH 24/77] Release candidate
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index ff7fbe2a..fe130725 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "keycloakify",
- "version": "11.2.8",
+ "version": "11.2.9-rc.0",
"description": "Framework to create custom Keycloak UIs",
"repository": {
"type": "git",
From bcb514ae9c7aa80910d20af82c1cfda2d8aab1b2 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Fri, 4 Oct 2024 12:44:03 +0200
Subject: [PATCH 25/77] Aditional context exclusion
---
.../keycloakify/generateFtl/kcContextDeclarationTemplate.ftl | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/bin/keycloakify/generateFtl/kcContextDeclarationTemplate.ftl b/src/bin/keycloakify/generateFtl/kcContextDeclarationTemplate.ftl
index 5cfc2755..4139df7c 100644
--- a/src/bin/keycloakify/generateFtl/kcContextDeclarationTemplate.ftl
+++ b/src/bin/keycloakify/generateFtl/kcContextDeclarationTemplate.ftl
@@ -235,6 +235,9 @@ function decodeHtmlEntities(htmlStr){
"identityFederationEnabled",
"userManagedAccessAllowed"
]?seq_contains(key)
+ ) || (
+ ["flowContext", "session", "realm"]?seq_contains(key) &&
+ areSamePath(path, ["social"])
)
>
<#-- <#local outSeq += ["/*" + path?join(".") + "." + key + " excluded*/"]> -->
From 4e982ee898b3df57bc0b24bd77010e17126e86fc Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Fri, 4 Oct 2024 12:44:22 +0200
Subject: [PATCH 26/77] Release candidate
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index fe130725..f6a41f99 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "keycloakify",
- "version": "11.2.9-rc.0",
+ "version": "11.2.9-rc.1",
"description": "Framework to create custom Keycloak UIs",
"repository": {
"type": "git",
From 6f416ad33508ca2e4106025ede077a1c711adc6c Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Fri, 4 Oct 2024 12:58:31 +0200
Subject: [PATCH 27/77] Update version ranges for Multi-Page account theme
---
.../buildJars/getKeycloakVersionRangeForJar.ts | 4 ++--
src/bin/shared/KeycloakVersionRange.ts | 2 +-
src/bin/shared/buildContext.ts | 12 +++++++++---
3 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/src/bin/keycloakify/buildJars/getKeycloakVersionRangeForJar.ts b/src/bin/keycloakify/buildJars/getKeycloakVersionRangeForJar.ts
index 6c301223..89c42ef7 100644
--- a/src/bin/keycloakify/buildJars/getKeycloakVersionRangeForJar.ts
+++ b/src/bin/keycloakify/buildJars/getKeycloakVersionRangeForJar.ts
@@ -52,9 +52,9 @@ export function getKeycloakVersionRangeForJar(params: {
case "0.6":
switch (keycloakThemeAdditionalInfoExtensionVersion) {
case null:
- return undefined;
+ return "26-and-above" as const;
case "1.1.5":
- return "25-and-above" as const;
+ return "25" as const;
}
}
assert>(false);
diff --git a/src/bin/shared/KeycloakVersionRange.ts b/src/bin/shared/KeycloakVersionRange.ts
index 1e118ea1..860f42f0 100644
--- a/src/bin/shared/KeycloakVersionRange.ts
+++ b/src/bin/shared/KeycloakVersionRange.ts
@@ -5,5 +5,5 @@ export type KeycloakVersionRange =
export namespace KeycloakVersionRange {
export type WithoutAccountV1Theme = "22-to-25" | "all-other-versions";
- export type WithAccountV1Theme = "21-and-below" | "23" | "24" | "25-and-above";
+ export type WithAccountV1Theme = "21-and-below" | "23" | "24" | "25" | "26-and-above";
}
diff --git a/src/bin/shared/buildContext.ts b/src/bin/shared/buildContext.ts
index 852bd1fd..5fc09c3a 100644
--- a/src/bin/shared/buildContext.ts
+++ b/src/bin/shared/buildContext.ts
@@ -277,7 +277,8 @@ export function getBuildContext(params: {
"21-and-below": z.union([z.boolean(), z.string()]),
"23": z.union([z.boolean(), z.string()]),
"24": z.union([z.boolean(), z.string()]),
- "25-and-above": z.union([z.boolean(), z.string()])
+ "25": z.union([z.boolean(), z.string()]),
+ "26-and-above": z.union([z.boolean(), z.string()])
})
.optional()
});
@@ -767,7 +768,11 @@ export function getBuildContext(params: {
return "24" as const;
}
- return "25-and-above" as const;
+ if (buildForKeycloakMajorVersionNumber === 25) {
+ return "25" as const;
+ }
+
+ return "26-and-above" as const;
})();
assert<
@@ -855,7 +860,8 @@ export function getBuildContext(params: {
"21-and-below",
"23",
"24",
- "25-and-above"
+ "25",
+ "26-and-above"
] as const) {
assert<
Equals<
From 8d9b80f54943c4f5e73e475e6b38ac7ccd0407db Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Fri, 4 Oct 2024 12:59:56 +0200
Subject: [PATCH 28/77] Update readme, support keycloak 26
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 78872df3..2c133223 100644
--- a/README.md
+++ b/README.md
@@ -41,7 +41,7 @@
-Keycloakify is fully compatible with Keycloak from version 11 to 25...[and beyond](https://github.com/keycloakify/keycloakify/discussions/346#discussioncomment-5889791)
+Keycloakify is fully compatible with Keycloak from version 11 to 26...[and beyond](https://github.com/keycloakify/keycloakify/discussions/346#discussioncomment-5889791)
## Sponsors
From da495b90aeb6776457e5f1d07fae16d186bc139b Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Fri, 4 Oct 2024 13:00:15 +0200
Subject: [PATCH 29/77] Bump version
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index f6a41f99..9a704e0e 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "keycloakify",
- "version": "11.2.9-rc.1",
+ "version": "11.2.9",
"description": "Framework to create custom Keycloak UIs",
"repository": {
"type": "git",
From e14f187fc037cf9d1df61c66a36a09b2828795d7 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Fri, 4 Oct 2024 16:56:02 +0200
Subject: [PATCH 30/77] Fix cache issue
---
src/bin/keycloakify/buildJars/buildJar.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/bin/keycloakify/buildJars/buildJar.ts b/src/bin/keycloakify/buildJars/buildJar.ts
index cdbc3f22..4a952343 100644
--- a/src/bin/keycloakify/buildJars/buildJar.ts
+++ b/src/bin/keycloakify/buildJars/buildJar.ts
@@ -197,7 +197,7 @@ export async function buildJar(params: {
await new Promise((resolve, reject) =>
child_process.exec(
- `mvn install -Dmaven.repo.local="${pathJoin(keycloakifyBuildCacheDirPath, ".m2")}"`,
+ `mvn clean install -Dmaven.repo.local="${pathJoin(keycloakifyBuildCacheDirPath, ".m2")}"`,
{ cwd: keycloakifyBuildCacheDirPath },
error => {
if (error !== null) {
From e3bd7f3bc56f8ad3b078be897343a65d451f61d9 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Fri, 4 Oct 2024 16:56:17 +0200
Subject: [PATCH 31/77] Bump version
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 9a704e0e..0564ddf0 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "keycloakify",
- "version": "11.2.9",
+ "version": "11.2.10",
"description": "Framework to create custom Keycloak UIs",
"repository": {
"type": "git",
From 35b012b93753605dadfe83295a05ad2a5bb24d24 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Sat, 5 Oct 2024 20:30:09 +0200
Subject: [PATCH 32/77] Implement custom handler cli hook
---
package.json | 1 +
src/bin/add-story.ts | 11 +-
src/bin/copy-keycloak-resources-to-public.ts | 9 +-
src/bin/eject-page.ts | 11 +-
.../initialize-account-theme.ts | 9 +-
src/bin/initialize-email-theme.ts | 9 +-
src/bin/keycloakify/keycloakify.ts | 9 +-
src/bin/main.ts | 297 +++++++++++-------
src/bin/shared/buildContext.ts | 9 +-
src/bin/shared/constants.ts | 5 +
src/bin/shared/customHandler.ts | 35 +++
src/bin/shared/customHandler_caller.ts | 47 +++
src/bin/start-keycloak/start-keycloak.ts | 22 +-
src/bin/update-kc-gen.ts | 11 +-
src/vite-plugin/vite-plugin.ts | 4 +-
15 files changed, 300 insertions(+), 189 deletions(-)
create mode 100644 src/bin/shared/customHandler.ts
create mode 100644 src/bin/shared/customHandler_caller.ts
diff --git a/package.json b/package.json
index 0564ddf0..70ca8dae 100644
--- a/package.json
+++ b/package.json
@@ -42,6 +42,7 @@
"dist/bin/*.index.js",
"dist/bin/*.node",
"dist/bin/shared/constants.js",
+ "dist/bin/shared/customHandler.js",
"dist/bin/shared/*.d.ts",
"dist/bin/shared/*.js.map",
"!dist/vite-plugin/",
diff --git a/src/bin/add-story.ts b/src/bin/add-story.ts
index b3ed5be7..b2be6d65 100644
--- a/src/bin/add-story.ts
+++ b/src/bin/add-story.ts
@@ -13,16 +13,11 @@ import * as fs from "fs";
import { join as pathJoin, relative as pathRelative, dirname as pathDirname } from "path";
import { kebabCaseToCamelCase } from "./tools/kebabCaseToSnakeCase";
import { assert, Equals } from "tsafe/assert";
-import type { CliCommandOptions } from "./main";
-import { getBuildContext } from "./shared/buildContext";
+import type { BuildContext } from "./shared/buildContext";
import chalk from "chalk";
-export async function command(params: { cliCommandOptions: CliCommandOptions }) {
- const { cliCommandOptions } = params;
-
- const buildContext = getBuildContext({
- cliCommandOptions
- });
+export async function command(params: { buildContext: BuildContext }) {
+ const { buildContext } = params;
console.log(chalk.cyan("Theme type:"));
diff --git a/src/bin/copy-keycloak-resources-to-public.ts b/src/bin/copy-keycloak-resources-to-public.ts
index b245076a..ba944068 100644
--- a/src/bin/copy-keycloak-resources-to-public.ts
+++ b/src/bin/copy-keycloak-resources-to-public.ts
@@ -1,11 +1,8 @@
import { copyKeycloakResourcesToPublic } from "./shared/copyKeycloakResourcesToPublic";
-import { getBuildContext } from "./shared/buildContext";
-import type { CliCommandOptions } from "./main";
+import type { BuildContext } from "./shared/buildContext";
-export async function command(params: { cliCommandOptions: CliCommandOptions }) {
- const { cliCommandOptions } = params;
-
- const buildContext = getBuildContext({ cliCommandOptions });
+export async function command(params: { buildContext: BuildContext }) {
+ const { buildContext } = params;
copyKeycloakResourcesToPublic({
buildContext
diff --git a/src/bin/eject-page.ts b/src/bin/eject-page.ts
index 404483ec..8874fd99 100644
--- a/src/bin/eject-page.ts
+++ b/src/bin/eject-page.ts
@@ -20,16 +20,11 @@ import {
} from "path";
import { kebabCaseToCamelCase } from "./tools/kebabCaseToSnakeCase";
import { assert, Equals } from "tsafe/assert";
-import type { CliCommandOptions } from "./main";
-import { getBuildContext } from "./shared/buildContext";
+import type { BuildContext } from "./shared/buildContext";
import chalk from "chalk";
-export async function command(params: { cliCommandOptions: CliCommandOptions }) {
- const { cliCommandOptions } = params;
-
- const buildContext = getBuildContext({
- cliCommandOptions
- });
+export async function command(params: { buildContext: BuildContext }) {
+ const { buildContext } = params;
console.log(chalk.cyan("Theme type:"));
diff --git a/src/bin/initialize-account-theme/initialize-account-theme.ts b/src/bin/initialize-account-theme/initialize-account-theme.ts
index e15b95ba..e29b6733 100644
--- a/src/bin/initialize-account-theme/initialize-account-theme.ts
+++ b/src/bin/initialize-account-theme/initialize-account-theme.ts
@@ -1,5 +1,4 @@
-import { getBuildContext } from "../shared/buildContext";
-import type { CliCommandOptions } from "../main";
+import type { BuildContext } from "../shared/buildContext";
import cliSelect from "cli-select";
import child_process from "child_process";
import chalk from "chalk";
@@ -8,10 +7,8 @@ import * as fs from "fs";
import { updateAccountThemeImplementationInConfig } from "./updateAccountThemeImplementationInConfig";
import { generateKcGenTs } from "../shared/generateKcGenTs";
-export async function command(params: { cliCommandOptions: CliCommandOptions }) {
- const { cliCommandOptions } = params;
-
- const buildContext = getBuildContext({ cliCommandOptions });
+export async function command(params: { buildContext: BuildContext }) {
+ const { buildContext } = params;
const accountThemeSrcDirPath = pathJoin(buildContext.themeSrcDirPath, "account");
diff --git a/src/bin/initialize-email-theme.ts b/src/bin/initialize-email-theme.ts
index f2520645..dfa0287c 100644
--- a/src/bin/initialize-email-theme.ts
+++ b/src/bin/initialize-email-theme.ts
@@ -1,15 +1,12 @@
import { join as pathJoin, relative as pathRelative } from "path";
import { transformCodebase } from "./tools/transformCodebase";
import { promptKeycloakVersion } from "./shared/promptKeycloakVersion";
-import { getBuildContext } from "./shared/buildContext";
+import type { BuildContext } from "./shared/buildContext";
import * as fs from "fs";
-import type { CliCommandOptions } from "./main";
import { downloadAndExtractArchive } from "./tools/downloadAndExtractArchive";
-export async function command(params: { cliCommandOptions: CliCommandOptions }) {
- const { cliCommandOptions } = params;
-
- const buildContext = getBuildContext({ cliCommandOptions });
+export async function command(params: { buildContext: BuildContext }) {
+ const { buildContext } = params;
const emailThemeSrcDirPath = pathJoin(buildContext.themeSrcDirPath, "email");
diff --git a/src/bin/keycloakify/keycloakify.ts b/src/bin/keycloakify/keycloakify.ts
index b39dcad8..0d027103 100644
--- a/src/bin/keycloakify/keycloakify.ts
+++ b/src/bin/keycloakify/keycloakify.ts
@@ -2,19 +2,16 @@ import { generateResources } from "./generateResources";
import { join as pathJoin, relative as pathRelative, sep as pathSep } from "path";
import * as child_process from "child_process";
import * as fs from "fs";
-import { getBuildContext } from "../shared/buildContext";
+import type { BuildContext } from "../shared/buildContext";
import { VITE_PLUGIN_SUB_SCRIPTS_ENV_NAMES } from "../shared/constants";
import { buildJars } from "./buildJars";
-import type { CliCommandOptions } from "../main";
import chalk from "chalk";
import { readThisNpmPackageVersion } from "../tools/readThisNpmPackageVersion";
import * as os from "os";
import { rmSync } from "../tools/fs.rmSync";
-export async function command(params: { cliCommandOptions: CliCommandOptions }) {
- const { cliCommandOptions } = params;
-
- const buildContext = getBuildContext({ cliCommandOptions });
+export async function command(params: { buildContext: BuildContext }) {
+ const { buildContext } = params;
exit_if_maven_not_installed: {
let commandOutput: Buffer | undefined = undefined;
diff --git a/src/bin/main.ts b/src/bin/main.ts
index 9f54242f..7ef2a9b8 100644
--- a/src/bin/main.ts
+++ b/src/bin/main.ts
@@ -4,8 +4,10 @@ import { termost } from "termost";
import { readThisNpmPackageVersion } from "./tools/readThisNpmPackageVersion";
import * as child_process from "child_process";
import { assertNoPnpmDlx } from "./tools/assertNoPnpmDlx";
+import { callHandlerIfAny } from "./shared/customHandler_caller";
+import { getBuildContext } from "./shared/buildContext";
-export type CliCommandOptions = {
+type CliCommandOptions = {
projectDirPath: string | undefined;
};
@@ -69,115 +71,154 @@ program
})
.task({
skip,
- handler: async cliCommandOptions => {
+ handler: async ({ projectDirPath }) => {
+ const buildContext = getBuildContext({ projectDirPath });
+
const { command } = await import("./keycloakify");
- await command({ cliCommandOptions });
+ await command({ buildContext });
}
});
-program
- .command<{
- port: number | undefined;
- keycloakVersion: string | undefined;
- realmJsonFilePath: string | undefined;
- }>({
- name: "start-keycloak",
- description:
- "Spin up a pre configured Docker image of Keycloak to test your theme."
- })
- .option({
- key: "port",
- name: (() => {
- const name = "port";
+{
+ const commandName = "start-keycloak";
- optionsKeys.push(name);
+ program
+ .command<{
+ port: number | undefined;
+ keycloakVersion: string | undefined;
+ realmJsonFilePath: string | undefined;
+ }>({
+ name: commandName,
+ description:
+ "Spin up a pre configured Docker image of Keycloak to test your theme."
+ })
+ .option({
+ key: "port",
+ name: (() => {
+ const name = "port";
- return name;
- })(),
- description: ["Keycloak server port.", "Example `--port 8085`"].join(" "),
- defaultValue: undefined
- })
- .option({
- key: "keycloakVersion",
- name: (() => {
- const name = "keycloak-version";
+ optionsKeys.push(name);
- optionsKeys.push(name);
+ return name;
+ })(),
+ description: ["Keycloak server port.", "Example `--port 8085`"].join(" "),
+ defaultValue: undefined
+ })
+ .option({
+ key: "keycloakVersion",
+ name: (() => {
+ const name = "keycloak-version";
- return name;
- })(),
- description: [
- "Use a specific version of Keycloak.",
- "Example `--keycloak-version 21.1.1`"
- ].join(" "),
- defaultValue: undefined
- })
- .option({
- key: "realmJsonFilePath",
- name: (() => {
- const name = "import";
+ optionsKeys.push(name);
- optionsKeys.push(name);
+ return name;
+ })(),
+ description: [
+ "Use a specific version of Keycloak.",
+ "Example `--keycloak-version 21.1.1`"
+ ].join(" "),
+ defaultValue: undefined
+ })
+ .option({
+ key: "realmJsonFilePath",
+ name: (() => {
+ const name = "import";
- return name;
- })(),
- defaultValue: undefined,
- description: [
- "Import your own realm configuration file",
- "Example `--import path/to/myrealm-realm.json`"
- ].join(" ")
- })
- .task({
- skip,
- handler: async cliCommandOptions => {
- const { command } = await import("./start-keycloak");
+ optionsKeys.push(name);
- await command({ cliCommandOptions });
- }
- });
+ return name;
+ })(),
+ defaultValue: undefined,
+ description: [
+ "Import your own realm configuration file",
+ "Example `--import path/to/myrealm-realm.json`"
+ ].join(" ")
+ })
+ .task({
+ skip,
+ handler: async ({
+ projectDirPath,
+ keycloakVersion,
+ port,
+ realmJsonFilePath
+ }) => {
+ const buildContext = getBuildContext({ projectDirPath });
-program
- .command({
- name: "eject-page",
- description: "Eject a Keycloak page."
- })
- .task({
- skip,
- handler: async cliCommandOptions => {
- const { command } = await import("./eject-page");
+ const { command } = await import("./start-keycloak");
- await command({ cliCommandOptions });
- }
- });
+ await command({
+ buildContext,
+ cliCommandOptions: { keycloakVersion, port, realmJsonFilePath }
+ });
+ }
+ });
+}
-program
- .command({
- name: "add-story",
- description: "Add *.stories.tsx file for a specific page to in your Storybook."
- })
- .task({
- skip,
- handler: async cliCommandOptions => {
- const { command } = await import("./add-story");
+{
+ const commandName = "eject-page";
- await command({ cliCommandOptions });
- }
- });
+ program
+ .command({
+ name: commandName,
+ description: "Eject a Keycloak page."
+ })
+ .task({
+ skip,
+ handler: async ({ projectDirPath }) => {
+ const buildContext = getBuildContext({ projectDirPath });
-program
- .command({
- name: "initialize-email-theme",
- description: "Initialize an email theme."
- })
- .task({
- skip,
- handler: async cliCommandOptions => {
- const { command } = await import("./initialize-email-theme");
+ callHandlerIfAny({ buildContext, commandName });
- await command({ cliCommandOptions });
- }
- });
+ const { command } = await import("./eject-page");
+
+ await command({ buildContext });
+ }
+ });
+}
+
+{
+ const commandName = "add-story";
+
+ program
+ .command({
+ name: commandName,
+ description:
+ "Add *.stories.tsx file for a specific page to in your Storybook."
+ })
+ .task({
+ skip,
+ handler: async ({ projectDirPath }) => {
+ const buildContext = getBuildContext({ projectDirPath });
+
+ callHandlerIfAny({ buildContext, commandName });
+
+ const { command } = await import("./add-story");
+
+ await command({ buildContext });
+ }
+ });
+}
+
+{
+ const comandName = "initialize-login-theme";
+
+ program
+ .command({
+ name: comandName,
+ description: "Initialize an email theme."
+ })
+ .task({
+ skip,
+ handler: async ({ projectDirPath }) => {
+ const buildContext = getBuildContext({ projectDirPath });
+
+ const { command } = await import("./initialize-email-theme");
+
+ await command({ buildContext });
+ }
+ });
+}
program
.command({
@@ -186,42 +227,58 @@ program
})
.task({
skip,
- handler: async cliCommandOptions => {
+ handler: async ({ projectDirPath }) => {
+ const buildContext = getBuildContext({ projectDirPath });
+
const { command } = await import("./initialize-account-theme");
- await command({ cliCommandOptions });
+ await command({ buildContext });
}
});
-program
- .command({
- name: "copy-keycloak-resources-to-public",
- description:
- "(Webpack/Create-React-App only) Copy Keycloak default theme resources to the public directory."
- })
- .task({
- skip,
- handler: async cliCommandOptions => {
- const { command } = await import("./copy-keycloak-resources-to-public");
+{
+ const commandName = "copy-keycloak-resources-to-public";
- await command({ cliCommandOptions });
- }
- });
+ program
+ .command({
+ name: commandName,
+ description:
+ "(Webpack/Create-React-App only) Copy Keycloak default theme resources to the public directory."
+ })
+ .task({
+ skip,
+ handler: async ({ projectDirPath }) => {
+ const buildContext = getBuildContext({ projectDirPath });
-program
- .command({
- name: "update-kc-gen",
- description:
- "(Webpack/Create-React-App only) Create/update the kc.gen.ts file in your project."
- })
- .task({
- skip,
- handler: async cliCommandOptions => {
- const { command } = await import("./update-kc-gen");
+ const { command } = await import("./copy-keycloak-resources-to-public");
- await command({ cliCommandOptions });
- }
- });
+ await command({ buildContext });
+ }
+ });
+}
+
+{
+ const commandName = "update-kc-gen";
+
+ program
+ .command({
+ name: commandName,
+ description:
+ "(Webpack/Create-React-App only) Create/update the kc.gen.ts file in your project."
+ })
+ .task({
+ skip,
+ handler: async ({ projectDirPath }) => {
+ const buildContext = getBuildContext({ projectDirPath });
+
+ callHandlerIfAny({ buildContext, commandName });
+
+ const { command } = await import("./update-kc-gen");
+
+ await command({ buildContext });
+ }
+ });
+}
// Fallback to build command if no command is provided
{
diff --git a/src/bin/shared/buildContext.ts b/src/bin/shared/buildContext.ts
index 5fc09c3a..fa658097 100644
--- a/src/bin/shared/buildContext.ts
+++ b/src/bin/shared/buildContext.ts
@@ -7,7 +7,6 @@ import {
dirname as pathDirname
} from "path";
import { getAbsoluteAndInOsFormatPath } from "../tools/getAbsoluteAndInOsFormatPath";
-import type { CliCommandOptions } from "../main";
import { z } from "zod";
import * as fs from "fs";
import { assert, type Equals } from "tsafe/assert";
@@ -129,14 +128,12 @@ export type ResolvedViteConfig = {
};
export function getBuildContext(params: {
- cliCommandOptions: CliCommandOptions;
+ projectDirPath: string | undefined;
}): BuildContext {
- const { cliCommandOptions } = params;
-
const projectDirPath =
- cliCommandOptions.projectDirPath !== undefined
+ params.projectDirPath !== undefined
? getAbsoluteAndInOsFormatPath({
- pathIsh: cliCommandOptions.projectDirPath,
+ pathIsh: params.projectDirPath,
cwd: process.cwd()
})
: process.cwd();
diff --git a/src/bin/shared/constants.ts b/src/bin/shared/constants.ts
index d0707a90..d2137b14 100644
--- a/src/bin/shared/constants.ts
+++ b/src/bin/shared/constants.ts
@@ -71,3 +71,8 @@ export type AccountThemePageId = (typeof ACCOUNT_THEME_PAGE_IDS)[number];
export const CONTAINER_NAME = "keycloak-keycloakify";
export const FALLBACK_LANGUAGE_TAG = "en";
+
+export const CUSTOM_HANDLER_ENV_NAMES = {
+ COMMAND_NAME: "KEYCLOAKIFY_COMMAND_NAME",
+ BUILD_CONTEXT: "KEYCLOAKIFY_BUILD_CONTEXT"
+};
diff --git a/src/bin/shared/customHandler.ts b/src/bin/shared/customHandler.ts
new file mode 100644
index 00000000..d858aaa5
--- /dev/null
+++ b/src/bin/shared/customHandler.ts
@@ -0,0 +1,35 @@
+import { assert } from "tsafe/assert";
+import type { BuildContext } from "./buildContext";
+import { CUSTOM_HANDLER_ENV_NAMES } from "./constants";
+
+export const BIN_NAME = "_keycloakify-custom-handler";
+
+export const NOT_IMPLEMENTED_EXIT_CODE = 78;
+
+export type CommandName = "update-kc-gen" | "eject-page" | "add-story";
+
+export type ApiVersion = "v1";
+
+export function readParams(params: { apiVersion: ApiVersion }) {
+ const { apiVersion } = params;
+
+ assert(apiVersion === "v1");
+
+ const commandName = (() => {
+ const envValue = process.env[CUSTOM_HANDLER_ENV_NAMES.COMMAND_NAME];
+
+ assert(envValue !== undefined);
+
+ return envValue as CommandName;
+ })();
+
+ const buildContext = (() => {
+ const envValue = process.env[CUSTOM_HANDLER_ENV_NAMES.BUILD_CONTEXT];
+
+ assert(envValue !== undefined);
+
+ return JSON.parse(envValue) as BuildContext;
+ })();
+
+ return { commandName, buildContext };
+}
diff --git a/src/bin/shared/customHandler_caller.ts b/src/bin/shared/customHandler_caller.ts
new file mode 100644
index 00000000..38f25972
--- /dev/null
+++ b/src/bin/shared/customHandler_caller.ts
@@ -0,0 +1,47 @@
+import { assert, type Equals } from "tsafe/assert";
+import type { BuildContext } from "./buildContext";
+import { CUSTOM_HANDLER_ENV_NAMES } from "./constants";
+import {
+ NOT_IMPLEMENTED_EXIT_CODE,
+ type CommandName,
+ BIN_NAME,
+ ApiVersion
+} from "./customHandler";
+import * as child_process from "child_process";
+import { is } from "tsafe/is";
+import { dirname as pathDirname } from "path";
+import * as fs from "fs";
+
+assert>();
+
+export function callHandlerIfAny(params: {
+ commandName: CommandName;
+ buildContext: BuildContext;
+}) {
+ const { commandName, buildContext } = params;
+
+ if (!fs.readdirSync(pathDirname(process.argv[1])).includes(BIN_NAME)) {
+ return;
+ }
+
+ try {
+ child_process.execSync(`npx ${BIN_NAME}`, {
+ stdio: "inherit",
+ env: {
+ ...process.env,
+ [CUSTOM_HANDLER_ENV_NAMES.COMMAND_NAME]: commandName,
+ [CUSTOM_HANDLER_ENV_NAMES.BUILD_CONTEXT]: JSON.stringify(buildContext)
+ }
+ });
+ } catch (error) {
+ assert(is(error));
+
+ if (error.code === NOT_IMPLEMENTED_EXIT_CODE) {
+ return;
+ }
+
+ process.exit(error.code);
+ }
+
+ process.exit(0);
+}
diff --git a/src/bin/start-keycloak/start-keycloak.ts b/src/bin/start-keycloak/start-keycloak.ts
index c85b09dc..e243fe2b 100644
--- a/src/bin/start-keycloak/start-keycloak.ts
+++ b/src/bin/start-keycloak/start-keycloak.ts
@@ -1,6 +1,5 @@
-import { getBuildContext } from "../shared/buildContext";
+import type { BuildContext } from "../shared/buildContext";
import { exclude } from "tsafe/exclude";
-import type { CliCommandOptions as CliCommandOptions_common } from "../main";
import { promptKeycloakVersion } from "../shared/promptKeycloakVersion";
import { CONTAINER_NAME } from "../shared/constants";
import { SemVer } from "../tools/SemVer";
@@ -29,13 +28,14 @@ import { existsAsync } from "../tools/fs.existsAsync";
import { rm } from "../tools/fs.rm";
import { downloadAndExtractArchive } from "../tools/downloadAndExtractArchive";
-export type CliCommandOptions = CliCommandOptions_common & {
- port: number | undefined;
- keycloakVersion: string | undefined;
- realmJsonFilePath: string | undefined;
-};
-
-export async function command(params: { cliCommandOptions: CliCommandOptions }) {
+export async function command(params: {
+ buildContext: BuildContext;
+ cliCommandOptions: {
+ port: number | undefined;
+ keycloakVersion: string | undefined;
+ realmJsonFilePath: string | undefined;
+ };
+}) {
exit_if_docker_not_installed: {
let commandOutput: string | undefined = undefined;
@@ -88,9 +88,7 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
process.exit(1);
}
- const { cliCommandOptions } = params;
-
- const buildContext = getBuildContext({ cliCommandOptions });
+ const { cliCommandOptions, buildContext } = params;
const { dockerImageTag } = await (async () => {
if (cliCommandOptions.keycloakVersion !== undefined) {
diff --git a/src/bin/update-kc-gen.ts b/src/bin/update-kc-gen.ts
index 585b0f22..b3d9ce15 100644
--- a/src/bin/update-kc-gen.ts
+++ b/src/bin/update-kc-gen.ts
@@ -1,13 +1,8 @@
-import type { CliCommandOptions } from "./main";
-import { getBuildContext } from "./shared/buildContext";
+import type { BuildContext } from "./shared/buildContext";
import { generateKcGenTs } from "./shared/generateKcGenTs";
-export async function command(params: { cliCommandOptions: CliCommandOptions }) {
- const { cliCommandOptions } = params;
-
- const buildContext = getBuildContext({
- cliCommandOptions
- });
+export async function command(params: { buildContext: BuildContext }) {
+ const { buildContext } = params;
await generateKcGenTs({ buildContext });
}
diff --git a/src/vite-plugin/vite-plugin.ts b/src/vite-plugin/vite-plugin.ts
index f22cb62a..3a7f3d26 100644
--- a/src/vite-plugin/vite-plugin.ts
+++ b/src/vite-plugin/vite-plugin.ts
@@ -122,9 +122,7 @@ export function keycloakify(params: keycloakify.Params) {
}
const buildContext = getBuildContext({
- cliCommandOptions: {
- projectDirPath
- }
+ projectDirPath
});
copyKeycloakResourcesToPublic({ buildContext }),
From 7f608ad8add9113aec8457b213c21d5657dc6623 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Sat, 5 Oct 2024 20:31:41 +0200
Subject: [PATCH 33/77] Release candidate
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 70ca8dae..bebb3ed3 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "keycloakify",
- "version": "11.2.10",
+ "version": "11.3.0-rc.0",
"description": "Framework to create custom Keycloak UIs",
"repository": {
"type": "git",
From 590de7a67b4d13889b43dcfb63d7d6d91ff1ab3b Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Sat, 5 Oct 2024 21:22:00 +0200
Subject: [PATCH 34/77] Fix missing exports
---
package.json | 2 +-
src/bin/shared/buildContext.ts | 4 ++--
src/bin/tools/fetchProxyOptions.ts | 14 ++++++++------
3 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/package.json b/package.json
index bebb3ed3..9a799b8f 100644
--- a/package.json
+++ b/package.json
@@ -43,7 +43,7 @@
"dist/bin/*.node",
"dist/bin/shared/constants.js",
"dist/bin/shared/customHandler.js",
- "dist/bin/shared/*.d.ts",
+ "dist/bin/*.d.ts",
"dist/bin/shared/*.js.map",
"!dist/vite-plugin/",
"dist/vite-plugin/index.js",
diff --git a/src/bin/shared/buildContext.ts b/src/bin/shared/buildContext.ts
index fa658097..26c746b8 100644
--- a/src/bin/shared/buildContext.ts
+++ b/src/bin/shared/buildContext.ts
@@ -23,7 +23,7 @@ import { objectEntries } from "tsafe/objectEntries";
import { type ThemeType } from "./constants";
import { id } from "tsafe/id";
import chalk from "chalk";
-import { getProxyFetchOptions, type ProxyFetchOptions } from "../tools/fetchProxyOptions";
+import { getProxyFetchOptions, type FetchOptionsLike } from "../tools/fetchProxyOptions";
import { is } from "tsafe/is";
export type BuildContext = {
@@ -42,7 +42,7 @@ export type BuildContext = {
* In this case the urlPathname will be "/my-app/" */
urlPathname: string | undefined;
assetsDirPath: string;
- fetchOptions: ProxyFetchOptions;
+ fetchOptions: FetchOptionsLike;
kcContextExclusionsFtlCode: string | undefined;
environmentVariables: { name: string; default: string }[];
themeSrcDirPath: string;
diff --git a/src/bin/tools/fetchProxyOptions.ts b/src/bin/tools/fetchProxyOptions.ts
index e6f8f497..c607feb9 100644
--- a/src/bin/tools/fetchProxyOptions.ts
+++ b/src/bin/tools/fetchProxyOptions.ts
@@ -1,16 +1,18 @@
-import { type FetchOptions } from "make-fetch-happen";
import * as child_process from "child_process";
import * as fs from "fs";
import { exclude } from "tsafe/exclude";
-export type ProxyFetchOptions = Pick<
- FetchOptions,
- "proxy" | "noProxy" | "strictSSL" | "cert" | "ca"
->;
+export type FetchOptionsLike = {
+ proxy: string | undefined;
+ noProxy: string | string[];
+ strictSSL: boolean;
+ cert: string | string[] | undefined;
+ ca: string[] | undefined;
+};
export function getProxyFetchOptions(params: {
npmConfigGetCwd: string;
-}): ProxyFetchOptions {
+}): FetchOptionsLike {
const { npmConfigGetCwd } = params;
const cfg = (() => {
From 052936f769da2db75fe7fd4bf147897b452b9c89 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Sat, 5 Oct 2024 21:23:57 +0200
Subject: [PATCH 35/77] Release candidate
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 9a799b8f..39c31f79 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "keycloakify",
- "version": "11.3.0-rc.0",
+ "version": "11.3.0-rc.1",
"description": "Framework to create custom Keycloak UIs",
"repository": {
"type": "git",
From cf18f9d06cd120fcbac37d5886f246cc6de90951 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Sat, 5 Oct 2024 21:39:14 +0200
Subject: [PATCH 36/77] Add other missing declaration files
---
package.json | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/package.json b/package.json
index 39c31f79..542b7aff 100644
--- a/package.json
+++ b/package.json
@@ -38,13 +38,14 @@
"dist/",
"!dist/tsconfig.tsbuildinfo",
"!dist/bin/",
+ "dist/bin/**/*.d.ts",
"dist/bin/main.js",
"dist/bin/*.index.js",
"dist/bin/*.node",
"dist/bin/shared/constants.js",
+ "dist/bin/shared/constants.js.map",
"dist/bin/shared/customHandler.js",
- "dist/bin/*.d.ts",
- "dist/bin/shared/*.js.map",
+ "dist/bin/shared/customHandler.js.map",
"!dist/vite-plugin/",
"dist/vite-plugin/index.js",
"dist/vite-plugin/index.d.ts",
From 7b9aec4ed070be2791033eba4fc71187c08050cb Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Sat, 5 Oct 2024 21:39:32 +0200
Subject: [PATCH 37/77] Release candidate
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 542b7aff..a472aa99 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "keycloakify",
- "version": "11.3.0-rc.1",
+ "version": "11.3.0-rc.2",
"description": "Framework to create custom Keycloak UIs",
"repository": {
"type": "git",
From 881386a123a46494e142789206faa03a35a2f0ec Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Sat, 5 Oct 2024 22:28:36 +0200
Subject: [PATCH 38/77] add debug logs
---
src/bin/main.ts | 4 ++++
src/bin/shared/customHandler_caller.ts | 5 ++++-
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/src/bin/main.ts b/src/bin/main.ts
index 7ef2a9b8..836bda9b 100644
--- a/src/bin/main.ts
+++ b/src/bin/main.ts
@@ -168,8 +168,12 @@ program
handler: async ({ projectDirPath }) => {
const buildContext = getBuildContext({ projectDirPath });
+ console.log("before callHandlerIfAny");
+
callHandlerIfAny({ buildContext, commandName });
+ console.log("after callHandlerIfAny");
+
const { command } = await import("./eject-page");
await command({ buildContext });
diff --git a/src/bin/shared/customHandler_caller.ts b/src/bin/shared/customHandler_caller.ts
index 38f25972..c4a49e7a 100644
--- a/src/bin/shared/customHandler_caller.ts
+++ b/src/bin/shared/customHandler_caller.ts
@@ -33,7 +33,10 @@ export function callHandlerIfAny(params: {
[CUSTOM_HANDLER_ENV_NAMES.BUILD_CONTEXT]: JSON.stringify(buildContext)
}
});
- } catch (error) {
+ } catch (error: any) {
+ console.log(error.message);
+ console.log(error.status);
+
assert(is(error));
if (error.code === NOT_IMPLEMENTED_EXIT_CODE) {
From 0fe49e3d6ee4342986639204de57bbc890e300cc Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Sat, 5 Oct 2024 22:29:13 +0200
Subject: [PATCH 39/77] Release candidate
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index a472aa99..d6ffdaf8 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "keycloakify",
- "version": "11.3.0-rc.2",
+ "version": "11.3.0-rc.3",
"description": "Framework to create custom Keycloak UIs",
"repository": {
"type": "git",
From 77f12a940d5ad04fe1b417417dcda9e08fdd8b46 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Sun, 6 Oct 2024 06:41:51 +0200
Subject: [PATCH 40/77] Fix not handling correctly exit cause
---
src/bin/main.ts | 4 ----
src/bin/shared/customHandler_caller.ts | 10 +++-------
2 files changed, 3 insertions(+), 11 deletions(-)
diff --git a/src/bin/main.ts b/src/bin/main.ts
index 836bda9b..7ef2a9b8 100644
--- a/src/bin/main.ts
+++ b/src/bin/main.ts
@@ -168,12 +168,8 @@ program
handler: async ({ projectDirPath }) => {
const buildContext = getBuildContext({ projectDirPath });
- console.log("before callHandlerIfAny");
-
callHandlerIfAny({ buildContext, commandName });
- console.log("after callHandlerIfAny");
-
const { command } = await import("./eject-page");
await command({ buildContext });
diff --git a/src/bin/shared/customHandler_caller.ts b/src/bin/shared/customHandler_caller.ts
index c4a49e7a..88d5a41c 100644
--- a/src/bin/shared/customHandler_caller.ts
+++ b/src/bin/shared/customHandler_caller.ts
@@ -8,7 +8,6 @@ import {
ApiVersion
} from "./customHandler";
import * as child_process from "child_process";
-import { is } from "tsafe/is";
import { dirname as pathDirname } from "path";
import * as fs from "fs";
@@ -34,16 +33,13 @@ export function callHandlerIfAny(params: {
}
});
} catch (error: any) {
- console.log(error.message);
- console.log(error.status);
+ const status = error.status;
- assert(is(error));
-
- if (error.code === NOT_IMPLEMENTED_EXIT_CODE) {
+ if (status === NOT_IMPLEMENTED_EXIT_CODE) {
return;
}
- process.exit(error.code);
+ process.exit(status);
}
process.exit(0);
From e62aa89d72830605427543dd5517732231ec0891 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Sun, 6 Oct 2024 06:42:04 +0200
Subject: [PATCH 41/77] Release candidate
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index d6ffdaf8..eb36617a 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "keycloakify",
- "version": "11.3.0-rc.3",
+ "version": "11.3.0-rc.4",
"description": "Framework to create custom Keycloak UIs",
"repository": {
"type": "git",
From e8609de7b4904d31b0dc02f860af3ff9f9fdd8f2 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Sun, 6 Oct 2024 06:44:53 +0200
Subject: [PATCH 42/77] No need to handle non react environement with custom
handler support
---
src/bin/shared/generateKcGenTs.ts | 104 ++++++++----------------------
1 file changed, 28 insertions(+), 76 deletions(-)
diff --git a/src/bin/shared/generateKcGenTs.ts b/src/bin/shared/generateKcGenTs.ts
index 7191a55c..e5bb7e86 100644
--- a/src/bin/shared/generateKcGenTs.ts
+++ b/src/bin/shared/generateKcGenTs.ts
@@ -1,10 +1,8 @@
-import { assert, type Equals } from "tsafe/assert";
-import { id } from "tsafe/id";
+import { assert } from "tsafe/assert";
import type { BuildContext } from "./buildContext";
import * as fs from "fs/promises";
import { join as pathJoin } from "path";
import { existsAsync } from "../tools/fs.existsAsync";
-import { z } from "zod";
export type BuildContextLike = {
projectDirPath: string;
@@ -25,45 +23,7 @@ export async function generateKcGenTs(params: {
}): Promise {
const { buildContext } = params;
- const isReactProject: boolean = await (async () => {
- const parsedPackageJson = await (async () => {
- type ParsedPackageJson = {
- dependencies?: Record;
- devDependencies?: Record;
- };
-
- const zParsedPackageJson = (() => {
- type TargetType = ParsedPackageJson;
-
- const zTargetType = z.object({
- dependencies: z.record(z.string()).optional(),
- devDependencies: z.record(z.string()).optional()
- });
-
- assert, TargetType>>();
-
- return id>(zTargetType);
- })();
-
- return zParsedPackageJson.parse(
- JSON.parse(
- (await fs.readFile(buildContext.packageJsonFilePath)).toString("utf8")
- )
- );
- })();
-
- return (
- {
- ...parsedPackageJson.dependencies,
- ...parsedPackageJson.devDependencies
- }.react !== undefined
- );
- })();
-
- const filePath = pathJoin(
- buildContext.themeSrcDirPath,
- `kc.gen.ts${isReactProject ? "x" : ""}`
- );
+ const filePath = pathJoin(buildContext.themeSrcDirPath, `kc.gen.tsx`);
const currentContent = (await existsAsync(filePath))
? await fs.readFile(filePath)
@@ -84,7 +44,7 @@ export async function generateKcGenTs(params: {
``,
`// This file is auto-generated by Keycloakify`,
``,
- isReactProject && `import { lazy, Suspense, type ReactNode } from "react";`,
+ `import { lazy, Suspense, type ReactNode } from "react";`,
``,
`export type ThemeName = ${buildContext.themeNames.map(themeName => `"${themeName}"`).join(" | ")};`,
``,
@@ -115,35 +75,31 @@ export async function generateKcGenTs(params: {
` }`,
`}`,
``,
- ...(!isReactProject
- ? []
- : [
- hasLoginTheme &&
- `export const KcLoginPage = lazy(() => import("./login/KcPage"));`,
- hasAccountTheme &&
- `export const KcAccountPage = lazy(() => import("./account/KcPage"));`,
- ``,
- `export function KcPage(`,
- ` props: {`,
- ` kcContext: KcContext;`,
- ` fallback?: ReactNode;`,
- ` }`,
- `) {`,
- ` const { kcContext, fallback } = props;`,
- ` return (`,
- ` `,
- ` {(() => {`,
- ` switch (kcContext.themeType) {`,
- hasLoginTheme &&
- ` case "login": return ;`,
- hasAccountTheme &&
- ` case "account": return ;`,
- ` }`,
- ` })()}`,
- ` `,
- ` );`,
- `}`
- ]),
+ hasLoginTheme &&
+ `export const KcLoginPage = lazy(() => import("./login/KcPage"));`,
+ hasAccountTheme &&
+ `export const KcAccountPage = lazy(() => import("./account/KcPage"));`,
+ ``,
+ `export function KcPage(`,
+ ` props: {`,
+ ` kcContext: KcContext;`,
+ ` fallback?: ReactNode;`,
+ ` }`,
+ `) {`,
+ ` const { kcContext, fallback } = props;`,
+ ` return (`,
+ ` `,
+ ` {(() => {`,
+ ` switch (kcContext.themeType) {`,
+ hasLoginTheme &&
+ ` case "login": return ;`,
+ hasAccountTheme &&
+ ` case "account": return ;`,
+ ` }`,
+ ` })()}`,
+ ` `,
+ ` );`,
+ `}`,
``,
`/* prettier-ignore-end */`,
``
@@ -160,10 +116,6 @@ export async function generateKcGenTs(params: {
await fs.writeFile(filePath, newContent);
delete_legacy_file: {
- if (!isReactProject) {
- break delete_legacy_file;
- }
-
const legacyFilePath = filePath.replace(/tsx$/, "ts");
if (!(await existsAsync(legacyFilePath))) {
From 63775b2866bcf208284330d338f31e9aff4b96e4 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Sun, 6 Oct 2024 06:45:06 +0200
Subject: [PATCH 43/77] Release candidate
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index eb36617a..133ddec1 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "keycloakify",
- "version": "11.3.0-rc.4",
+ "version": "11.3.0-rc.5",
"description": "Framework to create custom Keycloak UIs",
"repository": {
"type": "git",
From a04f07d149c646b1c2f8bb7a7f7ba52548d057c3 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Sun, 6 Oct 2024 09:03:15 +0200
Subject: [PATCH 44/77] Make sure the update-kc-gen command is delegated when
building with vite
---
.../initialize-account-theme.ts | 4 +-
src/bin/main.ts | 293 +++++++-----------
...er_caller.ts => customHandler_delegate.ts} | 2 +-
src/bin/shared/generateKcGenTs.ts | 127 --------
src/bin/update-kc-gen.ts | 112 ++++++-
src/vite-plugin/vite-plugin.ts | 7 +-
stories/login/pages/Register.stories.tsx | 6 +-
7 files changed, 239 insertions(+), 312 deletions(-)
rename src/bin/shared/{customHandler_caller.ts => customHandler_delegate.ts} (95%)
delete mode 100644 src/bin/shared/generateKcGenTs.ts
diff --git a/src/bin/initialize-account-theme/initialize-account-theme.ts b/src/bin/initialize-account-theme/initialize-account-theme.ts
index e29b6733..3caed327 100644
--- a/src/bin/initialize-account-theme/initialize-account-theme.ts
+++ b/src/bin/initialize-account-theme/initialize-account-theme.ts
@@ -5,7 +5,7 @@ import chalk from "chalk";
import { join as pathJoin, relative as pathRelative } from "path";
import * as fs from "fs";
import { updateAccountThemeImplementationInConfig } from "./updateAccountThemeImplementationInConfig";
-import { generateKcGenTs } from "../shared/generateKcGenTs";
+import { command as updateKcGenCommand } from "../update-kc-gen";
export async function command(params: { buildContext: BuildContext }) {
const { buildContext } = params;
@@ -94,7 +94,7 @@ export async function command(params: { buildContext: BuildContext }) {
updateAccountThemeImplementationInConfig({ buildContext, accountThemeType });
- await generateKcGenTs({
+ await updateKcGenCommand({
buildContext: {
...buildContext,
implementedThemeTypes: {
diff --git a/src/bin/main.ts b/src/bin/main.ts
index 7ef2a9b8..89b03d7c 100644
--- a/src/bin/main.ts
+++ b/src/bin/main.ts
@@ -4,7 +4,6 @@ import { termost } from "termost";
import { readThisNpmPackageVersion } from "./tools/readThisNpmPackageVersion";
import * as child_process from "child_process";
import { assertNoPnpmDlx } from "./tools/assertNoPnpmDlx";
-import { callHandlerIfAny } from "./shared/customHandler_caller";
import { getBuildContext } from "./shared/buildContext";
type CliCommandOptions = {
@@ -72,153 +71,117 @@ program
.task({
skip,
handler: async ({ projectDirPath }) => {
- const buildContext = getBuildContext({ projectDirPath });
-
const { command } = await import("./keycloakify");
- await command({ buildContext });
+ await command({ buildContext: getBuildContext({ projectDirPath }) });
}
});
-{
- const commandName = "start-keycloak";
+program
+ .command<{
+ port: number | undefined;
+ keycloakVersion: string | undefined;
+ realmJsonFilePath: string | undefined;
+ }>({
+ name: "start-keycloak",
+ description:
+ "Spin up a pre configured Docker image of Keycloak to test your theme."
+ })
+ .option({
+ key: "port",
+ name: (() => {
+ const name = "port";
- program
- .command<{
- port: number | undefined;
- keycloakVersion: string | undefined;
- realmJsonFilePath: string | undefined;
- }>({
- name: commandName,
- description:
- "Spin up a pre configured Docker image of Keycloak to test your theme."
- })
- .option({
- key: "port",
- name: (() => {
- const name = "port";
+ optionsKeys.push(name);
- optionsKeys.push(name);
+ return name;
+ })(),
+ description: ["Keycloak server port.", "Example `--port 8085`"].join(" "),
+ defaultValue: undefined
+ })
+ .option({
+ key: "keycloakVersion",
+ name: (() => {
+ const name = "keycloak-version";
- return name;
- })(),
- description: ["Keycloak server port.", "Example `--port 8085`"].join(" "),
- defaultValue: undefined
- })
- .option({
- key: "keycloakVersion",
- name: (() => {
- const name = "keycloak-version";
+ optionsKeys.push(name);
- optionsKeys.push(name);
+ return name;
+ })(),
+ description: [
+ "Use a specific version of Keycloak.",
+ "Example `--keycloak-version 21.1.1`"
+ ].join(" "),
+ defaultValue: undefined
+ })
+ .option({
+ key: "realmJsonFilePath",
+ name: (() => {
+ const name = "import";
- return name;
- })(),
- description: [
- "Use a specific version of Keycloak.",
- "Example `--keycloak-version 21.1.1`"
- ].join(" "),
- defaultValue: undefined
- })
- .option({
- key: "realmJsonFilePath",
- name: (() => {
- const name = "import";
+ optionsKeys.push(name);
- optionsKeys.push(name);
+ return name;
+ })(),
+ defaultValue: undefined,
+ description: [
+ "Import your own realm configuration file",
+ "Example `--import path/to/myrealm-realm.json`"
+ ].join(" ")
+ })
+ .task({
+ skip,
+ handler: async ({ projectDirPath, keycloakVersion, port, realmJsonFilePath }) => {
+ const { command } = await import("./start-keycloak");
- return name;
- })(),
- defaultValue: undefined,
- description: [
- "Import your own realm configuration file",
- "Example `--import path/to/myrealm-realm.json`"
- ].join(" ")
- })
- .task({
- skip,
- handler: async ({
- projectDirPath,
- keycloakVersion,
- port,
- realmJsonFilePath
- }) => {
- const buildContext = getBuildContext({ projectDirPath });
+ await command({
+ buildContext: getBuildContext({ projectDirPath }),
+ cliCommandOptions: { keycloakVersion, port, realmJsonFilePath }
+ });
+ }
+ });
- const { command } = await import("./start-keycloak");
+program
+ .command({
+ name: "eject-page",
+ description: "Eject a Keycloak page."
+ })
+ .task({
+ skip,
+ handler: async ({ projectDirPath }) => {
+ const { command } = await import("./eject-page");
- await command({
- buildContext,
- cliCommandOptions: { keycloakVersion, port, realmJsonFilePath }
- });
- }
- });
-}
+ await command({ buildContext: getBuildContext({ projectDirPath }) });
+ }
+ });
-{
- const commandName = "eject-page";
+program
+ .command({
+ name: "add-story",
+ description: "Add *.stories.tsx file for a specific page to in your Storybook."
+ })
+ .task({
+ skip,
+ handler: async ({ projectDirPath }) => {
+ const { command } = await import("./add-story");
- program
- .command({
- name: commandName,
- description: "Eject a Keycloak page."
- })
- .task({
- skip,
- handler: async ({ projectDirPath }) => {
- const buildContext = getBuildContext({ projectDirPath });
+ await command({ buildContext: getBuildContext({ projectDirPath }) });
+ }
+ });
- callHandlerIfAny({ buildContext, commandName });
+program
+ .command({
+ name: "initialize-login-theme",
+ description: "Initialize an email theme."
+ })
+ .task({
+ skip,
+ handler: async ({ projectDirPath }) => {
+ const { command } = await import("./initialize-email-theme");
- const { command } = await import("./eject-page");
-
- await command({ buildContext });
- }
- });
-}
-
-{
- const commandName = "add-story";
-
- program
- .command({
- name: commandName,
- description:
- "Add *.stories.tsx file for a specific page to in your Storybook."
- })
- .task({
- skip,
- handler: async ({ projectDirPath }) => {
- const buildContext = getBuildContext({ projectDirPath });
-
- callHandlerIfAny({ buildContext, commandName });
-
- const { command } = await import("./add-story");
-
- await command({ buildContext });
- }
- });
-}
-
-{
- const comandName = "initialize-login-theme";
-
- program
- .command({
- name: comandName,
- description: "Initialize an email theme."
- })
- .task({
- skip,
- handler: async ({ projectDirPath }) => {
- const buildContext = getBuildContext({ projectDirPath });
-
- const { command } = await import("./initialize-email-theme");
-
- await command({ buildContext });
- }
- });
-}
+ await command({ buildContext: getBuildContext({ projectDirPath }) });
+ }
+ });
program
.command({
@@ -228,57 +191,41 @@ program
.task({
skip,
handler: async ({ projectDirPath }) => {
- const buildContext = getBuildContext({ projectDirPath });
-
const { command } = await import("./initialize-account-theme");
- await command({ buildContext });
+ await command({ buildContext: getBuildContext({ projectDirPath }) });
}
});
-{
- const commandName = "copy-keycloak-resources-to-public";
+program
+ .command({
+ name: "copy-keycloak-resources-to-public",
+ description:
+ "(Webpack/Create-React-App only) Copy Keycloak default theme resources to the public directory."
+ })
+ .task({
+ skip,
+ handler: async ({ projectDirPath }) => {
+ const { command } = await import("./copy-keycloak-resources-to-public");
- program
- .command({
- name: commandName,
- description:
- "(Webpack/Create-React-App only) Copy Keycloak default theme resources to the public directory."
- })
- .task({
- skip,
- handler: async ({ projectDirPath }) => {
- const buildContext = getBuildContext({ projectDirPath });
+ await command({ buildContext: getBuildContext({ projectDirPath }) });
+ }
+ });
- const { command } = await import("./copy-keycloak-resources-to-public");
+program
+ .command({
+ name: "update-kc-gen",
+ description:
+ "(Webpack/Create-React-App only) Create/update the kc.gen.ts file in your project."
+ })
+ .task({
+ skip,
+ handler: async ({ projectDirPath }) => {
+ const { command } = await import("./update-kc-gen");
- await command({ buildContext });
- }
- });
-}
-
-{
- const commandName = "update-kc-gen";
-
- program
- .command({
- name: commandName,
- description:
- "(Webpack/Create-React-App only) Create/update the kc.gen.ts file in your project."
- })
- .task({
- skip,
- handler: async ({ projectDirPath }) => {
- const buildContext = getBuildContext({ projectDirPath });
-
- callHandlerIfAny({ buildContext, commandName });
-
- const { command } = await import("./update-kc-gen");
-
- await command({ buildContext });
- }
- });
-}
+ await command({ buildContext: getBuildContext({ projectDirPath }) });
+ }
+ });
// Fallback to build command if no command is provided
{
diff --git a/src/bin/shared/customHandler_caller.ts b/src/bin/shared/customHandler_delegate.ts
similarity index 95%
rename from src/bin/shared/customHandler_caller.ts
rename to src/bin/shared/customHandler_delegate.ts
index 88d5a41c..a41cbc7b 100644
--- a/src/bin/shared/customHandler_caller.ts
+++ b/src/bin/shared/customHandler_delegate.ts
@@ -13,7 +13,7 @@ import * as fs from "fs";
assert>();
-export function callHandlerIfAny(params: {
+export function maybeDelegateCommandToCustomHandler(params: {
commandName: CommandName;
buildContext: BuildContext;
}) {
diff --git a/src/bin/shared/generateKcGenTs.ts b/src/bin/shared/generateKcGenTs.ts
deleted file mode 100644
index e5bb7e86..00000000
--- a/src/bin/shared/generateKcGenTs.ts
+++ /dev/null
@@ -1,127 +0,0 @@
-import { assert } from "tsafe/assert";
-import type { BuildContext } from "./buildContext";
-import * as fs from "fs/promises";
-import { join as pathJoin } from "path";
-import { existsAsync } from "../tools/fs.existsAsync";
-
-export type BuildContextLike = {
- projectDirPath: string;
- themeNames: string[];
- environmentVariables: { name: string; default: string }[];
- themeSrcDirPath: string;
- implementedThemeTypes: Pick<
- BuildContext["implementedThemeTypes"],
- "login" | "account"
- >;
- packageJsonFilePath: string;
-};
-
-assert();
-
-export async function generateKcGenTs(params: {
- buildContext: BuildContextLike;
-}): Promise {
- const { buildContext } = params;
-
- const filePath = pathJoin(buildContext.themeSrcDirPath, `kc.gen.tsx`);
-
- const currentContent = (await existsAsync(filePath))
- ? await fs.readFile(filePath)
- : undefined;
-
- const hasLoginTheme = buildContext.implementedThemeTypes.login.isImplemented;
- const hasAccountTheme = buildContext.implementedThemeTypes.account.isImplemented;
-
- const newContent = Buffer.from(
- [
- `/* prettier-ignore-start */`,
- ``,
- `/* eslint-disable */`,
- ``,
- `// @ts-nocheck`,
- ``,
- `// noinspection JSUnusedGlobalSymbols`,
- ``,
- `// This file is auto-generated by Keycloakify`,
- ``,
- `import { lazy, Suspense, type ReactNode } from "react";`,
- ``,
- `export type ThemeName = ${buildContext.themeNames.map(themeName => `"${themeName}"`).join(" | ")};`,
- ``,
- `export const themeNames: ThemeName[] = [${buildContext.themeNames.map(themeName => `"${themeName}"`).join(", ")}];`,
- ``,
- `export type KcEnvName = ${buildContext.environmentVariables.length === 0 ? "never" : buildContext.environmentVariables.map(({ name }) => `"${name}"`).join(" | ")};`,
- ``,
- `export const kcEnvNames: KcEnvName[] = [${buildContext.environmentVariables.map(({ name }) => `"${name}"`).join(", ")}];`,
- ``,
- `export const kcEnvDefaults: Record = ${JSON.stringify(
- Object.fromEntries(
- buildContext.environmentVariables.map(
- ({ name, default: defaultValue }) => [name, defaultValue]
- )
- ),
- null,
- 2
- )};`,
- ``,
- `export type KcContext =`,
- hasLoginTheme && ` | import("./login/KcContext").KcContext`,
- hasAccountTheme && ` | import("./account/KcContext").KcContext`,
- ` ;`,
- ``,
- `declare global {`,
- ` interface Window {`,
- ` kcContext?: KcContext;`,
- ` }`,
- `}`,
- ``,
- hasLoginTheme &&
- `export const KcLoginPage = lazy(() => import("./login/KcPage"));`,
- hasAccountTheme &&
- `export const KcAccountPage = lazy(() => import("./account/KcPage"));`,
- ``,
- `export function KcPage(`,
- ` props: {`,
- ` kcContext: KcContext;`,
- ` fallback?: ReactNode;`,
- ` }`,
- `) {`,
- ` const { kcContext, fallback } = props;`,
- ` return (`,
- ` `,
- ` {(() => {`,
- ` switch (kcContext.themeType) {`,
- hasLoginTheme &&
- ` case "login": return ;`,
- hasAccountTheme &&
- ` case "account": return ;`,
- ` }`,
- ` })()}`,
- ` `,
- ` );`,
- `}`,
- ``,
- `/* prettier-ignore-end */`,
- ``
- ]
- .filter(item => typeof item === "string")
- .join("\n"),
- "utf8"
- );
-
- if (currentContent !== undefined && currentContent.equals(newContent)) {
- return;
- }
-
- await fs.writeFile(filePath, newContent);
-
- delete_legacy_file: {
- const legacyFilePath = filePath.replace(/tsx$/, "ts");
-
- if (!(await existsAsync(legacyFilePath))) {
- break delete_legacy_file;
- }
-
- await fs.unlink(legacyFilePath);
- }
-}
diff --git a/src/bin/update-kc-gen.ts b/src/bin/update-kc-gen.ts
index b3d9ce15..f126bcb1 100644
--- a/src/bin/update-kc-gen.ts
+++ b/src/bin/update-kc-gen.ts
@@ -1,8 +1,116 @@
import type { BuildContext } from "./shared/buildContext";
-import { generateKcGenTs } from "./shared/generateKcGenTs";
+import * as fs from "fs/promises";
+import { join as pathJoin } from "path";
+import { existsAsync } from "./tools/fs.existsAsync";
+import { maybeDelegateCommandToCustomHandler } from "./shared/customHandler_delegate";
export async function command(params: { buildContext: BuildContext }) {
const { buildContext } = params;
- await generateKcGenTs({ buildContext });
+ maybeDelegateCommandToCustomHandler({
+ commandName: "update-kc-gen",
+ buildContext
+ });
+
+ const filePath = pathJoin(buildContext.themeSrcDirPath, `kc.gen.tsx`);
+
+ const currentContent = (await existsAsync(filePath))
+ ? await fs.readFile(filePath)
+ : undefined;
+
+ const hasLoginTheme = buildContext.implementedThemeTypes.login.isImplemented;
+ const hasAccountTheme = buildContext.implementedThemeTypes.account.isImplemented;
+
+ const newContent = Buffer.from(
+ [
+ `/* prettier-ignore-start */`,
+ ``,
+ `/* eslint-disable */`,
+ ``,
+ `// @ts-nocheck`,
+ ``,
+ `// noinspection JSUnusedGlobalSymbols`,
+ ``,
+ `// This file is auto-generated by Keycloakify`,
+ ``,
+ `import { lazy, Suspense, type ReactNode } from "react";`,
+ ``,
+ `export type ThemeName = ${buildContext.themeNames.map(themeName => `"${themeName}"`).join(" | ")};`,
+ ``,
+ `export const themeNames: ThemeName[] = [${buildContext.themeNames.map(themeName => `"${themeName}"`).join(", ")}];`,
+ ``,
+ `export type KcEnvName = ${buildContext.environmentVariables.length === 0 ? "never" : buildContext.environmentVariables.map(({ name }) => `"${name}"`).join(" | ")};`,
+ ``,
+ `export const kcEnvNames: KcEnvName[] = [${buildContext.environmentVariables.map(({ name }) => `"${name}"`).join(", ")}];`,
+ ``,
+ `export const kcEnvDefaults: Record = ${JSON.stringify(
+ Object.fromEntries(
+ buildContext.environmentVariables.map(
+ ({ name, default: defaultValue }) => [name, defaultValue]
+ )
+ ),
+ null,
+ 2
+ )};`,
+ ``,
+ `export type KcContext =`,
+ hasLoginTheme && ` | import("./login/KcContext").KcContext`,
+ hasAccountTheme && ` | import("./account/KcContext").KcContext`,
+ ` ;`,
+ ``,
+ `declare global {`,
+ ` interface Window {`,
+ ` kcContext?: KcContext;`,
+ ` }`,
+ `}`,
+ ``,
+ hasLoginTheme &&
+ `export const KcLoginPage = lazy(() => import("./login/KcPage"));`,
+ hasAccountTheme &&
+ `export const KcAccountPage = lazy(() => import("./account/KcPage"));`,
+ ``,
+ `export function KcPage(`,
+ ` props: {`,
+ ` kcContext: KcContext;`,
+ ` fallback?: ReactNode;`,
+ ` }`,
+ `) {`,
+ ` const { kcContext, fallback } = props;`,
+ ` return (`,
+ ` `,
+ ` {(() => {`,
+ ` switch (kcContext.themeType) {`,
+ hasLoginTheme &&
+ ` case "login": return ;`,
+ hasAccountTheme &&
+ ` case "account": return ;`,
+ ` }`,
+ ` })()}`,
+ ` `,
+ ` );`,
+ `}`,
+ ``,
+ `/* prettier-ignore-end */`,
+ ``
+ ]
+ .filter(item => typeof item === "string")
+ .join("\n"),
+ "utf8"
+ );
+
+ if (currentContent !== undefined && currentContent.equals(newContent)) {
+ return;
+ }
+
+ await fs.writeFile(filePath, newContent);
+
+ delete_legacy_file: {
+ const legacyFilePath = filePath.replace(/tsx$/, "ts");
+
+ if (!(await existsAsync(legacyFilePath))) {
+ break delete_legacy_file;
+ }
+
+ await fs.unlink(legacyFilePath);
+ }
}
diff --git a/src/vite-plugin/vite-plugin.ts b/src/vite-plugin/vite-plugin.ts
index 3a7f3d26..e6dfb054 100644
--- a/src/vite-plugin/vite-plugin.ts
+++ b/src/vite-plugin/vite-plugin.ts
@@ -15,7 +15,7 @@ import {
type ResolvedViteConfig
} from "../bin/shared/buildContext";
import MagicString from "magic-string";
-import { generateKcGenTs } from "../bin/shared/generateKcGenTs";
+import { command as updateKcGenCommand } from "../bin/update-kc-gen";
export namespace keycloakify {
export type Params = BuildOptions & {
@@ -125,8 +125,9 @@ export function keycloakify(params: keycloakify.Params) {
projectDirPath
});
- copyKeycloakResourcesToPublic({ buildContext }),
- await generateKcGenTs({ buildContext });
+ copyKeycloakResourcesToPublic({ buildContext });
+
+ await updateKcGenCommand({ buildContext });
},
transform: (code, id) => {
assert(command !== undefined);
diff --git a/stories/login/pages/Register.stories.tsx b/stories/login/pages/Register.stories.tsx
index f25568cc..09cdf249 100644
--- a/stories/login/pages/Register.stories.tsx
+++ b/stories/login/pages/Register.stories.tsx
@@ -115,7 +115,6 @@ export const WithFavoritePet: Story = {
)
};
-
export const WithNewsletter: Story = {
render: () => (
)
};
-
export const WithEmailAsUsername: Story = {
render: () => (
Date: Sun, 6 Oct 2024 09:07:10 +0200
Subject: [PATCH 45/77] Release candidate
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 133ddec1..791e13e6 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "keycloakify",
- "version": "11.3.0-rc.5",
+ "version": "11.3.0-rc.6",
"description": "Framework to create custom Keycloak UIs",
"repository": {
"type": "git",
From 9de2ed9eaf17a4d75d84b7b096c0b0699d4f56c6 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Sun, 6 Oct 2024 12:44:46 +0200
Subject: [PATCH 46/77] Fix dead code
---
.../updateAccountThemeImplementationInConfig.ts | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/bin/initialize-account-theme/updateAccountThemeImplementationInConfig.ts b/src/bin/initialize-account-theme/updateAccountThemeImplementationInConfig.ts
index 976beb9a..1c60ef03 100644
--- a/src/bin/initialize-account-theme/updateAccountThemeImplementationInConfig.ts
+++ b/src/bin/initialize-account-theme/updateAccountThemeImplementationInConfig.ts
@@ -8,12 +8,14 @@ import { id } from "tsafe/id";
export type BuildContextLike = {
bundler: BuildContext["bundler"];
+ projectDirPath: string;
+ packageJsonFilePath: string;
};
assert();
export function updateAccountThemeImplementationInConfig(params: {
- buildContext: BuildContext;
+ buildContext: BuildContextLike;
accountThemeType: "Single-Page" | "Multi-Page";
}) {
const { buildContext, accountThemeType } = params;
From 5045c5e8bfdb82da169acb742de1d12791bb95c5 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Sun, 6 Oct 2024 13:18:12 +0200
Subject: [PATCH 47/77] Add initialize-email-theme, initialize-account-theme
and copy-keycloak-resources-to-public to commands that can be delegated to a
custom handler
---
src/bin/copy-keycloak-resources-to-public.ts | 6 ++++++
.../initialize-account-theme/initialize-account-theme.ts | 6 ++++++
src/bin/initialize-email-theme.ts | 6 ++++++
src/bin/shared/customHandler.ts | 8 +++++++-
4 files changed, 25 insertions(+), 1 deletion(-)
diff --git a/src/bin/copy-keycloak-resources-to-public.ts b/src/bin/copy-keycloak-resources-to-public.ts
index ba944068..b48f9d0e 100644
--- a/src/bin/copy-keycloak-resources-to-public.ts
+++ b/src/bin/copy-keycloak-resources-to-public.ts
@@ -1,9 +1,15 @@
import { copyKeycloakResourcesToPublic } from "./shared/copyKeycloakResourcesToPublic";
import type { BuildContext } from "./shared/buildContext";
+import { maybeDelegateCommandToCustomHandler } from "./shared/customHandler_delegate";
export async function command(params: { buildContext: BuildContext }) {
const { buildContext } = params;
+ maybeDelegateCommandToCustomHandler({
+ commandName: "copy-keycloak-resources-to-public",
+ buildContext
+ });
+
copyKeycloakResourcesToPublic({
buildContext
});
diff --git a/src/bin/initialize-account-theme/initialize-account-theme.ts b/src/bin/initialize-account-theme/initialize-account-theme.ts
index 3caed327..e7ae9223 100644
--- a/src/bin/initialize-account-theme/initialize-account-theme.ts
+++ b/src/bin/initialize-account-theme/initialize-account-theme.ts
@@ -6,10 +6,16 @@ import { join as pathJoin, relative as pathRelative } from "path";
import * as fs from "fs";
import { updateAccountThemeImplementationInConfig } from "./updateAccountThemeImplementationInConfig";
import { command as updateKcGenCommand } from "../update-kc-gen";
+import { maybeDelegateCommandToCustomHandler } from "../shared/customHandler_delegate";
export async function command(params: { buildContext: BuildContext }) {
const { buildContext } = params;
+ maybeDelegateCommandToCustomHandler({
+ commandName: "initialize-account-theme",
+ buildContext
+ });
+
const accountThemeSrcDirPath = pathJoin(buildContext.themeSrcDirPath, "account");
if (
diff --git a/src/bin/initialize-email-theme.ts b/src/bin/initialize-email-theme.ts
index dfa0287c..d5ce0fd8 100644
--- a/src/bin/initialize-email-theme.ts
+++ b/src/bin/initialize-email-theme.ts
@@ -4,10 +4,16 @@ import { promptKeycloakVersion } from "./shared/promptKeycloakVersion";
import type { BuildContext } from "./shared/buildContext";
import * as fs from "fs";
import { downloadAndExtractArchive } from "./tools/downloadAndExtractArchive";
+import { maybeDelegateCommandToCustomHandler } from "./shared/customHandler_delegate";
export async function command(params: { buildContext: BuildContext }) {
const { buildContext } = params;
+ maybeDelegateCommandToCustomHandler({
+ commandName: "initialize-email-theme",
+ buildContext
+ });
+
const emailThemeSrcDirPath = pathJoin(buildContext.themeSrcDirPath, "email");
if (
diff --git a/src/bin/shared/customHandler.ts b/src/bin/shared/customHandler.ts
index d858aaa5..7c0b9e1c 100644
--- a/src/bin/shared/customHandler.ts
+++ b/src/bin/shared/customHandler.ts
@@ -6,7 +6,13 @@ export const BIN_NAME = "_keycloakify-custom-handler";
export const NOT_IMPLEMENTED_EXIT_CODE = 78;
-export type CommandName = "update-kc-gen" | "eject-page" | "add-story";
+export type CommandName =
+ | "update-kc-gen"
+ | "eject-page"
+ | "add-story"
+ | "initialize-account-theme"
+ | "initialize-email-theme"
+ | "copy-keycloak-resources-to-public";
export type ApiVersion = "v1";
From 7156665684de3df18e49f9be3d60f671c70f0c81 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Sun, 6 Oct 2024 13:19:12 +0200
Subject: [PATCH 48/77] Release candidate
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 791e13e6..ae774e39 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "keycloakify",
- "version": "11.3.0-rc.6",
+ "version": "11.3.0-rc.7",
"description": "Framework to create custom Keycloak UIs",
"repository": {
"type": "git",
From 8d31866a0be2a37c99e6fb9ea0d98c98bbcccb0c Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Sun, 6 Oct 2024 15:09:53 +0200
Subject: [PATCH 49/77] Bump version
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index ae774e39..0fec7284 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "keycloakify",
- "version": "11.3.0-rc.7",
+ "version": "11.3.0",
"description": "Framework to create custom Keycloak UIs",
"repository": {
"type": "git",
From d63e5f4e542c2e3ac7d3abecb20b7d543a14d927 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Sun, 6 Oct 2024 15:37:32 +0200
Subject: [PATCH 50/77] Fix litle inconsistency
---
src/bin/eject-page.ts | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/bin/eject-page.ts b/src/bin/eject-page.ts
index 8874fd99..bacafe6f 100644
--- a/src/bin/eject-page.ts
+++ b/src/bin/eject-page.ts
@@ -239,12 +239,12 @@ export async function command(params: { buildContext: BuildContext }) {
)} copy pasted from the Keycloakify source code into your project`
);
- edit_KcApp: {
+ edit_KcPage: {
if (
pageIdOrComponent !== templateValue &&
pageIdOrComponent !== userProfileFormFieldsValue
) {
- break edit_KcApp;
+ break edit_KcPage;
}
const kcAppTsxPath = pathJoin(
From 52e33bba2d77f13c32aadecb935c861f1af7ec99 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Sun, 6 Oct 2024 22:08:43 +0200
Subject: [PATCH 51/77] Fix: check for delegation of the eject-page command
---
src/bin/eject-page.ts | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/bin/eject-page.ts b/src/bin/eject-page.ts
index bacafe6f..ee4a3581 100644
--- a/src/bin/eject-page.ts
+++ b/src/bin/eject-page.ts
@@ -22,10 +22,16 @@ import { kebabCaseToCamelCase } from "./tools/kebabCaseToSnakeCase";
import { assert, Equals } from "tsafe/assert";
import type { BuildContext } from "./shared/buildContext";
import chalk from "chalk";
+import { maybeDelegateCommandToCustomHandler } from "./shared/customHandler_delegate";
export async function command(params: { buildContext: BuildContext }) {
const { buildContext } = params;
+ maybeDelegateCommandToCustomHandler({
+ commandName: "eject-page",
+ buildContext
+ });
+
console.log(chalk.cyan("Theme type:"));
const themeType = await (async () => {
From 12534e57ad8cec04d36fe9f3f1d9b462369f1bc1 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Sun, 6 Oct 2024 22:09:21 +0200
Subject: [PATCH 52/77] Bump version
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 0fec7284..0ac79b18 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "keycloakify",
- "version": "11.3.0",
+ "version": "11.3.1",
"description": "Framework to create custom Keycloak UIs",
"repository": {
"type": "git",
From f6b48c88b9b0b9891c0259bad7092ec32937e25d Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Sun, 6 Oct 2024 22:55:18 +0200
Subject: [PATCH 53/77] Fix vite quitting if custom handler implemented
---
src/bin/copy-keycloak-resources-to-public.ts | 90 +++++++++++++++++-
src/bin/eject-page.ts | 6 +-
.../initialize-account-theme.ts | 6 +-
src/bin/initialize-email-theme.ts | 6 +-
.../shared/copyKeycloakResourcesToPublic.ts | 95 -------------------
src/bin/shared/customHandler_delegate.ts | 8 +-
src/bin/update-kc-gen.ts | 6 +-
src/vite-plugin/vite-plugin.ts | 4 +-
8 files changed, 111 insertions(+), 110 deletions(-)
delete mode 100644 src/bin/shared/copyKeycloakResourcesToPublic.ts
diff --git a/src/bin/copy-keycloak-resources-to-public.ts b/src/bin/copy-keycloak-resources-to-public.ts
index b48f9d0e..1925860d 100644
--- a/src/bin/copy-keycloak-resources-to-public.ts
+++ b/src/bin/copy-keycloak-resources-to-public.ts
@@ -1,16 +1,96 @@
-import { copyKeycloakResourcesToPublic } from "./shared/copyKeycloakResourcesToPublic";
-import type { BuildContext } from "./shared/buildContext";
import { maybeDelegateCommandToCustomHandler } from "./shared/customHandler_delegate";
+import { join as pathJoin, dirname as pathDirname } from "path";
+import { WELL_KNOWN_DIRECTORY_BASE_NAME } from "./shared/constants";
+import { readThisNpmPackageVersion } from "./tools/readThisNpmPackageVersion";
+import * as fs from "fs";
+import { rmSync } from "./tools/fs.rmSync";
+import type { BuildContext } from "./shared/buildContext";
+import { transformCodebase } from "./tools/transformCodebase";
+import { getThisCodebaseRootDirPath } from "./tools/getThisCodebaseRootDirPath";
export async function command(params: { buildContext: BuildContext }) {
const { buildContext } = params;
- maybeDelegateCommandToCustomHandler({
+ const { hasBeenHandled } = maybeDelegateCommandToCustomHandler({
commandName: "copy-keycloak-resources-to-public",
buildContext
});
- copyKeycloakResourcesToPublic({
- buildContext
+ if (hasBeenHandled) {
+ return;
+ }
+
+ const destDirPath = pathJoin(
+ buildContext.publicDirPath,
+ WELL_KNOWN_DIRECTORY_BASE_NAME.KEYCLOAKIFY_DEV_RESOURCES
+ );
+
+ const keycloakifyBuildinfoFilePath = pathJoin(destDirPath, "keycloakify.buildinfo");
+
+ const keycloakifyBuildinfoRaw = JSON.stringify(
+ {
+ keycloakifyVersion: readThisNpmPackageVersion()
+ },
+ null,
+ 2
+ );
+
+ skip_if_already_done: {
+ if (!fs.existsSync(keycloakifyBuildinfoFilePath)) {
+ break skip_if_already_done;
+ }
+
+ const keycloakifyBuildinfoRaw_previousRun = fs
+ .readFileSync(keycloakifyBuildinfoFilePath)
+ .toString("utf8");
+
+ if (keycloakifyBuildinfoRaw_previousRun !== keycloakifyBuildinfoRaw) {
+ break skip_if_already_done;
+ }
+
+ return;
+ }
+
+ rmSync(destDirPath, { force: true, recursive: true });
+
+ // NOTE: To remove in a while, remove the legacy keycloak-resources directory
+ rmSync(pathJoin(pathDirname(destDirPath), "keycloak-resources"), {
+ force: true,
+ recursive: true
});
+ rmSync(pathJoin(pathDirname(destDirPath), ".keycloakify"), {
+ force: true,
+ recursive: true
+ });
+
+ fs.mkdirSync(destDirPath, { recursive: true });
+
+ fs.writeFileSync(pathJoin(destDirPath, ".gitignore"), Buffer.from("*", "utf8"));
+
+ transformCodebase({
+ srcDirPath: pathJoin(
+ getThisCodebaseRootDirPath(),
+ "res",
+ "public",
+ WELL_KNOWN_DIRECTORY_BASE_NAME.KEYCLOAKIFY_DEV_RESOURCES
+ ),
+ destDirPath
+ });
+
+ fs.writeFileSync(
+ pathJoin(destDirPath, "README.txt"),
+ Buffer.from(
+ // prettier-ignore
+ [
+ "This directory is only used in dev mode by Keycloakify",
+ "It won't be included in your final build.",
+ "Do not modify anything in this directory.",
+ ].join("\n")
+ )
+ );
+
+ fs.writeFileSync(
+ keycloakifyBuildinfoFilePath,
+ Buffer.from(keycloakifyBuildinfoRaw, "utf8")
+ );
}
diff --git a/src/bin/eject-page.ts b/src/bin/eject-page.ts
index ee4a3581..e982c2f7 100644
--- a/src/bin/eject-page.ts
+++ b/src/bin/eject-page.ts
@@ -27,11 +27,15 @@ import { maybeDelegateCommandToCustomHandler } from "./shared/customHandler_dele
export async function command(params: { buildContext: BuildContext }) {
const { buildContext } = params;
- maybeDelegateCommandToCustomHandler({
+ const { hasBeenHandled } = maybeDelegateCommandToCustomHandler({
commandName: "eject-page",
buildContext
});
+ if (hasBeenHandled) {
+ return;
+ }
+
console.log(chalk.cyan("Theme type:"));
const themeType = await (async () => {
diff --git a/src/bin/initialize-account-theme/initialize-account-theme.ts b/src/bin/initialize-account-theme/initialize-account-theme.ts
index e7ae9223..dd7c61c8 100644
--- a/src/bin/initialize-account-theme/initialize-account-theme.ts
+++ b/src/bin/initialize-account-theme/initialize-account-theme.ts
@@ -11,11 +11,15 @@ import { maybeDelegateCommandToCustomHandler } from "../shared/customHandler_del
export async function command(params: { buildContext: BuildContext }) {
const { buildContext } = params;
- maybeDelegateCommandToCustomHandler({
+ const { hasBeenHandled } = maybeDelegateCommandToCustomHandler({
commandName: "initialize-account-theme",
buildContext
});
+ if (hasBeenHandled) {
+ return;
+ }
+
const accountThemeSrcDirPath = pathJoin(buildContext.themeSrcDirPath, "account");
if (
diff --git a/src/bin/initialize-email-theme.ts b/src/bin/initialize-email-theme.ts
index d5ce0fd8..7a81205b 100644
--- a/src/bin/initialize-email-theme.ts
+++ b/src/bin/initialize-email-theme.ts
@@ -9,11 +9,15 @@ import { maybeDelegateCommandToCustomHandler } from "./shared/customHandler_dele
export async function command(params: { buildContext: BuildContext }) {
const { buildContext } = params;
- maybeDelegateCommandToCustomHandler({
+ const { hasBeenHandled } = maybeDelegateCommandToCustomHandler({
commandName: "initialize-email-theme",
buildContext
});
+ if (hasBeenHandled) {
+ return;
+ }
+
const emailThemeSrcDirPath = pathJoin(buildContext.themeSrcDirPath, "email");
if (
diff --git a/src/bin/shared/copyKeycloakResourcesToPublic.ts b/src/bin/shared/copyKeycloakResourcesToPublic.ts
deleted file mode 100644
index db78d313..00000000
--- a/src/bin/shared/copyKeycloakResourcesToPublic.ts
+++ /dev/null
@@ -1,95 +0,0 @@
-import { join as pathJoin, dirname as pathDirname } from "path";
-import { WELL_KNOWN_DIRECTORY_BASE_NAME } from "../shared/constants";
-import { readThisNpmPackageVersion } from "../tools/readThisNpmPackageVersion";
-import { assert } from "tsafe/assert";
-import * as fs from "fs";
-import { rmSync } from "../tools/fs.rmSync";
-import type { BuildContext } from "./buildContext";
-import { transformCodebase } from "../tools/transformCodebase";
-import { getThisCodebaseRootDirPath } from "../tools/getThisCodebaseRootDirPath";
-
-export type BuildContextLike = {
- publicDirPath: string;
-};
-
-assert();
-
-export function copyKeycloakResourcesToPublic(params: {
- buildContext: BuildContextLike;
-}) {
- const { buildContext } = params;
-
- const destDirPath = pathJoin(
- buildContext.publicDirPath,
- WELL_KNOWN_DIRECTORY_BASE_NAME.KEYCLOAKIFY_DEV_RESOURCES
- );
-
- const keycloakifyBuildinfoFilePath = pathJoin(destDirPath, "keycloakify.buildinfo");
-
- const keycloakifyBuildinfoRaw = JSON.stringify(
- {
- keycloakifyVersion: readThisNpmPackageVersion()
- },
- null,
- 2
- );
-
- skip_if_already_done: {
- if (!fs.existsSync(keycloakifyBuildinfoFilePath)) {
- break skip_if_already_done;
- }
-
- const keycloakifyBuildinfoRaw_previousRun = fs
- .readFileSync(keycloakifyBuildinfoFilePath)
- .toString("utf8");
-
- if (keycloakifyBuildinfoRaw_previousRun !== keycloakifyBuildinfoRaw) {
- break skip_if_already_done;
- }
-
- return;
- }
-
- rmSync(destDirPath, { force: true, recursive: true });
-
- // NOTE: To remove in a while, remove the legacy keycloak-resources directory
- rmSync(pathJoin(pathDirname(destDirPath), "keycloak-resources"), {
- force: true,
- recursive: true
- });
- rmSync(pathJoin(pathDirname(destDirPath), ".keycloakify"), {
- force: true,
- recursive: true
- });
-
- fs.mkdirSync(destDirPath, { recursive: true });
-
- fs.writeFileSync(pathJoin(destDirPath, ".gitignore"), Buffer.from("*", "utf8"));
-
- transformCodebase({
- srcDirPath: pathJoin(
- getThisCodebaseRootDirPath(),
- "res",
- "public",
- WELL_KNOWN_DIRECTORY_BASE_NAME.KEYCLOAKIFY_DEV_RESOURCES
- ),
- destDirPath
- });
-
- fs.writeFileSync(
- pathJoin(destDirPath, "README.txt"),
- Buffer.from(
- // prettier-ignore
- [
- "This directory is only used in dev mode by Keycloakify",
- "It won't be included in your final build.",
- "Do not modify anything in this directory.",
- ].join("\n")
- )
- );
-
- fs.writeFileSync(
- keycloakifyBuildinfoFilePath,
- Buffer.from(keycloakifyBuildinfoRaw, "utf8")
- );
-}
diff --git a/src/bin/shared/customHandler_delegate.ts b/src/bin/shared/customHandler_delegate.ts
index a41cbc7b..691989df 100644
--- a/src/bin/shared/customHandler_delegate.ts
+++ b/src/bin/shared/customHandler_delegate.ts
@@ -16,11 +16,11 @@ assert>();
export function maybeDelegateCommandToCustomHandler(params: {
commandName: CommandName;
buildContext: BuildContext;
-}) {
+}): { hasBeenHandled: boolean } {
const { commandName, buildContext } = params;
if (!fs.readdirSync(pathDirname(process.argv[1])).includes(BIN_NAME)) {
- return;
+ return { hasBeenHandled: false };
}
try {
@@ -36,11 +36,11 @@ export function maybeDelegateCommandToCustomHandler(params: {
const status = error.status;
if (status === NOT_IMPLEMENTED_EXIT_CODE) {
- return;
+ return { hasBeenHandled: false };
}
process.exit(status);
}
- process.exit(0);
+ return { hasBeenHandled: true };
}
diff --git a/src/bin/update-kc-gen.ts b/src/bin/update-kc-gen.ts
index f126bcb1..e1366fd4 100644
--- a/src/bin/update-kc-gen.ts
+++ b/src/bin/update-kc-gen.ts
@@ -7,11 +7,15 @@ import { maybeDelegateCommandToCustomHandler } from "./shared/customHandler_dele
export async function command(params: { buildContext: BuildContext }) {
const { buildContext } = params;
- maybeDelegateCommandToCustomHandler({
+ const { hasBeenHandled } = maybeDelegateCommandToCustomHandler({
commandName: "update-kc-gen",
buildContext
});
+ if (hasBeenHandled) {
+ return;
+ }
+
const filePath = pathJoin(buildContext.themeSrcDirPath, `kc.gen.tsx`);
const currentContent = (await existsAsync(filePath))
diff --git a/src/vite-plugin/vite-plugin.ts b/src/vite-plugin/vite-plugin.ts
index e6dfb054..d7ec06d5 100644
--- a/src/vite-plugin/vite-plugin.ts
+++ b/src/vite-plugin/vite-plugin.ts
@@ -6,7 +6,7 @@ import {
} from "../bin/shared/constants";
import { id } from "tsafe/id";
import { rm } from "../bin/tools/fs.rm";
-import { copyKeycloakResourcesToPublic } from "../bin/shared/copyKeycloakResourcesToPublic";
+import { command as copyKeycloakResourcesToPublicCommand } from "../bin/copy-keycloak-resources-to-public";
import { assert } from "tsafe/assert";
import {
getBuildContext,
@@ -125,7 +125,7 @@ export function keycloakify(params: keycloakify.Params) {
projectDirPath
});
- copyKeycloakResourcesToPublic({ buildContext });
+ await copyKeycloakResourcesToPublicCommand({ buildContext });
await updateKcGenCommand({ buildContext });
},
From 88de58cc2231a9269bc8efbf9ba7ef56b881f396 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Sun, 6 Oct 2024 22:56:42 +0200
Subject: [PATCH 54/77] Bump version
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 0ac79b18..f2e015ac 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "keycloakify",
- "version": "11.3.1",
+ "version": "11.3.2",
"description": "Framework to create custom Keycloak UIs",
"repository": {
"type": "git",
From 4cdf26b6f91e64f0ae9fafc8e68d175c1a8152ef Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Mon, 7 Oct 2024 20:56:03 +0200
Subject: [PATCH 55/77] Announcement about Keycloak 26
---
README.md | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/README.md b/README.md
index 2c133223..c6edf2d0 100644
--- a/README.md
+++ b/README.md
@@ -43,6 +43,11 @@
Keycloakify is fully compatible with Keycloak from version 11 to 26...[and beyond](https://github.com/keycloakify/keycloakify/discussions/346#discussioncomment-5889791)
+> π£ **Keycloakify 26 Released**
+> Themes built with Keycloakify versions **prior** to Keycloak 26 are **incompatible** with Keycloak 26.
+> To ensure compatibility, simply upgrade to the latest Keycloakify version for your major release (v10 or v11) and rebuild your theme.
+> No breaking changes have been introduced, but the target version ranges have been updated. For more details, see [this guide](https://docs.keycloakify.dev/targeting-specific-keycloak-versions).
+
## Sponsors
Friends for the project, we trust and recommend their services.
From 9e19aafcd028f7e0cd09d7abe1f31c8470dd5066 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Mon, 7 Oct 2024 21:02:51 +0200
Subject: [PATCH 56/77] Fix initialize-email-theme
---
src/bin/main.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/bin/main.ts b/src/bin/main.ts
index 89b03d7c..a6abe1f5 100644
--- a/src/bin/main.ts
+++ b/src/bin/main.ts
@@ -171,7 +171,7 @@ program
program
.command({
- name: "initialize-login-theme",
+ name: "initialize-email-theme",
description: "Initialize an email theme."
})
.task({
From eb23b40e5c1e061a6553585cce62c39e3ecb00ff Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Mon, 7 Oct 2024 21:03:04 +0200
Subject: [PATCH 57/77] Bump version
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index f2e015ac..cf03259f 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "keycloakify",
- "version": "11.3.2",
+ "version": "11.3.3",
"description": "Framework to create custom Keycloak UIs",
"repository": {
"type": "git",
From 61a86e8e821b359d3fd0ddf79708ece5a8363172 Mon Sep 17 00:00:00 2001
From: "allcontributors[bot]"
<46447321+allcontributors[bot]@users.noreply.github.com>
Date: Mon, 7 Oct 2024 21:47:10 +0000
Subject: [PATCH 58/77] docs: update README.md [skip ci]
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index c6edf2d0..11eff6fe 100644
--- a/README.md
+++ b/README.md
@@ -141,6 +141,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
 Omid β οΈ π» |
 Katharina Eiserfey π» β οΈ π |
 Luca Peruzzo π» β οΈ |
+  Nima Shokouhfar π» β οΈ |
From 3e38beb19008821b7910366a0834a6d2114f11e7 Mon Sep 17 00:00:00 2001
From: "allcontributors[bot]"
<46447321+allcontributors[bot]@users.noreply.github.com>
Date: Mon, 7 Oct 2024 21:47:11 +0000
Subject: [PATCH 59/77] docs: update .all-contributorsrc [skip ci]
---
.all-contributorsrc | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/.all-contributorsrc b/.all-contributorsrc
index fdede216..f7d39edd 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -290,6 +290,16 @@
"code",
"test"
]
+ },
+ {
+ "login": "nima70",
+ "name": "Nima Shokouhfar",
+ "avatar_url": "https://avatars.githubusercontent.com/u/5094767?v=4",
+ "profile": "https://github.com/nima70",
+ "contributions": [
+ "code",
+ "test"
+ ]
}
],
"contributorsPerLine": 7,
From ecfdff5454d8cb997a306fe69277582d1f09309d Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Mon, 7 Oct 2024 23:53:05 +0200
Subject: [PATCH 60/77] Bump version
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index cf03259f..9be229b0 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "keycloakify",
- "version": "11.3.3",
+ "version": "11.3.4",
"description": "Framework to create custom Keycloak UIs",
"repository": {
"type": "git",
From 94e278629709d917258af1dc10d9f0bd696953cf Mon Sep 17 00:00:00 2001
From: Liam Lowsley-Williams
Date: Tue, 8 Oct 2024 16:50:11 -0500
Subject: [PATCH 61/77] fix: added parameter type for story context on register
page
---
stories/login/pages/Register.stories.tsx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/stories/login/pages/Register.stories.tsx b/stories/login/pages/Register.stories.tsx
index 8ab6c16d..3250f927 100644
--- a/stories/login/pages/Register.stories.tsx
+++ b/stories/login/pages/Register.stories.tsx
@@ -240,8 +240,8 @@ export const WithFieldErrors: Story = {
}
},
messagesPerField: {
- existsError: fieldName => ["username", "email"].includes(fieldName),
- get: fieldName => {
+ existsError: (fieldName: string) => ["username", "email"].includes(fieldName),
+ get: (fieldName: string) => {
if (fieldName === "username") return "Username is required.";
if (fieldName === "email") return "Invalid email format.";
}
From fbf6a329df7a549902209672be71c74cb334df30 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Fri, 11 Oct 2024 23:55:04 +0200
Subject: [PATCH 62/77] typesafety fix
---
.../updateAccountThemeImplementationInConfig.ts | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/bin/initialize-account-theme/updateAccountThemeImplementationInConfig.ts b/src/bin/initialize-account-theme/updateAccountThemeImplementationInConfig.ts
index 1c60ef03..65b3ba39 100644
--- a/src/bin/initialize-account-theme/updateAccountThemeImplementationInConfig.ts
+++ b/src/bin/initialize-account-theme/updateAccountThemeImplementationInConfig.ts
@@ -5,6 +5,7 @@ import * as fs from "fs";
import chalk from "chalk";
import { z } from "zod";
import { id } from "tsafe/id";
+import { is } from "tsafe/is";
export type BuildContextLike = {
bundler: BuildContext["bundler"];
@@ -83,6 +84,8 @@ export function updateAccountThemeImplementationInConfig(params: {
zParsedPackageJson.parse(parsedPackageJson);
+ assert(is(parsedPackageJson));
+
return parsedPackageJson;
})();
From 59c4675e8a2c19365c26e4953a0304d1ad413587 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Sat, 12 Oct 2024 17:30:30 +0200
Subject: [PATCH 63/77] Add dir=rtl attribut to html when using a RTL language
---
src/login/KcContext/KcContext.ts | 1 +
src/login/i18n/noJsx/getI18n.tsx | 44 ++++++++++++++++++++++++++++++++
2 files changed, 45 insertions(+)
diff --git a/src/login/KcContext/KcContext.ts b/src/login/KcContext/KcContext.ts
index 14d1169f..161e45de 100644
--- a/src/login/KcContext/KcContext.ts
+++ b/src/login/KcContext/KcContext.ts
@@ -94,6 +94,7 @@ export declare namespace KcContext {
languageTag: string;
}[];
currentLanguageTag: string;
+ rtl?: boolean;
};
auth?: {
showUsername?: boolean;
diff --git a/src/login/i18n/noJsx/getI18n.tsx b/src/login/i18n/noJsx/getI18n.tsx
index e560e2e3..f619a303 100644
--- a/src/login/i18n/noJsx/getI18n.tsx
+++ b/src/login/i18n/noJsx/getI18n.tsx
@@ -19,6 +19,7 @@ export type KcContextLike = {
locale?: {
currentLanguageTag: string;
supported: { languageTag: string; url: string; label: string }[];
+ rtl?: boolean;
};
"x-keycloakify": {
messages: Record;
@@ -95,6 +96,49 @@ export function createGetI18n<
const html = document.querySelector("html");
assert(html !== null);
html.lang = currentLanguageTag;
+
+ const isRtl = (() => {
+ const { rtl } = kcContext.locale ?? {};
+
+ if (rtl !== undefined) {
+ return rtl;
+ }
+
+ return [
+ /* spell-checker: disable */
+ // Common RTL languages
+ "ar", // Arabic
+ "fa", // Persian (Farsi)
+ "he", // Hebrew
+ "ur", // Urdu
+ "ps", // Pashto
+ "syr", // Syriac
+ "dv", // Divehi (Maldivian)
+ "ku", // Kurdish (Sorani)
+ "ug", // Uighur
+ "az", // Azerbaijani (Arabic script)
+ "sd", // Sindhi
+
+ // Less common RTL languages
+ "yi", // Yiddish
+ "ha", // Hausa (when written in Arabic script)
+ "ks", // Kashmiri (written in the Perso-Arabic script)
+ "bal", // Balochi (when written in Arabic script)
+ "khw", // Khowar (Chitrali)
+ "brh", // Brahui (when written in Arabic script)
+ "tmh", // Tamashek (some dialects use Arabic script)
+ "bgn", // Western Balochi
+ "arc", // Aramaic
+ "sam", // Samaritan Aramaic
+ "prd", // Parsi-Dari (a dialect of Persian)
+ "huz", // Hazaragi (a dialect of Persian)
+ "gbz", // Zaza (written in Arabic script in some areas)
+ "urj" // Urdu in Romanized script (not always RTL, but to account for edge cases)
+ /* spell-checker: enable */
+ ].includes(currentLanguageTag);
+ })();
+
+ html.dir = isRtl ? "rtl" : "ltr";
}
const getLanguageLabel = (languageTag: LanguageTag) => {
From b86039536e2752251ba1bd44757ff56829b54ea6 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Sat, 12 Oct 2024 17:33:44 +0200
Subject: [PATCH 64/77] Bump version
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 9be229b0..cfa9d0cd 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "keycloakify",
- "version": "11.3.4",
+ "version": "11.3.5",
"description": "Framework to create custom Keycloak UIs",
"repository": {
"type": "git",
From f5a9a281244b267b1dc616ee5cfb859f983f6fa2 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Sun, 13 Oct 2024 00:55:06 +0200
Subject: [PATCH 65/77] Resolve package.json path relative to the package.json
---
src/bin/shared/buildContext.ts | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/src/bin/shared/buildContext.ts b/src/bin/shared/buildContext.ts
index 26c746b8..89afa6f9 100644
--- a/src/bin/shared/buildContext.ts
+++ b/src/bin/shared/buildContext.ts
@@ -508,6 +508,15 @@ export function getBuildContext(params: {
return themeNames;
})();
+ const relativePathsCwd = (() => {
+ switch (bundler) {
+ case "vite":
+ return projectDirPath;
+ case "webpack":
+ return pathDirname(packageJsonFilePath);
+ }
+ })();
+
const projectBuildDirPath = (() => {
webpack: {
if (bundler !== "webpack") {
@@ -519,7 +528,7 @@ export function getBuildContext(params: {
if (parsedPackageJson.keycloakify.projectBuildDirPath !== undefined) {
return getAbsoluteAndInOsFormatPath({
pathIsh: parsedPackageJson.keycloakify.projectBuildDirPath,
- cwd: projectDirPath
+ cwd: relativePathsCwd
});
}
@@ -563,7 +572,7 @@ export function getBuildContext(params: {
if (buildOptions.keycloakifyBuildDirPath !== undefined) {
return getAbsoluteAndInOsFormatPath({
pathIsh: buildOptions.keycloakifyBuildDirPath,
- cwd: projectDirPath
+ cwd: relativePathsCwd
});
}
@@ -592,7 +601,7 @@ export function getBuildContext(params: {
if (parsedPackageJson.keycloakify.publicDirPath !== undefined) {
return getAbsoluteAndInOsFormatPath({
pathIsh: parsedPackageJson.keycloakify.publicDirPath,
- cwd: projectDirPath
+ cwd: relativePathsCwd
});
}
@@ -664,7 +673,7 @@ export function getBuildContext(params: {
pathIsh:
parsedPackageJson.keycloakify
.staticDirPathInProjectBuildDirPath,
- cwd: projectBuildDirPath
+ cwd: relativePathsCwd
});
}
@@ -992,7 +1001,7 @@ export function getBuildContext(params: {
type: "path",
path: getAbsoluteAndInOsFormatPath({
pathIsh: urlOrPath,
- cwd: projectDirPath
+ cwd: relativePathsCwd
})
};
}
@@ -1002,7 +1011,7 @@ export function getBuildContext(params: {
? undefined
: getAbsoluteAndInOsFormatPath({
pathIsh: buildOptions.startKeycloakOptions.realmJsonFilePath,
- cwd: projectDirPath
+ cwd: relativePathsCwd
}),
port: buildOptions.startKeycloakOptions?.port
}
From d56c53644687668bed774e36caca3e3ef2afcb16 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Sun, 13 Oct 2024 00:55:23 +0200
Subject: [PATCH 66/77] Bump version
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index cfa9d0cd..e6259f12 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "keycloakify",
- "version": "11.3.5",
+ "version": "11.3.6",
"description": "Framework to create custom Keycloak UIs",
"repository": {
"type": "git",
From c932c7d8f66bdb08fa42bbcbd46ff5857176b648 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Wed, 16 Oct 2024 03:37:00 +0200
Subject: [PATCH 67/77] Resize zone2 logo
---
README.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 11eff6fe..2b09cd04 100644
--- a/README.md
+++ b/README.md
@@ -50,19 +50,19 @@ Keycloakify is fully compatible with Keycloak from version 11 to 26...[and beyon
## Sponsors
-Friends for the project, we trust and recommend their services.
+Project backers, we trust and recommend their services.
-
+
-
+
From 06fe26fbe71b2ae4f3d9e1f3c409da287df7b65c Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Wed, 16 Oct 2024 04:10:17 +0200
Subject: [PATCH 68/77] Add phaseTwo as sponsor
---
README.md | 24 +++++++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 2b09cd04..6f3eb47a 100644
--- a/README.md
+++ b/README.md
@@ -56,6 +56,28 @@ Project backers, we trust and recommend their services.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Keycloak on Steroids as a Service - Keycloak community contributors of popular extensions providing free and dedicated Keycloak hosting and enterprise Keycloak support to businesses of all sizes.
+
+
+
+
+
+
+
+

@@ -87,7 +109,7 @@ Project backers, we trust and recommend their services.
-Managed Keycloak Provider - With Cloud-IAM powering your Keycloak clusters, you can sleep easy knowing you've got the software and the experts you need for operational excellence.
+Managed Keycloak Provider - With Cloud-IAM powering your Keycloak clusters, you can sleep easy knowing you've got the software and the experts you need for operational excellence. Cloud IAM is a french company.
Use code keycloakify5
at checkout for a 5% discount.
From 7c7e5544e4afa358911b2ee958f74d53844d9744 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Wed, 16 Oct 2024 05:13:52 +0200
Subject: [PATCH 69/77] Fix light mode rendering
---
README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 6f3eb47a..af64954c 100644
--- a/README.md
+++ b/README.md
@@ -56,7 +56,7 @@ Project backers, we trust and recommend their services.
-
+
@@ -78,7 +78,7 @@ Project backers, we trust and recommend their services.
-
+
From ee1b6868f80b2c685e4c6798f67164649bcc42a9 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Thu, 17 Oct 2024 19:54:14 +0200
Subject: [PATCH 70/77] Fix Phase two links
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index af64954c..81228618 100644
--- a/README.md
+++ b/README.md
@@ -69,7 +69,7 @@ Project backers, we trust and recommend their services.
- Keycloak on Steroids as a Service - Keycloak community contributors of popular extensions providing free and dedicated Keycloak hosting and enterprise Keycloak support to businesses of all sizes.
+ Keycloak as a Service - Keycloak community contributors of popular extensions providing free and dedicated Keycloak hosting and enterprise Keycloak support to businesses of all sizes.
From 31d7a938f2d0abd2cd4bc1aaeb5702b14fc81943 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Thu, 17 Oct 2024 23:23:26 +0200
Subject: [PATCH 71/77] #696
---
src/bin/initialize-email-theme.ts | 31 +++++++++++++++++++++++++++++--
1 file changed, 29 insertions(+), 2 deletions(-)
diff --git a/src/bin/initialize-email-theme.ts b/src/bin/initialize-email-theme.ts
index 7a81205b..62a5566a 100644
--- a/src/bin/initialize-email-theme.ts
+++ b/src/bin/initialize-email-theme.ts
@@ -5,6 +5,9 @@ import type { BuildContext } from "./shared/buildContext";
import * as fs from "fs";
import { downloadAndExtractArchive } from "./tools/downloadAndExtractArchive";
import { maybeDelegateCommandToCustomHandler } from "./shared/customHandler_delegate";
+import fetch from "make-fetch-happen";
+import { SemVer } from "./tools/SemVer";
+import { assert } from "tsafe/assert";
export async function command(params: { buildContext: BuildContext }) {
const { buildContext } = params;
@@ -36,7 +39,7 @@ export async function command(params: { buildContext: BuildContext }) {
console.log("Initialize with the base email theme from which version of Keycloak?");
- const { keycloakVersion } = await promptKeycloakVersion({
+ let { keycloakVersion } = await promptKeycloakVersion({
// NOTE: This is arbitrary
startingFromMajor: 17,
excludeMajorVersions: [],
@@ -44,8 +47,32 @@ export async function command(params: { buildContext: BuildContext }) {
buildContext
});
+ const getUrl = (keycloakVersion: string) => {
+ return `https://repo1.maven.org/maven2/org/keycloak/keycloak-themes/${keycloakVersion}/keycloak-themes-${keycloakVersion}.jar`;
+ };
+
+ keycloakVersion = await (async () => {
+ const keycloakVersionParsed = SemVer.parse(keycloakVersion);
+
+ while (true) {
+ const url = getUrl(SemVer.stringify(keycloakVersionParsed));
+
+ const response = await fetch(url, buildContext.fetchOptions);
+
+ if (response.ok) {
+ break;
+ }
+
+ assert(keycloakVersionParsed.patch !== 0);
+
+ keycloakVersionParsed.patch--;
+ }
+
+ return SemVer.stringify(keycloakVersionParsed);
+ })();
+
const { extractedDirPath } = await downloadAndExtractArchive({
- url: `https://repo1.maven.org/maven2/org/keycloak/keycloak-themes/${keycloakVersion}/keycloak-themes-${keycloakVersion}.jar`,
+ url: getUrl(keycloakVersion),
cacheDirPath: buildContext.cacheDirPath,
fetchOptions: buildContext.fetchOptions,
uniqueIdOfOnArchiveFile: "extractOnlyEmailTheme",
From 80fd4095c4037ab04de20f130ae83ece9da1a19d Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Thu, 17 Oct 2024 23:23:52 +0200
Subject: [PATCH 72/77] Bump version
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index e6259f12..ccb76d98 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "keycloakify",
- "version": "11.3.6",
+ "version": "11.3.7",
"description": "Framework to create custom Keycloak UIs",
"repository": {
"type": "git",
From c63648a1b007eaa2a0cfc2ae27ca364f77545535 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Sat, 19 Oct 2024 02:19:41 +0200
Subject: [PATCH 73/77] #693 #692
---
...skeysConditionalAuthenticate.useScript.tsx | 9 +++++-
...LoginRecoveryAuthnCodeConfig.useScript.tsx | 9 +++++-
.../pages/WebauthnAuthenticate.useScript.tsx | 9 +++++-
.../pages/WebauthnRegister.useScript.tsx | 9 +++++-
src/tools/waitForElementMountedOnDom.ts | 30 +++++++++++++++++++
5 files changed, 62 insertions(+), 4 deletions(-)
create mode 100644 src/tools/waitForElementMountedOnDom.ts
diff --git a/src/login/pages/LoginPasskeysConditionalAuthenticate.useScript.tsx b/src/login/pages/LoginPasskeysConditionalAuthenticate.useScript.tsx
index 9cd1c867..4807c6c1 100644
--- a/src/login/pages/LoginPasskeysConditionalAuthenticate.useScript.tsx
+++ b/src/login/pages/LoginPasskeysConditionalAuthenticate.useScript.tsx
@@ -2,6 +2,7 @@ import { useEffect } from "react";
import { useInsertScriptTags } from "keycloakify/tools/useInsertScriptTags";
import { assert } from "keycloakify/tools/assert";
import { KcContext } from "keycloakify/login/KcContext/KcContext";
+import { waitForElementMountedOnDom } from "keycloakify/tools/waitForElementMountedOnDom";
type KcContextLike = {
url: {
@@ -67,6 +68,12 @@ export function useScript(params: { authButtonId: string; kcContext: KcContextLi
return;
}
- insertScriptTags();
+ (async () => {
+ await waitForElementMountedOnDom({
+ elementId: authButtonId
+ });
+
+ insertScriptTags();
+ })();
}, [isFetchingTranslations]);
}
diff --git a/src/login/pages/LoginRecoveryAuthnCodeConfig.useScript.tsx b/src/login/pages/LoginRecoveryAuthnCodeConfig.useScript.tsx
index 8a5f9586..ef882462 100644
--- a/src/login/pages/LoginRecoveryAuthnCodeConfig.useScript.tsx
+++ b/src/login/pages/LoginRecoveryAuthnCodeConfig.useScript.tsx
@@ -1,5 +1,6 @@
import { useEffect } from "react";
import { useInsertScriptTags } from "keycloakify/tools/useInsertScriptTags";
+import { waitForElementMountedOnDom } from "keycloakify/tools/waitForElementMountedOnDom";
type I18nLike = {
msgStr: (key: "recovery-codes-download-file-header" | "recovery-codes-download-file-description" | "recovery-codes-download-file-date") => string;
@@ -137,6 +138,12 @@ export function useScript(params: { olRecoveryCodesListId: string; i18n: I18nLik
return;
}
- insertScriptTags();
+ (async () => {
+ await waitForElementMountedOnDom({
+ elementId: olRecoveryCodesListId
+ });
+
+ insertScriptTags();
+ })();
}, [isFetchingTranslations]);
}
diff --git a/src/login/pages/WebauthnAuthenticate.useScript.tsx b/src/login/pages/WebauthnAuthenticate.useScript.tsx
index bc8fde5a..0ffde595 100644
--- a/src/login/pages/WebauthnAuthenticate.useScript.tsx
+++ b/src/login/pages/WebauthnAuthenticate.useScript.tsx
@@ -2,6 +2,7 @@ import { useEffect } from "react";
import { useInsertScriptTags } from "keycloakify/tools/useInsertScriptTags";
import { assert } from "keycloakify/tools/assert";
import { KcContext } from "keycloakify/login/KcContext/KcContext";
+import { waitForElementMountedOnDom } from "keycloakify/tools/waitForElementMountedOnDom";
type KcContextLike = {
url: {
@@ -59,6 +60,12 @@ export function useScript(params: { authButtonId: string; kcContext: KcContextLi
return;
}
- insertScriptTags();
+ (async () => {
+ await waitForElementMountedOnDom({
+ elementId: authButtonId
+ });
+
+ insertScriptTags();
+ })();
}, [isFetchingTranslations]);
}
diff --git a/src/login/pages/WebauthnRegister.useScript.tsx b/src/login/pages/WebauthnRegister.useScript.tsx
index c1d8cd66..98f3dfa7 100644
--- a/src/login/pages/WebauthnRegister.useScript.tsx
+++ b/src/login/pages/WebauthnRegister.useScript.tsx
@@ -2,6 +2,7 @@ import { useEffect } from "react";
import { useInsertScriptTags } from "keycloakify/tools/useInsertScriptTags";
import { assert } from "keycloakify/tools/assert";
import { KcContext } from "keycloakify/login/KcContext/KcContext";
+import { waitForElementMountedOnDom } from "keycloakify/tools/waitForElementMountedOnDom";
type KcContextLike = {
url: {
@@ -88,6 +89,12 @@ export function useScript(params: { authButtonId: string; kcContext: KcContextLi
return;
}
- insertScriptTags();
+ (async () => {
+ await waitForElementMountedOnDom({
+ elementId: authButtonId
+ });
+
+ insertScriptTags();
+ })();
}, [isFetchingTranslations]);
}
diff --git a/src/tools/waitForElementMountedOnDom.ts b/src/tools/waitForElementMountedOnDom.ts
new file mode 100644
index 00000000..08934f74
--- /dev/null
+++ b/src/tools/waitForElementMountedOnDom.ts
@@ -0,0 +1,30 @@
+export async function waitForElementMountedOnDom(params: {
+ elementId: string;
+}): Promise {
+ const { elementId } = params;
+
+ const getElement = () => document.getElementById(elementId);
+
+ const element = getElement();
+
+ if (element === null) {
+ let prElementPresentInTheDom_resolve: () => void;
+ const prElementPresentInTheDom = new Promise(
+ resolve => (prElementPresentInTheDom_resolve = resolve)
+ );
+
+ // Observe the dom for the element to be added
+ const observer = new MutationObserver(() => {
+ const element = getElement();
+ if (element === null) {
+ return;
+ }
+ observer.disconnect();
+ prElementPresentInTheDom_resolve();
+ });
+
+ observer.observe(document.body, { childList: true, subtree: true });
+
+ await prElementPresentInTheDom;
+ }
+}
From 5ffc42c9db4caa110fc3a3ea174c428cc1285835 Mon Sep 17 00:00:00 2001
From: "allcontributors[bot]"
<46447321+allcontributors[bot]@users.noreply.github.com>
Date: Sat, 19 Oct 2024 00:24:36 +0000
Subject: [PATCH 74/77] docs: update README.md [skip ci]
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index 81228618..9894e35a 100644
--- a/README.md
+++ b/README.md
@@ -164,6 +164,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
 Katharina Eiserfey π» β οΈ π |
 Luca Peruzzo π» β οΈ |
 Nima Shokouhfar π» β οΈ |
+  Marvin A. Ruder π |
From dfe1e7ddd1938f9dc0f6274dc7c94a7d4157b085 Mon Sep 17 00:00:00 2001
From: "allcontributors[bot]"
<46447321+allcontributors[bot]@users.noreply.github.com>
Date: Sat, 19 Oct 2024 00:24:37 +0000
Subject: [PATCH 75/77] docs: update .all-contributorsrc [skip ci]
---
.all-contributorsrc | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/.all-contributorsrc b/.all-contributorsrc
index f7d39edd..64b2924f 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -300,6 +300,15 @@
"code",
"test"
]
+ },
+ {
+ "login": "marvinruder",
+ "name": "Marvin A. Ruder",
+ "avatar_url": "https://avatars.githubusercontent.com/u/18495294?v=4",
+ "profile": "https://mruder.dev",
+ "contributions": [
+ "bug"
+ ]
}
],
"contributorsPerLine": 7,
From e57232edde2b5cfa19892006d4ded4ef2ac16ab3 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Sat, 19 Oct 2024 02:28:11 +0200
Subject: [PATCH 76/77] #694 Probably some shell handle double quote
differently
---
src/bin/start-keycloak/start-keycloak.ts | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/bin/start-keycloak/start-keycloak.ts b/src/bin/start-keycloak/start-keycloak.ts
index e243fe2b..4e74bed6 100644
--- a/src/bin/start-keycloak/start-keycloak.ts
+++ b/src/bin/start-keycloak/start-keycloak.ts
@@ -396,12 +396,12 @@ export async function command(params: {
...(realmJsonFilePath === undefined
? []
: [
- `-v${SPACE_PLACEHOLDER}".${pathSep}${pathRelative(process.cwd(), realmJsonFilePath)}":/opt/keycloak/data/import/myrealm-realm.json`
+ `-v${SPACE_PLACEHOLDER}"${realmJsonFilePath}":/opt/keycloak/data/import/myrealm-realm.json`
]),
- `-v${SPACE_PLACEHOLDER}".${pathSep}${pathRelative(process.cwd(), jarFilePath_cacheDir)}":/opt/keycloak/providers/keycloak-theme.jar`,
+ `-v${SPACE_PLACEHOLDER}"${jarFilePath_cacheDir}":/opt/keycloak/providers/keycloak-theme.jar`,
...extensionJarFilePaths.map(
jarFilePath =>
- `-v${SPACE_PLACEHOLDER}".${pathSep}${pathRelative(process.cwd(), jarFilePath)}":/opt/keycloak/providers/${pathBasename(jarFilePath)}`
+ `-v${SPACE_PLACEHOLDER}"${jarFilePath}":/opt/keycloak/providers/${pathBasename(jarFilePath)}`
),
...(keycloakMajorVersionNumber <= 20
? [`-e${SPACE_PLACEHOLDER}JAVA_OPTS=-Dkeycloak.profile=preview`]
@@ -424,7 +424,7 @@ export async function command(params: {
}))
.map(
({ localDirPath, containerDirPath }) =>
- `-v${SPACE_PLACEHOLDER}".${pathSep}${pathRelative(process.cwd(), localDirPath)}":${containerDirPath}:rw`
+ `-v${SPACE_PLACEHOLDER}"${localDirPath}":${containerDirPath}:rw`
),
...buildContext.environmentVariables
.map(({ name }) => ({ name, envValue: process.env[name] }))
From 0d090d50d4cfdcb8906db8236724807ba42b4cb9 Mon Sep 17 00:00:00 2001
From: Joseph Garrone
Date: Sat, 19 Oct 2024 02:28:32 +0200
Subject: [PATCH 77/77] Bump version
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index ccb76d98..67c0865f 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "keycloakify",
- "version": "11.3.7",
+ "version": "11.3.8",
"description": "Framework to create custom Keycloak UIs",
"repository": {
"type": "git",