Compare commits

...

23 Commits

Author SHA1 Message Date
Joseph Garrone
d24a8e99cc
Fix badge 2025-04-09 16:33:19 +02:00
Joseph Garrone
59d2d56091
Fix badge 2025-04-09 16:30:27 +02:00
Joseph Garrone
8515b7060a
Merge pull request #833 from keycloakify/all-contributors/add-wnmzzzz
docs: add wnmzzzz as a contributor for test
2025-04-09 16:29:50 +02:00
allcontributors[bot]
a076b3f4d0
docs: update .all-contributorsrc [skip ci] 2025-04-09 14:29:32 +00:00
allcontributors[bot]
1e3240ef35
docs: update README.md [skip ci] 2025-04-09 14:29:31 +00:00
Joseph Garrone
d767080dfe
Merge pull request #831 from wnmzzzz/patch-1
Add Story for AppInitiatedAction to UpdatePassword
2025-04-09 16:29:02 +02:00
wnmzzzz
b228eda488
Add Story for AppInitiatedAction to UpdatePassword 2025-04-07 08:42:46 +02:00
garronej
35f54964ce Bump version 2025-04-04 23:57:42 +02:00
garronej
759b834ccc Follow up on #827 2025-04-04 23:57:13 +02:00
Joseph Garrone
137e12cbbb
Merge pull request #830 from keycloakify/all-contributors/add-kodebach
docs: add kodebach as a contributor for code
2025-04-04 23:57:08 +02:00
allcontributors[bot]
57b08d9dea
docs: update .all-contributorsrc [skip ci] 2025-04-04 21:56:54 +00:00
allcontributors[bot]
1dd7b673a1
docs: update README.md [skip ci] 2025-04-04 21:56:53 +00:00
Joseph Garrone
b00ffc50c3
Merge pull request #827 from kodebach/fix-keycloak-36012
Fix double submit bug in OTP Form
2025-04-04 23:34:01 +02:00
Klemens Böswirth
f9db40d33d fix: https://github.com/keycloak/keycloak/issues/36012
adapted from https://github.com/keycloak/keycloak/pull/36096
2025-04-02 12:08:37 +00:00
Joseph Garrone
4bc6a843d8
Merge pull request #820 from kingjan1999/fix-required-actions-whitespace
fix: add whitespace before required actions in info page
2025-03-21 13:21:02 +01:00
Jan Beckmann
da3e7514f0
fix: add whitespace before required actions in info page 2025-03-21 11:37:08 +01:00
garronej
bc396bc41b Update runPrettier so that it will still work if we ever switch to ESM 2025-03-16 02:17:11 +01:00
garronej
947efe8d63 Bump version 2025-03-16 00:49:08 +01:00
garronej
64189bf8fe #815 2025-03-16 00:48:50 +01:00
garronej
400c630418 Bump version 2025-03-13 22:03:16 +01:00
garronej
402360b436 #814 https://github.com/keycloak/keycloak/issues/38029 2025-03-13 22:03:02 +01:00
garronej
9f001f1521 Bump version 2025-03-13 13:32:23 +01:00
garronej
368e3a32c5 #772 2025-03-13 13:32:08 +01:00
13 changed files with 85 additions and 32 deletions

View File

@ -345,6 +345,24 @@
"contributions": [
"doc"
]
},
{
"login": "kodebach",
"name": "Klemens Böswirth",
"avatar_url": "https://avatars.githubusercontent.com/u/23529132?v=4",
"profile": "https://github.com/kodebach",
"contributions": [
"code"
]
},
{
"login": "wnmzzzz",
"name": "wnmzzzz",
"avatar_url": "https://avatars.githubusercontent.com/u/117174301?v=4",
"profile": "https://github.com/wnmzzzz",
"contributions": [
"test"
]
}
],
"contributorsPerLine": 7,

View File

