Compare commits

...

17 Commits

Author SHA1 Message Date
48501407fc Release v10 🎉 2024-08-26 04:05:40 +02:00
01cbdee2ca Release candidate 2024-08-25 19:02:33 +02:00
b70c0af0a9 Add users to provided realm configuration if none exists 2024-08-25 19:02:00 +02:00
dcaee9cb7f Release candidate 2024-08-25 03:19:58 +02:00
1d8b6c7792 Fix logical error in multivalued attributes 2024-08-25 03:19:34 +02:00
c98dbe84c6 Add missing space before the * 2024-08-25 02:54:46 +02:00
1785916d32 download and extract actually just for downloading and extracting 2024-08-24 23:15:54 +02:00
c6cf564842 Release candidate 2024-08-23 19:01:56 +02:00
380b739017 Don't pin the patch version in the docker tag 2024-08-23 19:01:37 +02:00
c3f3c55303 Release candidate 2024-08-23 18:45:56 +02:00
2c01018529 #618 2024-08-23 18:36:40 +02:00
dd2edf3013 Merge pull request #616 from keycloakify/all-contributors/add-oliviergoulet5
docs: add oliviergoulet5 as a contributor for code
2024-08-22 00:56:15 +02:00
7f3cdf9fac Release candidate 2024-08-22 00:55:39 +02:00
f75a91fbc1 docs: update .all-contributorsrc [skip ci] 2024-08-21 22:55:00 +00:00
f151086bb1 docs: update README.md [skip ci] 2024-08-21 22:54:59 +00:00
7c833e6f10 Merge pull request #615 from oliviergoulet5/fix-array-operations
Fix array comparison and improve type check
2024-08-22 00:53:48 +02:00
885e8314e8 Fix array comparison and type check 2024-08-21 17:13:06 -04:00
11 changed files with 79 additions and 55 deletions

View File

@ -240,6 +240,15 @@
"contributions": [
"code"
]
},
{
"login": "oliviergoulet5",
"name": "Olivier Goulet",
"avatar_url": "https://avatars.githubusercontent.com/u/17685861?v=4",
"profile": "https://github.com/oliviergoulet5",
"contributions": [
"code"
]
}
],
"contributorsPerLine": 7,

View File

