314 lines
8.9 KiB
TypeScript
Raw Normal View History

2024-12-13 09:07:11 +01:00
import { assert } from "tsafe/assert";
import type { ParsedRealmJson } from "./ParsedRealmJson";
import { getDefaultConfig } from "./defaultConfig";
import type { BuildContext } from "../../shared/buildContext";
import { objectKeys } from "tsafe/objectKeys";
export type BuildContextLike = {
themeNames: BuildContext["themeNames"];
implementedThemeTypes: BuildContext["implementedThemeTypes"];
};
assert<BuildContext extends BuildContextLike ? true : false>;
2024-12-13 09:07:11 +01:00
2024-12-13 12:16:41 +01:00
export function prepareRealmConfig(params: {
parsedRealmJson: ParsedRealmJson;
keycloakMajorVersionNumber: number;
buildContext: BuildContextLike;
2024-12-13 12:16:41 +01:00
}): {
realmName: string;
clientName: string;
username: string;
} {
const { parsedRealmJson, keycloakMajorVersionNumber, buildContext } = params;
2024-12-13 12:16:41 +01:00
const { username } = addOrEditTestUser({
parsedRealmJson,
keycloakMajorVersionNumber
});
const { clientId } = addOrEditClient({
parsedRealmJson,
keycloakMajorVersionNumber
});
editAccountConsoleAndSecurityAdminConsole({ parsedRealmJson });
enableCustomThemes({
parsedRealmJson,
themeName: buildContext.themeNames[0],
implementedThemeTypes: buildContext.implementedThemeTypes
});
enable_custom_events_listeners: {
const name = "keycloakify-logging";
if (parsedRealmJson.eventsListeners.includes(name)) {
break enable_custom_events_listeners;
}
parsedRealmJson.eventsListeners.push(name);
}
2024-12-13 12:16:41 +01:00
return {
realmName: parsedRealmJson.name,
clientName: clientId,
username
};
}
function enableCustomThemes(params: {
parsedRealmJson: ParsedRealmJson;
themeName: string;
implementedThemeTypes: BuildContextLike["implementedThemeTypes"];
}) {
const { parsedRealmJson, themeName, implementedThemeTypes } = params;
for (const themeType of objectKeys(implementedThemeTypes)) {
parsedRealmJson[`${themeType}Theme` as const] = implementedThemeTypes[themeType]
.isImplemented
? themeName
: "";
}
}
2024-12-13 09:07:11 +01:00
function addOrEditTestUser(params: {
parsedRealmJson: ParsedRealmJson;
keycloakMajorVersionNumber: number;
}): { username: string } {
const { parsedRealmJson, keycloakMajorVersionNumber } = params;
const parsedRealmJson_default = getDefaultConfig({ keycloakMajorVersionNumber });
const [defaultUser_default] = parsedRealmJson_default.users;
assert(defaultUser_default !== undefined);
const defaultUser_preexisting = parsedRealmJson.users.find(
user => user.username === defaultUser_default.username
);
const newUser = structuredClone(
defaultUser_preexisting ??
(() => {
const firstUser = parsedRealmJson.users[0];
if (firstUser === undefined) {
return undefined;
}
const firstUserCopy = structuredClone(firstUser);
firstUserCopy.id = defaultUser_default.id;
return firstUserCopy;
})() ??
defaultUser_default
);
newUser.username = defaultUser_default.username;
newUser.email = defaultUser_default.email;
delete_existing_password_credential_if_any: {
const i = newUser.credentials.findIndex(
credential => credential.type === "password"
);
if (i === -1) {
break delete_existing_password_credential_if_any;
}
newUser.credentials.splice(i, 1);
}
{
const credential = defaultUser_default.credentials.find(
credential => credential.type === "password"
);
assert(credential !== undefined);
newUser.credentials.push(credential);
}
{
const nameByClientId = Object.fromEntries(
parsedRealmJson.clients.map(client => [client.id, client.clientId] as const)
);
newUser.clientRoles = {};
for (const clientRole of parsedRealmJson.roles.client) {
const clientName = nameByClientId[clientRole.containerId];
assert(clientName !== undefined);
(newUser.clientRoles[clientName] ??= []).push(clientRole.name);
}
}
if (defaultUser_preexisting === undefined) {
parsedRealmJson.users.push(newUser);
} else {
const i = parsedRealmJson.users.indexOf(defaultUser_preexisting);
assert(i !== -1);
parsedRealmJson.users[i] = newUser;
}
return { username: newUser.username };
}
const TEST_APP_URL = "https://my-theme.keycloakify.dev";
function addOrEditClient(params: {
parsedRealmJson: ParsedRealmJson;
keycloakMajorVersionNumber: number;
}): { clientId: string } {
const { parsedRealmJson, keycloakMajorVersionNumber } = params;
const parsedRealmJson_default = getDefaultConfig({ keycloakMajorVersionNumber });
const testClient_default = (() => {
const clients = parsedRealmJson_default.clients.filter(client => {
return JSON.stringify(client).includes(TEST_APP_URL);
});
assert(clients.length === 1);
return clients[0];
})();
const clientIds_builtIn = parsedRealmJson_default.clients
.map(client => client.clientId)
.filter(clientId => clientId !== testClient_default.clientId);
const testClient_preexisting = (() => {
const clients = parsedRealmJson.clients
.filter(client => !clientIds_builtIn.includes(client.clientId))
.filter(client => client.protocol === "openid-connect");
{
const client = clients.find(
client => client.clientId === testClient_default.clientId
);
if (client !== undefined) {
return client;
}
}
{
const client = clients.find(
client =>
client.redirectUris?.find(redirectUri =>
redirectUri.startsWith(TEST_APP_URL)
) !== undefined
);
if (client !== undefined) {
return client;
}
}
const [client] = clients;
if (client === undefined) {
return undefined;
}
return client;
})();
let testClient: typeof testClient_default;
if (testClient_preexisting !== undefined) {
testClient = testClient_preexisting;
} else {
testClient = structuredClone(testClient_default);
delete testClient.protocolMappers;
parsedRealmJson.clients.push(testClient);
}
{
for (const redirectUri of [
`${TEST_APP_URL}/*`,
"http://localhost*",
"http://127.0.0.1*"
]) {
for (const propertyName of ["webOrigins", "redirectUris"] as const) {
const arr = (testClient[propertyName] ??= []);
if (arr.includes(redirectUri)) {
continue;
}
arr.push(redirectUri);
}
{
if (testClient.attributes === undefined) {
testClient.attributes = {};
}
const arr = (testClient.attributes["post.logout.redirect.uris"] ?? "")
.split("##")
.map(s => s.trim());
if (!arr.includes(redirectUri)) {
arr.push(redirectUri);
testClient.attributes["post.logout.redirect.uris"] = arr.join("##");
}
}
}
}
return { clientId: testClient.clientId };
}
function editAccountConsoleAndSecurityAdminConsole(params: {
parsedRealmJson: ParsedRealmJson;
}) {
const { parsedRealmJson } = params;
for (const clientId of ["account-console", "security-admin-console"]) {
const client = parsedRealmJson.clients.find(
client => client.clientId === clientId
);
assert(client !== undefined);
{
for (const redirectUri of [
`${TEST_APP_URL}/*`,
"http://localhost*",
"http://127.0.0.1*"
]) {
for (const propertyName of ["webOrigins", "redirectUris"] as const) {
const arr = (client[propertyName] ??= []);
if (arr.includes(redirectUri)) {
continue;
}
arr.push(redirectUri);
}
{
if (client.attributes === undefined) {
client.attributes = {};
}
const arr = (client.attributes["post.logout.redirect.uris"] ?? "")
.split("##")
.map(s => s.trim());
if (!arr.includes(redirectUri)) {
arr.push(redirectUri);
client.attributes["post.logout.redirect.uris"] = arr.join("##");
}
}
}
}
}
}