diff --git a/src/main/java/org/genesys2/server/api/v1/PermissionController.java b/src/main/java/org/genesys2/server/api/v1/PermissionController.java index f8fe3ac8ea9532bacbf4afc58f9b82b8faa3cffb..970bc94894d450dac5dcddb39a7dab994debeac8 100644 --- a/src/main/java/org/genesys2/server/api/v1/PermissionController.java +++ b/src/main/java/org/genesys2/server/api/v1/PermissionController.java @@ -15,17 +15,22 @@ */ package org.genesys2.server.api.v1; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; import org.genesys.blocks.model.JsonViews; import org.genesys.blocks.oauth.model.OAuthClient; import org.genesys.blocks.oauth.service.OAuthClientDetailsService; +import org.genesys.blocks.security.model.AclEntry; import org.genesys.blocks.security.model.AclObjectIdentity; import org.genesys.blocks.security.model.AclSid; +import org.genesys.blocks.security.serialization.AclEntriesToPermissions; import org.genesys.blocks.security.serialization.SidPermissions; import org.genesys.blocks.security.service.CustomAclService; import org.genesys2.server.api.ApiBaseController; @@ -45,7 +50,9 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import com.fasterxml.jackson.annotation.JsonUnwrapped; import com.fasterxml.jackson.annotation.JsonView; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; import io.swagger.annotations.Api; @@ -85,7 +92,7 @@ public class PermissionController { @Transactional @PostMapping(value = "/permissions/{clazz}/{id}", produces = MediaType.APPLICATION_JSON_VALUE) @JsonView(JsonViews.Minimal.class) - public AclObjectIdentity addPermission(@PathVariable(value = "clazz") final String className, @PathVariable("id") final long id, + public AclObjectIdentityExt addPermission(@PathVariable(value = "clazz") final String className, @PathVariable("id") final long id, @RequestBody final SidPermissions sidPermissions) { final AclObjectIdentity objectIdentity = aclService.ensureObjectIdentity(id, className); LOG.info("Setting permissions {}", sidPermissions); @@ -105,7 +112,7 @@ public class PermissionController { @Transactional(readOnly = true) @GetMapping(value = "/permissions/{clazz}/{id}", produces = MediaType.APPLICATION_JSON_VALUE) @JsonView(JsonViews.Minimal.class) - public AclObjectIdentity permissions(@PathVariable(value = "clazz") final String className, @PathVariable("id") final long id) { + public AclObjectIdentityExt permissions(@PathVariable(value = "clazz") final String className, @PathVariable("id") final long id) { final AclObjectIdentity objectIdentity = aclService.getObjectIdentity(id, className); return lazyLoadForJson(objectIdentity); } @@ -116,13 +123,33 @@ public class PermissionController { * @param objectIdentity the object identity * @return the acl object identity */ - protected AclObjectIdentity lazyLoadForJson(final AclObjectIdentity objectIdentity) { + protected AclObjectIdentityExt lazyLoadForJson(final AclObjectIdentity objectIdentity) { + AclObjectIdentityExt _aclObjectIdentity = new AclObjectIdentityExt(objectIdentity); + if (objectIdentity != null && objectIdentity.getAclEntries() != null) { objectIdentity.getAclEntries().size(); + + List inheritedEntries = inherited(objectIdentity, new ArrayList<>(), new HashSet<>()); + _aclObjectIdentity.inherited.addAll(inheritedEntries); // lazy load for JSON - objectIdentity.getAclEntries().forEach(entry -> entry.getAclSid().getId()); + _aclObjectIdentity.inherited.forEach(entry -> entry.getAclSid().getId()); + } + + return _aclObjectIdentity; + } + + private List inherited(AclObjectIdentity objectIdentity, List aclEntries, Set handled) { + if (objectIdentity == null || handled.contains(objectIdentity)) { + return aclEntries; + } + aclEntries.addAll(objectIdentity.getAclEntries()); + handled.add(objectIdentity); + + if (objectIdentity.getParentObject() != null) { + inherited(objectIdentity.getParentObject(), aclEntries, handled); } - return objectIdentity; + + return aclEntries; } /** @@ -131,9 +158,10 @@ public class PermissionController { * @param id the internal ID of aclObjectIdentity * @return the acl object identity */ + @Transactional(readOnly = true) @GetMapping(value = "/permissions/{aclObjectIdentityId}", produces = MediaType.APPLICATION_JSON_VALUE) @JsonView(JsonViews.Minimal.class) - public AclObjectIdentity permissions(@PathVariable(value = "aclObjectIdentityId") final long id) { + public AclObjectIdentityExt permissions(@PathVariable(value = "aclObjectIdentityId") final long id) { final AclObjectIdentity objectIdentity = aclService.getObjectIdentity(id); return lazyLoadForJson(objectIdentity); } @@ -211,4 +239,18 @@ public class PermissionController { } return oauthMap; } + + /** + * Wraps {@link AclObjectIdentity} and adds list of inherited permissions. + */ + private static class AclObjectIdentityExt { + @JsonUnwrapped + public AclObjectIdentity original; + @JsonSerialize(converter = AclEntriesToPermissions.class) + public List inherited = new ArrayList<>(); + + public AclObjectIdentityExt(AclObjectIdentity source) { + this.original = source; + } + } }