many small fixes

This commit is contained in:
Joseph Garrone
2021-03-08 00:09:52 +01:00
parent b93003e76d
commit 12e83c9468
16 changed files with 298 additions and 106 deletions

View File

@ -11,6 +11,7 @@ import { builtinThemesUrl } from "../install-builtin-keycloak-themes";
import { downloadAndUnzip } from "../tools/downloadAndUnzip";
import * as child_process from "child_process";
import { ftlValuesGlobalName } from "./ftlValuesGlobalName";
import { resourcesCommonPath, resourcesPath, subDirOfPublicDirBasename } from "../../lib/kcMockContext/urlResourcesPath";
export function generateKeycloakThemeResources(
params: {
@ -90,11 +91,54 @@ export function generateKeycloakThemeResources(
"destDirPath": tmpDirPath
});
const themeResourcesDirPath= pathJoin(themeDirPath, "resources");
transformCodebase({
"srcDirPath": pathJoin(tmpDirPath, "keycloak", "login", "resources"),
"destDirPath": pathJoin(themeDirPath, "resources")
"destDirPath": themeResourcesDirPath
});
//const keycloakResourcesWithinPublicDirPath = pathJoin(reactAppBuildDirPath, "..", "public", "keycloak_static");
const reactAppPublicDirPath = pathJoin(reactAppBuildDirPath, "..", "public");
transformCodebase({
"srcDirPath": themeResourcesDirPath,
"destDirPath": pathJoin(
reactAppPublicDirPath,
resourcesPath
)
});
transformCodebase({
"srcDirPath": pathJoin(tmpDirPath, "keycloak", "common", "resources"),
"destDirPath": pathJoin(
reactAppPublicDirPath,
resourcesCommonPath
)
});
const keycloakResourcesWithinPublicDirPath =
pathJoin(reactAppPublicDirPath, subDirOfPublicDirBasename);
fs.writeFileSync(
pathJoin(keycloakResourcesWithinPublicDirPath, ".gitignore"),
Buffer.from([
resourcesPath,
resourcesCommonPath
].join("\n"))
);
fs.writeFileSync(
pathJoin(keycloakResourcesWithinPublicDirPath, "README.txt"),
Buffer.from([
"This is just a test folder that helps develop",
"the login and register page without having to yarn build"
].join(" "))
);
child_process.execSync(`rm -r ${tmpDirPath}`);
}

View File

