mirror of
https://github.com/keycloak/keycloak.git
synced 2026-01-09 23:12:06 -03:30
Don't show global event listeners in the admin UI
Closes #34602 Signed-off-by: Alexander Schwartz <aschwart@redhat.com>
This commit is contained in:
parent
de14e1c310
commit
f4a208de6d
@ -2070,7 +2070,7 @@ addClientProfile=Add client profile
|
||||
maxFailureWaitSeconds=Max wait
|
||||
userEventsRegistered=User events registered
|
||||
renameAGroup=Rename group
|
||||
eventConfigError=Could not save event configuration {{error}}
|
||||
eventConfigError=Could not save event configuration\: {{error}}
|
||||
confirmAccessTokenTitle=Regenerate registration access token?
|
||||
target=Target
|
||||
impersonateConfirmDialog=Are you sure you want to log in as this user? If this user is in the same realm with you, your current login session will be logged out before you log in as this user.
|
||||
|
||||
@ -1,8 +1,19 @@
|
||||
import { ActionGroup, Button } from "@patternfly/react-core";
|
||||
import { FormProvider, UseFormReturn } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { SelectControl, SelectVariant } from "@keycloak/keycloak-ui-shared";
|
||||
import { useServerInfo } from "../../context/server-info/ServerInfoProvider";
|
||||
import {
|
||||
KeycloakSpinner,
|
||||
useFetch,
|
||||
SelectControl,
|
||||
SelectVariant,
|
||||
} from "@keycloak/keycloak-ui-shared";
|
||||
import { useState } from "react";
|
||||
import { fetchAdminUI } from "../../context/auth/admin-ui-endpoint";
|
||||
import { useAdminClient } from "../../admin-client";
|
||||
|
||||
type EventListenerRepresentation = {
|
||||
id: string;
|
||||
};
|
||||
|
||||
type EventListenersFormProps = {
|
||||
form: UseFormReturn;
|
||||
@ -15,8 +26,24 @@ export const EventListenersForm = ({
|
||||
}: EventListenersFormProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const serverInfo = useServerInfo();
|
||||
const eventListeners = serverInfo.providers?.eventsListener.providers;
|
||||
const [eventListeners, setEventListeners] =
|
||||
useState<EventListenerRepresentation[]>();
|
||||
|
||||
const { adminClient } = useAdminClient();
|
||||
|
||||
useFetch(
|
||||
() =>
|
||||
fetchAdminUI<EventListenerRepresentation[]>(
|
||||
adminClient,
|
||||
"ui-ext/available-event-listeners",
|
||||
),
|
||||
setEventListeners,
|
||||
[],
|
||||
);
|
||||
|
||||
if (!eventListeners) {
|
||||
return <KeycloakSpinner />;
|
||||
}
|
||||
|
||||
return (
|
||||
<FormProvider {...form}>
|
||||
@ -34,7 +61,7 @@ export const EventListenersForm = ({
|
||||
collapsedText: t("showRemaining"),
|
||||
}}
|
||||
variant={SelectVariant.typeaheadMulti}
|
||||
options={Object.keys(eventListeners!)}
|
||||
options={eventListeners.map((value) => value.id)}
|
||||
/>
|
||||
<ActionGroup>
|
||||
<Button
|
||||
|
||||
@ -35,6 +35,11 @@ public final class AdminExtResource {
|
||||
return new AvailableRoleMappingResource(session, realm, auth);
|
||||
}
|
||||
|
||||
@Path("/available-event-listeners")
|
||||
public AvailableEventListenersResource availableEventListeners() {
|
||||
return new AvailableEventListenersResource(session, auth);
|
||||
}
|
||||
|
||||
@Path("/effective-roles")
|
||||
public EffectiveRoleMappingResource effectiveRoles() {
|
||||
return new EffectiveRoleMappingResource(session, realm, auth);
|
||||
|
||||
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2024 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.admin.ui.rest;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import org.eclipse.microprofile.openapi.annotations.Operation;
|
||||
import org.eclipse.microprofile.openapi.annotations.enums.SchemaType;
|
||||
import org.eclipse.microprofile.openapi.annotations.media.Content;
|
||||
import org.eclipse.microprofile.openapi.annotations.media.Schema;
|
||||
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
|
||||
import org.keycloak.admin.ui.rest.model.EventListener;
|
||||
import org.keycloak.admin.ui.rest.model.ProviderMapper;
|
||||
import org.keycloak.events.EventListenerProvider;
|
||||
import org.keycloak.events.EventListenerProviderFactory;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
|
||||
|
||||
public class AvailableEventListenersResource {
|
||||
|
||||
private final KeycloakSession session;
|
||||
private final AdminPermissionEvaluator auth;
|
||||
|
||||
public AvailableEventListenersResource(KeycloakSession session, AdminPermissionEvaluator auth) {
|
||||
this.session = session;
|
||||
this.auth = auth;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/")
|
||||
@Produces({"application/json"})
|
||||
@Operation(
|
||||
summary = "List all available event listener providers",
|
||||
description = "This endpoint returns List all available event listener providers"
|
||||
)
|
||||
@APIResponse(
|
||||
responseCode = "200",
|
||||
description = "",
|
||||
content = {@Content(
|
||||
schema = @Schema(
|
||||
implementation = EventListener.class,
|
||||
type = SchemaType.ARRAY
|
||||
)
|
||||
)}
|
||||
)
|
||||
public final List<EventListener> listAvailableEventListeners() {
|
||||
auth.realm().requireViewEvents();
|
||||
this.auth.adminAuth().getRealm().getEventsListenersStream();
|
||||
|
||||
ArrayList<EventListener> result = new ArrayList<>();
|
||||
|
||||
session.getKeycloakSessionFactory().getProviderFactoriesStream(EventListenerProvider.class).forEach(
|
||||
providerFactory -> {
|
||||
if (!((EventListenerProviderFactory) providerFactory).isGlobal()) {
|
||||
result.add(ProviderMapper.convertToModel((EventListenerProviderFactory) providerFactory));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2024 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.admin.ui.rest.model;
|
||||
|
||||
import org.eclipse.microprofile.openapi.annotations.media.Schema;
|
||||
|
||||
public class EventListener {
|
||||
|
||||
@Schema(required = true)
|
||||
private String id;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2024 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.admin.ui.rest.model;
|
||||
|
||||
import org.keycloak.events.EventListenerProviderFactory;
|
||||
|
||||
public class ProviderMapper {
|
||||
public static EventListener convertToModel(EventListenerProviderFactory eventListenerProviderFactory) {
|
||||
EventListener eventListener = new EventListener();
|
||||
eventListener.setId(eventListenerProviderFactory.getId());
|
||||
return eventListener;
|
||||
}
|
||||
}
|
||||
@ -16,10 +16,14 @@
|
||||
*/
|
||||
package org.keycloak.services.managers;
|
||||
|
||||
import jakarta.ws.rs.ClientErrorException;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.common.Profile;
|
||||
import org.keycloak.common.enums.SslRequired;
|
||||
import org.keycloak.common.util.Encode;
|
||||
import org.keycloak.events.EventListenerProvider;
|
||||
import org.keycloak.events.EventListenerProviderFactory;
|
||||
import org.keycloak.models.AbstractKeycloakTransaction;
|
||||
import org.keycloak.models.AccountRoles;
|
||||
import org.keycloak.models.AdminRoles;
|
||||
@ -296,6 +300,15 @@ public class RealmManager {
|
||||
realm.setEventsEnabled(rep.isEventsEnabled());
|
||||
realm.setEventsExpiration(rep.getEventsExpiration() != null ? rep.getEventsExpiration() : 0);
|
||||
if (rep.getEventsListeners() != null) {
|
||||
for (String el : rep.getEventsListeners()) {
|
||||
EventListenerProviderFactory elpf = (EventListenerProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(EventListenerProvider.class, el);
|
||||
if (elpf == null) {
|
||||
throw new ClientErrorException("Unknown event listener", Response.Status.BAD_REQUEST);
|
||||
}
|
||||
if (elpf.isGlobal()) {
|
||||
throw new ClientErrorException("Global event listeners not allowed in realm specific configuration", Response.Status.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
realm.setEventsListeners(new HashSet<>(rep.getEventsListeners()));
|
||||
}
|
||||
if(rep.getEnabledEventTypes() != null) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user