Feat sml-post-form.ftl #277
This commit is contained in:
@ -21,7 +21,8 @@ export const loginThemePageIds = [
|
|||||||
"update-user-profile.ftl",
|
"update-user-profile.ftl",
|
||||||
"idp-review-user-profile.ftl",
|
"idp-review-user-profile.ftl",
|
||||||
"update-email.ftl",
|
"update-email.ftl",
|
||||||
"select-authenticator.ftl"
|
"select-authenticator.ftl",
|
||||||
|
"saml-post-form.ftl"
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
export const accountThemePageIds = ["password.ftl", "account.ftl"] as const;
|
export const accountThemePageIds = ["password.ftl", "account.ftl"] as const;
|
||||||
|
@ -27,6 +27,7 @@ const UpdateUserProfile = lazy(() => import("keycloakify/login/pages/UpdateUserP
|
|||||||
const IdpReviewUserProfile = lazy(() => import("keycloakify/login/pages/IdpReviewUserProfile"));
|
const IdpReviewUserProfile = lazy(() => import("keycloakify/login/pages/IdpReviewUserProfile"));
|
||||||
const UpdateEmail = lazy(() => import("keycloakify/login/pages/UpdateEmail"));
|
const UpdateEmail = lazy(() => import("keycloakify/login/pages/UpdateEmail"));
|
||||||
const SelectAuthenticator = lazy(() => import("keycloakify/login/pages/SelectAuthenticator"));
|
const SelectAuthenticator = lazy(() => import("keycloakify/login/pages/SelectAuthenticator"));
|
||||||
|
const SamlPostForm = lazy(() => import("keycloakify/login/pages/SamlPostForm"));
|
||||||
|
|
||||||
export default function Fallback(props: PageProps<KcContext, I18n>) {
|
export default function Fallback(props: PageProps<KcContext, I18n>) {
|
||||||
const { kcContext, ...rest } = props;
|
const { kcContext, ...rest } = props;
|
||||||
@ -81,6 +82,8 @@ export default function Fallback(props: PageProps<KcContext, I18n>) {
|
|||||||
return <UpdateEmail kcContext={kcContext} {...rest} />;
|
return <UpdateEmail kcContext={kcContext} {...rest} />;
|
||||||
case "select-authenticator.ftl":
|
case "select-authenticator.ftl":
|
||||||
return <SelectAuthenticator kcContext={kcContext} {...rest} />;
|
return <SelectAuthenticator kcContext={kcContext} {...rest} />;
|
||||||
|
case "saml-post-form.ftl":
|
||||||
|
return <SamlPostForm kcContext={kcContext} {...rest} />;
|
||||||
}
|
}
|
||||||
assert<Equals<typeof kcContext, never>>(false);
|
assert<Equals<typeof kcContext, never>>(false);
|
||||||
})()}
|
})()}
|
||||||
|
@ -32,7 +32,8 @@ export type KcContext =
|
|||||||
| KcContext.UpdateUserProfile
|
| KcContext.UpdateUserProfile
|
||||||
| KcContext.IdpReviewUserProfile
|
| KcContext.IdpReviewUserProfile
|
||||||
| KcContext.UpdateEmail
|
| KcContext.UpdateEmail
|
||||||
| KcContext.SelectAuthenticator;
|
| KcContext.SelectAuthenticator
|
||||||
|
| KcContext.SamlPostForm;
|
||||||
|
|
||||||
export declare namespace KcContext {
|
export declare namespace KcContext {
|
||||||
export type Common = {
|
export type Common = {
|
||||||
@ -85,6 +86,16 @@ export declare namespace KcContext {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type SamlPostForm = Common & {
|
||||||
|
pageId: "saml-post-form.ftl";
|
||||||
|
samlPost: {
|
||||||
|
url: string;
|
||||||
|
SAMLRequest?: string;
|
||||||
|
SAMLResponse?: string;
|
||||||
|
RelayState?: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export type Login = Common & {
|
export type Login = Common & {
|
||||||
pageId: "login.ftl";
|
pageId: "login.ftl";
|
||||||
url: {
|
url: {
|
||||||
@ -543,4 +554,13 @@ export declare namespace Validators {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
assert<Equals<KcContext["pageId"], LoginThemePageId>>();
|
{
|
||||||
|
type Got = KcContext["pageId"];
|
||||||
|
type Expected = LoginThemePageId;
|
||||||
|
|
||||||
|
type OnlyInGot = Exclude<Got, Expected>;
|
||||||
|
type OnlyInExpected = Exclude<Expected, Got>;
|
||||||
|
|
||||||
|
assert<Equals<OnlyInGot, never>>();
|
||||||
|
assert<Equals<OnlyInExpected, never>>();
|
||||||
|
}
|
||||||
|
@ -3,6 +3,8 @@ import type { KcContext, Attribute } from "./KcContext";
|
|||||||
import { resourcesCommonDirPathRelativeToPublicDir, resourcesDirPathRelativeToPublicDir } from "keycloakify/bin/mockTestingResourcesPath";
|
import { resourcesCommonDirPathRelativeToPublicDir, resourcesDirPathRelativeToPublicDir } from "keycloakify/bin/mockTestingResourcesPath";
|
||||||
import { pathJoin } from "keycloakify/bin/tools/pathJoin";
|
import { pathJoin } from "keycloakify/bin/tools/pathJoin";
|
||||||
import { id } from "tsafe/id";
|
import { id } from "tsafe/id";
|
||||||
|
import { assert, type Equals } from "tsafe/assert";
|
||||||
|
import type { LoginThemePageId } from "keycloakify/bin/keycloakify/generateFtl";
|
||||||
|
|
||||||
const PUBLIC_URL = process.env["PUBLIC_URL"] ?? "/";
|
const PUBLIC_URL = process.env["PUBLIC_URL"] ?? "/";
|
||||||
|
|
||||||
@ -243,7 +245,7 @@ const loginUrl = {
|
|||||||
"registrationUrl": "/auth/realms/myrealm/login-actions/registration?client_id=account&tab_id=HoAx28ja4xg"
|
"registrationUrl": "/auth/realms/myrealm/login-actions/registration?client_id=account&tab_id=HoAx28ja4xg"
|
||||||
};
|
};
|
||||||
|
|
||||||
export const kcContextMocks: KcContext[] = [
|
export const kcContextMocks = [
|
||||||
id<KcContext.Login>({
|
id<KcContext.Login>({
|
||||||
...kcContextCommonMock,
|
...kcContextCommonMock,
|
||||||
"pageId": "login.ftl",
|
"pageId": "login.ftl",
|
||||||
@ -519,5 +521,27 @@ export const kcContextMocks: KcContext[] = [
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
}),
|
||||||
|
id<KcContext.SamlPostForm>({
|
||||||
|
...kcContextCommonMock,
|
||||||
|
pageId: "saml-post-form.ftl",
|
||||||
|
"samlPost": {
|
||||||
|
"url": "https://saml-post-url"
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
id<KcContext.LoginPageExpired>({
|
||||||
|
...kcContextCommonMock,
|
||||||
|
pageId: "login-page-expired.ftl"
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|
||||||
|
{
|
||||||
|
type Got = (typeof kcContextMocks)[number]["pageId"];
|
||||||
|
type Expected = LoginThemePageId;
|
||||||
|
|
||||||
|
type OnlyInGot = Exclude<Got, Expected>;
|
||||||
|
type OnlyInExpected = Exclude<Expected, Got>;
|
||||||
|
|
||||||
|
assert<Equals<OnlyInGot, never>>();
|
||||||
|
assert<Equals<OnlyInExpected, never>>();
|
||||||
|
}
|
||||||
|
@ -14,7 +14,9 @@ export default function RegisterUserProfile(props: PageProps<Extract<KcContext,
|
|||||||
classes
|
classes
|
||||||
});
|
});
|
||||||
|
|
||||||
const { url, messagesPerField, recaptchaRequired, recaptchaSiteKey } = kcContext;
|
const { url, messagesPerField, recaptchaRequired, recaptchaSiteKey, realm } = kcContext;
|
||||||
|
|
||||||
|
realm.registrationEmailAsUsername;
|
||||||
|
|
||||||
const { msg, msgStr } = i18n;
|
const { msg, msgStr } = i18n;
|
||||||
|
|
||||||
|
27
src/login/pages/SamlPostForm.tsx
Normal file
27
src/login/pages/SamlPostForm.tsx
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import type { PageProps } from "keycloakify/login/pages/PageProps";
|
||||||
|
import type { KcContext } from "../kcContext";
|
||||||
|
import type { I18n } from "../i18n";
|
||||||
|
|
||||||
|
export default function SamlPostForm(props: PageProps<Extract<KcContext, { pageId: "saml-post-form.ftl" }>, I18n>) {
|
||||||
|
const { kcContext, i18n, doUseDefaultCss, Template, classes } = props;
|
||||||
|
|
||||||
|
const { msgStr, msg } = i18n;
|
||||||
|
|
||||||
|
const { samlPost } = kcContext;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Template {...{ kcContext, i18n, doUseDefaultCss, classes }} displayMessage={false} headerNode={msg("saml.post-form.title")}>
|
||||||
|
<script dangerouslySetInnerHTML={{ "__html": `window.onload = function() {document.forms[0].submit()};` }} />
|
||||||
|
<p>{msg("saml.post-form.message")}</p>
|
||||||
|
<form name="saml-post-binding" method="post" action={samlPost.url}>
|
||||||
|
{samlPost.SAMLRequest && <input type="hidden" name="SAMLRequest" value={samlPost.SAMLRequest} />}
|
||||||
|
{samlPost.SAMLResponse && <input type="hidden" name="SAMLResponse" value={samlPost.SAMLResponse} />}
|
||||||
|
{samlPost.RelayState && <input type="hidden" name="RelayState" value={samlPost.RelayState} />}
|
||||||
|
<noscript>
|
||||||
|
<p>{msg("saml.post-form.js-disabled")}</p>
|
||||||
|
<input type="submit" value={msgStr("doContinue")} />
|
||||||
|
</noscript>
|
||||||
|
</form>
|
||||||
|
</Template>
|
||||||
|
);
|
||||||
|
}
|
24
stories/login/pages/SamlPostForm.stories.tsx
Normal file
24
stories/login/pages/SamlPostForm.stories.tsx
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import React from "react";
|
||||||
|
import type { ComponentMeta } from "@storybook/react";
|
||||||
|
import { createPageStory } from "../createPageStory";
|
||||||
|
|
||||||
|
const pageId = "saml-post-form.ftl";
|
||||||
|
|
||||||
|
const { PageStory } = createPageStory({ pageId });
|
||||||
|
|
||||||
|
const meta: ComponentMeta<any> = {
|
||||||
|
title: `login/${pageId}`,
|
||||||
|
component: PageStory,
|
||||||
|
parameters: {
|
||||||
|
viewMode: "story",
|
||||||
|
previewTabs: {
|
||||||
|
"storybook/docs/panel": {
|
||||||
|
"hidden": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default meta;
|
||||||
|
|
||||||
|
export const Default = () => <PageStory />;
|
Reference in New Issue
Block a user