Compare commits

...

18 Commits

11 changed files with 83 additions and 20 deletions

View File

@ -3,7 +3,7 @@ on:
push: push:
branches: branches:
- main - main
- v* - v8
pull_request: pull_request:
branches: branches:
- main - main

View File

@ -47,12 +47,12 @@
> 📣 🛑 Account themes generated by Keycloakify are not currently compatible with Keycloak 22. > 📣 🛑 Account themes generated by Keycloakify are not currently compatible with Keycloak 22.
> We are working on a solution. [Follow progress](https://github.com/keycloakify/keycloakify/issues/389). > We are working on a solution. [Follow progress](https://github.com/keycloakify/keycloakify/issues/389).
> Login and email themes are not affected. > **Login and email themes are not affected**.
> UPDATE: [The PR](https://github.com/keycloak/keycloak/pull/22317) that should future proof Keycloakify account themes has been greenlighted > UPDATE: [The PR](https://github.com/keycloak/keycloak/pull/22317) that should future proof Keycloakify account themes has been
> by the Keycloak team. Resolution is only a matter of time. > merged into Keycloak! 🥳 Credit to @xgp. We are now waiting for a new Keycloak release to be published.
Keycloakify is fully compatible with Keycloak, starting from version 11 and is anticipated to maintain compatibility with all future versions. Keycloakify is fully compatible with Keycloak, starting from version 11 and is anticipated to maintain compatibility with all future versions.
You can update your Keycloak, your Keycloakify generated theme won't break. You can update your Keycloak, your Keycloakify generated theme won't break. (Well except for Keycloak 22's Account theme obviously but this was hopefully a one time debacle)
To understand the basis of my confidence in this, you can [visit this discussion thread where I've explained in detail](https://github.com/keycloakify/keycloakify/discussions/346#discussioncomment-5889791). To understand the basis of my confidence in this, you can [visit this discussion thread where I've explained in detail](https://github.com/keycloakify/keycloakify/discussions/346#discussioncomment-5889791).
## Sponsor 👼 ## Sponsor 👼

View File

@ -1,6 +1,6 @@
{ {
"name": "keycloakify", "name": "keycloakify",
"version": "8.3.0", "version": "8.4.3",
"description": "Create Keycloak themes using React", "description": "Create Keycloak themes using React",
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -6,6 +6,7 @@ export type KcContext = KcContext.Password | KcContext.Account;
export declare namespace KcContext { export declare namespace KcContext {
export type Common = { export type Common = {
themeVersion: string;
keycloakifyVersion: string; keycloakifyVersion: string;
themeType: "account"; themeType: "account";
themeName: string; themeName: string;

View File

@ -7,6 +7,7 @@ import type { KcContext } from "./KcContext";
const PUBLIC_URL = (typeof process !== "object" ? undefined : process.env?.["PUBLIC_URL"]) || "/"; const PUBLIC_URL = (typeof process !== "object" ? undefined : process.env?.["PUBLIC_URL"]) || "/";
export const kcContextCommonMock: KcContext.Common = { export const kcContextCommonMock: KcContext.Common = {
"themeVersion": "0.0.0",
"keycloakifyVersion": "0.0.0", "keycloakifyVersion": "0.0.0",
"themeType": "account", "themeType": "account",
"themeName": "my-theme-name", "themeName": "my-theme-name",

View File

@ -408,6 +408,14 @@
out["themeName"] = "KEYCLOAKIFY_THEME_NAME_cXxKd3xEer"; out["themeName"] = "KEYCLOAKIFY_THEME_NAME_cXxKd3xEer";
out["pageId"] = "${pageId}"; out["pageId"] = "${pageId}";
try {
out["url"]["resourcesCommonPath"] = out["url"]["resourcesPath"] + "/" + "RESOURCES_COMMON_cLsLsMrtDkpVv";
} catch(error) {
}
return out; return out;
})() })()
@ -423,7 +431,7 @@
<#if isHash> <#if isHash>
<#if path?size gt 10> <#if path?size gt 10>
<#return "ABORT: Too many recursive calls"> <#return "ABORT: Too many recursive calls, path: " + path?join(".")>
</#if> </#if>
<#local keys = ""> <#local keys = "">
@ -455,9 +463,10 @@
<#-- https://github.com/keycloakify/keycloakify/issues/91#issue-1212319466 (reports with error.ftl and Kc18) --> <#-- https://github.com/keycloakify/keycloakify/issues/91#issue-1212319466 (reports with error.ftl and Kc18) -->
<#-- https://github.com/keycloakify/keycloakify/issues/109#issuecomment-1134610163 --> <#-- https://github.com/keycloakify/keycloakify/issues/109#issuecomment-1134610163 -->
<#-- https://github.com/keycloakify/keycloakify/issues/357 --> <#-- https://github.com/keycloakify/keycloakify/issues/357 -->
<#-- https://github.com/keycloakify/keycloakify/discussions/406#discussioncomment-7514787 -->
key == "loginAction" && key == "loginAction" &&
are_same_path(path, ["url"]) && are_same_path(path, ["url"]) &&
["saml-post-form.ftl", "error.ftl", "info.ftl", "login-oauth-grant.ftl", "logout-confirm.ftl"]?seq_contains(pageId) && ["saml-post-form.ftl", "error.ftl", "info.ftl", "login-oauth-grant.ftl", "logout-confirm.ftl", "login-oauth2-device-verify-user-code.ftl"]?seq_contains(pageId) &&
!(auth?has_content && auth.showTryAnotherWayLink()) !(auth?has_content && auth.showTryAnotherWayLink())
) || ( ) || (
<#-- https://github.com/keycloakify/keycloakify/issues/362 --> <#-- https://github.com/keycloakify/keycloakify/issues/362 -->
@ -480,24 +489,33 @@
!["name", "displayName", "displayNameHtml", "internationalizationEnabled", "registrationEmailAsUsername" ]?seq_contains(key) !["name", "displayName", "displayNameHtml", "internationalizationEnabled", "registrationEmailAsUsername" ]?seq_contains(key)
) || ( ) || (
"applications.ftl" == pageId && "applications.ftl" == pageId &&
are_same_path(path, ["applications", "applications", "*", "client", "realm"]) is_subpath(path, ["applications", "applications"]) &&
(
key == "realm" ||
key == "container"
)
) || ( ) || (
"applications.ftl" == pageId && are_same_path(path, ["user"]) &&
"masterAdminClient" == key key == "delegateForUpdate"
) )
> >
<#local out_seq += ["/*If you need '" + key + "' on " + pageId + ", please submit an issue to the Keycloakify repo*/"]> <#local out_seq += ["/*If you need '" + path?join(".") + "." + key + "' on " + pageId + ", please submit an issue to the Keycloakify repo*/"]>
<#continue> <#continue>
</#if> </#if>
<#if pageId == "register.ftl" && key == "attemptedUsername" && are_same_path(path, ["auth"])> <#-- https://github.com/keycloakify/keycloakify/discussions/406 -->
<#if (
["register.ftl", "info.ftl", "login.ftl", "login-update-password.ftl", "login-oauth2-device-verify-user-code.ftl"]?seq_contains(pageId) &&
key == "attemptedUsername" && are_same_path(path, ["auth"])
)>
<#attempt> <#attempt>
<#-- https://github.com/keycloak/keycloak/blob/3a2bf0c04bcde185e497aaa32d0bb7ab7520cf4a/themes/src/main/resources/theme/base/login/template.ftl#L63 --> <#-- https://github.com/keycloak/keycloak/blob/3a2bf0c04bcde185e497aaa32d0bb7ab7520cf4a/themes/src/main/resources/theme/base/login/template.ftl#L63 -->
<#-- https://github.com/keycloakify/keycloakify/discussions/406 -->
<#if !(auth?has_content && auth.showUsername() && !auth.showResetCredentials())> <#if !(auth?has_content && auth.showUsername() && !auth.showResetCredentials())>
<#local out_seq += ["/*If you need '" + key + "' on " + pageId + ", please submit an issue to the Keycloakify repo*/"]>
<#continue> <#continue>
</#if> </#if>
<#recover> <#recover>
<#local out_seq += ["/*Testing if attemptedUsername should be skipped throwed an exception */"]>
</#attempt> </#attempt>
</#if> </#if>
@ -650,9 +668,9 @@
<#return "ABORT: Couldn't convert into string non hash, non method, non boolean, non enumerable object"> <#return "ABORT: Couldn't convert into string non hash, non method, non boolean, non enumerable object">
</#function> </#function>
<#function are_same_path path searchedPath> <#function is_subpath path searchedPath>
<#if path?size != searchedPath?size> <#if path?size < searchedPath?size>
<#return false> <#return false>
</#if> </#if>
@ -660,8 +678,14 @@
<#list path as property> <#list path as property>
<#if i == searchedPath?size >
<#continue>
</#if>
<#local searchedProperty=searchedPath[i]> <#local searchedProperty=searchedPath[i]>
<#local i+= 1>
<#if searchedProperty?is_string && searchedProperty == "*"> <#if searchedProperty?is_string && searchedProperty == "*">
<#continue> <#continue>
</#if> </#if>
@ -678,11 +702,13 @@
<#return false> <#return false>
</#if> </#if>
<#local i+= 1>
</#list> </#list>
<#return true> <#return true>
</#function> </#function>
<#function are_same_path path searchedPath>
<#return path?size == searchedPath?size && is_subpath(path, searchedPath)>
</#function>
</script> </script>

View File

@ -124,6 +124,27 @@ export function generateFtlFilesCodeFactory(params: {
].join("\n") ].join("\n")
); );
// Remove part of the document marked as ignored.
{
const startTags = $('meta[name="keycloakify-ignore-start"]');
startTags.each((...[, startTag]) => {
const $startTag = $(startTag);
const $endTag = $startTag.nextAll('meta[name="keycloakify-ignore-end"]').first();
if ($endTag.length) {
let currentNode = $startTag.next();
while (currentNode.length && !currentNode.is($endTag)) {
currentNode.remove();
currentNode = $startTag.next();
}
$startTag.remove();
$endTag.remove();
}
});
}
const partiallyFixedIndexHtmlCode = $.html(); const partiallyFixedIndexHtmlCode = $.html();
function generateFtlFilesCode(params: { pageId: string }): { function generateFtlFilesCode(params: { pageId: string }): {

View File

@ -39,6 +39,7 @@ export type KcContext =
export declare namespace KcContext { export declare namespace KcContext {
export type Common = { export type Common = {
themeVersion: string;
keycloakifyVersion: string; keycloakifyVersion: string;
themeType: "login"; themeType: "login";
themeName: string; themeName: string;

View File

@ -103,6 +103,7 @@ const attributes: Attribute[] = [
const attributesByName = Object.fromEntries(attributes.map(attribute => [attribute.name, attribute])) as any; const attributesByName = Object.fromEntries(attributes.map(attribute => [attribute.name, attribute])) as any;
export const kcContextCommonMock: KcContext.Common = { export const kcContextCommonMock: KcContext.Common = {
"themeVersion": "0.0.0",
"keycloakifyVersion": "0.0.0", "keycloakifyVersion": "0.0.0",
"themeType": "login", "themeType": "login",
"themeName": "my-theme-name", "themeName": "my-theme-name",

View File

@ -8,7 +8,10 @@ export default function Info(props: PageProps<Extract<KcContext, { pageId: "info
const { msgStr, msg } = i18n; const { msgStr, msg } = i18n;
assert(kcContext.message !== undefined); assert(
kcContext.message !== undefined,
"No message in kcContext.message, there will always be a message in production context, add it in your mock"
);
const { messageHeader, message, requiredActions, skipLink, pageRedirectUri, actionUri, client } = kcContext; const { messageHeader, message, requiredActions, skipLink, pageRedirectUri, actionUri, client } = kcContext;

View File

@ -21,4 +21,13 @@ const meta: ComponentMeta<any> = {
export default meta; export default meta;
export const Default = () => <PageStory />; export const Default = () => (
<PageStory
kcContext={{
message: {
summary: "This is the server message",
type: "info"
}
}}
/>
);