Merge pull request #553 from giorgoslytos/feat/federated-identity-account-page
Addition of Federated Identity Account page
This commit is contained in:
commit
662a76bbb6
@ -3,6 +3,7 @@ import type { PageProps } from "keycloakify/account/pages/PageProps";
|
|||||||
import type { I18n } from "keycloakify/account/i18n";
|
import type { I18n } from "keycloakify/account/i18n";
|
||||||
import type { KcContext } from "./kcContext";
|
import type { KcContext } from "./kcContext";
|
||||||
import { assert, type Equals } from "tsafe/assert";
|
import { assert, type Equals } from "tsafe/assert";
|
||||||
|
import FederatedIdentity from "./pages/FederatedIdentity";
|
||||||
|
|
||||||
const Password = lazy(() => import("keycloakify/account/pages/Password"));
|
const Password = lazy(() => import("keycloakify/account/pages/Password"));
|
||||||
const Account = lazy(() => import("keycloakify/account/pages/Account"));
|
const Account = lazy(() => import("keycloakify/account/pages/Account"));
|
||||||
@ -30,6 +31,8 @@ export default function Fallback(props: PageProps<KcContext, I18n>) {
|
|||||||
return <Applications kcContext={kcContext} {...rest} />;
|
return <Applications kcContext={kcContext} {...rest} />;
|
||||||
case "log.ftl":
|
case "log.ftl":
|
||||||
return <Log kcContext={kcContext} {...rest} />;
|
return <Log kcContext={kcContext} {...rest} />;
|
||||||
|
case "federatedIdentity.ftl":
|
||||||
|
return <FederatedIdentity kcContext={kcContext} {...rest} />;
|
||||||
}
|
}
|
||||||
assert<Equals<typeof kcContext, never>>(false);
|
assert<Equals<typeof kcContext, never>>(false);
|
||||||
})()}
|
})()}
|
||||||
|
@ -3,7 +3,14 @@ import { assert } from "tsafe/assert";
|
|||||||
import type { Equals } from "tsafe";
|
import type { Equals } from "tsafe";
|
||||||
import { type ThemeType } from "keycloakify/bin/constants";
|
import { type ThemeType } from "keycloakify/bin/constants";
|
||||||
|
|
||||||
export type KcContext = KcContext.Password | KcContext.Account | KcContext.Sessions | KcContext.Totp | KcContext.Applications | KcContext.Log;
|
export type KcContext =
|
||||||
|
| KcContext.Password
|
||||||
|
| KcContext.Account
|
||||||
|
| KcContext.Sessions
|
||||||
|
| KcContext.Totp
|
||||||
|
| KcContext.Applications
|
||||||
|
| KcContext.Log
|
||||||
|
| KcContext.FederatedIdentity;
|
||||||
|
|
||||||
export declare namespace KcContext {
|
export declare namespace KcContext {
|
||||||
export type Common = {
|
export type Common = {
|
||||||
@ -27,6 +34,7 @@ export declare namespace KcContext {
|
|||||||
sessionsUrl: string;
|
sessionsUrl: string;
|
||||||
applicationsUrl: string;
|
applicationsUrl: string;
|
||||||
logUrl: string;
|
logUrl: string;
|
||||||
|
logoutUrl: string;
|
||||||
resourceUrl: string;
|
resourceUrl: string;
|
||||||
resourcesCommonPath: string;
|
resourcesCommonPath: string;
|
||||||
resourcesPath: string;
|
resourcesPath: string;
|
||||||
@ -91,15 +99,6 @@ export declare namespace KcContext {
|
|||||||
username?: string;
|
username?: string;
|
||||||
};
|
};
|
||||||
properties: Record<string, string | undefined>;
|
properties: Record<string, string | undefined>;
|
||||||
sessions: {
|
|
||||||
sessions: {
|
|
||||||
ipAddress: string;
|
|
||||||
started?: any;
|
|
||||||
lastAccess?: any;
|
|
||||||
expires?: any;
|
|
||||||
clients: string[];
|
|
||||||
}[];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Password = Common & {
|
export type Password = Common & {
|
||||||
@ -126,11 +125,12 @@ export declare namespace KcContext {
|
|||||||
pageId: "sessions.ftl";
|
pageId: "sessions.ftl";
|
||||||
sessions: {
|
sessions: {
|
||||||
sessions: {
|
sessions: {
|
||||||
ipAddress: string;
|
expires: string;
|
||||||
started?: any;
|
|
||||||
lastAccess?: any;
|
|
||||||
expires?: any;
|
|
||||||
clients: string[];
|
clients: string[];
|
||||||
|
ipAddress: string;
|
||||||
|
started: string;
|
||||||
|
lastAccess: string;
|
||||||
|
id: string;
|
||||||
}[];
|
}[];
|
||||||
};
|
};
|
||||||
stateChecker: string;
|
stateChecker: string;
|
||||||
@ -193,12 +193,21 @@ export declare namespace KcContext {
|
|||||||
stateChecker: string;
|
stateChecker: string;
|
||||||
applications: {
|
applications: {
|
||||||
applications: {
|
applications: {
|
||||||
realmRolesAvailable: { name: string; description: string }[];
|
realmRolesAvailable: {
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
compositesStream?: Record<string, unknown>;
|
||||||
|
clientRole?: boolean;
|
||||||
|
composite?: boolean;
|
||||||
|
id?: string;
|
||||||
|
containerId?: string;
|
||||||
|
attributes?: Record<string, unknown>;
|
||||||
|
}[];
|
||||||
resourceRolesAvailable: Record<
|
resourceRolesAvailable: Record<
|
||||||
string,
|
string,
|
||||||
{
|
{
|
||||||
roleName: string;
|
roleName: string;
|
||||||
roleDescription: string;
|
roleDescription?: string;
|
||||||
clientName: string;
|
clientName: string;
|
||||||
clientId: string;
|
clientId: string;
|
||||||
}[]
|
}[]
|
||||||
@ -207,41 +216,44 @@ export declare namespace KcContext {
|
|||||||
clientScopesGranted: string[];
|
clientScopesGranted: string[];
|
||||||
effectiveUrl?: string;
|
effectiveUrl?: string;
|
||||||
client: {
|
client: {
|
||||||
consentScreenText: string;
|
|
||||||
surrogateAuthRequired: boolean;
|
|
||||||
bearerOnly: boolean;
|
|
||||||
id: string;
|
|
||||||
protocolMappersStream: Record<string, unknown>;
|
|
||||||
includeInTokenScope: boolean;
|
|
||||||
redirectUris: string[];
|
|
||||||
fullScopeAllowed: boolean;
|
|
||||||
registeredNodes: Record<string, unknown>;
|
|
||||||
enabled: boolean;
|
|
||||||
clientAuthenticatorType: string;
|
|
||||||
realmScopeMappingsStream: Record<string, unknown>;
|
|
||||||
scopeMappingsStream: Record<string, unknown>;
|
|
||||||
displayOnConsentScreen: boolean;
|
|
||||||
clientId: string;
|
|
||||||
rootUrl: string;
|
|
||||||
authenticationFlowBindingOverrides: Record<string, unknown>;
|
|
||||||
standardFlowEnabled: boolean;
|
|
||||||
attributes: Record<string, unknown>;
|
|
||||||
publicClient: boolean;
|
|
||||||
alwaysDisplayInConsole: boolean;
|
alwaysDisplayInConsole: boolean;
|
||||||
|
attributes: Record<string, unknown>;
|
||||||
|
authenticationFlowBindingOverrides: Record<string, unknown>;
|
||||||
|
baseUrl?: string;
|
||||||
|
bearerOnly: boolean;
|
||||||
|
clientAuthenticatorType: string;
|
||||||
|
clientId: string;
|
||||||
consentRequired: boolean;
|
consentRequired: boolean;
|
||||||
notBefore: string;
|
consentScreenText: string;
|
||||||
rolesStream: Record<string, unknown>;
|
description: string;
|
||||||
protocol: string;
|
|
||||||
dynamicScope: boolean;
|
|
||||||
directAccessGrantsEnabled: boolean;
|
directAccessGrantsEnabled: boolean;
|
||||||
name: string;
|
displayOnConsentScreen: boolean;
|
||||||
serviceAccountsEnabled: boolean;
|
dynamicScope: boolean;
|
||||||
|
enabled: boolean;
|
||||||
frontchannelLogout: boolean;
|
frontchannelLogout: boolean;
|
||||||
nodeReRegistrationTimeout: string;
|
fullScopeAllowed: boolean;
|
||||||
|
id: string;
|
||||||
implicitFlowEnabled: boolean;
|
implicitFlowEnabled: boolean;
|
||||||
baseUrl: string;
|
includeInTokenScope: boolean;
|
||||||
webOrigins: string[];
|
managementUrl: string;
|
||||||
|
name?: string;
|
||||||
|
nodeReRegistrationTimeout: string;
|
||||||
|
notBefore: string;
|
||||||
|
protocol: string;
|
||||||
|
protocolMappersStream: Record<string, unknown>;
|
||||||
|
publicClient: boolean;
|
||||||
realm: Record<string, unknown>;
|
realm: Record<string, unknown>;
|
||||||
|
realmScopeMappingsStream: Record<string, unknown>;
|
||||||
|
redirectUris: string[];
|
||||||
|
registeredNodes: Record<string, unknown>;
|
||||||
|
rolesStream: Record<string, unknown>;
|
||||||
|
rootUrl?: string;
|
||||||
|
scopeMappingsStream: Record<string, unknown>;
|
||||||
|
secret: string;
|
||||||
|
serviceAccountsEnabled: boolean;
|
||||||
|
standardFlowEnabled: boolean;
|
||||||
|
surrogateAuthRequired: boolean;
|
||||||
|
webOrigins: string[];
|
||||||
};
|
};
|
||||||
}[];
|
}[];
|
||||||
};
|
};
|
||||||
@ -254,11 +266,25 @@ export declare namespace KcContext {
|
|||||||
date: string | number | Date;
|
date: string | number | Date;
|
||||||
event: string;
|
event: string;
|
||||||
ipAddress: string;
|
ipAddress: string;
|
||||||
client: any;
|
client: string;
|
||||||
details: any[];
|
details: { value: string; key: string }[];
|
||||||
}[];
|
}[];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type FederatedIdentity = Common & {
|
||||||
|
pageId: "federatedIdentity.ftl";
|
||||||
|
stateChecker: string;
|
||||||
|
federatedIdentity: {
|
||||||
|
identities: {
|
||||||
|
providerId: string;
|
||||||
|
displayName: string;
|
||||||
|
userName: string;
|
||||||
|
connected: boolean;
|
||||||
|
}[];
|
||||||
|
removeLinkPossible: boolean;
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -17,6 +17,7 @@ export const kcContextCommonMock: KcContext.Common = {
|
|||||||
"resourceUrl": "#",
|
"resourceUrl": "#",
|
||||||
"accountUrl": "#",
|
"accountUrl": "#",
|
||||||
"applicationsUrl": "#",
|
"applicationsUrl": "#",
|
||||||
|
"logoutUrl": "#",
|
||||||
"getLogoutUrl": () => "#",
|
"getLogoutUrl": () => "#",
|
||||||
"logUrl": "#",
|
"logUrl": "#",
|
||||||
"passwordUrl": "#",
|
"passwordUrl": "#",
|
||||||
@ -156,17 +157,6 @@ export const kcContextCommonMock: KcContext.Common = {
|
|||||||
"css/account.css img/icon-sidebar-active.png img/logo.png resources-common/node_modules/patternfly/dist/css/patternfly.min.css resources-common/node_modules/patternfly/dist/css/patternfly-additions.min.css resources-common/node_modules/patternfly/dist/css/patternfly-additions.min.css",
|
"css/account.css img/icon-sidebar-active.png img/logo.png resources-common/node_modules/patternfly/dist/css/patternfly.min.css resources-common/node_modules/patternfly/dist/css/patternfly-additions.min.css resources-common/node_modules/patternfly/dist/css/patternfly-additions.min.css",
|
||||||
"kcButtonClass": "btn",
|
"kcButtonClass": "btn",
|
||||||
"kcButtonDefaultClass": "btn-default"
|
"kcButtonDefaultClass": "btn-default"
|
||||||
},
|
|
||||||
"sessions": {
|
|
||||||
"sessions": [
|
|
||||||
{
|
|
||||||
"ipAddress": "127.0.0.1",
|
|
||||||
"started": new Date().toString(),
|
|
||||||
"lastAccess": new Date().toString(),
|
|
||||||
"expires": new Date().toString(),
|
|
||||||
"clients": ["Chrome", "Firefox"]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -200,12 +190,12 @@ export const kcContextMocks: KcContext[] = [
|
|||||||
"sessions": {
|
"sessions": {
|
||||||
"sessions": [
|
"sessions": [
|
||||||
{
|
{
|
||||||
...kcContextCommonMock.sessions,
|
|
||||||
"ipAddress": "127.0.0.1",
|
"ipAddress": "127.0.0.1",
|
||||||
"started": new Date().toString(),
|
"started": new Date().toString(),
|
||||||
"lastAccess": new Date().toString(),
|
"lastAccess": new Date().toString(),
|
||||||
"expires": new Date().toString(),
|
"expires": new Date().toString(),
|
||||||
"clients": ["Chrome", "Firefox"]
|
"clients": ["Chrome", "Firefox"],
|
||||||
|
"id": "f8951177-817d-4a70-9c02-86d3c170fe51"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -246,9 +236,25 @@ export const kcContextMocks: KcContext[] = [
|
|||||||
"event": "login",
|
"event": "login",
|
||||||
"ipAddress": "172.17.0.1",
|
"ipAddress": "172.17.0.1",
|
||||||
"client": "security-admin-console",
|
"client": "security-admin-console",
|
||||||
"details": ["auth_method = openid-connect, username = admin"]
|
"details": [{ key: "openid-connect", value: "admin" }]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
}),
|
||||||
|
id<KcContext.FederatedIdentity>({
|
||||||
|
...kcContextCommonMock,
|
||||||
|
"stateChecker": "",
|
||||||
|
"pageId": "federatedIdentity.ftl",
|
||||||
|
"federatedIdentity": {
|
||||||
|
"identities": [
|
||||||
|
{
|
||||||
|
"providerId": "keycloak-oidc",
|
||||||
|
"displayName": "keycloak-oidc",
|
||||||
|
"userName": "John",
|
||||||
|
"connected": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"removeLinkPossible": true
|
||||||
|
}
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
@ -61,10 +61,10 @@ export default function Applications(props: PageProps<Extract<KcContext, { pageI
|
|||||||
|
|
||||||
<td>
|
<td>
|
||||||
{!isArrayWithEmptyObject(application.realmRolesAvailable) &&
|
{!isArrayWithEmptyObject(application.realmRolesAvailable) &&
|
||||||
application.realmRolesAvailable.map(role => (
|
application.realmRolesAvailable.map((role, index) => (
|
||||||
<span key={role.name}>
|
<span key={role.name}>
|
||||||
{role.description ? advancedMsg(role.description) : advancedMsg(role.name)}
|
{role.description ? advancedMsg(role.description) : advancedMsg(role.name)}
|
||||||
{role !== application.realmRolesAvailable[application.realmRolesAvailable.length - 1] && ", "}
|
{index < application.realmRolesAvailable.length - 1 && ", "}
|
||||||
</span>
|
</span>
|
||||||
))}
|
))}
|
||||||
{!isArrayWithEmptyObject(application.realmRolesAvailable) && application.resourceRolesAvailable && ", "}
|
{!isArrayWithEmptyObject(application.realmRolesAvailable) && application.resourceRolesAvailable && ", "}
|
||||||
|
58
src/account/pages/FederatedIdentity.tsx
Normal file
58
src/account/pages/FederatedIdentity.tsx
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import { PageProps } from "keycloakify/account";
|
||||||
|
import { I18n } from "keycloakify/account/i18n";
|
||||||
|
import { KcContext } from "keycloakify/account/kcContext";
|
||||||
|
|
||||||
|
export default function FederatedIdentity(props: PageProps<Extract<KcContext, { pageId: "federatedIdentity.ftl" }>, I18n>) {
|
||||||
|
const { kcContext, i18n, doUseDefaultCss, classes, Template } = props;
|
||||||
|
|
||||||
|
const { url, federatedIdentity, stateChecker } = kcContext;
|
||||||
|
const { msg } = i18n;
|
||||||
|
return (
|
||||||
|
<Template {...{ kcContext, i18n, doUseDefaultCss, classes }} active="federatedIdentity">
|
||||||
|
<div className="main-layout social">
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-10">
|
||||||
|
<h2>{msg("federatedIdentitiesHtmlTitle")}</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="federated-identities">
|
||||||
|
{federatedIdentity.identities.map(identity => (
|
||||||
|
<div key={identity.providerId} className="row margin-bottom">
|
||||||
|
<div className="col-sm-2 col-md-2">
|
||||||
|
<label htmlFor={identity.providerId} className="control-label">
|
||||||
|
{identity.displayName}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className="col-sm-5 col-md-5">
|
||||||
|
<input disabled className="form-control" value={identity.userName} />
|
||||||
|
</div>
|
||||||
|
<div className="col-sm-5 col-md-5">
|
||||||
|
{identity.connected ? (
|
||||||
|
federatedIdentity.removeLinkPossible && (
|
||||||
|
<form action={url.socialUrl} method="post" className="form-inline">
|
||||||
|
<input type="hidden" name="stateChecker" value={stateChecker} />
|
||||||
|
<input type="hidden" name="action" value="remove" />
|
||||||
|
<input type="hidden" name="providerId" value={identity.providerId} />
|
||||||
|
<button id={`remove-link-${identity.providerId}`} className="btn btn-default">
|
||||||
|
{msg("doRemove")}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
<form action={url.socialUrl} method="post" className="form-inline">
|
||||||
|
<input type="hidden" name="stateChecker" value={stateChecker} />
|
||||||
|
<input type="hidden" name="action" value="add" />
|
||||||
|
<input type="hidden" name="providerId" value={identity.providerId} />
|
||||||
|
<button id={`add-link-${identity.providerId}`} className="btn btn-default">
|
||||||
|
{msg("doAdd")}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Template>
|
||||||
|
);
|
||||||
|
}
|
@ -2,7 +2,7 @@ import type { PageProps } from "keycloakify/account/pages/PageProps";
|
|||||||
import type { KcContext } from "../kcContext";
|
import type { KcContext } from "../kcContext";
|
||||||
import type { I18n } from "../i18n";
|
import type { I18n } from "../i18n";
|
||||||
import { Key } from "react";
|
import { Key } from "react";
|
||||||
import { useGetClassName } from "../lib/useGetClassName";
|
import { useGetClassName } from "keycloakify/account/lib/useGetClassName";
|
||||||
|
|
||||||
export default function Log(props: PageProps<Extract<KcContext, { pageId: "log.ftl" }>, I18n>) {
|
export default function Log(props: PageProps<Extract<KcContext, { pageId: "log.ftl" }>, I18n>) {
|
||||||
const { kcContext, i18n, doUseDefaultCss, classes, Template } = props;
|
const { kcContext, i18n, doUseDefaultCss, classes, Template } = props;
|
||||||
|
@ -12,12 +12,9 @@ export default function Sessions(props: PageProps<Extract<KcContext, { pageId: "
|
|||||||
classes
|
classes
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log({ kcContext });
|
|
||||||
const { url, stateChecker, sessions } = kcContext;
|
const { url, stateChecker, sessions } = kcContext;
|
||||||
|
|
||||||
const { msg } = i18n;
|
const { msg } = i18n;
|
||||||
console.log({ sdf: kcContext.locale?.supported });
|
|
||||||
console.log({ asdf: "asdf" });
|
|
||||||
return (
|
return (
|
||||||
<Template {...{ kcContext, i18n, doUseDefaultCss, classes }} active="sessions">
|
<Template {...{ kcContext, i18n, doUseDefaultCss, classes }} active="sessions">
|
||||||
<div className={getClassName("kcContentWrapperClass")}>
|
<div className={getClassName("kcContentWrapperClass")}>
|
||||||
|
@ -7,6 +7,7 @@ import { MessageKey } from "keycloakify/account/i18n/i18n";
|
|||||||
|
|
||||||
export default function Totp(props: PageProps<Extract<KcContext, { pageId: "totp.ftl" }>, I18n>) {
|
export default function Totp(props: PageProps<Extract<KcContext, { pageId: "totp.ftl" }>, I18n>) {
|
||||||
const { kcContext, i18n, doUseDefaultCss, Template, classes } = props;
|
const { kcContext, i18n, doUseDefaultCss, Template, classes } = props;
|
||||||
|
|
||||||
const { getClassName } = useGetClassName({
|
const { getClassName } = useGetClassName({
|
||||||
doUseDefaultCss,
|
doUseDefaultCss,
|
||||||
classes
|
classes
|
||||||
@ -78,7 +79,7 @@ export default function Totp(props: PageProps<Extract<KcContext, { pageId: "totp
|
|||||||
<p>{msg("totpStep1")}</p>
|
<p>{msg("totpStep1")}</p>
|
||||||
|
|
||||||
<ul id="kc-totp-supported-apps">
|
<ul id="kc-totp-supported-apps">
|
||||||
{totp.supportedApplications.map(app => (
|
{totp.supportedApplications?.map(app => (
|
||||||
<li key={app}>{msg(app as MessageKey)}</li>
|
<li key={app}>{msg(app as MessageKey)}</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
@ -99,7 +100,6 @@ export default function Totp(props: PageProps<Extract<KcContext, { pageId: "totp
|
|||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<p>{msg("totpManualStep3")}</p>
|
<p>{msg("totpManualStep3")}</p>
|
||||||
<p>
|
|
||||||
<ul>
|
<ul>
|
||||||
<li id="kc-totp-type">
|
<li id="kc-totp-type">
|
||||||
{msg("totpType")}: {msg(`totp.${totp.policy.type}`)}
|
{msg("totpType")}: {msg(`totp.${totp.policy.type}`)}
|
||||||
@ -120,7 +120,6 @@ export default function Totp(props: PageProps<Extract<KcContext, { pageId: "totp
|
|||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
</ul>
|
</ul>
|
||||||
</p>
|
|
||||||
</li>
|
</li>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
|
@ -27,7 +27,15 @@ export const loginThemePageIds = [
|
|||||||
"saml-post-form.ftl"
|
"saml-post-form.ftl"
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
export const accountThemePageIds = ["password.ftl", "account.ftl", "sessions.ftl", "totp.ftl", "applications.ftl", "log.ftl"] as const;
|
export const accountThemePageIds = [
|
||||||
|
"password.ftl",
|
||||||
|
"account.ftl",
|
||||||
|
"sessions.ftl",
|
||||||
|
"totp.ftl",
|
||||||
|
"applications.ftl",
|
||||||
|
"log.ftl",
|
||||||
|
"federatedIdentity.ftl"
|
||||||
|
] as const;
|
||||||
|
|
||||||
export type LoginThemePageId = (typeof loginThemePageIds)[number];
|
export type LoginThemePageId = (typeof loginThemePageIds)[number];
|
||||||
export type AccountThemePageId = (typeof accountThemePageIds)[number];
|
export type AccountThemePageId = (typeof accountThemePageIds)[number];
|
||||||
|
@ -1,24 +1,19 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import type { ComponentMeta } from "@storybook/react";
|
import { Meta, StoryObj } from "@storybook/react";
|
||||||
import { createPageStory } from "../createPageStory";
|
import { createPageStory } from "../createPageStory";
|
||||||
|
|
||||||
const pageId = "account.ftl";
|
const pageId = "account.ftl";
|
||||||
|
|
||||||
const { PageStory } = createPageStory({ pageId });
|
const { PageStory } = createPageStory({ pageId });
|
||||||
|
|
||||||
const meta: ComponentMeta<any> = {
|
const meta = {
|
||||||
title: `account/${pageId}`,
|
title: "account/Account",
|
||||||
component: PageStory,
|
component: PageStory
|
||||||
parameters: {
|
} satisfies Meta<typeof PageStory>;
|
||||||
viewMode: "story",
|
|
||||||
previewTabs: {
|
|
||||||
"storybook/docs/panel": {
|
|
||||||
hidden: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
export const Default = () => <PageStory />;
|
type Story = StoryObj<typeof meta>;
|
||||||
|
|
||||||
|
export const Default: Story = {
|
||||||
|
render: () => <PageStory />
|
||||||
|
};
|
||||||
|
173
stories/account/pages/Authenticator.stories.tsx
Normal file
173
stories/account/pages/Authenticator.stories.tsx
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Meta } from "@storybook/react";
|
||||||
|
import { createPageStory } from "../createPageStory";
|
||||||
|
|
||||||
|
const { PageStory } = createPageStory({
|
||||||
|
pageId: "totp.ftl"
|
||||||
|
});
|
||||||
|
|
||||||
|
const meta = {
|
||||||
|
title: "account/Authenticator",
|
||||||
|
component: PageStory
|
||||||
|
} satisfies Meta<typeof PageStory>;
|
||||||
|
export default meta;
|
||||||
|
|
||||||
|
export const Default = () => (
|
||||||
|
<PageStory
|
||||||
|
kcContext={{
|
||||||
|
totp: {
|
||||||
|
enabled: false,
|
||||||
|
totpSecretEncoded: "HE4W MSTC OBKU CY2M ONXF OV3Q NYYU I3SH",
|
||||||
|
totpSecret: "99fJbpUAcLsnWWpn1DnG",
|
||||||
|
manualUrl: "http://localhost:8080/realms/myrealm/account/totp?mode=manual",
|
||||||
|
totpSecretQrCode:
|
||||||
|
"iVBORw0KGgoAAAANSUhEUgAAAPYAAAD2AQAAAADNaUdlAAACk0lEQVR4Xu2YQY6DMAxFjViw5AjcBC6GBBIXozfJEbpkger53wEKqOpmFvaikQYNeVRyHPvbiejXscp95jp+/D5zHT9+n7kO8qeIFDqKzjJo9dC1wUSPP7yG4IPq41lq9ZK+keLZSwXDGwMhOCZgdX4sBVD1qld+GYg/h6ScreBuIDo5FKfVM7Z8aWs9PB2E2/73DdOlwUrK9Ck+HDnzB7ziR8fjlD/OPI8pVQwCi899TkNw2M+tp9XSLFKPIq2UySIhBB906fCQTicFwiv1EUG6+d+bl4zPIYnUk5oIcS69/evPYStUp6P0dJhD/mhauijcth76mOsfw+GFrbfXKJx7LW2N15kijuWIMCYicLQOCEimDp1c0L8PzCLTs3/d+ZQLyl6VqeSIT9nz25szf2ZybHgC31yrXEQIbqaPjX0k9GqWy0N/nLkagsHWNXR0LZwsR357c0pjC6fm+meu5f6f6oszz/qj7GpYCdHf0LVH/gTgtJ/5bVavPJ9svwnBS9qaqwoHOh3G7Ln++HIIDgpKYpFW00dlkX7ruz836THBWQpzd23/xeDsFVroz15fRjsfMyaC8JX2Y8PZf+VIoKff+uTO6WSIUIfSkrl9/rbfnbPr30R8hnMtXA/98ea5lx4ZlSMgQlMsEnb73XnP+yNl/SuR3/lzTSZHMTirMpMcXjWr0U5Mp/rnzmk/TsXkC2/iKEJ5TRG4DZ5KrP/C0RiVmkp+5I8zN1uh2vv9Vs+bzJ4947Y+bz6wl6ZIcv87ZaU2+6PwnoKdb7VYmrf9Z02MxCmNdmparbVJtrA4nA+e9LgIS6dzfvly7j+4XWIuPJp8iE9PbvkzJHYNabt/o5MP+535t/Hj95nr+PH7zHX8m/8B+RAnloz5pi4AAAAASUVORK5CYII=",
|
||||||
|
policy: {
|
||||||
|
type: "totp"
|
||||||
|
},
|
||||||
|
qrUrl: "http://localhost:8080/realms/myrealm/account/totp?mode=qr",
|
||||||
|
otpCredentials: []
|
||||||
|
},
|
||||||
|
messagesPerField: {},
|
||||||
|
stateChecker: "ihTeSAMfNsobnPjYiktV8DY-5T4sVzVdrEZRdwfMm8Y",
|
||||||
|
realm: {
|
||||||
|
userManagedAccessAllowed: true,
|
||||||
|
internationalizationEnabled: false
|
||||||
|
},
|
||||||
|
url: {
|
||||||
|
totpUrl: "http://localhost:8080/realms/myrealm/account/totp"
|
||||||
|
},
|
||||||
|
keycloakifyVersion: "9.6.1",
|
||||||
|
themeVersion: "1.0.10",
|
||||||
|
themeType: "account",
|
||||||
|
themeName: "keycloakify",
|
||||||
|
pageId: "totp.ftl"
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const WithTotpEnabled = () => (
|
||||||
|
<PageStory
|
||||||
|
kcContext={{
|
||||||
|
totp: {
|
||||||
|
enabled: true,
|
||||||
|
totpSecretEncoded: "G55E MZKC JFUD MQLT MFIF EVSB JFLG M6SO",
|
||||||
|
totpSecret: "7zFeBIh6AsaPRVAIVfzN",
|
||||||
|
manualUrl: "http://localhost:8080/realms/myrealm/account/totp?mode=manual",
|
||||||
|
supportedApplications: ["totpAppFreeOTPName", "totpAppMicrosoftAuthenticatorName", "totpAppGoogleName"],
|
||||||
|
totpSecretQrCode:
|
||||||
|
"iVBORw0KGgoAAAANSUhEUgAAAPYAAAD2AQAAAADNaUdlAAACo0lEQVR4Xu2YPY6DMBCFJ6JwyRF8k+RiSCBxsXATjkDpAmX2vTGBwErbbDFTZIps4s8rmfl9RvRPW+W6crYvv66c7cuvK2cjX0Tkho9yW/q5PHSc5QYA62PwXnWqmzrRSUdNL+mygRC8kzQZWhqVO1CRds3YHopnfUkzp2c7ZAY+GIdXywOb0qsdJMXiFn9serYrncxNv/PDkdfUzObk/eNaX368mnl1kML8RH1vFoGzargA1DM/VeWhOpf9+by5iL5Q0NaEUETslHiSIz+dOc4q0tqBrcg7IsnpnZ8BeLmjqjFa4Fps4vlR3484nFHH6OP8o1cTc4I/Q3D4Uqw1TjpkeHqc2R/Rjvb89OUUDAL/CpycOf/o6fUjP505/phrOf8wn+tolsxyD8GZnzyrJSScrNyEcXhHJwrBh2yj2fShPlFB2PQxn935aK1HIB1G1nczm8+P+nbmC7si+zell53a4i97fnhz5Gddxc9iSgLPpPifGn9vDqN0YBL0lpozdx7nd+dDHSiFXkV+NlZO85Efzvzda8yrwkylvlEbhxE4bTJpiCEIkWNHbxD/w/++fJMOVX8p5Q70F0V2EI4LsUWd+ov6Wtgu5aM/OXNIf6jWbKq6zmekA77t88WZr5lXO6vvWaj6kbNo4nv/ceaon0TpYPqrmNJhue/x9+ZKLchbO+cLPrb+aI09BLeob1en2nqkKsUYfOvatSGa/ircmD7i78rNmJoYzXwIKh228z3+ztzef+Cb6S/lSxoWOXM2CO/ZuvlqARtLvX8u1Ie6+d+bd/X9pdS3lrrF/8jPCPytv9AVIbfvddxE4iNFLKL+hH/xCNudKgTvGX/r33ars/y062gQjljfWN8cyKm+f2NPOvqTL//Lvvy6crYvv66c7d/8B/9RFjk6Tp30AAAAAElFTkSuQmCC",
|
||||||
|
policy: {
|
||||||
|
type: "totp",
|
||||||
|
algorithm: "HmacSHA1"
|
||||||
|
},
|
||||||
|
qrUrl: "http://localhost:8080/realms/myrealm/account/totp?mode=qr",
|
||||||
|
otpCredentials: [
|
||||||
|
{
|
||||||
|
id: "7afaaf7d-f2d5-44f5-a966-e5297f0b2b7a",
|
||||||
|
userLabel: "mobile"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
message: {
|
||||||
|
summary: "Mobile authenticator configured.",
|
||||||
|
type: "success"
|
||||||
|
},
|
||||||
|
url: {
|
||||||
|
totpUrl: "http://localhost:8080/realms/myrealm/account/totp"
|
||||||
|
},
|
||||||
|
messagesPerField: {},
|
||||||
|
stateChecker: "0UvyCNJHRJXmdahtRmn0tTPCU2nwLtWBUfPaaX1qb4g",
|
||||||
|
realm: {
|
||||||
|
userManagedAccessAllowed: true,
|
||||||
|
internationalizationEnabled: false
|
||||||
|
},
|
||||||
|
keycloakifyVersion: "9.6.1",
|
||||||
|
themeVersion: "1.0.10",
|
||||||
|
themeType: "account",
|
||||||
|
themeName: "keycloakify",
|
||||||
|
pageId: "totp.ftl"
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const WithManualMode = () => (
|
||||||
|
<PageStory
|
||||||
|
kcContext={{
|
||||||
|
mode: "manual",
|
||||||
|
totp: {
|
||||||
|
enabled: false,
|
||||||
|
totpSecretEncoded: "KZ5H CYTW GBVV ASDE JRXG MMCK HAZU E6TX",
|
||||||
|
totpSecret: "Vzqbv0kPHdLnf0J83Bzw",
|
||||||
|
manualUrl: "http://localhost:8080/realms/myrealm/account/totp?mode=manual",
|
||||||
|
totpSecretQrCode:
|
||||||
|
"iVBORw0KGgoAAAANSUhEUgAAAPYAAAD2AQAAAADNaUdlAAACpklEQVR4Xu2YQa6rMAxFXTFgyBLYSbsxJJC6sb6dZAkdMkDNv8cBStHTm/yBM2ikIpqTgePY1w6W/xyLnWc+x5efZz7Hl59nPgf8aWaXPFl+2ZhbzfWaGPTT3yr4mPPPs8nty4ZeKxfzRQ6q4IO1P8zq0c/iffvqtIlLTfw5psxsK3f7JirjTHDqWpQ3T9fC/fytn2956u32bNJv8RHIyZ/n0MvJh8cpvwJ5GffkQaBNYPo2auCyv30YVmtitm4yu1qT5mtXCR9svsqXeih1/I1IbZHLKniTskxPOvCGSB3Wud2/0Vz+5YH9uHZAvzORUAlXaXmY9FHxyZuWI0L5sfs3lkt1vDTbtVtM8bmovrCT26o/0bxozVAWIY3IuTLpsvk3mDNeRv9QqrJWEp+25Xc01/uMVudHpySiE3PXklN1cLSm8yCgKmuWICUIxip4vqM6Y+kalNX3hJNtz+9orgOXQ60noZPrd/H5u74E86I/pfXXm/obXPvOr2juVW8o9nsTS77T5Ix18CZ71sh+qQ7n3+LzY32J5WptXt291Bdaf8tcVw76Hcvpqr31R3CUOri7Q79r4ap61+5O12XoT1leOrFK+HZ/asga/sr0tz5F85wozWq4aMKcP1DK3f54Ttfv+a0iqG1wCU2H/iGWl156IionQYWmngTpan84H9aGy+8nl7I8J5ejOnjP0SNCC/0/lVpydKyPwZz7u/Xef80ouaRHHt7PP5j74BJFfBpJ3vLp460/wdxtxX5KM6XPMvktJ6/7i+YjvfRS/Gs3za3218LJH5qwzKKf7fzd3fXwEWmkf5WTKS3JN1YRTxKhiY9IC6mzUKmP/g3knL8cqoeUiKvJL/EZyT1/sJ/vg+X7G07e7Q/mf40vP898ji8/z3yO/+b/ANUwOXCzdQgqAAAAAElFTkSuQmCC",
|
||||||
|
policy: {
|
||||||
|
type: "totp",
|
||||||
|
algorithm: "HmacSHA1"
|
||||||
|
},
|
||||||
|
qrUrl: "http://localhost:8080/realms/myrealm/account/totp?mode=qr",
|
||||||
|
otpCredentials: []
|
||||||
|
},
|
||||||
|
messagesPerField: {},
|
||||||
|
stateChecker: "HiBl2ADzLwKwQS813LOEig1Ymm4xpEu_NacYtWJIuHU",
|
||||||
|
realm: {
|
||||||
|
userManagedAccessAllowed: true,
|
||||||
|
internationalizationEnabled: false
|
||||||
|
},
|
||||||
|
url: {
|
||||||
|
totpUrl: "http://localhost:8080/realms/myrealm/account/totp?mode=manual"
|
||||||
|
},
|
||||||
|
keycloakifyVersion: "9.6.1",
|
||||||
|
themeVersion: "1.0.10",
|
||||||
|
themeType: "account",
|
||||||
|
themeName: "keycloakify",
|
||||||
|
pageId: "totp.ftl"
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const MoreThanOneTotpProviders = () => (
|
||||||
|
<PageStory
|
||||||
|
kcContext={{
|
||||||
|
totp: {
|
||||||
|
enabled: true,
|
||||||
|
totpSecretEncoded: "G55E MZKC JFUD MQLT MFIF EVSB JFLG M6SO",
|
||||||
|
totpSecret: "7zFeBIh6AsaPRVAIVfzN",
|
||||||
|
manualUrl: "http://localhost:8080/realms/myrealm/account/totp?mode=manual",
|
||||||
|
supportedApplications: ["totpAppFreeOTPName", "totpAppMicrosoftAuthenticatorName", "totpAppGoogleName"],
|
||||||
|
totpSecretQrCode:
|
||||||
|
"iVBORw0KGgoAAAANSUhEUgAAAPYAAAD2AQAAAADNaUdlAAACo0lEQVR4Xu2YPY6DMBCFJ6JwyRF8k+RiSCBxsXATjkDpAmX2vTGBwErbbDFTZIps4s8rmfl9RvRPW+W6crYvv66c7cuvK2cjX0Tkho9yW/q5PHSc5QYA62PwXnWqmzrRSUdNL+mygRC8kzQZWhqVO1CRds3YHopnfUkzp2c7ZAY+GIdXywOb0qsdJMXiFn9serYrncxNv/PDkdfUzObk/eNaX368mnl1kML8RH1vFoGzargA1DM/VeWhOpf9+by5iL5Q0NaEUETslHiSIz+dOc4q0tqBrcg7IsnpnZ8BeLmjqjFa4Fps4vlR3484nFHH6OP8o1cTc4I/Q3D4Uqw1TjpkeHqc2R/Rjvb89OUUDAL/CpycOf/o6fUjP505/phrOf8wn+tolsxyD8GZnzyrJSScrNyEcXhHJwrBh2yj2fShPlFB2PQxn935aK1HIB1G1nczm8+P+nbmC7si+zell53a4i97fnhz5Gddxc9iSgLPpPifGn9vDqN0YBL0lpozdx7nd+dDHSiFXkV+NlZO85Efzvzda8yrwkylvlEbhxE4bTJpiCEIkWNHbxD/w/++fJMOVX8p5Q70F0V2EI4LsUWd+ov6Wtgu5aM/OXNIf6jWbKq6zmekA77t88WZr5lXO6vvWaj6kbNo4nv/ceaon0TpYPqrmNJhue/x9+ZKLchbO+cLPrb+aI09BLeob1en2nqkKsUYfOvatSGa/ircmD7i78rNmJoYzXwIKh228z3+ztzef+Cb6S/lSxoWOXM2CO/ZuvlqARtLvX8u1Ie6+d+bd/X9pdS3lrrF/8jPCPytv9AVIbfvddxE4iNFLKL+hH/xCNudKgTvGX/r33ars/y062gQjljfWN8cyKm+f2NPOvqTL//Lvvy6crYvv66c7d/8B/9RFjk6Tp30AAAAAElFTkSuQmCC",
|
||||||
|
policy: {
|
||||||
|
type: "totp",
|
||||||
|
algorithm: "HmacSHA1"
|
||||||
|
},
|
||||||
|
qrUrl: "http://localhost:8080/realms/myrealm/account/totp?mode=qr",
|
||||||
|
otpCredentials: [
|
||||||
|
{
|
||||||
|
id: "7afaaf7d-f2d5-44f5-a966-e5297f0b2b7a",
|
||||||
|
userLabel: "Samsung S23"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "fbe22500-d979-45a3-9666-84c99e27958e",
|
||||||
|
userLabel: "Apple Iphone 15"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
url: {
|
||||||
|
totpUrl: "http://localhost:8080/realms/myrealm/account/totp"
|
||||||
|
},
|
||||||
|
messagesPerField: {},
|
||||||
|
stateChecker: "0UvyCNJHRJXmdahtRmn0tTPCU2nwLtWBUfPaaX1qb4g",
|
||||||
|
realm: {
|
||||||
|
userManagedAccessAllowed: true,
|
||||||
|
internationalizationEnabled: false
|
||||||
|
},
|
||||||
|
keycloakifyVersion: "9.6.1",
|
||||||
|
themeVersion: "1.0.10",
|
||||||
|
themeType: "account",
|
||||||
|
themeName: "keycloakify",
|
||||||
|
pageId: "totp.ftl"
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
34
stories/account/pages/FederatedIdentity.stories.tsx
Normal file
34
stories/account/pages/FederatedIdentity.stories.tsx
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Meta } from "@storybook/react";
|
||||||
|
import { createPageStory } from "../createPageStory";
|
||||||
|
|
||||||
|
const pageId = "federatedIdentity.ftl";
|
||||||
|
|
||||||
|
const { PageStory } = createPageStory({ pageId });
|
||||||
|
|
||||||
|
const meta = {
|
||||||
|
title: "account/FederatedIdentity",
|
||||||
|
component: PageStory
|
||||||
|
} satisfies Meta<typeof PageStory>;
|
||||||
|
|
||||||
|
export default meta;
|
||||||
|
|
||||||
|
export const Default = () => <PageStory />;
|
||||||
|
|
||||||
|
export const NotConnected = () => (
|
||||||
|
<PageStory
|
||||||
|
kcContext={{
|
||||||
|
pageId: "federatedIdentity.ftl",
|
||||||
|
federatedIdentity: {
|
||||||
|
identities: [
|
||||||
|
{
|
||||||
|
providerId: "google",
|
||||||
|
displayName: "keycloak-oidc",
|
||||||
|
connected: false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
removeLinkPossible: true
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
354
stories/account/pages/Log.stories.tsx
Normal file
354
stories/account/pages/Log.stories.tsx
Normal file
@ -0,0 +1,354 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Meta } from "@storybook/react";
|
||||||
|
import { createPageStory } from "../createPageStory";
|
||||||
|
|
||||||
|
const pageId = "log.ftl";
|
||||||
|
|
||||||
|
const { PageStory } = createPageStory({
|
||||||
|
pageId
|
||||||
|
});
|
||||||
|
|
||||||
|
const meta = {
|
||||||
|
title: "account/Log",
|
||||||
|
component: PageStory
|
||||||
|
} satisfies Meta<typeof PageStory>;
|
||||||
|
|
||||||
|
export default meta;
|
||||||
|
|
||||||
|
export const Default = () => (
|
||||||
|
<PageStory
|
||||||
|
kcContext={{
|
||||||
|
log: {
|
||||||
|
events: [
|
||||||
|
{
|
||||||
|
date: "2024-04-26T12:29:08Z",
|
||||||
|
ipAddress: "127.0.0.1",
|
||||||
|
client: "keycloakify-frontend",
|
||||||
|
details: [
|
||||||
|
{
|
||||||
|
value: "openid-connect",
|
||||||
|
key: "auth_method"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "john.doe",
|
||||||
|
key: "username"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
event: "login"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: "2024-04-26T12:10:56Z",
|
||||||
|
ipAddress: "127.0.0.1",
|
||||||
|
client: "keycloakify-frontend",
|
||||||
|
details: [
|
||||||
|
{
|
||||||
|
value: "openid-connect",
|
||||||
|
key: "auth_method"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "john.doe",
|
||||||
|
key: "username"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
event: "login"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: "2024-04-26T11:57:34Z",
|
||||||
|
ipAddress: "127.0.0.1",
|
||||||
|
client: "account",
|
||||||
|
details: [],
|
||||||
|
event: "update totp"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: "2024-04-26T11:57:21Z",
|
||||||
|
ipAddress: "127.0.0.1",
|
||||||
|
client: "account",
|
||||||
|
details: [],
|
||||||
|
event: "update totp"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: "2024-04-26T11:56:56Z",
|
||||||
|
ipAddress: "127.0.0.1",
|
||||||
|
client: "account",
|
||||||
|
details: [],
|
||||||
|
event: "remove totp"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: "2024-04-26T11:56:55Z",
|
||||||
|
ipAddress: "127.0.0.1",
|
||||||
|
client: "account",
|
||||||
|
details: [],
|
||||||
|
event: "remove totp"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: "2024-04-26T11:56:41Z",
|
||||||
|
ipAddress: "127.0.0.1",
|
||||||
|
client: "account",
|
||||||
|
details: [],
|
||||||
|
event: "update totp"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: "2024-04-26T11:56:36Z",
|
||||||
|
ipAddress: "127.0.0.1",
|
||||||
|
client: "account",
|
||||||
|
details: [],
|
||||||
|
event: "update totp"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: "2024-04-26T11:32:54Z",
|
||||||
|
ipAddress: "127.0.0.1",
|
||||||
|
client: "keycloakify-frontend",
|
||||||
|
details: [
|
||||||
|
{
|
||||||
|
value: "openid-connect",
|
||||||
|
key: "auth_method"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "john.doe",
|
||||||
|
key: "username"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
event: "login"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: "2024-04-26T09:42:54Z",
|
||||||
|
ipAddress: "127.0.0.1",
|
||||||
|
client: "keycloakify-frontend",
|
||||||
|
details: [
|
||||||
|
{
|
||||||
|
value: "openid-connect",
|
||||||
|
key: "auth_method"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "john.doe",
|
||||||
|
key: "username"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
event: "login"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: "2024-04-26T09:42:52Z",
|
||||||
|
ipAddress: "127.0.0.1",
|
||||||
|
client: "keycloakify-frontend",
|
||||||
|
details: [
|
||||||
|
{
|
||||||
|
value: "openid-connect",
|
||||||
|
key: "auth_method"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "john.doe",
|
||||||
|
key: "username"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
event: "login"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: "2024-04-26T09:42:40Z",
|
||||||
|
ipAddress: "127.0.0.1",
|
||||||
|
client: "keycloakify-frontend",
|
||||||
|
details: [
|
||||||
|
{
|
||||||
|
value: "openid-connect",
|
||||||
|
key: "auth_method"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "john.doe",
|
||||||
|
key: "username"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
event: "login"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: "2024-04-26T09:42:09Z",
|
||||||
|
ipAddress: "127.0.0.1",
|
||||||
|
client: "keycloakify-frontend",
|
||||||
|
details: [
|
||||||
|
{
|
||||||
|
value: "openid-connect",
|
||||||
|
key: "auth_method"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "false",
|
||||||
|
key: "remember_me"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "john.doe",
|
||||||
|
key: "username"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
event: "login"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: "2024-04-26T09:24:17Z",
|
||||||
|
ipAddress: "127.0.0.1",
|
||||||
|
client: "keycloakify-frontend",
|
||||||
|
details: [],
|
||||||
|
event: "logout"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: "2024-04-26T09:23:54Z",
|
||||||
|
ipAddress: "127.0.0.1",
|
||||||
|
client: "keycloakify-frontend",
|
||||||
|
details: [
|
||||||
|
{
|
||||||
|
value: "openid-connect",
|
||||||
|
key: "auth_method"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "john.doe",
|
||||||
|
key: "username"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
event: "login"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: "2024-04-26T09:23:50Z",
|
||||||
|
ipAddress: "127.0.0.1",
|
||||||
|
client: "keycloakify-frontend",
|
||||||
|
details: [
|
||||||
|
{
|
||||||
|
value: "openid-connect",
|
||||||
|
key: "auth_method"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "john.doe",
|
||||||
|
key: "username"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
event: "login"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: "2024-04-26T09:23:47Z",
|
||||||
|
ipAddress: "127.0.0.1",
|
||||||
|
client: "account",
|
||||||
|
details: [
|
||||||
|
{
|
||||||
|
value: "openid-connect",
|
||||||
|
key: "auth_method"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "john.doe",
|
||||||
|
key: "username"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
event: "login"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: "2024-04-26T09:23:15Z",
|
||||||
|
ipAddress: "127.0.0.1",
|
||||||
|
client: "keycloakify-frontend",
|
||||||
|
details: [],
|
||||||
|
event: "logout"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: "2024-04-26T09:23:06Z",
|
||||||
|
ipAddress: "127.0.0.1",
|
||||||
|
client: "keycloakify-frontend",
|
||||||
|
details: [
|
||||||
|
{
|
||||||
|
value: "openid-connect",
|
||||||
|
key: "auth_method"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "john.doe",
|
||||||
|
key: "username"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
event: "login"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: "2024-04-26T09:22:53Z",
|
||||||
|
ipAddress: "127.0.0.1",
|
||||||
|
client: "keycloakify-frontend",
|
||||||
|
details: [],
|
||||||
|
event: "logout"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: "2024-04-26T09:21:29Z",
|
||||||
|
ipAddress: "127.0.0.1",
|
||||||
|
client: "keycloakify-frontend",
|
||||||
|
details: [
|
||||||
|
{
|
||||||
|
value: "openid-connect",
|
||||||
|
key: "auth_method"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "false",
|
||||||
|
key: "remember_me"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "john.doe",
|
||||||
|
key: "username"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
event: "login"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: "2024-04-26T09:17:32Z",
|
||||||
|
ipAddress: "127.0.0.1",
|
||||||
|
client: "keycloakify-frontend",
|
||||||
|
details: [
|
||||||
|
{
|
||||||
|
value: "openid-connect",
|
||||||
|
key: "auth_method"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "john.doe",
|
||||||
|
key: "username"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
event: "login"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: "2024-04-18T11:19:09Z",
|
||||||
|
ipAddress: "127.0.0.1",
|
||||||
|
client: "keycloakify-frontend",
|
||||||
|
details: [
|
||||||
|
{
|
||||||
|
value: "openid-connect",
|
||||||
|
key: "auth_method"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "john.doe",
|
||||||
|
key: "username"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
event: "login"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: "2024-04-18T11:18:50Z",
|
||||||
|
ipAddress: "127.0.0.1",
|
||||||
|
client: "keycloakify-frontend",
|
||||||
|
details: [
|
||||||
|
{
|
||||||
|
value: "openid-connect",
|
||||||
|
key: "auth_method"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "john.doe",
|
||||||
|
key: "username"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
event: "login"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: "2024-04-18T11:18:24Z",
|
||||||
|
ipAddress: "127.0.0.1",
|
||||||
|
client: "account",
|
||||||
|
details: [
|
||||||
|
{
|
||||||
|
value: "openid-connect",
|
||||||
|
key: "auth_method"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "john.doe",
|
||||||
|
key: "username"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
event: "login"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
@ -1,23 +1,15 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import type { ComponentMeta } from "@storybook/react";
|
import { Meta } from "@storybook/react";
|
||||||
import { createPageStory } from "../createPageStory";
|
import { createPageStory } from "../createPageStory";
|
||||||
|
|
||||||
const pageId = "password.ftl";
|
const pageId = "password.ftl";
|
||||||
|
|
||||||
const { PageStory } = createPageStory({ pageId });
|
const { PageStory } = createPageStory({ pageId });
|
||||||
|
|
||||||
const meta: ComponentMeta<any> = {
|
const meta = {
|
||||||
title: `account/${pageId}`,
|
title: "account/Password",
|
||||||
component: PageStory,
|
component: PageStory
|
||||||
parameters: {
|
} satisfies Meta<typeof PageStory>;
|
||||||
viewMode: "story",
|
|
||||||
previewTabs: {
|
|
||||||
"storybook/docs/panel": {
|
|
||||||
hidden: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
|
@ -1,26 +1,55 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import type { ComponentMeta } from "@storybook/react";
|
import { Meta } from "@storybook/react";
|
||||||
import { createPageStory } from "../createPageStory";
|
import { createPageStory } from "../createPageStory";
|
||||||
|
|
||||||
const pageId = "sessions.ftl";
|
const pageId = "sessions.ftl";
|
||||||
|
|
||||||
const { PageStory } = createPageStory({ pageId });
|
const { PageStory } = createPageStory({ pageId });
|
||||||
|
|
||||||
const meta: ComponentMeta<any> = {
|
const meta = {
|
||||||
title: `account/${pageId}`,
|
title: "account/Sessions",
|
||||||
component: PageStory,
|
component: PageStory
|
||||||
parameters: {
|
} satisfies Meta<typeof PageStory>;
|
||||||
viewMode: "story",
|
|
||||||
previewTabs: {
|
|
||||||
"storybook/docs/panel": {
|
|
||||||
hidden: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
export const Default = () => <PageStory />;
|
export const Default = () => (
|
||||||
|
<PageStory
|
||||||
|
kcContext={{
|
||||||
|
sessions: {
|
||||||
|
sessions: [
|
||||||
|
{
|
||||||
|
expires: "2024-04-26T18:14:19Z",
|
||||||
|
clients: ["account"],
|
||||||
|
ipAddress: "172.20.0.1",
|
||||||
|
started: "2024-04-26T08:14:19Z",
|
||||||
|
lastAccess: "2024-04-26T08:30:54Z",
|
||||||
|
id: "af835e30-4821-43b1-b4f7-e732d3cc15d2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
expires: "2024-04-26T18:14:09Z",
|
||||||
|
clients: ["security-admin-console", "account"],
|
||||||
|
ipAddress: "172.20.0.1",
|
||||||
|
started: "2024-04-26T08:14:09Z",
|
||||||
|
lastAccess: "2024-04-26T08:15:14Z",
|
||||||
|
id: "60a9d8b8-617d-441e-8643-08c3fe30e231"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
stateChecker: "xQ7EOgFrLi4EvnJ8dbXKhwFGWk_bkOp0X89mhilt1os"
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
export const WithMessage = () => <PageStory kcContext={{}} />;
|
export const WithError = () => (
|
||||||
|
<PageStory
|
||||||
|
kcContext={{
|
||||||
|
url: { passwordUrl: "/auth/realms/keycloakify/account/password" },
|
||||||
|
stateChecker: "xQ7EOgFrLi4EvnJ8dbXKhwFGWk_bkOp0X89mhilt1os",
|
||||||
|
message: {
|
||||||
|
summary: "Invalid existing password.",
|
||||||
|
type: "error"
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
@ -1,23 +1,15 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import type { ComponentMeta } from "@storybook/react";
|
import { Meta } from "@storybook/react";
|
||||||
import { createPageStory } from "../createPageStory";
|
import { createPageStory } from "../createPageStory";
|
||||||
|
|
||||||
const pageId = "totp.ftl";
|
const pageId = "totp.ftl";
|
||||||
|
|
||||||
const { PageStory } = createPageStory({ pageId });
|
const { PageStory } = createPageStory({ pageId });
|
||||||
|
|
||||||
const meta: ComponentMeta<any> = {
|
const meta = {
|
||||||
title: `account/${pageId}`,
|
title: "account/Authenticator",
|
||||||
component: PageStory,
|
component: PageStory
|
||||||
parameters: {
|
} satisfies Meta<typeof PageStory>;
|
||||||
viewMode: "story",
|
|
||||||
previewTabs: {
|
|
||||||
"storybook/docs/panel": {
|
|
||||||
hidden: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user