Changes the contract to make it simpler and rely on the realm available from the current session
Closes #28403 Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com>
This commit is contained in:
parent
9bb2402d3b
commit
fefeb83588
8 changed files with 57 additions and 83 deletions
|
@ -42,16 +42,21 @@ public class JpaOrganizationProvider implements OrganizationProvider {
|
|||
private final EntityManager em;
|
||||
private final GroupProvider groupProvider;
|
||||
private final UserProvider userProvider;
|
||||
private final RealmModel realm;
|
||||
|
||||
public JpaOrganizationProvider(KeycloakSession session) {
|
||||
em = session.getProvider(JpaConnectionProvider.class).getEntityManager();
|
||||
groupProvider = session.groups();
|
||||
userProvider = session.users();
|
||||
realm = session.getContext().getRealm();
|
||||
if (realm == null) {
|
||||
throw new IllegalArgumentException("Session not bound to a realm");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public OrganizationModel createOrganization(RealmModel realm, String name) {
|
||||
GroupModel group = createOrganizationGroup(realm, name);
|
||||
public OrganizationModel create(String name) {
|
||||
GroupModel group = createOrganizationGroup(name);
|
||||
OrganizationEntity entity = new OrganizationEntity();
|
||||
|
||||
entity.setId(KeycloakModelUtils.generateId());
|
||||
|
@ -65,14 +70,14 @@ public class JpaOrganizationProvider implements OrganizationProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean removeOrganization(RealmModel realm, OrganizationModel organization) {
|
||||
GroupModel group = getOrganizationGroup(realm, organization);
|
||||
public boolean remove(OrganizationModel organization) {
|
||||
GroupModel group = getOrganizationGroup(organization);
|
||||
|
||||
//TODO: won't scale, requires a better mechanism for bulk deleting users
|
||||
userProvider.getGroupMembersStream(realm, group).forEach(userModel -> userProvider.removeUser(realm, userModel));
|
||||
groupProvider.removeGroup(realm, group);
|
||||
|
||||
OrganizationAdapter adapter = getAdapter(realm, organization.getId());
|
||||
OrganizationAdapter adapter = getAdapter(organization.getId());
|
||||
|
||||
em.remove(adapter.getEntity());
|
||||
|
||||
|
@ -80,18 +85,18 @@ public class JpaOrganizationProvider implements OrganizationProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void removeOrganizations(RealmModel realm) {
|
||||
public void removeAll() {
|
||||
//TODO: won't scale, requires a better mechanism for bulk deleting organizations within a realm
|
||||
getOrganizationsStream(realm).forEach(organization -> removeOrganization(realm, organization));
|
||||
getAllStream().forEach(this::remove);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addOrganizationMember(RealmModel realm, OrganizationModel organization, UserModel user) {
|
||||
public boolean addMember(OrganizationModel organization, UserModel user) {
|
||||
throwExceptionIfOrganizationIsNull(organization);
|
||||
if (user == null) {
|
||||
throw new ModelException("User can not be null");
|
||||
}
|
||||
OrganizationAdapter adapter = getAdapter(realm, organization.getId());
|
||||
OrganizationAdapter adapter = getAdapter(organization.getId());
|
||||
GroupModel group = groupProvider.getGroupById(realm, adapter.getGroupId());
|
||||
|
||||
if (user.isMemberOf(group)) {
|
||||
|
@ -109,13 +114,12 @@ public class JpaOrganizationProvider implements OrganizationProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
public OrganizationModel getOrganizationById(RealmModel realm, String id) {
|
||||
return getAdapter(realm, id, false);
|
||||
public OrganizationModel getById(String id) {
|
||||
return getAdapter(id, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<OrganizationModel> getOrganizationsStream(RealmModel realm) {
|
||||
throwExceptionIfRealmIsNull(realm);
|
||||
public Stream<OrganizationModel> getAllStream() {
|
||||
TypedQuery<OrganizationEntity> query = em.createNamedQuery("getByRealm", OrganizationEntity.class);
|
||||
|
||||
query.setParameter("realmId", realm.getId());
|
||||
|
@ -124,17 +128,16 @@ public class JpaOrganizationProvider implements OrganizationProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Stream<UserModel> getMembersStream(RealmModel realm, OrganizationModel organization) {
|
||||
public Stream<UserModel> getMembersStream(OrganizationModel organization) {
|
||||
throwExceptionIfOrganizationIsNull(organization);
|
||||
OrganizationAdapter adapter = getAdapter(realm, organization.getId());
|
||||
GroupModel group = getOrganizationGroup(realm, adapter);
|
||||
OrganizationAdapter adapter = getAdapter(organization.getId());
|
||||
GroupModel group = getOrganizationGroup(adapter);
|
||||
|
||||
return userProvider.getGroupMembersStream(realm, group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserModel getMemberById(RealmModel realm, OrganizationModel organization, String id) {
|
||||
throwExceptionIfRealmIsNull(realm);
|
||||
public UserModel getMemberById(OrganizationModel organization, String id) {
|
||||
throwExceptionIfOrganizationIsNull(organization);
|
||||
UserModel user = userProvider.getUserById(realm, id);
|
||||
|
||||
|
@ -152,8 +155,7 @@ public class JpaOrganizationProvider implements OrganizationProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
public OrganizationModel getOrganizationByMember(RealmModel realm, UserModel member) {
|
||||
throwExceptionIfRealmIsNull(realm);
|
||||
public OrganizationModel getByMember(UserModel member) {
|
||||
if (member == null) {
|
||||
throw new ModelException("User can not be null");
|
||||
}
|
||||
|
@ -164,7 +166,7 @@ public class JpaOrganizationProvider implements OrganizationProvider {
|
|||
return null;
|
||||
}
|
||||
|
||||
return getOrganizationById(realm, orgId);
|
||||
return getById(orgId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -172,12 +174,11 @@ public class JpaOrganizationProvider implements OrganizationProvider {
|
|||
|
||||
}
|
||||
|
||||
private OrganizationAdapter getAdapter(RealmModel realm, String id) {
|
||||
return getAdapter(realm, id, true);
|
||||
private OrganizationAdapter getAdapter(String id) {
|
||||
return getAdapter(id, true);
|
||||
}
|
||||
|
||||
private OrganizationAdapter getAdapter(RealmModel realm, String id, boolean failIfNotFound) {
|
||||
throwExceptionIfRealmIsNull(realm);
|
||||
private OrganizationAdapter getAdapter(String id, boolean failIfNotFound) {
|
||||
OrganizationEntity entity = em.find(OrganizationEntity.class, id);
|
||||
|
||||
if (entity == null) {
|
||||
|
@ -194,8 +195,7 @@ public class JpaOrganizationProvider implements OrganizationProvider {
|
|||
return new OrganizationAdapter(realm, entity);
|
||||
}
|
||||
|
||||
private GroupModel createOrganizationGroup(RealmModel realm, String name) {
|
||||
throwExceptionIfRealmIsNull(realm);
|
||||
private GroupModel createOrganizationGroup(String name) {
|
||||
if (name == null) {
|
||||
throw new ModelException("name can not be null");
|
||||
}
|
||||
|
@ -214,9 +214,9 @@ public class JpaOrganizationProvider implements OrganizationProvider {
|
|||
return "kc.org." + name;
|
||||
}
|
||||
|
||||
private GroupModel getOrganizationGroup(RealmModel realm, OrganizationModel organization) {
|
||||
private GroupModel getOrganizationGroup(OrganizationModel organization) {
|
||||
throwExceptionIfOrganizationIsNull(organization);
|
||||
OrganizationAdapter adapter = getAdapter(realm, organization.getId());
|
||||
OrganizationAdapter adapter = getAdapter(organization.getId());
|
||||
|
||||
GroupModel group = groupProvider.getGroupById(realm, adapter.getGroupId());
|
||||
|
||||
|
@ -232,10 +232,4 @@ public class JpaOrganizationProvider implements OrganizationProvider {
|
|||
throw new ModelException("organization can not be null");
|
||||
}
|
||||
}
|
||||
|
||||
private void throwExceptionIfRealmIsNull(RealmModel realm) {
|
||||
if (realm == null) {
|
||||
throw new ModelException("realm can not be null");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,8 +57,7 @@ public class JpaOrganizationProviderFactory implements OrganizationProviderFacto
|
|||
if (event instanceof RealmRemovedEvent) {
|
||||
KeycloakSession session = ((RealmRemovedEvent) event).getKeycloakSession();
|
||||
OrganizationProvider provider = session.getProvider(OrganizationProvider.class);
|
||||
RealmModel realm = ((RealmRemovedEvent) event).getRealm();
|
||||
provider.removeOrganizations(realm);
|
||||
provider.removeAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,8 +37,7 @@ public final class OrganizationAdapter implements OrganizationModel, JpaModel<Or
|
|||
return entity.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RealmModel getRealm() {
|
||||
RealmModel getRealm() {
|
||||
return realm;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,88 +20,81 @@ import java.util.stream.Stream;
|
|||
|
||||
import org.keycloak.models.ModelDuplicateException;
|
||||
import org.keycloak.models.OrganizationModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.provider.Provider;
|
||||
|
||||
/**
|
||||
* A {@link Provider} that manages organization and its data within the scope of a realm.
|
||||
*/
|
||||
public interface OrganizationProvider extends Provider {
|
||||
|
||||
/**
|
||||
* Creates a new organization with given {@code name} to the given realm.
|
||||
* The internal ID of the organization will be created automatically.
|
||||
* @param realm Realm owning this organization.
|
||||
* @param name String name of the organization.
|
||||
* @throws ModelDuplicateException If there is already an organization with the given name
|
||||
* @return Model of the created organization.
|
||||
*/
|
||||
OrganizationModel createOrganization(RealmModel realm, String name);
|
||||
OrganizationModel create(String name);
|
||||
|
||||
/**
|
||||
* Returns a {@link OrganizationModel} by its {@code id};
|
||||
*
|
||||
* @param realm the realm
|
||||
* @param id the id of an organization
|
||||
* @return the organization with the given {@code id}
|
||||
*/
|
||||
OrganizationModel getOrganizationById(RealmModel realm, String id);
|
||||
OrganizationModel getById(String id);
|
||||
|
||||
/**
|
||||
* Removes the given organization from the given realm.
|
||||
*
|
||||
* @param realm Realm.
|
||||
* @param organization Organization to be removed.
|
||||
* @return true if the organization was removed, false if group doesn't exist or doesn't belong to the given realm
|
||||
*/
|
||||
boolean removeOrganization(RealmModel realm, OrganizationModel organization);
|
||||
boolean remove(OrganizationModel organization);
|
||||
|
||||
/**
|
||||
* Removes all organizations from the given realm.
|
||||
* @param realm Realm.
|
||||
*/
|
||||
void removeOrganizations(RealmModel realm);
|
||||
void removeAll();
|
||||
|
||||
/**
|
||||
* Adds the give {@link UserModel} as a member of the given {@link OrganizationModel}.
|
||||
*
|
||||
* @param realm the realm
|
||||
* @param organization the organization
|
||||
* @param user the user
|
||||
* @return {@code true} if the user was added as a member. Otherwise, returns {@code false}
|
||||
*/
|
||||
boolean addOrganizationMember(RealmModel realm, OrganizationModel organization, UserModel user);
|
||||
boolean addMember(OrganizationModel organization, UserModel user);
|
||||
|
||||
/**
|
||||
* Returns the organizations of the given realm as a stream.
|
||||
* @param realm Realm.
|
||||
* @return Stream of the organizations. Never returns {@code null}.
|
||||
*/
|
||||
Stream<OrganizationModel> getOrganizationsStream(RealmModel realm);
|
||||
Stream<OrganizationModel> getAllStream();
|
||||
|
||||
/**
|
||||
* Returns the members of a given {@code organization}.
|
||||
*
|
||||
* @param realm the realm
|
||||
* @param organization the organization
|
||||
* @return the organization with the given {@code id}
|
||||
*/
|
||||
Stream<UserModel> getMembersStream(RealmModel realm, OrganizationModel organization);
|
||||
Stream<UserModel> getMembersStream(OrganizationModel organization);
|
||||
|
||||
/**
|
||||
* Returns the member of an {@code organization} by its {@code id}.
|
||||
*
|
||||
* @param realm the realm
|
||||
* @param organization the organization
|
||||
* @param id the member id
|
||||
* @return the organization with the given {@code id}
|
||||
*/
|
||||
UserModel getMemberById(RealmModel realm, OrganizationModel organization, String id);
|
||||
UserModel getMemberById(OrganizationModel organization, String id);
|
||||
|
||||
/**
|
||||
* Returns the {@link OrganizationModel} that a {@code member} belongs to.
|
||||
*
|
||||
* @param realm the realm
|
||||
* @param member the member of a organization
|
||||
* @return the organization the {@code member} belongs to
|
||||
*/
|
||||
OrganizationModel getOrganizationByMember(RealmModel realm, UserModel member);
|
||||
OrganizationModel getByMember(UserModel member);
|
||||
}
|
||||
|
|
|
@ -26,6 +26,4 @@ public interface OrganizationModel {
|
|||
void setName(String name);
|
||||
|
||||
String getName();
|
||||
|
||||
RealmModel getRealm();
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ public class OrganizationMemberResource {
|
|||
OrganizationProvider provider = session.getProvider(OrganizationProvider.class);
|
||||
|
||||
try {
|
||||
if (provider.addOrganizationMember(realm, organization, member)) {
|
||||
if (provider.addMember(organization, member)) {
|
||||
return Response.created(session.getContext().getUri().getAbsolutePathBuilder().path(member.getId()).build()).build();
|
||||
}
|
||||
} catch (ModelException me) {
|
||||
|
@ -110,7 +110,7 @@ public class OrganizationMemberResource {
|
|||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Stream<UserRepresentation> getMembers() {
|
||||
return provider.getMembersStream(realm, organization).map(this::toRepresentation);
|
||||
return provider.getMembersStream(organization).map(this::toRepresentation);
|
||||
}
|
||||
|
||||
@Path("{id}")
|
||||
|
@ -152,7 +152,7 @@ public class OrganizationMemberResource {
|
|||
}
|
||||
|
||||
UserModel member = getMember(id);
|
||||
OrganizationModel organization = provider.getOrganizationByMember(realm, member);
|
||||
OrganizationModel organization = provider.getByMember(member);
|
||||
OrganizationRepresentation rep = new OrganizationRepresentation();
|
||||
|
||||
rep.setId(organization.getId());
|
||||
|
@ -161,7 +161,7 @@ public class OrganizationMemberResource {
|
|||
}
|
||||
|
||||
private UserModel getMember(String id) {
|
||||
UserModel member = provider.getMemberById(realm, organization, id);
|
||||
UserModel member = provider.getMemberById(organization, id);
|
||||
|
||||
if (member == null) {
|
||||
throw new NotFoundException();
|
||||
|
|
|
@ -34,7 +34,6 @@ import jakarta.ws.rs.core.Response;
|
|||
import jakarta.ws.rs.ext.Provider;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.OrganizationModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.organization.OrganizationProvider;
|
||||
import org.keycloak.representations.idm.OrganizationRepresentation;
|
||||
import org.keycloak.services.resources.admin.AdminEventBuilder;
|
||||
|
@ -68,8 +67,7 @@ public class OrganizationResource {
|
|||
throw new BadRequestException();
|
||||
}
|
||||
|
||||
RealmModel realm = session.getContext().getRealm();
|
||||
OrganizationModel model = provider.createOrganization(realm, organization.getName());
|
||||
OrganizationModel model = provider.create(organization.getName());
|
||||
|
||||
return Response.created(session.getContext().getUri().getAbsolutePathBuilder().path(model.getId()).build()).build();
|
||||
}
|
||||
|
@ -77,7 +75,7 @@ public class OrganizationResource {
|
|||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Stream<OrganizationRepresentation> get() {
|
||||
return provider.getOrganizationsStream(session.getContext().getRealm()).map(this::toRepresentation);
|
||||
return provider.getAllStream().map(this::toRepresentation);
|
||||
}
|
||||
|
||||
@Path("{id}")
|
||||
|
@ -88,7 +86,7 @@ public class OrganizationResource {
|
|||
throw new BadRequestException();
|
||||
}
|
||||
|
||||
return toRepresentation(getOrganization(session.getContext().getRealm(), id));
|
||||
return toRepresentation(getOrganization(id));
|
||||
}
|
||||
|
||||
@Path("{id}")
|
||||
|
@ -98,8 +96,7 @@ public class OrganizationResource {
|
|||
throw new BadRequestException();
|
||||
}
|
||||
|
||||
RealmModel realm = session.getContext().getRealm();
|
||||
provider.removeOrganization(realm, getOrganization(realm, id));
|
||||
provider.remove(getOrganization(id));
|
||||
|
||||
return Response.noContent().build();
|
||||
}
|
||||
|
@ -108,8 +105,7 @@ public class OrganizationResource {
|
|||
@PUT
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Response update(@PathParam("id") String id, OrganizationRepresentation organization) {
|
||||
RealmModel realm = session.getContext().getRealm();
|
||||
OrganizationModel model = getOrganization(realm, id);
|
||||
OrganizationModel model = getOrganization(id);
|
||||
|
||||
toModel(organization, model);
|
||||
|
||||
|
@ -118,18 +114,16 @@ public class OrganizationResource {
|
|||
|
||||
@Path("{id}/members")
|
||||
public OrganizationMemberResource members(@PathParam("id") String id) {
|
||||
RealmModel realm = session.getContext().getRealm();
|
||||
OrganizationModel model = getOrganization(realm, id);
|
||||
|
||||
return new OrganizationMemberResource(session, model, auth, adminEvent);
|
||||
OrganizationModel organization = getOrganization(id);
|
||||
return new OrganizationMemberResource(session, organization, auth, adminEvent);
|
||||
}
|
||||
|
||||
private OrganizationModel getOrganization(RealmModel realm, String id) {
|
||||
private OrganizationModel getOrganization(String id) {
|
||||
if (id == null) {
|
||||
throw new BadRequestException();
|
||||
}
|
||||
|
||||
OrganizationModel model = provider.getOrganizationById(realm, id);
|
||||
OrganizationModel model = provider.getById(id);
|
||||
|
||||
if (model == null) {
|
||||
throw new NotFoundException();
|
||||
|
|
|
@ -28,7 +28,6 @@ import org.keycloak.models.ClientSessionContext;
|
|||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.OrganizationModel;
|
||||
import org.keycloak.models.ProtocolMapperModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.UserSessionModel;
|
||||
import org.keycloak.organization.OrganizationProvider;
|
||||
|
@ -70,11 +69,9 @@ public class OrganizationMembershipMapper extends AbstractOIDCProtocolMapper imp
|
|||
|
||||
@Override
|
||||
protected void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession, KeycloakSession keycloakSession, ClientSessionContext clientSessionCtx) {
|
||||
|
||||
RealmModel realm = keycloakSession.getContext().getRealm();
|
||||
UserModel user = userSession.getUser();
|
||||
OrganizationProvider organizationProvider = keycloakSession.getProvider(OrganizationProvider.class);
|
||||
OrganizationModel organization = organizationProvider.getOrganizationByMember(realm, user);
|
||||
OrganizationModel organization = organizationProvider.getByMember(user);
|
||||
|
||||
if (organization != null) {
|
||||
Map<String, Map<String, Object>> claim = new HashMap<>();
|
||||
|
|
Loading…
Reference in a new issue