Compare commits
24 Commits
Author | SHA1 | Date | |
---|---|---|---|
d4ac67dba8 | |||
23f4b59559 | |||
4a7ba4a1c9 | |||
a3e765e1fc | |||
ee3614dbf1 | |||
8099ec1ffe | |||
2e2b0ab3ae | |||
a1f15f2f6b | |||
8fe74fe7ee | |||
232be50225 | |||
a00bb0c4db | |||
5517d6baf4 | |||
e2975503a4 | |||
1231c92198 | |||
64ca0bc0ca | |||
2bceb9385c | |||
954bc43c22 | |||
8c99aa4b9d | |||
884195d30d | |||
17dd726158 | |||
7ee30b6a42 | |||
397f8133bf | |||
c9abc6dc5c | |||
e78eafd1f1 |
@ -309,6 +309,24 @@
|
|||||||
"contributions": [
|
"contributions": [
|
||||||
"bug"
|
"bug"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "zvn2060",
|
||||||
|
"name": "HI_OuO",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/45450852?v=4",
|
||||||
|
"profile": "https://github.com/zvn2060",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "tripheo0412",
|
||||||
|
"name": "Tri Hoang",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/25382052?v=4",
|
||||||
|
"profile": "https://github.com/tripheo0412",
|
||||||
|
"contributions": [
|
||||||
|
"doc"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"contributorsPerLine": 7,
|
"contributorsPerLine": 7,
|
||||||
|
@ -165,6 +165,8 @@ 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/luca-peruzzo"><img src="https://avatars.githubusercontent.com/u/69015314?v=4?s=100" width="100px;" alt="Luca Peruzzo"/><br /><sub><b>Luca Peruzzo</b></sub></a><br /><a href="https://github.com/keycloakify/keycloakify/commits?author=luca-peruzzo" title="Code">💻</a> <a href="https://github.com/keycloakify/keycloakify/commits?author=luca-peruzzo" title="Tests">⚠️</a></td>
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/luca-peruzzo"><img src="https://avatars.githubusercontent.com/u/69015314?v=4?s=100" width="100px;" alt="Luca Peruzzo"/><br /><sub><b>Luca Peruzzo</b></sub></a><br /><a href="https://github.com/keycloakify/keycloakify/commits?author=luca-peruzzo" title="Code">💻</a> <a href="https://github.com/keycloakify/keycloakify/commits?author=luca-peruzzo" title="Tests">⚠️</a></td>
|
||||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/nima70"><img src="https://avatars.githubusercontent.com/u/5094767?v=4?s=100" width="100px;" alt="Nima Shokouhfar"/><br /><sub><b>Nima Shokouhfar</b></sub></a><br /><a href="https://github.com/keycloakify/keycloakify/commits?author=nima70" title="Code">💻</a> <a href="https://github.com/keycloakify/keycloakify/commits?author=nima70" title="Tests">⚠️</a></td>
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/nima70"><img src="https://avatars.githubusercontent.com/u/5094767?v=4?s=100" width="100px;" alt="Nima Shokouhfar"/><br /><sub><b>Nima Shokouhfar</b></sub></a><br /><a href="https://github.com/keycloakify/keycloakify/commits?author=nima70" title="Code">💻</a> <a href="https://github.com/keycloakify/keycloakify/commits?author=nima70" title="Tests">⚠️</a></td>
|
||||||
<td align="center" valign="top" width="14.28%"><a href="https://mruder.dev"><img src="https://avatars.githubusercontent.com/u/18495294?v=4?s=100" width="100px;" alt="Marvin A. Ruder"/><br /><sub><b>Marvin A. Ruder</b></sub></a><br /><a href="https://github.com/keycloakify/keycloakify/issues?q=author%3Amarvinruder" title="Bug reports">🐛</a></td>
|
<td align="center" valign="top" width="14.28%"><a href="https://mruder.dev"><img src="https://avatars.githubusercontent.com/u/18495294?v=4?s=100" width="100px;" alt="Marvin A. Ruder"/><br /><sub><b>Marvin A. Ruder</b></sub></a><br /><a href="https://github.com/keycloakify/keycloakify/issues?q=author%3Amarvinruder" title="Bug reports">🐛</a></td>
|
||||||
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zvn2060"><img src="https://avatars.githubusercontent.com/u/45450852?v=4?s=100" width="100px;" alt="HI_OuO"/><br /><sub><b>HI_OuO</b></sub></a><br /><a href="https://github.com/keycloakify/keycloakify/commits?author=zvn2060" title="Code">💻</a></td>
|
||||||
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/tripheo0412"><img src="https://avatars.githubusercontent.com/u/25382052?v=4?s=100" width="100px;" alt="Tri Hoang"/><br /><sub><b>Tri Hoang</b></sub></a><br /><a href="https://github.com/keycloakify/keycloakify/commits?author=tripheo0412" title="Documentation">📖</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "keycloakify",
|
"name": "keycloakify",
|
||||||
"version": "11.3.20",
|
"version": "11.3.25",
|
||||||
"description": "Framework to create custom Keycloak UIs",
|
"description": "Framework to create custom Keycloak UIs",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -32,27 +32,38 @@ export async function getUiModuleFileSourceCodeReadyToBeCopied(params: {
|
|||||||
await fsPr.readFile(pathJoin(uiModuleDirPath, KEYCLOAK_THEME, fileRelativePath))
|
await fsPr.readFile(pathJoin(uiModuleDirPath, KEYCLOAK_THEME, fileRelativePath))
|
||||||
).toString("utf8");
|
).toString("utf8");
|
||||||
|
|
||||||
const comment = (() => {
|
const toComment = (lines: string[]) => {
|
||||||
if (isForEjection) {
|
for (const ext of [".ts", ".tsx", ".css", ".less", ".sass", ".js", ".jsx"]) {
|
||||||
return [
|
if (!fileRelativePath.endsWith(ext)) {
|
||||||
`/*`,
|
continue;
|
||||||
`This file was ejected from ${uiModuleName} version ${uiModuleVersion}.`,
|
}
|
||||||
`*/`
|
|
||||||
].join("\n");
|
|
||||||
} else {
|
|
||||||
return [
|
|
||||||
`/*`,
|
|
||||||
`WARNING: Before modifying this file run the following command:`,
|
|
||||||
``,
|
|
||||||
`npx keycloakify eject-file --file ${fileRelativePath.split(pathSep).join("/")}\``,
|
|
||||||
``,
|
|
||||||
`This file comes from ${uiModuleName} version ${uiModuleVersion}.`,
|
|
||||||
`*/`
|
|
||||||
];
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
sourceCode = [comment, ``, sourceCode].join("\n");
|
return [`/**`, ...lines.map(line => ` * ${line}`), ` */`].join("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileRelativePath.endsWith(".html")) {
|
||||||
|
return [`<!--`, ...lines.map(line => ` ${line}`), `-->`].join("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const comment = toComment(
|
||||||
|
isForEjection
|
||||||
|
? [`This file was ejected from ${uiModuleName} version ${uiModuleVersion}.`]
|
||||||
|
: [
|
||||||
|
`WARNING: Before modifying this file run the following command:`,
|
||||||
|
``,
|
||||||
|
`$ npx keycloakify eject-file --file ${fileRelativePath.split(pathSep).join("/")}`,
|
||||||
|
``,
|
||||||
|
`This file comes from ${uiModuleName} version ${uiModuleVersion}.`,
|
||||||
|
`This file has been copied over to your repo by your postinstall script: \`npx keycloakify postinstall\``
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
if (comment !== undefined) {
|
||||||
|
sourceCode = [comment, ``, sourceCode].join("\n");
|
||||||
|
}
|
||||||
|
|
||||||
const destFilePath = pathJoin(buildContext.themeSrcDirPath, fileRelativePath);
|
const destFilePath = pathJoin(buildContext.themeSrcDirPath, fileRelativePath);
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ import { SemVer } from "../tools/SemVer";
|
|||||||
import { same } from "evt/tools/inDepth/same";
|
import { same } from "evt/tools/inDepth/same";
|
||||||
import { runPrettier, getIsPrettierAvailable } from "../tools/runPrettier";
|
import { runPrettier, getIsPrettierAvailable } from "../tools/runPrettier";
|
||||||
import { npmInstall } from "../tools/npmInstall";
|
import { npmInstall } from "../tools/npmInstall";
|
||||||
|
import { dirname as pathDirname } from "path";
|
||||||
|
|
||||||
export type BuildContextLike = {
|
export type BuildContextLike = {
|
||||||
packageJsonFilePath: string;
|
packageJsonFilePath: string;
|
||||||
@ -150,7 +151,7 @@ export async function installUiModulesPeerDependencies(params: {
|
|||||||
await fsPr.writeFile(buildContext.packageJsonFilePath, packageJsonContentStr);
|
await fsPr.writeFile(buildContext.packageJsonFilePath, packageJsonContentStr);
|
||||||
|
|
||||||
npmInstall({
|
npmInstall({
|
||||||
packageJsonDirPath: buildContext.packageJsonFilePath
|
packageJsonDirPath: pathDirname(buildContext.packageJsonFilePath)
|
||||||
});
|
});
|
||||||
|
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
|
@ -38,9 +38,9 @@ export async function writeManagedGitignoreFile(params: {
|
|||||||
`# This file is managed by Keycloakify, do not edit it manually.`,
|
`# This file is managed by Keycloakify, do not edit it manually.`,
|
||||||
``,
|
``,
|
||||||
DELIMITER_START,
|
DELIMITER_START,
|
||||||
...ejectedFilesRelativePaths.map(fileRelativePath =>
|
...ejectedFilesRelativePaths
|
||||||
fileRelativePath.split(pathSep).join("/")
|
.map(fileRelativePath => fileRelativePath.split(pathSep).join("/"))
|
||||||
),
|
.map(line => `# ${line}`),
|
||||||
DELIMITER_END,
|
DELIMITER_END,
|
||||||
``,
|
``,
|
||||||
...uiModuleMetas
|
...uiModuleMetas
|
||||||
@ -122,6 +122,7 @@ export async function readManagedGitignoreFile(params: {
|
|||||||
const ejectedFilesRelativePaths = payload
|
const ejectedFilesRelativePaths = payload
|
||||||
.split("\n")
|
.split("\n")
|
||||||
.map(line => line.trim())
|
.map(line => line.trim())
|
||||||
|
.map(line => line.replace(/^# /, ""))
|
||||||
.filter(line => line !== "")
|
.filter(line => line !== "")
|
||||||
.map(line =>
|
.map(line =>
|
||||||
getAbsoluteAndInOsFormatPath({
|
getAbsoluteAndInOsFormatPath({
|
||||||
|
@ -9,6 +9,8 @@ import { dirname as pathDirname } from "path";
|
|||||||
import { join as pathJoin } from "path";
|
import { join as pathJoin } from "path";
|
||||||
import { existsAsync } from "../tools/fs.existsAsync";
|
import { existsAsync } from "../tools/fs.existsAsync";
|
||||||
import * as fsPr from "fs/promises";
|
import * as fsPr from "fs/promises";
|
||||||
|
import { getIsTrackedByGit } from "../tools/isTrackedByGit";
|
||||||
|
import { untrackFromGit } from "../tools/untrackFromGit";
|
||||||
|
|
||||||
export async function command(params: { buildContext: BuildContext }) {
|
export async function command(params: { buildContext: BuildContext }) {
|
||||||
const { buildContext } = params;
|
const { buildContext } = params;
|
||||||
@ -45,8 +47,10 @@ export async function command(params: { buildContext: BuildContext }) {
|
|||||||
fileRelativePath
|
fileRelativePath
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const doesFileExist = await existsAsync(destFilePath);
|
||||||
|
|
||||||
skip_condition: {
|
skip_condition: {
|
||||||
if (!(await existsAsync(destFilePath))) {
|
if (!doesFileExist) {
|
||||||
break skip_condition;
|
break skip_condition;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,8 +65,26 @@ export async function command(params: { buildContext: BuildContext }) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
git_untrack: {
|
||||||
|
if (!doesFileExist) {
|
||||||
|
break git_untrack;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isTracked = await getIsTrackedByGit({
|
||||||
|
filePath: destFilePath
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!isTracked) {
|
||||||
|
break git_untrack;
|
||||||
|
}
|
||||||
|
|
||||||
|
await untrackFromGit({
|
||||||
|
filePath: destFilePath
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
const dirName = pathDirname(copyableFilePath);
|
const dirName = pathDirname(destFilePath);
|
||||||
|
|
||||||
if (!(await existsAsync(dirName))) {
|
if (!(await existsAsync(dirName))) {
|
||||||
await fsPr.mkdir(dirName, { recursive: true });
|
await fsPr.mkdir(dirName, { recursive: true });
|
||||||
|
@ -16,6 +16,7 @@ import {
|
|||||||
} from "./getUiModuleFileSourceCodeReadyToBeCopied";
|
} from "./getUiModuleFileSourceCodeReadyToBeCopied";
|
||||||
import * as crypto from "crypto";
|
import * as crypto from "crypto";
|
||||||
import { KEYCLOAK_THEME } from "../shared/constants";
|
import { KEYCLOAK_THEME } from "../shared/constants";
|
||||||
|
import { exclude } from "tsafe/exclude";
|
||||||
|
|
||||||
export type UiModuleMeta = {
|
export type UiModuleMeta = {
|
||||||
moduleName: string;
|
moduleName: string;
|
||||||
@ -113,11 +114,16 @@ export async function getUiModuleMetas(params: {
|
|||||||
moduleName.includes("keycloakify") && moduleName !== "keycloakify"
|
moduleName.includes("keycloakify") && moduleName !== "keycloakify"
|
||||||
});
|
});
|
||||||
|
|
||||||
return Promise.all(
|
return (
|
||||||
installedModulesWithKeycloakifyInTheName.filter(async ({ dirPath }) =>
|
await Promise.all(
|
||||||
existsAsync(pathJoin(dirPath, KEYCLOAK_THEME))
|
installedModulesWithKeycloakifyInTheName.map(async entry => {
|
||||||
|
if (!(await existsAsync(pathJoin(entry.dirPath, KEYCLOAK_THEME)))) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return entry;
|
||||||
|
})
|
||||||
)
|
)
|
||||||
);
|
).filter(exclude(undefined));
|
||||||
})();
|
})();
|
||||||
|
|
||||||
const cacheContent = await (async () => {
|
const cacheContent = await (async () => {
|
||||||
|
@ -6,19 +6,19 @@ import { assert, type Equals } from "tsafe/assert";
|
|||||||
export async function crawlAsync(params: {
|
export async function crawlAsync(params: {
|
||||||
dirPath: string;
|
dirPath: string;
|
||||||
returnedPathsType: "absolute" | "relative to dirPath";
|
returnedPathsType: "absolute" | "relative to dirPath";
|
||||||
onFileFound: (filePath: string) => void;
|
onFileFound: (filePath: string) => Promise<void>;
|
||||||
}) {
|
}) {
|
||||||
const { dirPath, returnedPathsType, onFileFound } = params;
|
const { dirPath, returnedPathsType, onFileFound } = params;
|
||||||
|
|
||||||
await crawlAsyncRec({
|
await crawlAsyncRec({
|
||||||
dirPath,
|
dirPath,
|
||||||
onFileFound: ({ filePath }) => {
|
onFileFound: async ({ filePath }) => {
|
||||||
switch (returnedPathsType) {
|
switch (returnedPathsType) {
|
||||||
case "absolute":
|
case "absolute":
|
||||||
onFileFound(filePath);
|
await onFileFound(filePath);
|
||||||
return;
|
return;
|
||||||
case "relative to dirPath":
|
case "relative to dirPath":
|
||||||
onFileFound(pathRelative(dirPath, filePath));
|
await onFileFound(pathRelative(dirPath, filePath));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assert<Equals<typeof returnedPathsType, never>>();
|
assert<Equals<typeof returnedPathsType, never>>();
|
||||||
@ -28,7 +28,7 @@ export async function crawlAsync(params: {
|
|||||||
|
|
||||||
async function crawlAsyncRec(params: {
|
async function crawlAsyncRec(params: {
|
||||||
dirPath: string;
|
dirPath: string;
|
||||||
onFileFound: (params: { filePath: string }) => void;
|
onFileFound: (params: { filePath: string }) => Promise<void>;
|
||||||
}) {
|
}) {
|
||||||
const { dirPath, onFileFound } = params;
|
const { dirPath, onFileFound } = params;
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ async function crawlAsyncRec(params: {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
onFileFound({ filePath: fileOrDirPath });
|
await onFileFound({ filePath: fileOrDirPath });
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
29
src/bin/tools/isTrackedByGit.ts
Normal file
29
src/bin/tools/isTrackedByGit.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import * as child_process from "child_process";
|
||||||
|
import { dirname as pathDirname, basename as pathBasename } from "path";
|
||||||
|
import { Deferred } from "evt/tools/Deferred";
|
||||||
|
|
||||||
|
export function getIsTrackedByGit(params: { filePath: string }): Promise<boolean> {
|
||||||
|
const { filePath } = params;
|
||||||
|
|
||||||
|
const dIsTracked = new Deferred<boolean>();
|
||||||
|
|
||||||
|
child_process.exec(
|
||||||
|
`git ls-files --error-unmatch ${pathBasename(filePath)}`,
|
||||||
|
{ cwd: pathDirname(filePath) },
|
||||||
|
error => {
|
||||||
|
if (error === null) {
|
||||||
|
dIsTracked.resolve(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error.code === 1) {
|
||||||
|
dIsTracked.resolve(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dIsTracked.reject(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return dIsTracked.pr;
|
||||||
|
}
|
@ -1,10 +1,13 @@
|
|||||||
import { getNodeModulesBinDirPath } from "./nodeModulesBinDirPath";
|
import { getNodeModulesBinDirPath } from "./nodeModulesBinDirPath";
|
||||||
import { join as pathJoin } from "path";
|
import { join as pathJoin, resolve as pathResolve } from "path";
|
||||||
import * as fsPr from "fs/promises";
|
import * as fsPr from "fs/promises";
|
||||||
import { id } from "tsafe/id";
|
import { id } from "tsafe/id";
|
||||||
import { assert } from "tsafe/assert";
|
import { assert } from "tsafe/assert";
|
||||||
import chalk from "chalk";
|
import chalk from "chalk";
|
||||||
import * as crypto from "crypto";
|
import * as crypto from "crypto";
|
||||||
|
import { is } from "tsafe/is";
|
||||||
|
import { symToStr } from "tsafe/symToStr";
|
||||||
|
import { readThisNpmPackageVersion } from "./readThisNpmPackageVersion";
|
||||||
|
|
||||||
getIsPrettierAvailable.cache = id<boolean | undefined>(undefined);
|
getIsPrettierAvailable.cache = id<boolean | undefined>(undefined);
|
||||||
|
|
||||||
@ -40,7 +43,25 @@ export async function getPrettier(): Promise<PrettierAndConfigHash> {
|
|||||||
return getPrettier.cache;
|
return getPrettier.cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
const prettier = await import("prettier");
|
let prettier = id<typeof import("prettier") | undefined>(undefined);
|
||||||
|
|
||||||
|
import_prettier: {
|
||||||
|
// NOTE: When module is linked we want to make sure we import the correct version
|
||||||
|
// of prettier, that is the one of the project, not the one of this repo.
|
||||||
|
// So we do a sketchy eval to bypass ncc.
|
||||||
|
// We make sure to only do that when linking, otherwise we import properly.
|
||||||
|
if (readThisNpmPackageVersion() === "0.0.0") {
|
||||||
|
eval(
|
||||||
|
`${symToStr({ prettier })} = require("${pathResolve(pathJoin(getNodeModulesBinDirPath(), "..", "prettier"))}")`
|
||||||
|
);
|
||||||
|
|
||||||
|
assert(!is<undefined>(prettier));
|
||||||
|
|
||||||
|
break import_prettier;
|
||||||
|
}
|
||||||
|
|
||||||
|
prettier = await import("prettier");
|
||||||
|
}
|
||||||
|
|
||||||
const configHash = await (async () => {
|
const configHash = await (async () => {
|
||||||
const configFilePath = await prettier.resolveConfigFile(
|
const configFilePath = await prettier.resolveConfigFile(
|
||||||
|
24
src/bin/tools/untrackFromGit.ts
Normal file
24
src/bin/tools/untrackFromGit.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import * as child_process from "child_process";
|
||||||
|
import { dirname as pathDirname, basename as pathBasename } from "path";
|
||||||
|
import { Deferred } from "evt/tools/Deferred";
|
||||||
|
|
||||||
|
export async function untrackFromGit(params: { filePath: string }): Promise<void> {
|
||||||
|
const { filePath } = params;
|
||||||
|
|
||||||
|
const dDone = new Deferred<void>();
|
||||||
|
|
||||||
|
child_process.exec(
|
||||||
|
`git rm --cached ${pathBasename(filePath)}`,
|
||||||
|
{ cwd: pathDirname(filePath) },
|
||||||
|
error => {
|
||||||
|
if (error !== null) {
|
||||||
|
dDone.reject(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dDone.resolve();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await dDone.pr;
|
||||||
|
}
|
@ -115,62 +115,61 @@ export default function LoginPasskeysConditionalAuthenticate(
|
|||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<div id="kc-form">
|
|
||||||
<div id="kc-form-wrapper">
|
|
||||||
{realm.password && (
|
|
||||||
<form
|
|
||||||
id="kc-form-passkey"
|
|
||||||
action={url.loginAction}
|
|
||||||
method="post"
|
|
||||||
style={{ display: "none" }}
|
|
||||||
onSubmit={event => {
|
|
||||||
try {
|
|
||||||
// @ts-expect-error
|
|
||||||
event.target.login.disabled = true;
|
|
||||||
} catch {}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{!usernameHidden && (
|
|
||||||
<div className={kcClsx("kcFormGroupClass")}>
|
|
||||||
<label htmlFor="username" className={kcClsx("kcLabelClass")}>
|
|
||||||
{msg("passkey-autofill-select")}
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
tabIndex={1}
|
|
||||||
id="username"
|
|
||||||
aria-invalid={messagesPerField.existsError("username")}
|
|
||||||
className={kcClsx("kcInputClass")}
|
|
||||||
name="username"
|
|
||||||
defaultValue={login.username ?? ""}
|
|
||||||
//autoComplete="username webauthn"
|
|
||||||
type="text"
|
|
||||||
autoFocus
|
|
||||||
autoComplete="off"
|
|
||||||
/>
|
|
||||||
{messagesPerField.existsError("username") && (
|
|
||||||
<span id="input-error-username" className={kcClsx("kcInputErrorMessageClass")} aria-live="polite">
|
|
||||||
{messagesPerField.get("username")}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</form>
|
|
||||||
)}
|
|
||||||
<div id="kc-form-passkey-button" className={kcClsx("kcFormButtonsClass")} style={{ display: "none" }}>
|
|
||||||
<input
|
|
||||||
id={authButtonId}
|
|
||||||
type="button"
|
|
||||||
autoFocus
|
|
||||||
value={msgStr("passkey-doAuthenticate")}
|
|
||||||
className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonBlockClass", "kcButtonLargeClass")}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
<div id="kc-form">
|
||||||
|
<div id="kc-form-wrapper">
|
||||||
|
{realm.password && (
|
||||||
|
<form
|
||||||
|
id="kc-form-login"
|
||||||
|
action={url.loginAction}
|
||||||
|
method="post"
|
||||||
|
style={{ display: "none" }}
|
||||||
|
onSubmit={event => {
|
||||||
|
try {
|
||||||
|
// @ts-expect-error
|
||||||
|
event.target.login.disabled = true;
|
||||||
|
} catch {}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{!usernameHidden && (
|
||||||
|
<div className={kcClsx("kcFormGroupClass")}>
|
||||||
|
<label htmlFor="username" className={kcClsx("kcLabelClass")}>
|
||||||
|
{msg("passkey-autofill-select")}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
tabIndex={1}
|
||||||
|
id="username"
|
||||||
|
aria-invalid={messagesPerField.existsError("username")}
|
||||||
|
className={kcClsx("kcInputClass")}
|
||||||
|
name="username"
|
||||||
|
defaultValue={login.username ?? ""}
|
||||||
|
autoComplete="username webauthn"
|
||||||
|
type="text"
|
||||||
|
autoFocus
|
||||||
|
/>
|
||||||
|
{messagesPerField.existsError("username") && (
|
||||||
|
<span id="input-error-username" className={kcClsx("kcInputErrorMessageClass")} aria-live="polite">
|
||||||
|
{messagesPerField.get("username")}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</form>
|
||||||
|
)}
|
||||||
|
<div id="kc-form-passkey-button" className={kcClsx("kcFormButtonsClass")} style={{ display: "none" }}>
|
||||||
|
<input
|
||||||
|
id={authButtonId}
|
||||||
|
type="button"
|
||||||
|
autoFocus
|
||||||
|
value={msgStr("passkey-doAuthenticate")}
|
||||||
|
className={kcClsx("kcButtonClass", "kcButtonPrimaryClass", "kcButtonBlockClass", "kcButtonLargeClass")}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Template>
|
</Template>
|
||||||
);
|
);
|
||||||
|
Reference in New Issue
Block a user