From 37790c79561d4a12467f562e383d2cbc89c983d2 Mon Sep 17 00:00:00 2001 From: Erik Jan de Wit Date: Mon, 22 Jan 2024 09:19:58 +0100 Subject: [PATCH] Add a way to extend the UI with an Java API (#23772) * POC to see how we could extend the UI This is very crude and there are still open issues that need to be worked out Signed-off-by: Erik Jan de Wit * added saving option Signed-off-by: Erik Jan de Wit * added list and recreate client form Signed-off-by: Erik Jan de Wit * add tab ui Signed-off-by: Erik Jan de Wit * integrate tabs Signed-off-by: Erik Jan de Wit * remove examples Signed-off-by: Erik Jan de Wit * fixed error messages Signed-off-by: Erik Jan de Wit * added Feature for ui customization Signed-off-by: Erik Jan de Wit --------- Signed-off-by: Erik Jan de Wit --- .../java/org/keycloak/common/Profile.java | 3 + .../java/org/keycloak/common/ProfileTest.java | 1 + .../admin/messages/messages_en.properties | 14 +- js/apps/admin-ui/src/App.tsx | 44 +++--- js/apps/admin-ui/src/PageNav.tsx | 21 ++- .../components/routable-tabs/RoutableTabs.tsx | 60 +++++++- js/apps/admin-ui/src/page/Page.tsx | 67 +++++++++ js/apps/admin-ui/src/page/PageHandler.tsx | 107 +++++++++++++ js/apps/admin-ui/src/page/PageList.tsx | 140 ++++++++++++++++++ js/apps/admin-ui/src/page/routes.tsx | 39 +++++ js/apps/admin-ui/src/routes.tsx | 2 + ...ndDistTest.testBuildHelp.unix.approved.txt | 17 ++- ...istTest.testBuildHelp.windows.approved.txt | 17 ++- ...dDistTest.testExportHelp.unix.approved.txt | 17 ++- ...stTest.testExportHelpAll.unix.approved.txt | 17 ++- ...dDistTest.testImportHelp.unix.approved.txt | 17 ++- ...stTest.testImportHelpAll.unix.approved.txt | 17 ++- ...istTest.testStartDevHelp.unix.approved.txt | 17 ++- ...Test.testStartDevHelp.windows.approved.txt | 23 +-- ...Test.testStartDevHelpAll.unix.approved.txt | 17 ++- ...t.testStartDevHelpAll.windows.approved.txt | 23 +-- ...ndDistTest.testStartHelp.unix.approved.txt | 17 ++- ...istTest.testStartHelp.windows.approved.txt | 23 +-- ...istTest.testStartHelpAll.unix.approved.txt | 17 ++- ...Test.testStartHelpAll.windows.approved.txt | 23 +-- .../services/ui/extend/UiPageProvider.java | 10 ++ .../ui/extend/UiPageProviderFactory.java | 12 ++ .../services/ui/extend/UiPageSpi.java | 33 +++++ .../services/ui/extend/UiTabProvider.java | 8 + .../ui/extend/UiTabProviderFactory.java | 26 ++++ .../keycloak/services/ui/extend/UiTabSpi.java | 33 +++++ .../services/org.keycloak.provider.Spi | 2 + 32 files changed, 729 insertions(+), 155 deletions(-) create mode 100644 js/apps/admin-ui/src/page/Page.tsx create mode 100644 js/apps/admin-ui/src/page/PageHandler.tsx create mode 100644 js/apps/admin-ui/src/page/PageList.tsx create mode 100644 js/apps/admin-ui/src/page/routes.tsx create mode 100644 server-spi-private/src/main/java/org/keycloak/services/ui/extend/UiPageProvider.java create mode 100644 server-spi-private/src/main/java/org/keycloak/services/ui/extend/UiPageProviderFactory.java create mode 100644 server-spi-private/src/main/java/org/keycloak/services/ui/extend/UiPageSpi.java create mode 100644 server-spi-private/src/main/java/org/keycloak/services/ui/extend/UiTabProvider.java create mode 100644 server-spi-private/src/main/java/org/keycloak/services/ui/extend/UiTabProviderFactory.java create mode 100644 server-spi-private/src/main/java/org/keycloak/services/ui/extend/UiTabSpi.java diff --git a/common/src/main/java/org/keycloak/common/Profile.java b/common/src/main/java/org/keycloak/common/Profile.java index 5b5a1ea9fd..57f41ca778 100755 --- a/common/src/main/java/org/keycloak/common/Profile.java +++ b/common/src/main/java/org/keycloak/common/Profile.java @@ -105,8 +105,11 @@ public class Profile { MULTI_SITE("Multi-site support", Type.PREVIEW), OFFLINE_SESSION_PRELOADING("Offline session preloading", Type.DEPRECATED), + HOSTNAME_V1("Hostname Options V1", Type.DEFAULT), //HOSTNAME_V2("Hostname Options V2", Type.DEFAULT, 2), + + DECLARATIVE_UI("declarative ui spi", Type.EXPERIMENTAL), ; private final Type type; diff --git a/common/src/test/java/org/keycloak/common/ProfileTest.java b/common/src/test/java/org/keycloak/common/ProfileTest.java index d58c99e7fa..0e09657edf 100644 --- a/common/src/test/java/org/keycloak/common/ProfileTest.java +++ b/common/src/test/java/org/keycloak/common/ProfileTest.java @@ -78,6 +78,7 @@ public class ProfileTest { Profile.Feature.DYNAMIC_SCOPES, Profile.Feature.DOCKER, Profile.Feature.MULTI_SITE, + Profile.Feature.DECLARATIVE_UI, Profile.Feature.RECOVERY_CODES, Profile.Feature.SCRIPTS, Profile.Feature.TOKEN_EXCHANGE, diff --git a/js/apps/admin-ui/maven-resources/theme/keycloak.v2/admin/messages/messages_en.properties b/js/apps/admin-ui/maven-resources/theme/keycloak.v2/admin/messages/messages_en.properties index f9b3d23759..860ebf6c43 100644 --- a/js/apps/admin-ui/maven-resources/theme/keycloak.v2/admin/messages/messages_en.properties +++ b/js/apps/admin-ui/maven-resources/theme/keycloak.v2/admin/messages/messages_en.properties @@ -2986,4 +2986,16 @@ customValue=Custom value termsAndConditionsUserAttribute=Terms and conditions accepted timestamp realmOverridesDescription= Realm overrides allow you to specify translations that will take effect for the entire realm. These translations will override any translation specified by a theme. addTranslation=Add translation -effectiveMessageBundlesDescription=An effective message bundle is the set of translations for a given language, theme, and theme type. It also takes into account any realm overrides, which will take precedence. \ No newline at end of file +effectiveMessageBundlesDescription=An effective message bundle is the set of translations for a given language, theme, and theme type. It also takes into account any realm overrides, which will take precedence. +clientsClientScopesHelp=The scopes associated with this resource. +searchItem=Search item +createItem=Create item +itemDelete=Delete item +itemDeleteConfirm=Are you sure you want to permanently delete the item +itemDeleteConfirmTitle=Delete item? +itemDeletedSuccess=The item has been deleted +itemDeleteError=Could not delete item: {{error}} +noItems=There are no items +noItemsInstructions=You haven't created any items in this realm. Create a item to get started. +itemSaveError=Error could not save item\! {{error}} +itemSaveSuccessful=Sucessful saved \ No newline at end of file diff --git a/js/apps/admin-ui/src/App.tsx b/js/apps/admin-ui/src/App.tsx index a17a9d25eb..af0202c3fa 100644 --- a/js/apps/admin-ui/src/App.tsx +++ b/js/apps/admin-ui/src/App.tsx @@ -24,21 +24,23 @@ import { AuthWall } from "./root/AuthWall"; const AppContexts = ({ children }: PropsWithChildren) => ( - - - - - - - - {children} - - - - - - - + + + + + + + + + {children} + + + + + + + + ); @@ -53,13 +55,11 @@ export const App = () => { mainContainerId={mainPageContentId} > - - }> - - - - - + }> + + + + diff --git a/js/apps/admin-ui/src/PageNav.tsx b/js/apps/admin-ui/src/PageNav.tsx index af28026954..eb169fd251 100644 --- a/js/apps/admin-ui/src/PageNav.tsx +++ b/js/apps/admin-ui/src/PageNav.tsx @@ -9,23 +9,25 @@ import { import { FormEvent } from "react"; import { useTranslation } from "react-i18next"; import { NavLink, useMatch, useNavigate } from "react-router-dom"; - import { RealmSelector } from "./components/realm-selector/RealmSelector"; import { useAccess } from "./context/access/Access"; import { useRealm } from "./context/realm-context/RealmContext"; +import { useServerInfo } from "./context/server-info/ServerInfoProvider"; +import { toPage } from "./page/routes"; import { AddRealmRoute } from "./realm/routes/AddRealm"; import { routes } from "./routes"; import "./page-nav.css"; -type LeftNavProps = { title: string; path: string }; +type LeftNavProps = { title: string; path: string; id?: string }; -const LeftNav = ({ title, path }: LeftNavProps) => { +const LeftNav = ({ title, path, id }: LeftNavProps) => { const { t } = useTranslation(); const { hasAccess } = useAccess(); const { realm } = useRealm(); const route = routes.find( - (route) => route.path.replace(/\/:.+?(\?|(?:(?!\/).)*|$)/g, "") === path, + (route) => + route.path.replace(/\/:.+?(\?|(?:(?!\/).)*|$)/g, "") === (id || path), ); const accessAllowed = @@ -56,6 +58,9 @@ const LeftNav = ({ title, path }: LeftNavProps) => { export const PageNav = () => { const { t } = useTranslation(); const { hasSomeAccess } = useAccess(); + const { componentTypes } = useServerInfo(); + const pages = + componentTypes?.["org.keycloak.services.ui.extend.UiPageProvider"]; const navigate = useNavigate(); @@ -116,6 +121,14 @@ export const PageNav = () => { + {pages?.map((p) => ( + + ))} )} diff --git a/js/apps/admin-ui/src/components/routable-tabs/RoutableTabs.tsx b/js/apps/admin-ui/src/components/routable-tabs/RoutableTabs.tsx index e84dcd3712..57e4fc6b16 100644 --- a/js/apps/admin-ui/src/components/routable-tabs/RoutableTabs.tsx +++ b/js/apps/admin-ui/src/components/routable-tabs/RoutableTabs.tsx @@ -1,4 +1,5 @@ import { + Tab, TabProps, Tabs, TabsComponent, @@ -6,11 +7,22 @@ import { } from "@patternfly/react-core"; import { Children, - isValidElement, JSXElementConstructor, + PropsWithChildren, ReactElement, + isValidElement, } from "react"; -import { Path, useHref, useLocation } from "react-router-dom"; +import { + Path, + generatePath, + matchPath, + useHref, + useLocation, + useParams, +} from "react-router-dom"; +import { useServerInfo } from "../../context/server-info/ServerInfoProvider"; +import { PageHandler } from "../../page/PageHandler"; +import { TAB_PROVIDER } from "../../page/PageList"; // TODO: Remove the custom 'children' props and type once the following issue has been resolved: // https://github.com/patternfly/patternfly-react/issues/6766 @@ -32,14 +44,31 @@ export const RoutableTabs = ({ ...otherProps }: RoutableTabsProps) => { const { pathname } = useLocation(); + const params = useParams(); + const { componentTypes } = useServerInfo(); + const tabs = componentTypes?.[TAB_PROVIDER] || []; - // Extract event keys from children. + const matchedTabs = tabs + .filter((tab) => matchPath({ path: tab.metadata.path }, pathname)) + .map((t) => ({ + ...t, + pathname: generatePath(t.metadata.path, { + ...params, + ...t.metadata.params, + }), + })); + // Extract all keys from matchedTabs + const matchedTabsKeys = matchedTabs.map((t) => t.pathname); + + // Extract event keys from children const eventKeys = Children.toArray(children) .filter((child): child is ChildElement => isValidElement(child)) .map((child) => child.props.eventKey.toString()); + const allKeys = [...eventKeys, ...matchedTabsKeys]; + // Determine if there is an exact match. - const exactMatch = eventKeys.find( + const exactMatch = allKeys.find( (eventKey) => eventKey === decodeURI(pathname), ); @@ -63,10 +92,33 @@ export const RoutableTabs = ({ {...otherProps} > {children} + {matchedTabs.map((t) => ( + + + + ))} ); }; +type DynamicTabProps = { + title: string; + eventKey: string; +}; + +const DynamicTab = ({ + children, + ...props +}: PropsWithChildren) => { + const href = useHref(props.eventKey); + + return ( + + {children} + + ); +}; + export const useRoutableTab = (to: Partial) => ({ eventKey: to.pathname ?? "", href: useHref(to), diff --git a/js/apps/admin-ui/src/page/Page.tsx b/js/apps/admin-ui/src/page/Page.tsx new file mode 100644 index 0000000000..b58be17355 --- /dev/null +++ b/js/apps/admin-ui/src/page/Page.tsx @@ -0,0 +1,67 @@ +import { ButtonVariant, DropdownItem } from "@patternfly/react-core"; +import { useTranslation } from "react-i18next"; +import { useNavigate, useParams } from "react-router-dom"; +import { adminClient } from "../admin-client"; +import { useAlerts } from "../components/alert/Alerts"; +import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog"; +import { ViewHeader } from "../components/view-header/ViewHeader"; +import { useServerInfo } from "../context/server-info/ServerInfoProvider"; +import { PageHandler } from "./PageHandler"; +import { PAGE_PROVIDER } from "./PageList"; +import { PageParams, toPage } from "./routes"; +import { useRealm } from "../context/realm-context/RealmContext"; + +export default function Page() { + const { t } = useTranslation(); + const { componentTypes } = useServerInfo(); + const { realm } = useRealm(); + const pages = componentTypes?.[PAGE_PROVIDER]; + const navigate = useNavigate(); + const { id, providerId } = useParams(); + const { addAlert, addError } = useAlerts(); + + const page = pages?.find((p) => p.id === providerId); + if (!page) { + throw new Error(t("notFound")); + } + + const [toggleDeleteDialog, DeleteConfirm] = useConfirmDialog({ + titleKey: "itemDeleteConfirmTitle", + messageKey: "itemDeleteConfirm", + continueButtonLabel: "delete", + continueButtonVariant: ButtonVariant.danger, + onConfirm: async () => { + try { + await adminClient.components.del({ + id: id!, + }); + addAlert(t("itemDeletedSuccess")); + navigate(toPage({ realm, providerId: providerId! })); + } catch (error) { + addError("itemSaveError", error); + } + }, + }); + return ( + <> + + toggleDeleteDialog()} + > + {t("delete")} + , + ] + : undefined + } + /> + + + ); +} diff --git a/js/apps/admin-ui/src/page/PageHandler.tsx b/js/apps/admin-ui/src/page/PageHandler.tsx new file mode 100644 index 0000000000..1d4bfe8f7f --- /dev/null +++ b/js/apps/admin-ui/src/page/PageHandler.tsx @@ -0,0 +1,107 @@ +import ComponentRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentRepresentation"; +import ComponentTypeRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentTypeRepresentation"; +import RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation"; +import { ActionGroup, Button, Form, PageSection } from "@patternfly/react-core"; +import { useState } from "react"; +import { FormProvider, useForm } from "react-hook-form"; +import { useTranslation } from "react-i18next"; +import { Link } from "react-router-dom"; +import { adminClient } from "../admin-client"; +import { useAlerts } from "../components/alert/Alerts"; +import { DynamicComponents } from "../components/dynamic/DynamicComponents"; +import { useRealm } from "../context/realm-context/RealmContext"; +import { useFetch } from "../utils/useFetch"; +import { PAGE_PROVIDER, TAB_PROVIDER } from "./PageList"; +import { toPage } from "./routes"; + +type PageHandlerProps = { + id?: string; + providerType: typeof TAB_PROVIDER | typeof PAGE_PROVIDER; + page: ComponentTypeRepresentation; +}; + +export const PageHandler = ({ + id: idAttribute, + providerType, + page: { id: providerId, ...page }, +}: PageHandlerProps) => { + const { t } = useTranslation(); + const form = useForm(); + const { realm: realmName } = useRealm(); + const [realm, setRealm] = useState(); + const { addAlert, addError } = useAlerts(); + const [id, setId] = useState(idAttribute); + + useFetch( + async () => + await Promise.all([ + adminClient.realms.findOne({ realm: realmName }), + id ? adminClient.components.findOne({ id }) : Promise.resolve(), + providerType === TAB_PROVIDER + ? adminClient.components.find({ type: TAB_PROVIDER }) + : Promise.resolve(), + ]), + ([realm, data, tabs]) => { + setRealm(realm); + const tab = (tabs || []).find((t) => t.providerId === providerId); + form.reset(data || tab || {}); + if (tab) setId(tab.id); + }, + [], + ); + + const onSubmit = async (component: ComponentRepresentation) => { + if (component.config) + Object.entries(component.config).forEach( + ([key, value]) => + (component.config![key] = Array.isArray(value) ? value : [value]), + ); + try { + const updatedComponent = { + ...component, + providerId, + providerType, + parentId: realm?.id, + }; + if (id) { + await adminClient.components.update({ id }, updatedComponent); + } else { + await adminClient.components.create(updatedComponent); + } + addAlert("itemSaveSuccessful"); + } catch (error) { + addError("itemSaveError", error); + } + }; + + return ( + +
+ + + + + + + + +
+
+ ); +}; diff --git a/js/apps/admin-ui/src/page/PageList.tsx b/js/apps/admin-ui/src/page/PageList.tsx new file mode 100644 index 0000000000..056a1deece --- /dev/null +++ b/js/apps/admin-ui/src/page/PageList.tsx @@ -0,0 +1,140 @@ +import ComponentRepresentation from "@keycloak/keycloak-admin-client/lib/defs/componentRepresentation"; +import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation"; +import type { ComponentQuery } from "@keycloak/keycloak-admin-client/lib/resources/components"; +import { + Button, + ButtonVariant, + PageSection, + ToolbarItem, +} from "@patternfly/react-core"; +import { IRowData } from "@patternfly/react-table"; +import { useState } from "react"; +import { useTranslation } from "react-i18next"; +import { Link, useNavigate, useParams } from "react-router-dom"; +import { adminClient } from "../admin-client"; +import { useAlerts } from "../components/alert/Alerts"; +import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog"; +import { ListEmptyState } from "../components/list-empty-state/ListEmptyState"; +import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable"; +import { ViewHeader } from "../components/view-header/ViewHeader"; +import { useRealm } from "../context/realm-context/RealmContext"; +import { useServerInfo } from "../context/server-info/ServerInfoProvider"; +import { useFetch } from "../utils/useFetch"; +import { PageListParams, toDetailPage } from "./routes"; + +export const PAGE_PROVIDER = "org.keycloak.services.ui.extend.UiPageProvider"; +export const TAB_PROVIDER = "org.keycloak.services.ui.extend.UiTabProvider"; + +const DetailLink = (obj: ComponentRepresentation) => { + const { realm } = useRealm(); + return ( + + {obj.id} + + ); +}; +export default function PageList() { + const { t } = useTranslation(); + const { addAlert, addError } = useAlerts(); + const navigate = useNavigate(); + const { providerId } = useParams(); + const [key, setKey] = useState(0); + const refresh = () => setKey(key + 1); + + const { realm: realmName } = useRealm(); + const [realm, setRealm] = useState(); + const [selectedItem, setSelectedItem] = useState(); + const { componentTypes } = useServerInfo(); + const pages = componentTypes?.[PAGE_PROVIDER]; + + const page = pages?.find((p) => p.id === providerId)!; + + useFetch( + async () => adminClient.realms.findOne({ realm: realmName }), + setRealm, + [], + ); + + const loader = async () => { + const params: ComponentQuery = { + parent: realm?.id, + type: PAGE_PROVIDER, + }; + return await adminClient.components.find({ ...params }); + }; + + const [toggleDeleteDialog, DeleteConfirm] = useConfirmDialog({ + titleKey: "itemDeleteConfirmTitle", + messageKey: "itemDeleteConfirm", + continueButtonLabel: "delete", + continueButtonVariant: ButtonVariant.danger, + onConfirm: async () => { + try { + await adminClient.components.del({ + id: selectedItem!.id!, + }); + addAlert(t("itemDeletedSuccess")); + refresh(); + } catch (error) { + addError("itemSaveError", error); + } + }, + }); + + return ( + + + + + + + } + actionResolver={(item: IRowData) => [ + { + title: t("delete"), + onClick() { + setSelectedItem(item.data); + toggleDeleteDialog(); + }, + }, + ]} + searchPlaceholderKey="searchItem" + loader={loader} + columns={[ + { name: "id", cellRenderer: DetailLink }, + ...page.properties.slice(0, 3).map((p) => ({ + name: `config.${p.name}[0]`, + displayKey: p.label, + })), + ]} + ariaLabelKey="list" + emptyState={ + + navigate(toDetailPage({ realm: realmName, providerId: page.id })) + } + /> + } + /> + + ); +} diff --git a/js/apps/admin-ui/src/page/routes.tsx b/js/apps/admin-ui/src/page/routes.tsx new file mode 100644 index 0000000000..0ffb86e383 --- /dev/null +++ b/js/apps/admin-ui/src/page/routes.tsx @@ -0,0 +1,39 @@ +import { Path, generatePath } from "react-router-dom"; +import type { AppRouteObject } from "../routes"; +import { lazy } from "react"; + +export type PageListParams = { realm?: string; providerId: string }; +export type PageParams = { realm: string; providerId: string; id?: string }; + +const PageList = lazy(() => import("./PageList")); +const Page = lazy(() => import("./Page")); + +const PageListRoute: AppRouteObject = { + path: "/:realm?/page-section/:providerId", + element: , + breadcrumb: (t) => t("page"), + handle: { + access: "view-realm", + }, +}; + +const PageDetailRoute: AppRouteObject = { + path: "/:realm/page/:providerId/:id?", + element: , + breadcrumb: (t) => t("page"), + handle: { + access: "view-realm", + }, +}; + +const routes: AppRouteObject[] = [PageListRoute, PageDetailRoute]; + +export const toPage = (params: PageListParams): Partial => ({ + pathname: generatePath(PageListRoute.path, params), +}); + +export const toDetailPage = (params: PageParams): Partial => ({ + pathname: generatePath(PageDetailRoute.path, params), +}); + +export default routes; diff --git a/js/apps/admin-ui/src/routes.tsx b/js/apps/admin-ui/src/routes.tsx index f71b74cae9..077d04842a 100644 --- a/js/apps/admin-ui/src/routes.tsx +++ b/js/apps/admin-ui/src/routes.tsx @@ -18,6 +18,7 @@ import realmRoutes from "./realm/routes"; import sessionRoutes from "./sessions/routes"; import userFederationRoutes from "./user-federation/routes"; import userRoutes from "./user/routes"; +import pageRoutes from "./page/routes"; export type AppRouteObjectHandle = { access: AccessType | AccessType[]; @@ -51,6 +52,7 @@ export const routes: AppRouteObject[] = [ ...userRoutes, ...groupsRoutes, ...dashboardRoutes, + ...pageRoutes, NotFoundRoute, ]; diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testBuildHelp.unix.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testBuildHelp.unix.approved.txt index 8b90686ac8..c965b912fd 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testBuildHelp.unix.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testBuildHelp.unix.approved.txt @@ -64,20 +64,21 @@ Feature: --features Enables a set of one or more features. Possible values are: account-api[:v1], account2[:v1], account3[:v1], admin-api[:v1], admin-fine-grained-authz[:v1], admin2[:v1], authorization[:v1], ciba[:v1], client-policies[:v1], - client-secret-rotation[:v1], device-flow[:v1], docker[:v1], dpop[:v1], - dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation[:v1], js-adapter - [:v1], kerberos[:v1], linkedin-oauth[:v1], multi-site[:v1], + client-secret-rotation[:v1], declarative-ui[:v1], device-flow[:v1], docker[: + v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation + [:v1], js-adapter[:v1], kerberos[:v1], linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1], step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1], update-email[:v1], web-authn[:v1]. --features-disabled Disables a set of one or more features. Possible values are: account-api, account2, account3, admin-api, admin-fine-grained-authz, admin2, - authorization, ciba, client-policies, client-secret-rotation, device-flow, - docker, dpop, dynamic-scopes, fips, impersonation, js-adapter, kerberos, - linkedin-oauth, multi-site, offline-session-preloading, par, preview, - recovery-codes, scripts, step-up-authentication, token-exchange, - transient-users, update-email, web-authn. + authorization, ciba, client-policies, client-secret-rotation, + declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, + impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, + offline-session-preloading, par, preview, recovery-codes, scripts, + step-up-authentication, token-exchange, transient-users, update-email, + web-authn. HTTP(S): diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testBuildHelp.windows.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testBuildHelp.windows.approved.txt index ebcf0dbd3a..c9cb3c5b9d 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testBuildHelp.windows.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testBuildHelp.windows.approved.txt @@ -64,20 +64,21 @@ Feature: --features Enables a set of one or more features. Possible values are: account-api[:v1], account2[:v1], account3[:v1], admin-api[:v1], admin-fine-grained-authz[:v1], admin2[:v1], authorization[:v1], ciba[:v1], client-policies[:v1], - client-secret-rotation[:v1], device-flow[:v1], docker[:v1], dpop[:v1], - dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation[:v1], js-adapter - [:v1], kerberos[:v1], linkedin-oauth[:v1], multi-site[:v1], + client-secret-rotation[:v1], declarative-ui[:v1], device-flow[:v1], docker[: + v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation + [:v1], js-adapter[:v1], kerberos[:v1], linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1], step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1], update-email[:v1], web-authn[:v1]. --features-disabled Disables a set of one or more features. Possible values are: account-api, account2, account3, admin-api, admin-fine-grained-authz, admin2, - authorization, ciba, client-policies, client-secret-rotation, device-flow, - docker, dpop, dynamic-scopes, fips, impersonation, js-adapter, kerberos, - linkedin-oauth, multi-site, offline-session-preloading, par, preview, - recovery-codes, scripts, step-up-authentication, token-exchange, - transient-users, update-email, web-authn. + authorization, ciba, client-policies, client-secret-rotation, + declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, + impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, + offline-session-preloading, par, preview, recovery-codes, scripts, + step-up-authentication, token-exchange, transient-users, update-email, + web-authn. HTTP(S): diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testExportHelp.unix.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testExportHelp.unix.approved.txt index 15146fadfa..af3b7659cb 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testExportHelp.unix.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testExportHelp.unix.approved.txt @@ -59,20 +59,21 @@ Feature: --features Enables a set of one or more features. Possible values are: account-api[:v1], account2[:v1], account3[:v1], admin-api[:v1], admin-fine-grained-authz[:v1], admin2[:v1], authorization[:v1], ciba[:v1], client-policies[:v1], - client-secret-rotation[:v1], device-flow[:v1], docker[:v1], dpop[:v1], - dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation[:v1], js-adapter - [:v1], kerberos[:v1], linkedin-oauth[:v1], multi-site[:v1], + client-secret-rotation[:v1], declarative-ui[:v1], device-flow[:v1], docker[: + v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation + [:v1], js-adapter[:v1], kerberos[:v1], linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1], step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1], update-email[:v1], web-authn[:v1]. --features-disabled Disables a set of one or more features. Possible values are: account-api, account2, account3, admin-api, admin-fine-grained-authz, admin2, - authorization, ciba, client-policies, client-secret-rotation, device-flow, - docker, dpop, dynamic-scopes, fips, impersonation, js-adapter, kerberos, - linkedin-oauth, multi-site, offline-session-preloading, par, preview, - recovery-codes, scripts, step-up-authentication, token-exchange, - transient-users, update-email, web-authn. + authorization, ciba, client-policies, client-secret-rotation, + declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, + impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, + offline-session-preloading, par, preview, recovery-codes, scripts, + step-up-authentication, token-exchange, transient-users, update-email, + web-authn. Config: diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testExportHelpAll.unix.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testExportHelpAll.unix.approved.txt index 15146fadfa..af3b7659cb 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testExportHelpAll.unix.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testExportHelpAll.unix.approved.txt @@ -59,20 +59,21 @@ Feature: --features Enables a set of one or more features. Possible values are: account-api[:v1], account2[:v1], account3[:v1], admin-api[:v1], admin-fine-grained-authz[:v1], admin2[:v1], authorization[:v1], ciba[:v1], client-policies[:v1], - client-secret-rotation[:v1], device-flow[:v1], docker[:v1], dpop[:v1], - dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation[:v1], js-adapter - [:v1], kerberos[:v1], linkedin-oauth[:v1], multi-site[:v1], + client-secret-rotation[:v1], declarative-ui[:v1], device-flow[:v1], docker[: + v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation + [:v1], js-adapter[:v1], kerberos[:v1], linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1], step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1], update-email[:v1], web-authn[:v1]. --features-disabled Disables a set of one or more features. Possible values are: account-api, account2, account3, admin-api, admin-fine-grained-authz, admin2, - authorization, ciba, client-policies, client-secret-rotation, device-flow, - docker, dpop, dynamic-scopes, fips, impersonation, js-adapter, kerberos, - linkedin-oauth, multi-site, offline-session-preloading, par, preview, - recovery-codes, scripts, step-up-authentication, token-exchange, - transient-users, update-email, web-authn. + authorization, ciba, client-policies, client-secret-rotation, + declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, + impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, + offline-session-preloading, par, preview, recovery-codes, scripts, + step-up-authentication, token-exchange, transient-users, update-email, + web-authn. Config: diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testImportHelp.unix.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testImportHelp.unix.approved.txt index 328527ca57..ae700b6695 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testImportHelp.unix.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testImportHelp.unix.approved.txt @@ -59,20 +59,21 @@ Feature: --features Enables a set of one or more features. Possible values are: account-api[:v1], account2[:v1], account3[:v1], admin-api[:v1], admin-fine-grained-authz[:v1], admin2[:v1], authorization[:v1], ciba[:v1], client-policies[:v1], - client-secret-rotation[:v1], device-flow[:v1], docker[:v1], dpop[:v1], - dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation[:v1], js-adapter - [:v1], kerberos[:v1], linkedin-oauth[:v1], multi-site[:v1], + client-secret-rotation[:v1], declarative-ui[:v1], device-flow[:v1], docker[: + v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation + [:v1], js-adapter[:v1], kerberos[:v1], linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1], step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1], update-email[:v1], web-authn[:v1]. --features-disabled Disables a set of one or more features. Possible values are: account-api, account2, account3, admin-api, admin-fine-grained-authz, admin2, - authorization, ciba, client-policies, client-secret-rotation, device-flow, - docker, dpop, dynamic-scopes, fips, impersonation, js-adapter, kerberos, - linkedin-oauth, multi-site, offline-session-preloading, par, preview, - recovery-codes, scripts, step-up-authentication, token-exchange, - transient-users, update-email, web-authn. + authorization, ciba, client-policies, client-secret-rotation, + declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, + impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, + offline-session-preloading, par, preview, recovery-codes, scripts, + step-up-authentication, token-exchange, transient-users, update-email, + web-authn. Config: diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testImportHelpAll.unix.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testImportHelpAll.unix.approved.txt index 328527ca57..ae700b6695 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testImportHelpAll.unix.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testImportHelpAll.unix.approved.txt @@ -59,20 +59,21 @@ Feature: --features Enables a set of one or more features. Possible values are: account-api[:v1], account2[:v1], account3[:v1], admin-api[:v1], admin-fine-grained-authz[:v1], admin2[:v1], authorization[:v1], ciba[:v1], client-policies[:v1], - client-secret-rotation[:v1], device-flow[:v1], docker[:v1], dpop[:v1], - dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation[:v1], js-adapter - [:v1], kerberos[:v1], linkedin-oauth[:v1], multi-site[:v1], + client-secret-rotation[:v1], declarative-ui[:v1], device-flow[:v1], docker[: + v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation + [:v1], js-adapter[:v1], kerberos[:v1], linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1], step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1], update-email[:v1], web-authn[:v1]. --features-disabled Disables a set of one or more features. Possible values are: account-api, account2, account3, admin-api, admin-fine-grained-authz, admin2, - authorization, ciba, client-policies, client-secret-rotation, device-flow, - docker, dpop, dynamic-scopes, fips, impersonation, js-adapter, kerberos, - linkedin-oauth, multi-site, offline-session-preloading, par, preview, - recovery-codes, scripts, step-up-authentication, token-exchange, - transient-users, update-email, web-authn. + authorization, ciba, client-policies, client-secret-rotation, + declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, + impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, + offline-session-preloading, par, preview, recovery-codes, scripts, + step-up-authentication, token-exchange, transient-users, update-email, + web-authn. Config: diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartDevHelp.unix.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartDevHelp.unix.approved.txt index 74ce2256c0..805a9729a7 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartDevHelp.unix.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartDevHelp.unix.approved.txt @@ -89,20 +89,21 @@ Feature: --features Enables a set of one or more features. Possible values are: account-api[:v1], account2[:v1], account3[:v1], admin-api[:v1], admin-fine-grained-authz[:v1], admin2[:v1], authorization[:v1], ciba[:v1], client-policies[:v1], - client-secret-rotation[:v1], device-flow[:v1], docker[:v1], dpop[:v1], - dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation[:v1], js-adapter - [:v1], kerberos[:v1], linkedin-oauth[:v1], multi-site[:v1], + client-secret-rotation[:v1], declarative-ui[:v1], device-flow[:v1], docker[: + v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation + [:v1], js-adapter[:v1], kerberos[:v1], linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1], step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1], update-email[:v1], web-authn[:v1]. --features-disabled Disables a set of one or more features. Possible values are: account-api, account2, account3, admin-api, admin-fine-grained-authz, admin2, - authorization, ciba, client-policies, client-secret-rotation, device-flow, - docker, dpop, dynamic-scopes, fips, impersonation, js-adapter, kerberos, - linkedin-oauth, multi-site, offline-session-preloading, par, preview, - recovery-codes, scripts, step-up-authentication, token-exchange, - transient-users, update-email, web-authn. + authorization, ciba, client-policies, client-secret-rotation, + declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, + impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, + offline-session-preloading, par, preview, recovery-codes, scripts, + step-up-authentication, token-exchange, transient-users, update-email, + web-authn. Hostname: diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartDevHelp.windows.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartDevHelp.windows.approved.txt index 27044fc912..bd1a3f3795 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartDevHelp.windows.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartDevHelp.windows.approved.txt @@ -89,20 +89,21 @@ Feature: --features Enables a set of one or more features. Possible values are: account-api[:v1], account2[:v1], account3[:v1], admin-api[:v1], admin-fine-grained-authz[:v1], admin2[:v1], authorization[:v1], ciba[:v1], client-policies[:v1], - client-secret-rotation[:v1], device-flow[:v1], docker[:v1], dpop[:v1], - dynamic-scopes[:v1], fips[:v1], hostname[:v1],impersonation[:v1], js-adapter[:v1], kerberos - [:v1], linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[: - v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1], - step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1], - update-email[:v1], web-authn[:v1]. + client-secret-rotation[:v1], declarative-ui[:v1], device-flow[:v1], docker[: + v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation + [:v1], js-adapter[:v1], kerberos[:v1], linkedin-oauth[:v1], multi-site[:v1], + offline-session-preloading[:v1], par[:v1], preview, recovery-codes[:v1], + scripts[:v1], step-up-authentication[:v1], token-exchange[:v1], + transient-users[:v1], update-email[:v1], web-authn[:v1]. --features-disabled Disables a set of one or more features. Possible values are: account-api, account2, account3, admin-api, admin-fine-grained-authz, admin2, - authorization, ciba, client-policies, client-secret-rotation, device-flow, - docker, dpop, dynamic-scopes, fips, impersonation, js-adapter, kerberos, - linkedin-oauth, multi-site, offline-session-preloading, par, preview, - recovery-codes, scripts, step-up-authentication, token-exchange, - transient-users, update-email, web-authn. + authorization, ciba, client-policies, client-secret-rotation, + declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, + impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, + offline-session-preloading, par, preview, recovery-codes, scripts, + step-up-authentication, token-exchange, transient-users, update-email, + web-authn. Hostname: diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartDevHelpAll.unix.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartDevHelpAll.unix.approved.txt index 74ce2256c0..805a9729a7 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartDevHelpAll.unix.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartDevHelpAll.unix.approved.txt @@ -89,20 +89,21 @@ Feature: --features Enables a set of one or more features. Possible values are: account-api[:v1], account2[:v1], account3[:v1], admin-api[:v1], admin-fine-grained-authz[:v1], admin2[:v1], authorization[:v1], ciba[:v1], client-policies[:v1], - client-secret-rotation[:v1], device-flow[:v1], docker[:v1], dpop[:v1], - dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation[:v1], js-adapter - [:v1], kerberos[:v1], linkedin-oauth[:v1], multi-site[:v1], + client-secret-rotation[:v1], declarative-ui[:v1], device-flow[:v1], docker[: + v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation + [:v1], js-adapter[:v1], kerberos[:v1], linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1], step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1], update-email[:v1], web-authn[:v1]. --features-disabled Disables a set of one or more features. Possible values are: account-api, account2, account3, admin-api, admin-fine-grained-authz, admin2, - authorization, ciba, client-policies, client-secret-rotation, device-flow, - docker, dpop, dynamic-scopes, fips, impersonation, js-adapter, kerberos, - linkedin-oauth, multi-site, offline-session-preloading, par, preview, - recovery-codes, scripts, step-up-authentication, token-exchange, - transient-users, update-email, web-authn. + authorization, ciba, client-policies, client-secret-rotation, + declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, + impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, + offline-session-preloading, par, preview, recovery-codes, scripts, + step-up-authentication, token-exchange, transient-users, update-email, + web-authn. Hostname: diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartDevHelpAll.windows.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartDevHelpAll.windows.approved.txt index 27044fc912..bd1a3f3795 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartDevHelpAll.windows.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartDevHelpAll.windows.approved.txt @@ -89,20 +89,21 @@ Feature: --features Enables a set of one or more features. Possible values are: account-api[:v1], account2[:v1], account3[:v1], admin-api[:v1], admin-fine-grained-authz[:v1], admin2[:v1], authorization[:v1], ciba[:v1], client-policies[:v1], - client-secret-rotation[:v1], device-flow[:v1], docker[:v1], dpop[:v1], - dynamic-scopes[:v1], fips[:v1], hostname[:v1],impersonation[:v1], js-adapter[:v1], kerberos - [:v1], linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[: - v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1], - step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1], - update-email[:v1], web-authn[:v1]. + client-secret-rotation[:v1], declarative-ui[:v1], device-flow[:v1], docker[: + v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation + [:v1], js-adapter[:v1], kerberos[:v1], linkedin-oauth[:v1], multi-site[:v1], + offline-session-preloading[:v1], par[:v1], preview, recovery-codes[:v1], + scripts[:v1], step-up-authentication[:v1], token-exchange[:v1], + transient-users[:v1], update-email[:v1], web-authn[:v1]. --features-disabled Disables a set of one or more features. Possible values are: account-api, account2, account3, admin-api, admin-fine-grained-authz, admin2, - authorization, ciba, client-policies, client-secret-rotation, device-flow, - docker, dpop, dynamic-scopes, fips, impersonation, js-adapter, kerberos, - linkedin-oauth, multi-site, offline-session-preloading, par, preview, - recovery-codes, scripts, step-up-authentication, token-exchange, - transient-users, update-email, web-authn. + authorization, ciba, client-policies, client-secret-rotation, + declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, + impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, + offline-session-preloading, par, preview, recovery-codes, scripts, + step-up-authentication, token-exchange, transient-users, update-email, + web-authn. Hostname: diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartHelp.unix.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartHelp.unix.approved.txt index 587c1701e9..31a64523ba 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartHelp.unix.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartHelp.unix.approved.txt @@ -90,20 +90,21 @@ Feature: --features Enables a set of one or more features. Possible values are: account-api[:v1], account2[:v1], account3[:v1], admin-api[:v1], admin-fine-grained-authz[:v1], admin2[:v1], authorization[:v1], ciba[:v1], client-policies[:v1], - client-secret-rotation[:v1], device-flow[:v1], docker[:v1], dpop[:v1], - dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation[:v1], js-adapter - [:v1], kerberos[:v1], linkedin-oauth[:v1], multi-site[:v1], + client-secret-rotation[:v1], declarative-ui[:v1], device-flow[:v1], docker[: + v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation + [:v1], js-adapter[:v1], kerberos[:v1], linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1], step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1], update-email[:v1], web-authn[:v1]. --features-disabled Disables a set of one or more features. Possible values are: account-api, account2, account3, admin-api, admin-fine-grained-authz, admin2, - authorization, ciba, client-policies, client-secret-rotation, device-flow, - docker, dpop, dynamic-scopes, fips, impersonation, js-adapter, kerberos, - linkedin-oauth, multi-site, offline-session-preloading, par, preview, - recovery-codes, scripts, step-up-authentication, token-exchange, - transient-users, update-email, web-authn. + authorization, ciba, client-policies, client-secret-rotation, + declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, + impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, + offline-session-preloading, par, preview, recovery-codes, scripts, + step-up-authentication, token-exchange, transient-users, update-email, + web-authn. Hostname: diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartHelp.windows.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartHelp.windows.approved.txt index 9ece031fc1..9c14fd37df 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartHelp.windows.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartHelp.windows.approved.txt @@ -90,20 +90,21 @@ Feature: --features Enables a set of one or more features. Possible values are: account-api[:v1], account2[:v1], account3[:v1], admin-api[:v1], admin-fine-grained-authz[:v1], admin2[:v1], authorization[:v1], ciba[:v1], client-policies[:v1], - client-secret-rotation[:v1], device-flow[:v1], docker[:v1], dpop[:v1], - dynamic-scopes[:v1], fips[:v1], hostname[:v1],impersonation[:v1], js-adapter[:v1], kerberos - [:v1], linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[: - v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1], - step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1], - update-email[:v1], web-authn[:v1]. + client-secret-rotation[:v1], declarative-ui[:v1], device-flow[:v1], docker[: + v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation + [:v1], js-adapter[:v1], kerberos[:v1], linkedin-oauth[:v1], multi-site[:v1], + offline-session-preloading[:v1], par[:v1], preview, recovery-codes[:v1], + scripts[:v1], step-up-authentication[:v1], token-exchange[:v1], + transient-users[:v1], update-email[:v1], web-authn[:v1]. --features-disabled Disables a set of one or more features. Possible values are: account-api, account2, account3, admin-api, admin-fine-grained-authz, admin2, - authorization, ciba, client-policies, client-secret-rotation, device-flow, - docker, dpop, dynamic-scopes, fips, impersonation, js-adapter, kerberos, - linkedin-oauth, multi-site, offline-session-preloading, par, preview, - recovery-codes, scripts, step-up-authentication, token-exchange, - transient-users, update-email, web-authn. + authorization, ciba, client-policies, client-secret-rotation, + declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, + impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, + offline-session-preloading, par, preview, recovery-codes, scripts, + step-up-authentication, token-exchange, transient-users, update-email, + web-authn. Hostname: diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartHelpAll.unix.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartHelpAll.unix.approved.txt index 587c1701e9..31a64523ba 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartHelpAll.unix.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartHelpAll.unix.approved.txt @@ -90,20 +90,21 @@ Feature: --features Enables a set of one or more features. Possible values are: account-api[:v1], account2[:v1], account3[:v1], admin-api[:v1], admin-fine-grained-authz[:v1], admin2[:v1], authorization[:v1], ciba[:v1], client-policies[:v1], - client-secret-rotation[:v1], device-flow[:v1], docker[:v1], dpop[:v1], - dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation[:v1], js-adapter - [:v1], kerberos[:v1], linkedin-oauth[:v1], multi-site[:v1], + client-secret-rotation[:v1], declarative-ui[:v1], device-flow[:v1], docker[: + v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation + [:v1], js-adapter[:v1], kerberos[:v1], linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[:v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1], step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1], update-email[:v1], web-authn[:v1]. --features-disabled Disables a set of one or more features. Possible values are: account-api, account2, account3, admin-api, admin-fine-grained-authz, admin2, - authorization, ciba, client-policies, client-secret-rotation, device-flow, - docker, dpop, dynamic-scopes, fips, impersonation, js-adapter, kerberos, - linkedin-oauth, multi-site, offline-session-preloading, par, preview, - recovery-codes, scripts, step-up-authentication, token-exchange, - transient-users, update-email, web-authn. + authorization, ciba, client-policies, client-secret-rotation, + declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, + impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, + offline-session-preloading, par, preview, recovery-codes, scripts, + step-up-authentication, token-exchange, transient-users, update-email, + web-authn. Hostname: diff --git a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartHelpAll.windows.approved.txt b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartHelpAll.windows.approved.txt index 9ece031fc1..9c14fd37df 100644 --- a/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartHelpAll.windows.approved.txt +++ b/quarkus/tests/integration/src/test/resources/org/keycloak/it/cli/dist/approvals/cli/help/HelpCommandDistTest.testStartHelpAll.windows.approved.txt @@ -90,20 +90,21 @@ Feature: --features Enables a set of one or more features. Possible values are: account-api[:v1], account2[:v1], account3[:v1], admin-api[:v1], admin-fine-grained-authz[:v1], admin2[:v1], authorization[:v1], ciba[:v1], client-policies[:v1], - client-secret-rotation[:v1], device-flow[:v1], docker[:v1], dpop[:v1], - dynamic-scopes[:v1], fips[:v1], hostname[:v1],impersonation[:v1], js-adapter[:v1], kerberos - [:v1], linkedin-oauth[:v1], multi-site[:v1], offline-session-preloading[: - v1], par[:v1], preview, recovery-codes[:v1], scripts[:v1], - step-up-authentication[:v1], token-exchange[:v1], transient-users[:v1], - update-email[:v1], web-authn[:v1]. + client-secret-rotation[:v1], declarative-ui[:v1], device-flow[:v1], docker[: + v1], dpop[:v1], dynamic-scopes[:v1], fips[:v1], hostname[:v1], impersonation + [:v1], js-adapter[:v1], kerberos[:v1], linkedin-oauth[:v1], multi-site[:v1], + offline-session-preloading[:v1], par[:v1], preview, recovery-codes[:v1], + scripts[:v1], step-up-authentication[:v1], token-exchange[:v1], + transient-users[:v1], update-email[:v1], web-authn[:v1]. --features-disabled Disables a set of one or more features. Possible values are: account-api, account2, account3, admin-api, admin-fine-grained-authz, admin2, - authorization, ciba, client-policies, client-secret-rotation, device-flow, - docker, dpop, dynamic-scopes, fips, impersonation, js-adapter, kerberos, - linkedin-oauth, multi-site, offline-session-preloading, par, preview, - recovery-codes, scripts, step-up-authentication, token-exchange, - transient-users, update-email, web-authn. + authorization, ciba, client-policies, client-secret-rotation, + declarative-ui, device-flow, docker, dpop, dynamic-scopes, fips, + impersonation, js-adapter, kerberos, linkedin-oauth, multi-site, + offline-session-preloading, par, preview, recovery-codes, scripts, + step-up-authentication, token-exchange, transient-users, update-email, + web-authn. Hostname: diff --git a/server-spi-private/src/main/java/org/keycloak/services/ui/extend/UiPageProvider.java b/server-spi-private/src/main/java/org/keycloak/services/ui/extend/UiPageProvider.java new file mode 100644 index 0000000000..3b82522805 --- /dev/null +++ b/server-spi-private/src/main/java/org/keycloak/services/ui/extend/UiPageProvider.java @@ -0,0 +1,10 @@ +package org.keycloak.services.ui.extend; + +import org.keycloak.provider.ConfiguredProvider; +import org.keycloak.provider.Provider; + +import java.util.List; + +public interface UiPageProvider extends Provider, ConfiguredProvider { + +} diff --git a/server-spi-private/src/main/java/org/keycloak/services/ui/extend/UiPageProviderFactory.java b/server-spi-private/src/main/java/org/keycloak/services/ui/extend/UiPageProviderFactory.java new file mode 100644 index 0000000000..cbd931642a --- /dev/null +++ b/server-spi-private/src/main/java/org/keycloak/services/ui/extend/UiPageProviderFactory.java @@ -0,0 +1,12 @@ +package org.keycloak.services.ui.extend; + +import org.keycloak.component.ComponentFactory; +import org.keycloak.component.ComponentModel; +import org.keycloak.models.KeycloakSession; +import org.keycloak.provider.ProviderFactory; + +public interface UiPageProviderFactory extends ComponentFactory { + default T create(KeycloakSession session, ComponentModel model) { + return null; + } +} diff --git a/server-spi-private/src/main/java/org/keycloak/services/ui/extend/UiPageSpi.java b/server-spi-private/src/main/java/org/keycloak/services/ui/extend/UiPageSpi.java new file mode 100644 index 0000000000..c1249cee10 --- /dev/null +++ b/server-spi-private/src/main/java/org/keycloak/services/ui/extend/UiPageSpi.java @@ -0,0 +1,33 @@ +package org.keycloak.services.ui.extend; + +import org.keycloak.common.Profile; +import org.keycloak.provider.Provider; +import org.keycloak.provider.ProviderFactory; +import org.keycloak.provider.Spi; + +public class UiPageSpi implements Spi { + @Override + public boolean isInternal() { + return true; + } + + @Override + public String getName() { + return "ui-page"; + } + + @Override + public Class getProviderClass() { + return UiPageProvider.class; + } + + @Override + public Class getProviderFactoryClass() { + return UiPageProviderFactory.class; + } + + @Override + public boolean isEnabled() { + return Profile.isFeatureEnabled(Profile.Feature.DECLARATIVE_UI); + } +} diff --git a/server-spi-private/src/main/java/org/keycloak/services/ui/extend/UiTabProvider.java b/server-spi-private/src/main/java/org/keycloak/services/ui/extend/UiTabProvider.java new file mode 100644 index 0000000000..480a8d0489 --- /dev/null +++ b/server-spi-private/src/main/java/org/keycloak/services/ui/extend/UiTabProvider.java @@ -0,0 +1,8 @@ +package org.keycloak.services.ui.extend; + +import org.keycloak.provider.ConfiguredProvider; +import org.keycloak.provider.Provider; + +public interface UiTabProvider extends Provider, ConfiguredProvider { + +} diff --git a/server-spi-private/src/main/java/org/keycloak/services/ui/extend/UiTabProviderFactory.java b/server-spi-private/src/main/java/org/keycloak/services/ui/extend/UiTabProviderFactory.java new file mode 100644 index 0000000000..6587192081 --- /dev/null +++ b/server-spi-private/src/main/java/org/keycloak/services/ui/extend/UiTabProviderFactory.java @@ -0,0 +1,26 @@ +package org.keycloak.services.ui.extend; + +import org.keycloak.component.ComponentFactory; +import org.keycloak.component.ComponentModel; +import org.keycloak.models.KeycloakSession; + +import java.util.HashMap; +import java.util.Map; + +public interface UiTabProviderFactory extends ComponentFactory { + default T create(KeycloakSession session, ComponentModel model) { + return null; + } + + @Override + default Map getTypeMetadata() { + Map metadata = new HashMap<>(); + metadata.put("path", getPath()); + metadata.put("params", getParams()); + return metadata; + } + + String getPath(); + + Map getParams(); +} diff --git a/server-spi-private/src/main/java/org/keycloak/services/ui/extend/UiTabSpi.java b/server-spi-private/src/main/java/org/keycloak/services/ui/extend/UiTabSpi.java new file mode 100644 index 0000000000..bc97ef080d --- /dev/null +++ b/server-spi-private/src/main/java/org/keycloak/services/ui/extend/UiTabSpi.java @@ -0,0 +1,33 @@ +package org.keycloak.services.ui.extend; + +import org.keycloak.common.Profile; +import org.keycloak.provider.Provider; +import org.keycloak.provider.ProviderFactory; +import org.keycloak.provider.Spi; + +public class UiTabSpi implements Spi { + @Override + public boolean isInternal() { + return true; + } + + @Override + public String getName() { + return "ui-tab"; + } + + @Override + public Class getProviderClass() { + return UiTabProvider.class; + } + + @Override + public Class getProviderFactoryClass() { + return UiTabProviderFactory.class; + } + + @Override + public boolean isEnabled() { + return Profile.isFeatureEnabled(Profile.Feature.DECLARATIVE_UI); + } +} diff --git a/server-spi-private/src/main/resources/META-INF/services/org.keycloak.provider.Spi b/server-spi-private/src/main/resources/META-INF/services/org.keycloak.provider.Spi index 3a1a5cd941..5d26788ba9 100755 --- a/server-spi-private/src/main/resources/META-INF/services/org.keycloak.provider.Spi +++ b/server-spi-private/src/main/resources/META-INF/services/org.keycloak.provider.Spi @@ -38,6 +38,8 @@ org.keycloak.scripting.ScriptingSpi org.keycloak.services.managers.BruteForceProtectorSpi org.keycloak.services.resource.AccountResourceSpi org.keycloak.services.resource.RealmResourceSPI +org.keycloak.services.ui.extend.UiPageSpi +org.keycloak.services.ui.extend.UiTabSpi org.keycloak.sessions.AuthenticationSessionSpi org.keycloak.sessions.StickySessionEncoderSpi org.keycloak.protocol.ClientInstallationSpi