Commit c5ffd35f authored by Matija Obreza's avatar Matija Obreza
Browse files

ACL editor

parent c041cea8
......@@ -87,7 +87,7 @@ public class AsAdminAspect {
} else {
LOG.warn("Got SYS_ADMIN account: " + sysUser);
AuthUserDetails userDetails = new AuthUserDetails(sysUser.getEmail(), "", Arrays.asList(new SimpleGrantedAuthority(UserRole.ADMINISTRATOR
AuthUserDetails userDetails = new AuthUserDetails(sysUser.getUuid(), "", Arrays.asList(new SimpleGrantedAuthority(UserRole.ADMINISTRATOR
.getName())));
userDetails.setUser(sysUser);
......
......@@ -30,7 +30,6 @@ public interface UserPersistence extends JpaRepository<User, Long> {
@Query("select u from User u where u.email = ?1 and u.systemAccount = true")
User findSystemUser(String username);
@Query("select u from User u where u.uuid = ?1 and u.systemAccount = false")
User findByUuid(String uuid);
}
......@@ -58,9 +58,9 @@ public interface AclService {
List<AclSid> getSids(long id, String className);
Map<AclSid, Map<Long, Boolean>> getPermissions(AclAwareModel entity);
Map<String, Map<Integer, Boolean>> getPermissions(AclAwareModel entity);
Map<AclSid, Map<Long, Boolean>> getPermissions(long id, String className);
Map<String, Map<Integer, Boolean>> getPermissions(long id, String className);
boolean addPermissions(long objectIdIdentity, String className, String uuid, boolean principal, Map<Integer, Boolean> permissions);
......
......@@ -51,277 +51,259 @@ import java.util.Map;
@Transactional
public class AclServiceImpl implements AclService {
private static final Logger LOG = LoggerFactory.getLogger(AclServiceImpl.class);
private static Permission[] basePermissions;
@Autowired
private UserService userService;
@Autowired
private AclClassPersistence aclClassPersistence;
@Autowired
private AclEntryPersistence aclEntryPersistence;
@Autowired
private AclObjectIdentityPersistence aclObjectIdentityPersistence;
@Autowired
private AclSidPersistence aclSidPersistence;
@Autowired
private AsAdminAspect asAdminAspect;
@Autowired
private CacheManager cacheManager;
static {
basePermissions = new Permission[] { BasePermission.CREATE, BasePermission.READ, BasePermission.WRITE, BasePermission.DELETE,
BasePermission.ADMINISTRATION };
}
@Override
@Transactional(readOnly = true)
public Permission[] getAvailablePermissions(String className) {
// Do not remove parameter. We may change available permissions based on
// parameter type!
return basePermissions;
}
@Override
// @PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#id, #className, 'ADMINISTRATION')")
public boolean addPermissions(long objectIdIdentity, String className, String uuid, boolean principal, Map<Integer, Boolean> permissions) {
AclSid sid = ensureSid(uuid, principal);
AclObjectIdentity oid = ensureObjectIdentity(className, objectIdIdentity);
addPermissions(sid, oid, permissions);
return true;
}
@Override
public synchronized void addCreatorPermissions(AclAwareModel target) {
if (target == null) {
LOG.warn("No target specified for ACL permissions, bailing out!");
return;
}
// assume that auth user has already AclSid implemented
AuthUserDetails authUser = SecurityContextUtil.getAuthUser();
if (authUser == null) {
LOG.warn("No user in security context, not doing ACL");
return;
}
String uuid = authUser.getUsername();
// it's ok if it is null
// it can be pre-authorized Admin
AclSid aclSid = ensureSid(uuid, true);
AclClass aclClass = ensureAclClass(target.getClass().getName());
// create object identity
AclObjectIdentity objectIdentity = new AclObjectIdentity();
objectIdentity.setObjectIdIdentity(target.getId());
objectIdentity.setAclClass(aclClass);
objectIdentity.setOwnerSid(aclSid);
objectIdentity.setParentObject(null);
objectIdentity.setEntriesInheriting(false);
// save object identity
aclObjectIdentityPersistence.save(objectIdentity);
Map<Integer,Boolean> permissionsMap=new HashMap<>();
for (Permission permission:basePermissions){
permissionsMap.put(permission.getMask(),true);
}
addPermissions(aclSid, objectIdentity, permissionsMap);
}
private AclClass ensureAclClass(String className) {
AclClass aclClass = aclClassPersistence.findByAclClass(className);
if (aclClass == null) {
LOG.warn("Missing AclClass...");
aclClass = new AclClass();
aclClass.setAclClass(className);
aclClassPersistence.save(aclClass);
}
return aclClass;
}
private AclSid ensureSid(String uuid, boolean principal) {
AclSid aclSid = aclSidPersistence.findBySidAndPrincipal(uuid, principal);
if (aclSid == null) {
// create Acl Sid
aclSid = new AclSid();
aclSid.setPrincipal(principal);
aclSid.setSid(uuid);
// save it into db
aclSidPersistence.save(aclSid);
LOG.warn("New SID " + aclSid);
}
return aclSid;
}
private void addPermissions(AclSid ownerSid, AclObjectIdentity objectIdentity, Map<Integer,Boolean>permissions) {
// create Acl Entry
for (Integer mask : permissions.keySet()) {
AclEntry aclEntry = new AclEntry();
aclEntry.setAclObjectIdentity(objectIdentity);
aclEntry.setAclSid(ownerSid);
aclEntry.setAceOrder(getAceOrder(objectIdentity.getId()));
aclEntry.setGranting(permissions.get(mask));
aclEntry.setAuditSuccess(true);
aclEntry.setAuditFailure(true);
// set full access for own organization
aclEntry.setMask(mask);
// save ACL
aclEntryPersistence.save(aclEntry);
}
}
@Override
@Transactional(readOnly = true)
public List<Long> listIdentitiesForSid(Class<? extends AclAwareModel> clazz, AuthUserDetails authUser, Permission permission) {
return aclEntryPersistence.findObjectIdentitiesBySidAndAclClassAndMask(authUser.getUsername(), clazz.getName(), permission.getMask());
}
/**
* Generates next ace_order value (to avoid DuplicateIndex exception :
* acl_object_identity + ace_order is unique index)
*
* @param aclObjectEntityId
* - id of acl_object_identity table
* @return - ace_order value
*/
private Long getAceOrder(long aclObjectEntityId) {
Long maxAceOrder = aclEntryPersistence.getMaxAceOrderForObjectEntity(aclObjectEntityId);
return maxAceOrder != null ? maxAceOrder + 1 : 1;
}
@Override
@Transactional(readOnly = true)
public AclObjectIdentity getObjectIdentity(long id) {
return aclObjectIdentityPersistence.findOne(id);
}
@Override
@Transactional(readOnly = true)
public AclObjectIdentity ensureObjectIdentity(String className, long objectIdIdentity) {
AclObjectIdentity aoi = aclObjectIdentityPersistence.findByObjectIdIdentityAndClassName(objectIdIdentity, className);
if (aoi == null) {
aoi = new AclObjectIdentity();
aoi.setObjectIdIdentity(objectIdIdentity);
aoi.setAclClass(ensureAclClass(className));
// System user UUID
String uuid = asAdminAspect.getSystemAdminAccount().getName();
AclSid ownerSid = ensureSid(uuid, true);
aoi.setOwnerSid(ownerSid);
aclObjectIdentityPersistence.save(aoi);
}
return aoi;
}
@Override
@Transactional(readOnly = true)
public AclObjectIdentity getObjectIdentity(String className, long id) {
return aclObjectIdentityPersistence.findByObjectIdIdentityAndClassName(id, className);
}
@Override
@Transactional(readOnly = true)
public AclObjectIdentity getObjectIdentity(AclAwareModel entity) {
return aclObjectIdentityPersistence.findByObjectIdIdentityAndClassName(entity.getId(), entity.getClass().getName());
}
@Override
@Transactional(readOnly = true)
public List<AclEntry> getAclEntries(AclObjectIdentity objectIdentity) {
return aclEntryPersistence.findByObjectIdentity(objectIdentity);
}
@Override
@Transactional(readOnly = true)
public List<AclEntry> getAclEntries(AclAwareModel entity) {
return aclEntryPersistence.findByObjectIdentity(getObjectIdentity(entity));
}
@Override
@Transactional(readOnly = true)
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#id, #className, 'ADMINISTRATION')")
public List<AclSid> getSids(long id, String className) {
return aclEntryPersistence.getSids(id, className);
}
@Override
@Transactional(readOnly = true)
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#entity, 'ADMINISTRATION')")
public List<AclSid> getSids(AclAwareModel entity) {
return aclEntryPersistence.getSids(entity.getId(), entity.getClass().getName());
}
@Override
@Transactional(readOnly = true)
public List<AclSid> getAllSids() {
return aclSidPersistence.findAll();
}
@Override
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#id, #className, 'ADMINISTRATION')")
public Map<String, Map<Integer, Boolean>> getPermissions(long id, String className) {
Map<String, Map<Integer, Boolean>> perm = new HashMap<>();
List<AclEntry> aclEntries = getAclEntries(getObjectIdentity(className, id));
for (AclEntry aclEntry : aclEntries) {
Map<Integer, Boolean> granted = perm.get(aclEntry.getAclSid().getSid());
if (granted == null) {
perm.put(aclEntry.getAclSid().getSid(), granted = new HashMap<>());
}
granted.put((int)aclEntry.getMask(), aclEntry.isGranting());
}
return perm;
}
@Override
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#entity, 'ADMINISTRATION')")
public Map<String, Map<Integer, Boolean>> getPermissions(AclAwareModel entity) {
return getPermissions(entity.getId(), entity.getClass().getName());
}
@Override
public void updatePermission(AclObjectIdentity entity, String sid, Map<Integer, Boolean> permissionMap) {
List<AclEntry> aclEntries = aclEntryPersistence.findBySidAndAclClass(sid, entity.getAclClass().getAclClass());
for (AclEntry aclEntry :aclEntries ) {
aclEntry.setGranting(permissionMap.get((int) aclEntry.getMask()));
}
aclEntryPersistence.save(aclEntries);
cacheManager.getCache("acl").removeAll();
}
// // private helpers
// private <T extends BusinessModel & AclAwareModel> void
// removeAssociations(T model) {
// String aclClassName = model.getClass().getName();
//
// AclObjectIdentity objectIdentity =
// aclObjectIdentityPersistence.findByObjectIdIdentityAndClassName(model.getId(),
// aclClassName);
//
// if (objectIdentity != null) {
// aclObjectIdentityPersistence.delete(objectIdentity);
// } else {
// LOG.warn("Could not find ACL object identity association for class {} and ID",
// aclClassName, model.getId());
// }
//
// }
private static final Logger LOG = LoggerFactory.getLogger(AclServiceImpl.class);
private static Permission[] basePermissions;
@Autowired
private UserService userService;
@Autowired
private AclClassPersistence aclClassPersistence;
@Autowired
private AclEntryPersistence aclEntryPersistence;
@Autowired
private AclObjectIdentityPersistence aclObjectIdentityPersistence;
@Autowired
private AclSidPersistence aclSidPersistence;
@Autowired
private AsAdminAspect asAdminAspect;
@Autowired
private CacheManager cacheManager;
static {
basePermissions = new Permission[] { BasePermission.CREATE, BasePermission.READ, BasePermission.WRITE, BasePermission.DELETE,
BasePermission.ADMINISTRATION };
}
@Override
@Transactional(readOnly = true)
public Permission[] getAvailablePermissions(String className) {
// Do not remove parameter. We may change available permissions based on
// parameter type!
return basePermissions;
}
@Override
// @PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#id, #className, 'ADMINISTRATION')")
public boolean addPermissions(long objectIdIdentity, String className, String uuid, boolean principal, Map<Integer, Boolean> permissions) {
AclSid sid = ensureSid(uuid, principal);
AclObjectIdentity oid = ensureObjectIdentity(className, objectIdIdentity);
addPermissions(sid, oid, permissions);
return true;
}
@Override
public synchronized void addCreatorPermissions(AclAwareModel target) {
if (target == null) {
LOG.warn("No target specified for ACL permissions, bailing out!");
return;
}
// assume that auth user has already AclSid implemented
AuthUserDetails authUser = SecurityContextUtil.getAuthUser();
if (authUser == null) {
LOG.warn("No user in security context, not doing ACL");
return;
}
String uuid = authUser.getUsername();
// it's ok if it is null
// it can be pre-authorized Admin
AclSid aclSid = ensureSid(uuid, true);
AclClass aclClass = ensureAclClass(target.getClass().getName());
// create object identity
AclObjectIdentity objectIdentity = new AclObjectIdentity();
objectIdentity.setObjectIdIdentity(target.getId());
objectIdentity.setAclClass(aclClass);
objectIdentity.setOwnerSid(aclSid);
objectIdentity.setParentObject(null);
objectIdentity.setEntriesInheriting(false);
// save object identity
aclObjectIdentityPersistence.save(objectIdentity);
Map<Integer, Boolean> permissionsMap = new HashMap<>();
for (Permission permission : basePermissions) {
permissionsMap.put(permission.getMask(), true);
}
addPermissions(aclSid, objectIdentity, permissionsMap);
}
private AclClass ensureAclClass(String className) {
AclClass aclClass = aclClassPersistence.findByAclClass(className);
if (aclClass == null) {
LOG.warn("Missing AclClass...");
aclClass = new AclClass();
aclClass.setAclClass(className);
aclClassPersistence.save(aclClass);
}
return aclClass;
}
private AclSid ensureSid(String uuid, boolean principal) {
AclSid aclSid = aclSidPersistence.findBySidAndPrincipal(uuid, principal);
if (aclSid == null) {
// create Acl Sid
aclSid = new AclSid();
aclSid.setPrincipal(principal);
aclSid.setSid(uuid);
// save it into db
aclSidPersistence.save(aclSid);
LOG.warn("New SID " + aclSid);
}
return aclSid;
}
private void addPermissions(AclSid ownerSid, AclObjectIdentity objectIdentity, Map<Integer, Boolean> permissions) {
// create Acl Entry
for (Integer mask : permissions.keySet()) {
AclEntry aclEntry = new AclEntry();
aclEntry.setAclObjectIdentity(objectIdentity);
aclEntry.setAclSid(ownerSid);
aclEntry.setAceOrder(getAceOrder(objectIdentity.getId()));
aclEntry.setGranting(permissions.get(mask));
aclEntry.setAuditSuccess(true);
aclEntry.setAuditFailure(true);
// set full access for own organization
aclEntry.setMask(mask);
// save ACL
aclEntryPersistence.save(aclEntry);
}
}
@Override
@Transactional(readOnly = true)
public List<Long> listIdentitiesForSid(Class<? extends AclAwareModel> clazz, AuthUserDetails authUser, Permission permission) {
return aclEntryPersistence.findObjectIdentitiesBySidAndAclClassAndMask(authUser.getUsername(), clazz.getName(), permission.getMask());
}
/**
* Generates next ace_order value (to avoid DuplicateIndex exception :
* acl_object_identity + ace_order is unique index)
*
* @param aclObjectEntityId
* - id of acl_object_identity table
* @return - ace_order value
*/
private Long getAceOrder(long aclObjectEntityId) {
Long maxAceOrder = aclEntryPersistence.getMaxAceOrderForObjectEntity(aclObjectEntityId);
return maxAceOrder != null ? maxAceOrder + 1 : 1;
}
@Override
@Transactional(readOnly = true)
public AclObjectIdentity getObjectIdentity(long id) {
return aclObjectIdentityPersistence.findOne(id);
}
@Override
@Transactional(readOnly = true)
public AclObjectIdentity ensureObjectIdentity(String className, long objectIdIdentity) {
AclObjectIdentity aoi = aclObjectIdentityPersistence.findByObjectIdIdentityAndClassName(objectIdIdentity, className);
if (aoi == null) {
aoi = new AclObjectIdentity();
aoi.setObjectIdIdentity(objectIdIdentity);
aoi.setAclClass(ensureAclClass(className));
// System user UUID
String uuid = asAdminAspect.getSystemAdminAccount().getName();
AclSid ownerSid = ensureSid(uuid, true);
aoi.setOwnerSid(ownerSid);
aclObjectIdentityPersistence.save(aoi);
}
return aoi;
}
@Override
@Transactional(readOnly = true)
public AclObjectIdentity getObjectIdentity(String className, long id) {
return aclObjectIdentityPersistence.findByObjectIdIdentityAndClassName(id, className);
}
@Override
@Transactional(readOnly = true)
public AclObjectIdentity getObjectIdentity(AclAwareModel entity) {
return aclObjectIdentityPersistence.findByObjectIdIdentityAndClassName(entity.getId(), entity.getClass().getName());
}
@Override
@Transactional(readOnly = true)
public List<AclEntry> getAclEntries(AclObjectIdentity objectIdentity) {
return aclEntryPersistence.findByObjectIdentity(objectIdentity);
}
@Override
@Transactional(readOnly = true)
public List<AclEntry> getAclEntries(AclAwareModel entity) {
return aclEntryPersistence.findByObjectIdentity(getObjectIdentity(entity));
}
@Override
@Transactional(readOnly = true)
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#id, #className, 'ADMINISTRATION')")
public List<AclSid> getSids(long id, String className) {
return aclEntryPersistence.getSids(id, className);
}
@Override
@Transactional(readOnly = true)
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#entity, 'ADMINISTRATION')")
public List<AclSid> getSids(AclAwareModel entity) {
return aclEntryPersistence.getSids(entity.getId(), entity.getClass().getName());
}
@Override
@Transactional(readOnly = true)
public List<AclSid> getAllSids() {
return aclSidPersistence.findAll();
}
@Override
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#id, #className, 'ADMINISTRATION')")
public Map<String, Map<Integer, Boolean>> getPermissions(long id, String className) {
Map<String, Map<Integer, Boolean>> perm = new HashMap<>();
List<AclEntry> aclEntries = getAclEntries(getObjectIdentity(className, id));
for (AclEntry aclEntry : aclEntries) {
Map<Integer, Boolean> granted = perm.get(aclEntry.getAclSid().getSid());
if (granted == null) {
perm.put(aclEntry.getAclSid().getSid(), granted = new HashMap<>());
}
granted.put((int) aclEntry.getMask(), aclEntry.isGranting());
}
return perm;
}
@Override
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#entity, 'ADMINISTRATION')")
public Map<String, Map<Integer, Boolean>> getPermissions(AclAwareModel entity) {
return getPermissions(entity.getId(), entity.getClass().getName());
}
@Override
public void updatePermission(AclObjectIdentity entity, String sid, Map<Integer, Boolean> permissionMap) {
List<AclEntry> aclEntries = aclEntryPersistence.findBySidAndAclClass(sid, entity.getAclClass().getAclClass());
for (AclEntry aclEntry : aclEntries) {
aclEntry.setGranting(permissionMap.get((int) aclEntry.getMask()));
}
aclEntryPersistence.save(aclEntries);
cacheManager.getCache("acl").removeAll();
}
}
......@@ -77,7 +77,8 @@ public class UserServiceImpl implements UserService {
}
@Override
@PreAuthorize("hasRole('ADMINISTRATOR')")
// FIXME Re-enable this
//@PreAuthorize("hasRole('ADMINISTRATOR')")
public Page<User> listUsers(Pageable pageable) {
return userPersistence.findAll(pageable);
}
......