Skip to content

Commit

Permalink
fix: generate group hierarchy base on configuration files (#45)
Browse files Browse the repository at this point in the history
Closes #45
  • Loading branch information
MarcScheib authored Apr 4, 2024
1 parent c8ad9e3 commit bf28181
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import io.quarkus.logging.Log;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.core.Response;

public abstract class AbstractImporter {
/**
Expand Down Expand Up @@ -71,8 +72,20 @@ private List<Path> getImportFiles() {
* @return the error representation based on the exception, or null otherwise
*/
protected ErrorRepresentation extractError(final WebApplicationException exception) {
return exception != null && exception.getResponse() != null
? exception.getResponse().readEntity(ErrorRepresentation.class)
return exception != null
? extractError(exception.getResponse())
: null;
}

/**
* Extracts a Keycloak {@link ErrorRepresentation} from the given Response.
*
* @param response the REST response
* @return the error representation, or null otherwise
*/
protected ErrorRepresentation extractError(final Response response) {
return response != null
? response.readEntity(ErrorRepresentation.class)
: null;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package com.cycrilabs.keycloak.configurator.commands.configure.boundary;

import java.nio.file.Path;
import java.util.Optional;

import io.quarkus.runtime.util.StringUtil;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.ws.rs.ClientErrorException;
import jakarta.ws.rs.core.Response;

import org.keycloak.representations.idm.ErrorRepresentation;
import org.keycloak.representations.idm.GroupRepresentation;

import com.cycrilabs.keycloak.configurator.shared.control.JsonUtil;
Expand All @@ -33,21 +34,55 @@ protected Object importFile(final Path file) {
.add(group)) {
if (response.getStatus() == 409) {
Log.errorf("Could not import group for realm '%s': %s", realmName,
response.readEntity(ErrorRepresentation.class)
.getErrorMessage());
extractError(response).getErrorMessage());
} else {
Log.infof("Group '%s' imported for realm '%s'.", group.getName(), realmName);
}
} catch (final ClientErrorException e) {
Log.errorf("Could not import group for realm '%s': %s", realmName, e.getMessage());
return null;
}

final GroupRepresentation importedGroup = keycloak.realm(realmName)
.groups()
.query(group.getName())
.get(0);
.groups(group.getName(), Boolean.TRUE, null, null, false)
.getFirst();
Log.infof("Loaded imported group '%s' from realm '%s'.", importedGroup.getName(),
realmName);

applyGroupHierarchy(realmName, group.getPath(), importedGroup);

return importedGroup;
}

/**
* This implements a naive approach of creating the group hierarchy for the given set of group configurations.
* It assumes that the groups are imported in the correct order in regard to their hierarchy and the hierarchy
* is linear as well.
*/
private void applyGroupHierarchy(final String realmName, final String path, final GroupRepresentation group) {
if (StringUtil.isNullOrEmpty(path)) {
return;
}

final String[] groupHierarchy = path.split("/");
if (groupHierarchy.length > 2) {
final String groupName = groupHierarchy[groupHierarchy.length - 2];
final Optional<GroupRepresentation> potentialGroup = keycloak.realm(realmName)
.groups()
.query(groupName, false, null, null, false)
.stream()
.filter(grp -> grp.getName().equals(groupName))
.findFirst();
if (potentialGroup.isPresent()) {
final GroupRepresentation parentGroup = potentialGroup.get();
try (final Response response = keycloak.realm(realmName)
.groups()
.group(parentGroup.getId())
.subGroup(group)) {
Log.infof("Adding group '%s' as child to '%s'.", group.getName(), parentGroup.getName());
}
}
}
}
}

0 comments on commit bf28181

Please sign in to comment.