@ -6,7 +6,7 @@
<br>
<br>
<a href="https://github.com/garronej/keycloakify/actions">
<img src="https://github.com/garronej/keycloakify/workflows/ci/badge.svg?branch=main">
<img src="https://github.com/keycloakify/keycloakify/actions/workflows/ci.yaml/badge.svg">
</a>
<a href="https://www.npmjs.com/package/keycloakify">
<img src="https://img.shields.io/npm/dm/keycloakify">
@ -171,6 +171,8 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
<tr>
<td align="center" valign="top" width="14.28%"><a href="http://t.me/AAT_L"><img src="https://avatars.githubusercontent.com/u/118743608?v=4?s=100" width="100px;" alt="Lesha"/><br /><sub><b>Lesha</b></sub></a><br /><a href="https://github.com/keycloakify/keycloakify/commits?author=EternalSide" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://blog.bacongobbler.com"><img src="https://avatars.githubusercontent.com/u/1360539?v=4?s=100" width="100px;" alt="Matthew Fisher"/><br /><sub><b>Matthew Fisher</b></sub></a><br /><a href="https://github.com/keycloakify/keycloakify/commits?author=bacongobbler" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/kodebach"><img src="https://avatars.githubusercontent.com/u/23529132?v=4?s=100" width="100px;" alt="Klemens Böswirth"/><br /><sub><b>Klemens Böswirth</b></sub></a><br /><a href="https://github.com/keycloakify/keycloakify/commits?author=kodebach" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wnmzzzz"><img src="https://avatars.githubusercontent.com/u/117174301?v=4?s=100" width="100px;" alt="wnmzzzz"/><br /><sub><b>wnmzzzz</b></sub></a><br /><a href="https://github.com/keycloakify/keycloakify/commits?author=wnmzzzz" title="Tests">⚠️</a></td>
</tr>
</tbody>
</table>

View File

