Commit 736264c1 authored by Matija Obreza's avatar Matija Obreza
Browse files

Refactored ACL services, UserService#listUsers for ADMINISTRATOR role

parent af5add88
...@@ -33,7 +33,7 @@ public class AclAssignerAspect { ...@@ -33,7 +33,7 @@ public class AclAssignerAspect {
private static final Logger LOG = LoggerFactory.getLogger(AclAssignerAspect.class); private static final Logger LOG = LoggerFactory.getLogger(AclAssignerAspect.class);
@Autowired @Autowired
private AclService aclAssignerService; private AclService aclService;
@Around("execution(* org.genesys2.server.persistence.domain.*.save(..))") @Around("execution(* org.genesys2.server.persistence.domain.*.save(..))")
public Object aroundSaveAclObject(ProceedingJoinPoint pjp) throws Throwable { public Object aroundSaveAclObject(ProceedingJoinPoint pjp) throws Throwable {
...@@ -50,7 +50,7 @@ public class AclAssignerAspect { ...@@ -50,7 +50,7 @@ public class AclAssignerAspect {
if (needsAcl) { if (needsAcl) {
AclAwareModel aclModel = (AclAwareModel) retval; AclAwareModel aclModel = (AclAwareModel) retval;
LOG.warn("Inserting ACL entries for owner: " + aclModel.getId()); LOG.warn("Inserting ACL entries for owner: " + aclModel.getId());
aclAssignerService.addCreatorPermissions(aclModel); aclService.addCreatorPermissions(aclModel);
} }
return retval; return retval;
......
...@@ -48,7 +48,7 @@ public class AsAdminAspect { ...@@ -48,7 +48,7 @@ public class AsAdminAspect {
@Around("org.genesys2.server.aspect.SystemArchitecture.allServices()" + " && @annotation(org.genesys2.server.aspect.AsAdmin)") @Around("org.genesys2.server.aspect.SystemArchitecture.allServices()" + " && @annotation(org.genesys2.server.aspect.AsAdmin)")
public Object authenticateAsAdmin(ProceedingJoinPoint pjp) throws Throwable { public Object authenticateAsAdmin(ProceedingJoinPoint pjp) throws Throwable {
loadSystemAdminAccount("SYSTEM"); getSystemAdminAccount();
// store previous version of auth (if any exists) // store previous version of auth (if any exists)
Authentication prevAuth = SecurityContextHolder.getContext().getAuthentication(); Authentication prevAuth = SecurityContextHolder.getContext().getAuthentication();
...@@ -75,7 +75,7 @@ public class AsAdminAspect { ...@@ -75,7 +75,7 @@ public class AsAdminAspect {
} }
} }
private synchronized void loadSystemAdminAccount(String string) { public synchronized Authentication getSystemAdminAccount() {
if (SYS_ADMIN == null) { if (SYS_ADMIN == null) {
LOG.warn("SYS_ADMIN not loaded. Loading now."); LOG.warn("SYS_ADMIN not loaded. Loading now.");
User sysUser = userService.getSystemUser("SYSTEM"); User sysUser = userService.getSystemUser("SYSTEM");
...@@ -94,6 +94,8 @@ public class AsAdminAspect { ...@@ -94,6 +94,8 @@ public class AsAdminAspect {
SYS_ADMIN = new PreAuthenticatedAuthenticationToken(userDetails, null, userDetails.getAuthorities()); SYS_ADMIN = new PreAuthenticatedAuthenticationToken(userDetails, null, userDetails.getAuthorities());
} }
} }
return SYS_ADMIN;
} }
} }
...@@ -25,6 +25,7 @@ import org.genesys2.server.model.UserRole; ...@@ -25,6 +25,7 @@ import org.genesys2.server.model.UserRole;
import org.genesys2.server.model.impl.User; import org.genesys2.server.model.impl.User;
import org.genesys2.server.service.UserService; import org.genesys2.server.service.UserService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@Service("createAdminListener") @Service("createAdminListener")
...@@ -37,7 +38,7 @@ public class CreateAdminListener extends RunAsAdminListener { ...@@ -37,7 +38,7 @@ public class CreateAdminListener extends RunAsAdminListener {
public void init() throws Exception { public void init() throws Exception {
_logger.info("Checking for at least one account"); _logger.info("Checking for at least one account");
if (userService.getCurrentPage(0, 1).getTotalElements() == 0) { if (userService.listUsers(new PageRequest(0, 1)).getTotalElements() == 0) {
createDefaultAccounts(); createDefaultAccounts();
} }
......
...@@ -91,7 +91,7 @@ public interface AclEntryPersistence extends JpaRepository<AclEntry, Long> { ...@@ -91,7 +91,7 @@ public interface AclEntryPersistence extends JpaRepository<AclEntry, Long> {
@Query("select max(ae.aceOrder) from AclEntry ae join ae.aclObjectIdentity aoi where aoi.id = ?1") @Query("select max(ae.aceOrder) from AclEntry ae join ae.aclObjectIdentity aoi where aoi.id = ?1")
Long getMaxAceOrderForObjectEntity(long aclObjectEntityId); Long getMaxAceOrderForObjectEntity(long aclObjectEntityId);
@Query("select distinct ae.aclSid from AclEntry ae where ae.aclObjectIdentity = :aclObjectIdentity") @Query("select distinct ae.aclSid from AclEntry ae join ae.aclObjectIdentity aoi join aoi.aclClass ac where aoi.objectIdIdentity = :objectIdIdentity and ac.aclClass = :aclClass")
List<AclSid> getSids(@Param("aclObjectIdentity") AclObjectIdentity objectIdentity); List<AclSid> getSids(@Param("objectIdIdentity") long objectIdIdentity, @Param("aclClass") String aclClass);
} }
...@@ -23,8 +23,6 @@ import org.springframework.data.repository.query.Param; ...@@ -23,8 +23,6 @@ import org.springframework.data.repository.query.Param;
public interface AclObjectIdentityPersistence extends JpaRepository<AclObjectIdentity, Long> { public interface AclObjectIdentityPersistence extends JpaRepository<AclObjectIdentity, Long> {
AclObjectIdentity findByObjectIdIdentity(Long objectIdIdentity);
@Query("select aoi from AclObjectIdentity aoi where aoi.objectIdIdentity = :objectIdIdentity and aoi.aclClass.aclClass = :aclClass") @Query("select aoi from AclObjectIdentity aoi where aoi.objectIdIdentity = :objectIdIdentity and aoi.aclClass.aclClass = :aclClass")
AclObjectIdentity findByObjectIdIdentityAndClassName(@Param("objectIdIdentity") long objectIdentityId, @Param("aclClass") String aclClass); AclObjectIdentity findByObjectIdIdentityAndClassName(@Param("objectIdIdentity") long objectIdentityId, @Param("aclClass") String aclClass);
} }
...@@ -21,6 +21,6 @@ import org.springframework.data.jpa.repository.JpaRepository; ...@@ -21,6 +21,6 @@ import org.springframework.data.jpa.repository.JpaRepository;
public interface AclSidPersistence extends JpaRepository<AclSid, Long> { public interface AclSidPersistence extends JpaRepository<AclSid, Long> {
AclSid findBySid(String sid); AclSid findBySidAndPrincipal(String sid, boolean principal);
} }
...@@ -39,14 +39,22 @@ public interface AclService { ...@@ -39,14 +39,22 @@ public interface AclService {
*/ */
List<Long> listIdentitiesForSid(Class<? extends AclAwareModel> clazz, AuthUserDetails authUser, Permission permission); List<Long> listIdentitiesForSid(Class<? extends AclAwareModel> clazz, AuthUserDetails authUser, Permission permission);
AclObjectIdentity getObjectIdentity(long id);
AclObjectIdentity getObjectIdentity(String clazz, long id);
AclObjectIdentity ensureObjectIdentity(String clazz, long id);
AclObjectIdentity getObjectIdentity(AclAwareModel entity); AclObjectIdentity getObjectIdentity(AclAwareModel entity);
List<AclEntry> getAclEntries(AclObjectIdentity objectIdentity);
List<AclEntry> getAclEntries(AclAwareModel entity); List<AclEntry> getAclEntries(AclAwareModel entity);
List<Permission> getAvailablePermissions(AclAwareModel entity); Permission[] getAvailablePermissions(String className);
List<AclSid> getSids(AclAwareModel entity); List<AclSid> getSids(AclAwareModel entity);
List<AclSid> getSids(long id, String className);
Map<AclSid, Map<Long, Boolean>> getPermissions(AclAwareModel entity); Map<AclSid, Map<Long, Boolean>> getPermissions(AclAwareModel entity);
Map<AclSid, Map<Long, Boolean>> getPermissions(long id, String className);
boolean addPermissions(long objectIdIdentity, String className, String uuid, boolean principal, Permission ... permissions);
} }
...@@ -20,12 +20,11 @@ import org.genesys2.server.exception.UserException; ...@@ -20,12 +20,11 @@ import org.genesys2.server.exception.UserException;
import org.genesys2.server.model.impl.User; import org.genesys2.server.model.impl.User;
import org.genesys2.server.model.wrapper.UserWrapper; import org.genesys2.server.model.wrapper.UserWrapper;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
public interface UserService { public interface UserService {
Page<User> getCurrentPage(int page, int pageSize) throws UserException;
@PreAuthorize("hasRole('ADMINISTRATOR')") @PreAuthorize("hasRole('ADMINISTRATOR')")
void addUser(User user) throws UserException; void addUser(User user) throws UserException;
...@@ -63,6 +62,6 @@ public interface UserService { ...@@ -63,6 +62,6 @@ public interface UserService {
User getSystemUser(String string); User getSystemUser(String string);
Page<User> listUsers(Pageable pageable);
} }
...@@ -16,11 +16,11 @@ ...@@ -16,11 +16,11 @@
package org.genesys2.server.service.impl; package org.genesys2.server.service.impl;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.genesys2.server.aspect.AsAdminAspect;
import org.genesys2.server.model.AclAwareModel; import org.genesys2.server.model.AclAwareModel;
import org.genesys2.server.model.acl.AclClass; import org.genesys2.server.model.acl.AclClass;
import org.genesys2.server.model.acl.AclEntry; import org.genesys2.server.model.acl.AclEntry;
...@@ -37,6 +37,7 @@ import org.genesys2.spring.SecurityContextUtil; ...@@ -37,6 +37,7 @@ import org.genesys2.spring.SecurityContextUtil;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.acls.domain.BasePermission; import org.springframework.security.acls.domain.BasePermission;
import org.springframework.security.acls.model.Permission; import org.springframework.security.acls.model.Permission;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
...@@ -51,7 +52,7 @@ public class AclServiceImpl implements AclService { ...@@ -51,7 +52,7 @@ public class AclServiceImpl implements AclService {
private static final Logger LOG = LoggerFactory.getLogger(AclServiceImpl.class); private static final Logger LOG = LoggerFactory.getLogger(AclServiceImpl.class);
private static ArrayList<Permission> basePermissions; private static Permission[] basePermissions;
@Autowired @Autowired
private UserService userService; private UserService userService;
...@@ -68,24 +69,34 @@ public class AclServiceImpl implements AclService { ...@@ -68,24 +69,34 @@ public class AclServiceImpl implements AclService {
@Autowired @Autowired
private AclSidPersistence aclSidPersistence; private AclSidPersistence aclSidPersistence;
@Autowired
private AsAdminAspect asAdminAspect;
static { static {
basePermissions = new ArrayList<Permission>(); basePermissions = new Permission[] { BasePermission.CREATE, BasePermission.READ, BasePermission.WRITE, BasePermission.DELETE,
basePermissions.add(BasePermission.CREATE); BasePermission.ADMINISTRATION };
basePermissions.add(BasePermission.READ);
basePermissions.add(BasePermission.WRITE);
basePermissions.add(BasePermission.DELETE);
} }
@Override @Override
@Transactional(readOnly = true) @Transactional(readOnly = true)
public List<Permission> getAvailablePermissions(AclAwareModel entity) { public Permission[] getAvailablePermissions(String className) {
// Do not remove parameter. We may change available permissions based on // Do not remove parameter. We may change available permissions based on
// parameter type! // parameter type!
return basePermissions; return basePermissions;
} }
@Override @Override
public void addCreatorPermissions(AclAwareModel target) { @PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#id, #className, 'ADMINISTRATION')")
public boolean addPermissions(long objectIdIdentity, String className, String uuid, boolean principal, Permission... 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) { if (target == null) {
LOG.warn("No target specified for ACL permissions, bailing out!"); LOG.warn("No target specified for ACL permissions, bailing out!");
return; return;
...@@ -101,45 +112,57 @@ public class AclServiceImpl implements AclService { ...@@ -101,45 +112,57 @@ public class AclServiceImpl implements AclService {
// it's ok if it is null // it's ok if it is null
// it can be pre-authorized Admin // it can be pre-authorized Admin
AclSid aclSid = aclSidPersistence.findBySid(uuid); AclSid aclSid = ensureSid(uuid, true);
if (aclSid == null) { AclClass aclClass = ensureAclClass(target.getClass().getName());
// create Acl Sid
AclSid pwnerSid = new AclSid();
pwnerSid.setPrincipal(true);
pwnerSid.setSid(uuid);
// save it into db
aclSidPersistence.save(pwnerSid);
LOG.warn("New SID " + pwnerSid);
aclSid = pwnerSid;
}
AclClass aclClass = aclClassPersistence.findByAclClass(target.getClass().getName());
if (aclClass == null) {
LOG.warn("Missing AclClass...");
aclClass = new AclClass();
aclClass.setAclClass(target.getClass().getName());
aclClassPersistence.save(aclClass);
}
// create object identity // create object identity
AclObjectIdentity objectIdentity = new AclObjectIdentity(); AclObjectIdentity objectIdentity = new AclObjectIdentity();
objectIdentity.setObjectIdIdentity(target.getId()); objectIdentity.setObjectIdIdentity(target.getId());
objectIdentity.setAclClass(aclClass); objectIdentity.setAclClass(aclClass);
objectIdentity.setOwnerSid(aclSid); objectIdentity.setOwnerSid(aclSid);
objectIdentity.setParentObject(null);
objectIdentity.setEntriesInheriting(false); objectIdentity.setEntriesInheriting(false);
// save object identity // save object identity
aclObjectIdentityPersistence.save(objectIdentity); aclObjectIdentityPersistence.save(objectIdentity);
fullPermissionsSet(aclSid, objectIdentity); addPermissions(aclSid, objectIdentity, basePermissions);
}
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 void fullPermissionsSet(AclSid ownerSid, AclObjectIdentity objectIdentity) { 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, Permission... permissions) {
// create Acl Entry // create Acl Entry
for (Permission permission : basePermissions) { for (Permission permission : permissions) {
AclEntry aclEntry = new AclEntry(); AclEntry aclEntry = new AclEntry();
aclEntry.setAclObjectIdentity(objectIdentity); aclEntry.setAclObjectIdentity(objectIdentity);
aclEntry.setAclSid(ownerSid); aclEntry.setAclSid(ownerSid);
...@@ -174,12 +197,47 @@ public class AclServiceImpl implements AclService { ...@@ -174,12 +197,47 @@ public class AclServiceImpl implements AclService {
return maxAceOrder != null ? maxAceOrder + 1 : 1; 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 @Override
@Transactional(readOnly = true) @Transactional(readOnly = true)
public AclObjectIdentity getObjectIdentity(AclAwareModel entity) { public AclObjectIdentity getObjectIdentity(AclAwareModel entity) {
return aclObjectIdentityPersistence.findByObjectIdIdentityAndClassName(entity.getId(), entity.getClass().getName()); return aclObjectIdentityPersistence.findByObjectIdIdentityAndClassName(entity.getId(), entity.getClass().getName());
} }
@Override
@Transactional(readOnly = true)
public List<AclEntry> getAclEntries(AclObjectIdentity objectIdentity) {
return aclEntryPersistence.findByObjectIdentity(objectIdentity);
}
@Override @Override
@Transactional(readOnly = true) @Transactional(readOnly = true)
public List<AclEntry> getAclEntries(AclAwareModel entity) { public List<AclEntry> getAclEntries(AclAwareModel entity) {
...@@ -188,26 +246,41 @@ public class AclServiceImpl implements AclService { ...@@ -188,26 +246,41 @@ public class AclServiceImpl implements AclService {
@Override @Override
@Transactional(readOnly = true) @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) { public List<AclSid> getSids(AclAwareModel entity) {
return aclEntryPersistence.getSids(getObjectIdentity(entity)); return aclEntryPersistence.getSids(entity.getId(), entity.getClass().getName());
} }
@Override @Override
public Map<AclSid, Map<Long, Boolean>> getPermissions(AclAwareModel entity) { @PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#id, #className, 'ADMINISTRATION')")
Map<AclSid, Map<Long, Boolean>> perm=new HashMap<AclSid, Map<Long, Boolean>>(); public Map<AclSid, Map<Long, Boolean>> getPermissions(long id, String className) {
Map<AclSid, Map<Long, Boolean>> perm = new HashMap<AclSid, Map<Long, Boolean>>();
List<AclEntry> aclEntries = getAclEntries(entity);
List<AclEntry> aclEntries = getAclEntries(getObjectIdentity(className, id));
for (AclEntry aclEntry : aclEntries) { for (AclEntry aclEntry : aclEntries) {
Map<Long, Boolean> granted = perm.get(aclEntry.getAclSid()); Map<Long, Boolean> granted = perm.get(aclEntry.getAclSid());
if (granted==null) { if (granted == null) {
perm.put(aclEntry.getAclSid(), granted=new HashMap<Long, Boolean>()); perm.put(aclEntry.getAclSid(), granted = new HashMap<Long, Boolean>());
} }
granted.put(aclEntry.getMask(), Boolean.TRUE); granted.put(aclEntry.getMask(), Boolean.TRUE);
} }
return perm; return perm;
} }
@Override
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#entity, 'ADMINISTRATION')")
public Map<AclSid, Map<Long, Boolean>> getPermissions(AclAwareModel entity) {
return getPermissions(entity.getId(), entity.getClass().getName());
}
// // private helpers // // private helpers
// private <T extends BusinessModel & AclAwareModel> void // private <T extends BusinessModel & AclAwareModel> void
// removeAssociations(T model) { // removeAssociations(T model) {
......
...@@ -53,20 +53,9 @@ public class UserServiceImpl implements UserService { ...@@ -53,20 +53,9 @@ public class UserServiceImpl implements UserService {
private PasswordEncoder passwordEncoder; private PasswordEncoder passwordEncoder;
@Override @Override
public Page<User> getCurrentPage(int startRow, int pageSize) throws UserException { @PreAuthorize("hasRole('ADMINISTRATOR')")
Pageable pageable = null; public Page<User> listUsers(Pageable pageable) {
if (startRow >= 0 && pageSize > 0) { return userPersistence.findAll(pageable);
pageable = new PageRequest(startRow / pageSize, pageSize);
}
try {
Page<User> users = userPersistence.findAll(pageable);
for (User user : users) {
user.getRoles().size();
}
return users;
} catch (RuntimeException e) {
throw new UserException(e);
}
} }
@Override @Override
...@@ -225,7 +214,7 @@ public class UserServiceImpl implements UserService { ...@@ -225,7 +214,7 @@ public class UserServiceImpl implements UserService {
if (user != null) { if (user != null) {
user.getRoles().size(); user.getRoles().size();
} }
return user; return user;
} }
......
...@@ -25,6 +25,8 @@ import org.genesys2.server.service.UserService; ...@@ -25,6 +25,8 @@ import org.genesys2.server.service.UserService;
import org.genesys2.spring.ResourceNotFoundException; import org.genesys2.spring.ResourceNotFoundException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;