Skip to content

Commit

Permalink
Better handling for roles
Browse files Browse the repository at this point in the history
  • Loading branch information
sonOfRa committed Mar 8, 2023
1 parent ea474cd commit e4b30b6
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 44 deletions.
Expand Up @@ -22,6 +22,8 @@

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
import org.javers.core.Javers;
import org.javers.core.JaversBuilder;
Expand Down Expand Up @@ -66,13 +68,16 @@ public Javers unOrderedJavers() {
public YAMLMapper yamlMapper() {
var ym = new YAMLMapper();
ym.setSerializationInclusion(JsonInclude.Include.NON_NULL);
ym.enable(SerializationFeature.INDENT_OUTPUT);
ym.enable(YAMLGenerator.Feature.INDENT_ARRAYS_WITH_INDICATOR);
return ym;
}

@Bean
public ObjectMapper objectMapper() {
var om = new ObjectMapper();
om.setSerializationInclusion(JsonInclude.Include.NON_NULL);
om.enable(SerializationFeature.INDENT_OUTPUT);
return om;
}

Expand Down Expand Up @@ -111,7 +116,7 @@ private JaversBuilder commonJavers() {
List.of("id", "authorizationSettings", "protocolMappers")))
.registerEntity(new EntityDefinition(ProtocolMapperRepresentation.class, "name", List.of("id")))
.registerEntity(new EntityDefinition(ClientScopeRepresentation.class, "name", List.of("id", "protocolMappers")))
.registerEntity(new EntityDefinition(RoleRepresentation.class, "name", List.of("id", "containerId", "composites")))
.registerEntity(new EntityDefinition(RoleRepresentation.class, "name", List.of("id", "containerId", "composites", "attributes")))
.registerEntity(new EntityDefinition(GroupRepresentation.class, "path", List.of("id", "subGroups", "attributes", "clientRoles")))
.registerEntity(new EntityDefinition(AuthenticationFlowRepresentation.class, "alias", List.of("id", "authenticationExecutions")))
.registerEntity(new EntityDefinition(IdentityProviderRepresentation.class, "alias", List.of("internalId")))
Expand Down
Expand Up @@ -145,6 +145,7 @@ public void normalizeGroupList(List<GroupRepresentation> groups) {
normalizeGroupList(group.getSubGroups());
}
}
group.setId(null);
}
}
}
Expand Up @@ -31,6 +31,7 @@
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;

import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
Expand Down Expand Up @@ -61,69 +62,96 @@ public RolesRepresentation normalizeRoles(RolesRepresentation exportedRoles, Rol
var baselineOrEmpty = baselineRoles == null ? new RolesRepresentation() : baselineRoles;
var clientRoles = normalizeClientRoles(exportedOrEmpty.getClient(), baselineOrEmpty.getClient());
var realmRoles = normalizeRealmRoles(exportedOrEmpty.getRealm(), baselineOrEmpty.getRealm());
if (clientRoles == null && realmRoles == null) {
return null;
}
var normalizedRoles = new RolesRepresentation();
normalizedRoles.setClient(clientRoles);
normalizedRoles.setRealm(realmRoles);
if (!clientRoles.isEmpty()) {
normalizedRoles.setClient(clientRoles);
}
if (!realmRoles.isEmpty()) {
normalizedRoles.setRealm(realmRoles);
}
return normalizedRoles;
}