@ -3,24 +3,20 @@ import { memo } from "react";
import { Template } from "./Template";
import type { KcProps } from "./KcProps";
import { assert } from "../tools/assert";
import { kcContext } from "../kcContext";
import type { KcContext } from "../KcContext";
import { useKcMessage } from "../i18n/useKcMessage";
export const Error = memo((props: KcProps) => {
export const Error = memo(({ kcContext, ...props }: { kcContext: KcContext.Error; } & KcProps) => {
const { msg } = useKcMessage();
assert(
kcContext !== undefined &&
kcContext.pageId === "error.ftl" &&
kcContext.message !== undefined
);
assert(kcContext.message !== undefined);
const { message, client } = kcContext;
return (
<Template
{...props}
{...{ kcContext, ...props }}
displayMessage={false}
headerNode={msg("errorTitle")}
formNode={

View File

@ -3,18 +3,14 @@ import { memo } from "react";
import { Template } from "./Template";
import type { KcProps } from "./KcProps";
import { assert } from "../tools/assert";
import { kcContext } from "../kcContext";
import type { KcContext } from "../KcContext";
import { useKcMessage } from "../i18n/useKcMessage";
export const Info = memo((props: KcProps) => {
export const Info = memo(({ kcContext, ...props }: { kcContext: KcContext.Info; } & KcProps) => {
const { msg } = useKcMessage();
assert(
kcContext !== undefined &&
kcContext.pageId === "info.ftl" &&
kcContext.message !== undefined
);
assert(kcContext.message !== undefined);
const {
messageHeader,
@ -28,7 +24,7 @@ export const Info = memo((props: KcProps) => {
return (
<Template
{...props}
{...{ kcContext, ...props }}
displayMessage={false}
headerNode={
messageHeader !== undefined ?

View File

@ -1,7 +1,6 @@
import { memo } from "react";
import { kcContext } from "../kcContext";
import { assert } from "../tools/assert";
import type { KcContext } from "../KcContext";
import type { KcProps } from "./KcProps";
import { Login } from "./Login";
import { Register } from "./Register";
@ -10,17 +9,13 @@ import { Error } from "./Error";
import { LoginResetPassword } from "./LoginResetPassword";
import { LoginVerifyEmail } from "./LoginVerifyEmail";
export const KcApp = memo((props: KcProps) => {
assert(kcContext !== undefined, "App is not currently served by a Keycloak server");
export const KcApp = memo(({ kcContext, ...props }: { kcContext: KcContext; } & KcProps ) => {
switch (kcContext.pageId) {
case "login.ftl": return <Login {...props} />;
case "register.ftl": return <Register {...props} />;
case "info.ftl": return <Info {...props} />;
case "error.ftl": return <Error {...props} />;
case "login-reset-password.ftl": return <LoginResetPassword {...props} />;
case "login-verify-email.ftl": return <LoginVerifyEmail {...props} />;
case "login.ftl": return <Login {...{ kcContext, ...props }} />;
case "register.ftl": return <Register {...{ kcContext, ...props }} />;
case "info.ftl": return <Info {...{ kcContext, ...props }} />;
case "error.ftl": return <Error {...{ kcContext, ...props }} />;
case "login-reset-password.ftl": return <LoginResetPassword {...{ kcContext, ...props }} />;
case "login-verify-email.ftl": return <LoginVerifyEmail {...{ kcContext, ...props }} />;
}
});

View File

@ -2,21 +2,15 @@
import { useState, memo } from "react";
import { Template } from "./Template";
import type { KcProps } from "./KcProps";
import { assert } from "../tools/assert";
import { kcContext } from "../kcContext";
import type { KcContext } from "../KcContext";
import { useKcMessage } from "../i18n/useKcMessage";
import { cx } from "tss-react";
import { useConstCallback } from "powerhooks";
export const Login = memo((props: KcProps) => {
export const Login = memo(({ kcContext, ...props }: { kcContext: KcContext.Login; } & KcProps) => {
const { msg, msgStr } = useKcMessage();
assert(
kcContext !== undefined &&
kcContext.pageId === "login.ftl"
);
const {
social, realm, url,
usernameEditDisabled, login,
@ -31,7 +25,7 @@ export const Login = memo((props: KcProps) => {
return (
<Template
{...props}
{...{ kcContext, ...props }}
displayInfo={social.displayInfo}
displayWide={realm.password && social.providers !== undefined}
headerNode={msg("doLogIn")}
@ -68,7 +62,7 @@ export const Login = memo((props: KcProps) => {
name="username"
defaultValue={login.username ?? ''}
type="text"
{...(usernameEditDisabled ? { "disabled": true } : { "autoFocus": true, "autocomplete": "off" })}
{...(usernameEditDisabled ? { "disabled": true } : { "autoFocus": true, "autoComplete": "off" })}
/>
</div>
<div className={cx(props.kcFormGroupClass)}>

View File

@ -2,20 +2,14 @@
import { memo } from "react";
import { Template } from "./Template";
import type { KcProps } from "./KcProps";
import { assert } from "../tools/assert";
import { kcContext } from "../kcContext";
import type { KcContext } from "../KcContext";
import { useKcMessage } from "../i18n/useKcMessage";
import { cx } from "tss-react";
export const LoginResetPassword = memo((props: KcProps) => {
export const LoginResetPassword = memo(({ kcContext, ...props }: { kcContext: KcContext.LoginResetPassword; } & KcProps) => {
const { msg, msgStr } = useKcMessage();
assert(
kcContext !== undefined &&
kcContext.pageId === "login-reset-password.ftl"
);
const {
url,
realm,
@ -24,7 +18,7 @@ export const LoginResetPassword = memo((props: KcProps) => {
return (
<Template
{...props}
{...{ kcContext, ...props }}
displayMessage={false}
headerNode={msg("emailForgotTitle")}
formNode={

View File

@ -2,26 +2,20 @@
import { memo } from "react";
import { Template } from "./Template";
import type { KcProps } from "./KcProps";
import { assert } from "../tools/assert";
import { kcContext } from "../kcContext";
import type { KcContext } from "../KcContext";
import { useKcMessage } from "../i18n/useKcMessage";
export const LoginVerifyEmail = memo((props: KcProps) => {
export const LoginVerifyEmail = memo(({ kcContext, ...props }: { kcContext: KcContext.LoginVerifyEmail; } & KcProps) => {
const { msg } = useKcMessage();
assert(
kcContext !== undefined &&
kcContext.pageId === "login-verify-email.ftl"
);
const {
url
} = kcContext;
return (
<Template
{...props}
{...{ kcContext, ...props }}
displayMessage={false}
headerNode={msg("emailVerifyTitle")}
formNode={

View File

@ -1,20 +1,14 @@
import { memo } from "react";
import { Template } from "./Template";
import type { KcProps } from "./KcProps";
import { assert } from "../tools/assert";
import { kcContext } from "../kcContext";
import type { KcContext } from "../KcContext";
import { useKcMessage } from "../i18n/useKcMessage";
import { cx } from "tss-react";
export const Register = memo((props: KcProps) => {
export const Register = memo(({ kcContext, ...props }: { kcContext: KcContext.Register; } & KcProps) => {
const { msg, msgStr } = useKcMessage();
assert(
kcContext !== undefined &&
kcContext.pageId === "register.ftl"
);
const {
url,
messagesPerField,
@ -27,7 +21,7 @@ export const Register = memo((props: KcProps) => {
return (
<Template
{...props}
{...{ kcContext, ...props }}
headerNode={msg("registerTitle")}
formNode={
<form id="kc-register-form" className={cx(props.kcFormClass)} action={url.registrationAction} method="post">

View File

@ -3,7 +3,7 @@ import { useReducer, useEffect, memo } from "react";
import type { ReactNode } from "react";
import { useKcMessage } from "../i18n/useKcMessage";
import { useKcLanguageTag } from "../i18n/useKcLanguageTag";
import { kcContext } from "../kcContext";
import type { KcContext } from "../KcContext";
import { assert } from "../tools/assert";
import { cx } from "tss-react";
import type { KcLanguageTag } from "../i18n/KcLanguageTag";
@ -25,7 +25,7 @@ export type TemplateProps = {
showUsernameNode?: ReactNode;
formNode: ReactNode;
infoNode?: ReactNode;
} & KcTemplateProps;
} & { kcContext: KcContext.Template; } & KcTemplateProps;
export const Template = memo((props: TemplateProps) => {
@ -39,7 +39,8 @@ export const Template = memo((props: TemplateProps) => {
headerNode,
showUsernameNode = null,
formNode,
infoNode = null
infoNode = null,
kcContext
} = props;
useEffect(() => { console.log("Rendering this page with react using keycloakify") }, []);
@ -58,8 +59,6 @@ export const Template = memo((props: TemplateProps) => {
(document.forms["kc-select-try-another-way-form" as never].submit(), false)
);
assert(kcContext !== undefined);
const {
realm, locale, auth,
url, message, isAppInitiatedAction
@ -153,8 +152,8 @@ export const Template = memo((props: TemplateProps) => {
<ul>
{
locale.supported.map(
({ languageTag }) =>
<li className="kc-dropdown-item">
({ languageTag }) =>
<li key={languageTag} className="kc-dropdown-item">
<a href="#" onClick={onChangeLanguageClickFactory(languageTag)}>
{getKcLanguageTagLabel(languageTag)}
</a>

View File

@ -1,9 +1,10 @@
import { createUseGlobalState } from "powerhooks";
import { kcContext } from "../kcContext";
import { kcContext } from "../KcContext";
import { getBestMatchAmongKcLanguageTag } from "./KcLanguageTag";
export const { useKcLanguageTag } = createUseGlobalState(
//export const { useKcLanguageTag, evtKcLanguageTag } = createUseGlobalState(
const wrap = createUseGlobalState(
"kcLanguageTag",
() => getBestMatchAmongKcLanguageTag(
kcContext?.locale?.current ??
@ -11,3 +12,12 @@ export const { useKcLanguageTag } = createUseGlobalState(
),
{ "persistance": "cookie" }
);
export const { useKcLanguageTag } = wrap;
export function getEvtKcLanguage() {
return wrap.evtKcLanguageTag;
}

View File

@ -1,4 +1,4 @@
export * from "./kcContext";
export * from "./KcContext";
export * from "./i18n/KcLanguageTag";
export * from "./i18n/useKcLanguageTag";
@ -13,4 +13,6 @@ export * from "./components/Error";
export * from "./components/LoginResetPassword";
export * from "./components/LoginVerifyEmail";
export * from "./tools/assert";
export * from "./tools/assert";
export * as kcContextMock from "./kcMockContext";

View File

@ -157,3 +157,5 @@ doExtends<KcContext["pageId"], PageId>();
doExtends<PageId, KcContext["pageId"]>();
export const kcContext = id<KcContext | undefined>((window as any)[ftlValuesGlobalName]);

View File

@ -0,0 +1,147 @@
import type { KcContext } from "../KcContext";
import { getEvtKcLanguage } from "../i18n/useKcLanguageTag";
import { getKcLanguageTagLabel } from "../i18n/KcLanguageTag";
//NOTE: Aside because we want to be able to import them from node
import { resourcesCommonPath, resourcesPath } from "./urlResourcesPath";
export const kcTemplateContext: KcContext.Template = {
"url": {
"loginAction": "#",
"resourcesPath": "/" + resourcesPath,
"resourcesCommonPath": "/" + resourcesCommonPath,
"loginRestartFlowUrl": "/auth/realms/myrealm/login-actions/restart?client_id=account&tab_id=HoAx28ja4xg",
"loginUrl": "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg",
},
"realm": {
"displayName": "myrealm",
"displayNameHtml": "myrealm",
"internationalizationEnabled": true,
"registrationEmailAsUsername": true,
},
"locale": {
"supported": [
{
"url": "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=de",
"languageTag": "de"
},
{
"url": "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=no",
"languageTag": "no"
},
{
"url": "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=ru",
"languageTag": "ru"
},
{
"url": "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=sv",
"languageTag": "sv"
},
{
"url": "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=pt-BR",
"languageTag": "pt-BR"
},
{
"url": "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=lt",
"languageTag": "lt"
},
{
"url": "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=en",
"languageTag": "en"
},
{
"url": "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=it",
"languageTag": "it"
},
{
"url": "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=fr",
"languageTag": "fr"
},
{
"url": "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=zh-CN",
"languageTag": "zh-CN"
},
{
"url": "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=es",
"languageTag": "es"
},
{
"url": "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=cs",
"languageTag": "cs"
},
{
"url": "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=ja",
"languageTag": "ja"
},
{
"url": "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=sk",
"languageTag": "sk"
},
{
"url": "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=pl",
"languageTag": "pl"
},
{
"url": "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=ca",
"languageTag": "ca"
},
{
"url": "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=nl",
"languageTag": "nl"
},
{
"url": "/auth/realms/myrealm/login-actions/authenticate?client_id=account&tab_id=HoAx28ja4xg&execution=ee6c2834-46a4-4a20-a1b6-f6d6f6451b36&kc_locale=tr",
"languageTag": "tr"
}
],
"current": null as any
},
"auth": {
"showUsername": false,
"showResetCredentials": false,
"showTryAnotherWayLink": false
},
"scripts": [],
"message": {
"type": "success",
"summary": "This is a test message"
},
"isAppInitiatedAction": false,
};
Object.defineProperty(
kcTemplateContext.locale!,
"current",
{
"get": () => getKcLanguageTagLabel(getEvtKcLanguage().state),
"enumerable": true
}
);
export const kcLoginContext: KcContext.Login = {
...kcTemplateContext,
"pageId": "login.ftl",
"url": {
...kcTemplateContext.url,
"loginResetCredentialsUrl": "/auth/realms/myrealm/login-actions/reset-credentials?client_id=account&tab_id=HoAx28ja4xg",
"registrationUrl": "/auth/realms/myrealm/login-actions/registration?client_id=account&tab_id=HoAx28ja4xg"
},
"realm": {
...kcTemplateContext.realm,
"loginWithEmailAllowed": true,
"rememberMe": true,
"password": true,
"resetPasswordAllowed": true,
"registrationAllowed": true
},
"auth": kcTemplateContext.auth!,
"social": {
"displayInfo": true
},
"usernameEditDisabled": false,
"login": {
"rememberMe": false
},
"registrationDisabled": false,
};

View File

@ -0,0 +1,6 @@
import { join as pathJoin } from "path";
export const subDirOfPublicDirBasename = "keycloak_static";
export const resourcesPath = pathJoin(subDirOfPublicDirBasename, "/resources");
export const resourcesCommonPath = pathJoin(subDirOfPublicDirBasename, "/resources_common");