@ -1,6 +1,6 @@
{
"name": "keycloakify",
"version": "11.8.19",
"version": "11.8.23",
"description": "Framework to create custom Keycloak UIs",
"repository": {
"type": "git",

View File

@ -18,7 +18,7 @@ export async function command(params: { buildContext: BuildContext }) {
const { buildContext } = params;
const { hasBeenHandled } = await maybeDelegateCommandToCustomHandler({
commandName: "initialize-account-theme",
commandName: "initialize-email-theme",
buildContext
});

View File

@ -45,12 +45,12 @@ export async function getExtensionModuleFileSourceCodeReadyToBeCopied(params: {
`This file has been claimed for ownership from ${extensionModuleName} version ${extensionModuleVersion}.`,
`To relinquish ownership and restore this file to its original content, run the following command:`,
``,
`$ npx keycloakify own --path '${path}' --revert`
`$ npx keycloakify own --path "${path}" --revert`
]
: [
`WARNING: Before modifying this file, run the following command:`,
``,
`$ npx keycloakify own --path '${path}'`,
`$ npx keycloakify own --path "${path}"`,
``,
`This file is provided by ${extensionModuleName} version ${extensionModuleVersion}.`,
`It was copied into your repository by the postinstall script: \`keycloakify sync-extensions\`.`

View File

@ -14,6 +14,8 @@ export function getAbsoluteAndInOsFormatPath(params: {
let pathOut = pathIsh;
pathOut = pathOut.replace(/^['"]/, "").replace(/['"]$/, "");
pathOut = pathOut.replace(/\//g, pathSep);
if (pathOut.startsWith("~")) {

View File

@ -52,10 +52,26 @@ export async function getPrettier(): Promise<PrettierAndConfigHash> {
// So we do a sketchy eval to bypass ncc.
// We make sure to only do that when linking, otherwise we import properly.
if (readThisNpmPackageVersion().startsWith("0.0.0")) {
eval(
`${symToStr({ prettier })} = require("${pathResolve(pathJoin(getNodeModulesBinDirPath({ packageJsonFilePath: undefined }), "..", "prettier"))}")`
const prettierDirPath = pathResolve(
pathJoin(
getNodeModulesBinDirPath({ packageJsonFilePath: undefined }),
"..",
"prettier"
)
);
const isCJS = typeof module !== "undefined" && module.exports;
if (isCJS) {
eval(`${symToStr({ prettier })} = require("${prettierDirPath}")`);
} else {
prettier = await new Promise(_resolve => {
eval(
`import("file:///${pathJoin(prettierDirPath, "index.mjs").replace(/\\/g, "/")}").then(prettier => _resolve(prettier))`
);
});
}
assert(!is<undefined>(prettier));
break import_prettier;

View File

@ -90,7 +90,6 @@ export default function UserProfileFormFields(props: UserProfileFormFieldsProps<
{advancedMsg(attribute.annotations.inputHelperTextAfter)}
</div>
)}
{AfterField !== undefined && (
<AfterField
attribute={attribute}
@ -107,6 +106,10 @@ export default function UserProfileFormFields(props: UserProfileFormFieldsProps<
</Fragment>
);
})}
{/* See: https://github.com/keycloak/keycloak/issues/38029 */}
{kcContext.locale !== undefined && formFieldStates.find(x => x.attribute.name === "locale") === undefined && (
<input type="hidden" name="locale" value={i18n.currentLanguage.languageTag} />
)}
</>
);
}

View File

@ -217,25 +217,6 @@ export function createGetI18n<
return enabledLanguages;
})();
// See: https://github.com/keycloak/keycloak/issues/38029
patch_keycloak_issue_38029: {
const enabledLanguage_current = enabledLanguages.find(({ languageTag }) => languageTag === currentLanguage.languageTag);
assert(enabledLanguage_current !== undefined);
if (!enabledLanguage_current.href.includes("kc_locale=")) {
// NOTE: Probably a mock
break patch_keycloak_issue_38029;
}
// NOTE: Best effort, we don't wait for it to be done
// and we don't handle errors
fetch(enabledLanguage_current.href).then(
() => {},
() => {}
);
}
const { createI18nTranslationFunctions } = createI18nTranslationFunctionsFactory<MessageKey_themeDefined>({
themeName: kcContext.themeName,
messages_themeDefined:

View File

@ -31,10 +31,10 @@ export default function Info(props: PageProps<Extract<KcContext, { pageId: "info
dangerouslySetInnerHTML={{
__html: kcSanitize(
(() => {
let html = message.summary;
let html = message.summary?.trim();
if (requiredActions) {
html += "<b>";
html += " <b>";
html += requiredActions.map(requiredAction => advancedMsgStr(`requiredAction.${requiredAction}`)).join(", ");

View File

@ -1,4 +1,4 @@
import { Fragment } from "react";
import { Fragment, useState } from "react";
import { getKcClsx } from "keycloakify/login/lib/kcClsx";
import { kcSanitize } from "keycloakify/lib/kcSanitize";
import type { PageProps } from "keycloakify/login/pages/PageProps";
@ -17,6 +17,8 @@ export default function LoginOtp(props: PageProps<Extract<KcContext, { pageId: "
const { msg, msgStr } = i18n;
const [isSubmitting, setIsSubmitting] = useState(false);
return (
<Template
kcContext={kcContext}
@ -26,7 +28,16 @@ export default function LoginOtp(props: PageProps<Extract<KcContext, { pageId: "
displayMessage={!messagesPerField.existsError("totp")}
headerNode={msg("doLogIn")}
>
<form id="kc-otp-login-form" className={kcClsx("kcFormClass")} action={url.loginAction} method="post">
<form
id="kc-otp-login-form"
className={kcClsx("kcFormClass")}
action={url.loginAction}
onSubmit={() => {
setIsSubmitting(true);
return true;
}}
method="post"
>
{otpLogin.userOtpCredentials.length > 1 && (
<div className={kcClsx("kcFormGroupClass")}>
<div className={kcClsx("kcInputWrapperClass")}>
@ -94,6 +105,7 @@ export default function LoginOtp(props: PageProps<Extract<KcContext, { pageId: "
id="kc-login"
type="submit"
value={msgStr("doLogIn")}
disabled={isSubmitting}
/>
</div>
</div>

View File

@ -46,7 +46,7 @@ export const WithRequiredActions: Story = {
kcContext={{
messageHeader: "Message header",
message: {
summary: "Required actions: "
summary: "Required actions:"
},
requiredActions: ["CONFIGURE_TOTP", "UPDATE_PROFILE", "VERIFY_EMAIL", "CUSTOM_ACTION"],
"x-keycloakify": {

View File

@ -62,3 +62,22 @@ export const WithPasswordConfirmError: Story = {
/>
)
};
/**
* WithAppInitiatedAction:
* - Purpose: Tests when the update password action was triggered by an app.
* - Scenario: Simulates the case where the user presses a 'change password' button in an app and is redirected to Keycloak to change it.
* - Key Aspect: Ensures the 'Cancel' button is shown correctly, which displays only when the action is app initiated.
*/
export const WithAppInitiatedAction: Story = {
render: () => (
<KcPageStory
kcContext={{
url: {
loginAction: "/mock-login-action"
},
isAppInitiatedAction: true
}}
/>
)
};