public List<RoleRepresentation> normalizeRealmRoles(List<RoleRepresentation> exportedRealmRoles, List<RoleRepresentation> baselineRealmRoles) {
List<RoleRepresentation> exportedOrEmpty = exportedRealmRoles == null ? List.of() : exportedRealmRoles;
List<RoleRepresentation> baselineOrEmpty = baselineRealmRoles == null ? List.of() : baselineRealmRoles;
public List<RoleRepresentation> normalizeRealmRoles(List<RoleRepresentation> exportedRoles, List<RoleRepresentation> baselineRoles) {
return normalizeRoleList(exportedRoles, baselineRoles, null);
}

public Map<String, List<RoleRepresentation>> normalizeClientRoles(Map<String, List<RoleRepresentation>> exportedRoles, Map<String, List<RoleRepresentation>> baselineRoles) {
Map<String, List<RoleRepresentation>> exportedOrEmpty = exportedRoles == null ? Map.of() : exportedRoles;
Map<String, List<RoleRepresentation>> baselineOrEmpty = baselineRoles == null ? Map.of() : baselineRoles;

var normalizedRoles = new HashMap<String, List<RoleRepresentation>>();
for (var entry : baselineOrEmpty.entrySet()) {
var clientId = entry.getKey();
var baselineClientRoles = entry.getValue();
var exportedClientRoles = exportedOrEmpty.remove(clientId);
exportedClientRoles = exportedClientRoles == null ? List.of() : exportedClientRoles;

var normalizedClientRoles = normalizeRoleList(exportedClientRoles, baselineClientRoles, clientId);
if (!normalizedClientRoles.isEmpty()) {
normalizedRoles.put(clientId, normalizedClientRoles);
}
}

for (var entry : exportedOrEmpty.entrySet()) {
var clientId = entry.getKey();
var roles = entry.getValue();

if (!roles.isEmpty()) {
normalizedRoles.put(clientId, normalizeList(roles));
}
}
return normalizedRoles;
}

var exportedMap = exportedOrEmpty.stream().collect(Collectors.toMap(RoleRepresentation::getName, Function.identity()));
var baselineMap = baselineOrEmpty.stream().collect(Collectors.toMap(RoleRepresentation::getName, Function.identity()));
public List<RoleRepresentation> normalizeRoleList(List<RoleRepresentation> exportedRoles, List<RoleRepresentation> baselineRoles, String clientId) {
List<RoleRepresentation> exportedOrEmpty = exportedRoles == null ? List.of() : exportedRoles;
List<RoleRepresentation> baselineOrEmpty = baselineRoles == null ? List.of() : baselineRoles;

var exportedMap = exportedOrEmpty.stream()
.collect(Collectors.toMap(RoleRepresentation::getName, Function.identity()));
var baselineMap = baselineOrEmpty.stream()
.collect(Collectors.toMap(RoleRepresentation::getName, Function.identity()));
var normalizedRoles = new ArrayList<RoleRepresentation>();
for (var entry : baselineMap.entrySet()) {
var roleName = entry.getKey();
var baselineRole = entry.getValue();
var exportedRole = exportedMap.remove(roleName);
if (exportedRole == null) {
logger.warn("Default realm role '{}' was deleted in exported realm. It may be reintroduced during import", roleName);
if (clientId == null) {
logger.warn("Default realm role '{}' was deleted in exported realm. It may be reintroduced during import!", roleName);
} else {
logger.warn("Default realm client-role '{}' for client '{}' was deleted in the exported realm. "
+ "It may be reintroduced during import!", roleName, clientId);
}
continue;
}

var baselineRole = entry.getValue();

var diff = unOrderedJavers.compare(baselineRole, exportedRole);

if (diff.hasChanges()
|| attributeNormalizationService.listAttributesChanged(exportedRole.getAttributes(), baselineRole.getAttributes())
|| compositesChanged(exportedRole.getComposites(), baselineRole.getComposites())) {
var normalizedRole = new RoleRepresentation();
normalizedRole.setName(roleName);
for (var change : diff.getChangesByType(PropertyChange.class)) {
javersUtil.applyChange(normalizedRole, change);
}
normalizedRole.setAttributes(attributeNormalizationService.normalizeListAttributes(exportedRole.getAttributes(),
baselineRole.getAttributes()));
normalizedRoles.add(normalizedRole);
normalizedRole.setComposites(exportedRole.getComposites());
|| compositesChanged(exportedRole.getComposites(), baselineRole.getComposites())
|| attributeNormalizationService.listAttributesChanged(exportedRole.getAttributes(), baselineRole.getAttributes())) {
normalizedRoles.add(exportedRole);
}
}
return normalizedRoles.isEmpty() ? null : normalizedRoles;
normalizedRoles.addAll(exportedMap.values());
return normalizeList(normalizedRoles);
}

private boolean compositesChanged(RoleRepresentation.Composites exportedComposites, RoleRepresentation.Composites baselineComposites) {
return unOrderedJavers.compare(baselineComposites, exportedComposites).hasChanges();
}

public Map<String, List<RoleRepresentation>> normalizeClientRoles(Map<String, List<RoleRepresentation>> exportedClientRoles,
Map<String, List<RoleRepresentation>> baselineClientRoles) {
Map<String, List<RoleRepresentation>> exportedOrEmpty = exportedClientRoles == null ? Map.of() : exportedClientRoles;
Map<String, List<RoleRepresentation>> baselineOrEmpty = baselineClientRoles == null ? Map.of() : baselineClientRoles;

Map<String, List<RoleRepresentation>> normalizedClientRoles = new HashMap<>();
for (var entry : baselineOrEmpty.entrySet()) {
var clientName = entry.getKey();
var baselineRoles = entry.getValue();
var exportedRoles = exportedOrEmpty.remove(clientName);

var normalizedRoles = normalizeRealmRoles(exportedRoles, baselineRoles);
if (normalizedRoles != null) {
normalizedClientRoles.put(clientName, normalizedRoles);
public List<RoleRepresentation> normalizeList(List<RoleRepresentation> roles) {
for (var role : roles) {
role.setId(null);
if (role.getAttributes().isEmpty()) {
role.setAttributes(null);
}
}
return normalizedClientRoles.isEmpty() ? null : normalizedClientRoles;
return roles;
}

public boolean compositesChanged(RoleRepresentation.Composites exportedComposites, RoleRepresentation.Composites baselineComposites) {
return unOrderedJavers.compare(baselineComposites, exportedComposites)
.hasChanges();
}
}

0 comments on commit e4b30b6

Please sign in to comment.