@ -43,9 +43,6 @@
Keycloakify is fully compatible with Keycloak 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, [~~22~~](https://github.com/keycloakify/keycloakify/issues/389#issuecomment-1822509763), 23, 24, 25...[and beyond](https://github.com/keycloakify/keycloakify/discussions/346#discussioncomment-5889791)
> NOTE: Keycloakify 10, while still being tagged as release candidate is the version you should use if you are starting today.
> Use `yarn add keycloakify@next` or pin [the latest version candidate](https://www.npmjs.com/package/keycloakify?activeTab=versions).
## Sponsors
Friends for the project, we trust and recommend their services.
@ -132,6 +129,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
<td align="center" valign="top" width="14.28%"><a href="https://github.com/law108000"><img src="https://avatars.githubusercontent.com/u/8112024?v=4?s=100" width="100px;" alt="Rlok"/><br /><sub><b>Rlok</b></sub></a><br /><a href="https://github.com/keycloakify/keycloakify/commits?author=law108000" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Moulyy"><img src="https://avatars.githubusercontent.com/u/115405804?v=4?s=100" width="100px;" alt="Moulyy"/><br /><sub><b>Moulyy</b></sub></a><br /><a href="https://github.com/keycloakify/keycloakify/commits?author=Moulyy" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/madmadson"><img src="https://avatars.githubusercontent.com/u/798831?v=4?s=100" width="100px;" alt="Tobias Matt"/><br /><sub><b>Tobias Matt</b></sub></a><br /><a href="https://github.com/keycloakify/keycloakify/commits?author=madmadson" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/oliviergoulet5"><img src="https://avatars.githubusercontent.com/u/17685861?v=4?s=100" width="100px;" alt="Olivier Goulet"/><br /><sub><b>Olivier Goulet</b></sub></a><br /><a href="https://github.com/keycloakify/keycloakify/commits?author=oliviergoulet5" title="Code">💻</a></td>
</tr>
</tbody>
</table>

View File

@ -1,6 +1,6 @@
{
"name": "keycloakify",
"version": "10.0.0-rc.144",
"version": "10.0.0",
"description": "Create Keycloak themes using React",
"repository": {
"type": "git",

View File

@ -314,8 +314,7 @@ export async function generateResourcesForMainTheme(params: {
}
const { extractedDirPath } = await downloadAndExtractArchive({
urlOrPath:
"https://repo1.maven.org/maven2/org/keycloak/keycloak-account-ui/25.0.1/keycloak-account-ui-25.0.1.jar",
url: "https://repo1.maven.org/maven2/org/keycloak/keycloak-account-ui/25.0.1/keycloak-account-ui-25.0.1.jar",
cacheDirPath: buildContext.cacheDirPath,
fetchOptions: buildContext.fetchOptions,
uniqueIdOfOnArchiveFile: "bring_in_account_v3_i18n_messages",

View File

@ -21,7 +21,7 @@ export async function downloadKeycloakDefaultTheme(params: {
let kcNodeModulesKeepFilePaths_lastAccountV1: Set<string> | undefined = undefined;
const { extractedDirPath } = await downloadAndExtractArchive({
urlOrPath: `https://repo1.maven.org/maven2/org/keycloak/keycloak-themes/${keycloakVersion}/keycloak-themes-${keycloakVersion}.jar`,
url: `https://repo1.maven.org/maven2/org/keycloak/keycloak-themes/${keycloakVersion}/keycloak-themes-${keycloakVersion}.jar`,
cacheDirPath: buildContext.cacheDirPath,
fetchOptions: buildContext.fetchOptions,
uniqueIdOfOnArchiveFile: "downloadKeycloakDefaultTheme",

View File

@ -55,7 +55,7 @@ export async function promptKeycloakVersion(params: {
});
const lastMajorVersions = Array.from(semVersionedTagByMajor.values()).map(
({ tag }) => tag
({ version }) => `${version.major}.${version.minor}`
);
const { value } = await cliSelect<string>({

View File

@ -10,7 +10,8 @@ import {
join as pathJoin,
relative as pathRelative,
sep as pathSep,
basename as pathBasename
basename as pathBasename,
dirname as pathDirname
} from "path";
import * as child_process from "child_process";
import chalk from "chalk";
@ -200,7 +201,7 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
const { archiveFilePath } = await downloadAndExtractArchive({
cacheDirPath: buildContext.cacheDirPath,
fetchOptions: buildContext.fetchOptions,
urlOrPath: extensionJar.url,
url: extensionJar.url,
uniqueIdOfOnArchiveFile: "no extraction",
onArchiveFile: async () => {}
});
@ -211,6 +212,17 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
})
);
const getRealmJsonFilePath_defaultForKeycloakMajor = (
keycloakMajorVersionNumber: number
) =>
pathJoin(
getThisCodebaseRootDirPath(),
"src",
"bin",
"start-keycloak",
`myrealm-realm-${keycloakMajorVersionNumber}.json`
);
const realmJsonFilePath = await (async () => {
if (cliCommandOptions.realmJsonFilePath !== undefined) {
if (cliCommandOptions.realmJsonFilePath === "none") {
@ -231,20 +243,12 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
}
const internalFilePath = await (async () => {
const dirPath = pathJoin(
getThisCodebaseRootDirPath(),
"src",
"bin",
"start-keycloak"
const defaultFilePath = getRealmJsonFilePath_defaultForKeycloakMajor(
keycloakMajorVersionNumber
);
const filePath = pathJoin(
dirPath,
`myrealm-realm-${keycloakMajorVersionNumber}.json`
);
if (fs.existsSync(filePath)) {
return filePath;
if (fs.existsSync(defaultFilePath)) {
return defaultFilePath;
}
console.log(
@ -255,6 +259,8 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
console.log(chalk.cyan("Select what configuration to use:"));
const dirPath = pathDirname(defaultFilePath);
const { value } = await cliSelect<string>({
values: [
...fs
@ -296,6 +302,40 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
return filePath;
})();
add_test_user_if_missing: {
if (realmJsonFilePath === undefined) {
break add_test_user_if_missing;
}
const realm: Record<string, unknown> = JSON.parse(
fs.readFileSync(realmJsonFilePath).toString("utf8")
);
if (realm.users !== undefined) {
break add_test_user_if_missing;
}
const realmJsonFilePath_internal = (() => {
const filePath = getRealmJsonFilePath_defaultForKeycloakMajor(
keycloakMajorVersionNumber
);
if (!fs.existsSync(filePath)) {
return getRealmJsonFilePath_defaultForKeycloakMajor(25);
}
return filePath;
})();
const users = JSON.parse(
fs.readFileSync(realmJsonFilePath_internal).toString("utf8")
).users;
realm.users = users;
fs.writeFileSync(realmJsonFilePath, JSON.stringify(realm, null, 2), "utf8");
}
async function extractThemeResourcesFromJar() {
await extractArchive({
archiveFilePath: jarFilePath,
@ -357,7 +397,7 @@ export async function command(params: { cliCommandOptions: CliCommandOptions })
: [
`-v${SPACE_PLACEHOLDER}".${pathSep}${pathRelative(process.cwd(), realmJsonFilePath)}":/opt/keycloak/data/import/myrealm-realm.json`
]),
`-v${SPACE_PLACEHOLDER}"./${pathRelative(process.cwd(), jarFilePath_cacheDir)}":/opt/keycloak/providers/keycloak-theme.jar`,
`-v${SPACE_PLACEHOLDER}".${pathSep}${pathRelative(process.cwd(), jarFilePath_cacheDir)}":/opt/keycloak/providers/keycloak-theme.jar`,
...extensionJarFilePaths.map(
jarFilePath =>
`-v${SPACE_PLACEHOLDER}".${pathSep}${pathRelative(process.cwd(), jarFilePath)}":/opt/keycloak/providers/${pathBasename(jarFilePath)}`

View File

@ -1,15 +1,14 @@
import fetch, { type FetchOptions } from "make-fetch-happen";
import { mkdir, unlink, writeFile, readdir, readFile } from "fs/promises";
import { dirname as pathDirname, join as pathJoin, basename as pathBasename } from "path";
import { dirname as pathDirname, join as pathJoin } from "path";
import { assert } from "tsafe/assert";
import { extractArchive } from "./extractArchive";
import { existsAsync } from "./fs.existsAsync";
import * as crypto from "crypto";
import { rm } from "./fs.rm";
import * as fsPr from "fs/promises";
export async function downloadAndExtractArchive(params: {
urlOrPath: string;
url: string;
uniqueIdOfOnArchiveFile: string;
onArchiveFile: (params: {
fileRelativePath: string;
@ -22,33 +21,16 @@ export async function downloadAndExtractArchive(params: {
cacheDirPath: string;
fetchOptions: FetchOptions | undefined;
}): Promise<{ extractedDirPath: string; archiveFilePath: string }> {
const {
urlOrPath,
uniqueIdOfOnArchiveFile,
onArchiveFile,
cacheDirPath,
fetchOptions
} = params;
const { url, uniqueIdOfOnArchiveFile, onArchiveFile, cacheDirPath, fetchOptions } =
params;
const isUrl = /^https?:\/\//.test(urlOrPath);
const archiveFileBasename = isUrl
? urlOrPath.split("?")[0].split("/").reverse()[0]
: pathBasename(urlOrPath);
const archiveFileBasename = url.split("?")[0].split("/").reverse()[0];
const archiveFilePath = pathJoin(cacheDirPath, archiveFileBasename);
download: {
await mkdir(pathDirname(archiveFilePath), { recursive: true });
if (!isUrl) {
await fsPr.copyFile(urlOrPath, archiveFilePath);
break download;
}
const url = urlOrPath;
if (await existsAsync(archiveFilePath)) {
const isDownloaded = await SuccessTracker.getIsDownloaded({
cacheDirPath,

View File

@ -58,7 +58,7 @@ export default function UserProfileFormFields(props: UserProfileFormFieldsProps<
<label htmlFor={attribute.name} className={kcClsx("kcLabelClass")}>
{advancedMsg(attribute.displayName ?? "")}
</label>
{attribute.required && <>*</>}
{attribute.required && <> *</>}
</div>
<div className={kcClsx("kcInputWrapperClass")}>
{attribute.annotations.inputHelperTextBefore !== undefined && (

View File

@ -1394,14 +1394,10 @@ export function getButtonToDisplayForMultivaluedAttributeField(params: { attribu
})();
if (maxCount === undefined) {
return false;
return true;
}
if (values.length === maxCount) {
return false;
}
return true;
return values.length !== maxCount;
})();
return { hasRemove, hasAdd };

View File

@ -153,7 +153,7 @@ export default function WebauthnRegister(props: PageProps<Extract<KcContext, { p
function getPubKeyCredParams(signatureAlgorithmsList) {
let pubKeyCredParams = [];
if (signatureAlgorithmsList === []) {
if (signatureAlgorithmsList.length === 0) {
pubKeyCredParams.push({type: "public-key", alg: -7});
return pubKeyCredParams;
}
@ -184,7 +184,7 @@ export default function WebauthnRegister(props: PageProps<Extract<KcContext, { p
}
function getTransportsAsString(transportsList) {
if (transportsList === '' || transportsList.constructor !== Array) return "";
if (transportsList === '' || Array.isArray(transportsList)) return "";
let transportsString = "";