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 {
private static final Logger LOG = LoggerFactory.getLogger(AclAssignerAspect.class);
@Autowired
private AclService aclAssignerService;
private AclService aclService;
@Around("execution(* org.genesys2.server.persistence.domain.*.save(..))")
public Object aroundSaveAclObject(ProceedingJoinPoint pjp) throws Throwable {
......@@ -50,7 +50,7 @@ public class AclAssignerAspect {
if (needsAcl) {
AclAwareModel aclModel = (AclAwareModel) retval;
LOG.warn("Inserting ACL entries for owner: " + aclModel.getId());
aclAssignerService.addCreatorPermissions(aclModel);
aclService.addCreatorPermissions(aclModel);
}
return retval;
......
......@@ -48,7 +48,7 @@ public class AsAdminAspect {
@Around("org.genesys2.server.aspect.SystemArchitecture.allServices()" + " && @annotation(org.genesys2.server.aspect.AsAdmin)")
public Object authenticateAsAdmin(ProceedingJoinPoint pjp) throws Throwable {
loadSystemAdminAccount("SYSTEM");
getSystemAdminAccount();
// store previous version of auth (if any exists)
Authentication prevAuth = SecurityContextHolder.getContext().getAuthentication();
......@@ -75,7 +75,7 @@ public class AsAdminAspect {
}
}
private synchronized void loadSystemAdminAccount(String string) {
public synchronized Authentication getSystemAdminAccount() {
if (SYS_ADMIN == null) {
LOG.warn("SYS_ADMIN not loaded. Loading now.");
User sysUser = userService.getSystemUser("SYSTEM");
......@@ -94,6 +94,8 @@ public class AsAdminAspect {
SYS_ADMIN = new PreAuthenticatedAuthenticationToken(userDetails, null, userDetails.getAuthorities());
}
}
return SYS_ADMIN;
}
}
......@@ -25,6 +25,7 @@ import org.genesys2.server.model.UserRole;
import org.genesys2.server.model.impl.User;
import org.genesys2.server.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
@Service("createAdminListener")
......@@ -37,7 +38,7 @@ public class CreateAdminListener extends RunAsAdminListener {
public void init() throws Exception {
_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();
}
......
......@@ -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")
Long getMaxAceOrderForObjectEntity(long aclObjectEntityId);
@Query("select distinct ae.aclSid from AclEntry ae where ae.aclObjectIdentity = :aclObjectIdentity")
List<AclSid> getSids(@Param("aclObjectIdentity") AclObjectIdentity objectIdentity);
@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("objectIdIdentity") long objectIdIdentity, @Param("aclClass") String aclClass);
}
......@@ -23,8 +23,6 @@ import org.springframework.data.repository.query.Param;
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")
AclObjectIdentity findByObjectIdIdentityAndClassName(@Param("objectIdIdentity") long objectIdentityId, @Param("aclClass") String aclClass);
}
......@@ -21,6 +21,6 @@ import org.springframework.data.jpa.repository.JpaRepository;
public interface AclSidPersistence extends JpaRepository<AclSid, Long> {
AclSid findBySid(String sid);
AclSid findBySidAndPrincipal(String sid, boolean principal);
}
......@@ -39,14 +39,22 @@ public interface AclService {
*/
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);
List<AclEntry> getAclEntries(AclObjectIdentity objectIdentity);
List<AclEntry> getAclEntries(AclAwareModel entity);
List<Permission> getAvailablePermissions(AclAwareModel entity);
Permission[] getAvailablePermissions(String className);
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(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;
import org.genesys2.server.model.impl.User;
import org.genesys2.server.model.wrapper.UserWrapper;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.access.prepost.PreAuthorize;
public interface UserService {
Page<User> getCurrentPage(int page, int pageSize) throws UserException;
@PreAuthorize("hasRole('ADMINISTRATOR')")
void addUser(User user) throws UserException;
......@@ -63,6 +62,6 @@ public interface UserService {
User getSystemUser(String string);
Page<User> listUsers(Pageable pageable);
}
......@@ -16,11 +16,11 @@
package org.genesys2.server.service.impl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.genesys2.server.aspect.AsAdminAspect;
import org.genesys2.server.model.AclAwareModel;
import org.genesys2.server.model.acl.AclClass;
import org.genesys2.server.model.acl.AclEntry;
......@@ -37,6 +37,7 @@ import org.genesys2.spring.SecurityContextUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.model.Permission;
import org.springframework.stereotype.Service;
......@@ -51,7 +52,7 @@ public class AclServiceImpl implements AclService {
private static final Logger LOG = LoggerFactory.getLogger(AclServiceImpl.class);
private static ArrayList<Permission> basePermissions;
private static Permission[] basePermissions;
@Autowired
private UserService userService;
......@@ -68,24 +69,34 @@ public class AclServiceImpl implements AclService {
@Autowired
private AclSidPersistence aclSidPersistence;
@Autowired
private AsAdminAspect asAdminAspect;
static {
basePermissions = new ArrayList<Permission>();
basePermissions.add(BasePermission.CREATE);
basePermissions.add(BasePermission.READ);
basePermissions.add(BasePermission.WRITE);
basePermissions.add(BasePermission.DELETE);
basePermissions = new Permission[] { BasePermission.CREATE, BasePermission.READ, BasePermission.WRITE, BasePermission.DELETE,
BasePermission.ADMINISTRATION };
}
@Override
@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
// parameter type!
return basePermissions;
}
@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) {
LOG.warn("No target specified for ACL permissions, bailing out!");
return;
......@@ -101,45 +112,57 @@ public class AclServiceImpl implements AclService {
// it's ok if it is null
// it can be pre-authorized Admin
AclSid aclSid = aclSidPersistence.findBySid(uuid);
AclSid aclSid = ensureSid(uuid, true);
if (aclSid == null) {
// create Acl Sid
AclSid pwnerSid = new AclSid();
pwnerSid.setPrincipal(true);
pwnerSid.setSid(uuid);
AclClass aclClass = ensureAclClass(target.getClass().getName());
// save it into db
aclSidPersistence.save(pwnerSid);
LOG.warn("New SID " + pwnerSid);
aclSid = pwnerSid;
// 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);
addPermissions(aclSid, objectIdentity, basePermissions);
}
AclClass aclClass = aclClassPersistence.findByAclClass(target.getClass().getName());
private AclClass ensureAclClass(String className) {
AclClass aclClass = aclClassPersistence.findByAclClass(className);
if (aclClass == null) {
LOG.warn("Missing AclClass...");
aclClass = new AclClass();
aclClass.setAclClass(target.getClass().getName());
aclClass.setAclClass(className);
aclClassPersistence.save(aclClass);
}
// create object identity
AclObjectIdentity objectIdentity = new AclObjectIdentity();
objectIdentity.setObjectIdIdentity(target.getId());
objectIdentity.setAclClass(aclClass);
objectIdentity.setOwnerSid(aclSid);
objectIdentity.setEntriesInheriting(false);
return aclClass;
}
// save object identity
aclObjectIdentityPersistence.save(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);
}
fullPermissionsSet(aclSid, objectIdentity);
return aclSid;
}
private void fullPermissionsSet(AclSid ownerSid, AclObjectIdentity objectIdentity) {
private void addPermissions(AclSid ownerSid, AclObjectIdentity objectIdentity, Permission... permissions) {
// create Acl Entry
for (Permission permission : basePermissions) {
for (Permission permission : permissions) {
AclEntry aclEntry = new AclEntry();
aclEntry.setAclObjectIdentity(objectIdentity);
aclEntry.setAclSid(ownerSid);
......@@ -174,12 +197,47 @@ public class AclServiceImpl implements AclService {
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) {
......@@ -188,19 +246,28 @@ public class AclServiceImpl implements AclService {
@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(getObjectIdentity(entity));
return aclEntryPersistence.getSids(entity.getId(), entity.getClass().getName());
}
@Override
public Map<AclSid, Map<Long, Boolean>> getPermissions(AclAwareModel entity) {
Map<AclSid, Map<Long, Boolean>> perm=new HashMap<AclSid, Map<Long, Boolean>>();
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#id, #className, 'ADMINISTRATION')")
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) {
Map<Long, Boolean> granted = perm.get(aclEntry.getAclSid());
if (granted==null) {
perm.put(aclEntry.getAclSid(), granted=new HashMap<Long, Boolean>());
if (granted == null) {
perm.put(aclEntry.getAclSid(), granted = new HashMap<Long, Boolean>());
}
granted.put(aclEntry.getMask(), Boolean.TRUE);
}
......@@ -208,6 +275,12 @@ public class AclServiceImpl implements AclService {
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 <T extends BusinessModel & AclAwareModel> void
// removeAssociations(T model) {
......
......@@ -53,20 +53,9 @@ public class UserServiceImpl implements UserService {
private PasswordEncoder passwordEncoder;
@Override
public Page<User> getCurrentPage(int startRow, int pageSize) throws UserException {
Pageable pageable = null;
if (startRow >= 0 && pageSize > 0) {
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);
}
@PreAuthorize("hasRole('ADMINISTRATOR')")
public Page<User> listUsers(Pageable pageable) {
return userPersistence.findAll(pageable);
}
@Override
......
......@@ -25,6 +25,8 @@ import org.genesys2.server.service.UserService;
import org.genesys2.spring.ResourceNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
......@@ -63,6 +65,13 @@ public class UserProfileController extends BaseController {
return "redirect:/profile/" + user.getUuid();
}
@RequestMapping("/list")
@PreAuthorize("hasRole('ADMINISTRATOR')")
public String list(ModelMap model, @RequestParam(value = "page", defaultValue = "1") int page) {
model.addAttribute("pagedData", userService.listUsers(new PageRequest(page - 1, 50, new Sort("name"))));
return "/user/index";
}
@RequestMapping("/{uuid:.+}")
public String someProfile(ModelMap model, @PathVariable("uuid") String uuid) {
User user = userService.getUserByUuid(uuid);
......
......@@ -86,6 +86,7 @@ menu.privacy=Privacy policy
page.home.title=Genesys Sandbox
user.pulldown.administration=Administration
user.pulldown.users=User list
user.pulldown.logout=Logout
user.pulldown.profile=View profile
user.pulldown.heading=You are {0}
......@@ -95,6 +96,7 @@ user.email=E-mail Address
userprofile.page.title=User profile
userprofile.update.title=Update your profile
user.page.list.title=Registered user accounts
crop.croplist=Crop list
crop.page.profile.title={0} profile
......@@ -329,5 +331,5 @@ acl.owner=Object Owner
acl.permission.1=Read
acl.permission.2=Write
acl.permission.4=Create
acl.permission.16=Delete
acl.permission.8=Manage
acl.permission.8=Delete
acl.permission.16=Manage
......@@ -58,6 +58,7 @@
<ul class="dropdown-menu">
<security:authorize access="hasRole('ADMINISTRATOR')">
<li><a href="<c:url value="/admin/" />"><spring:message code="user.pulldown.administration" /></a></li>
<li><a href="<c:url value="/profile/list" />"><spring:message code="user.pulldown.users" /></a></li>
</security:authorize>
<li><a href="<c:url value="/profile/${user.username}" />"><spring:message code="user.pulldown.profile" /></a></li>
<li><a href="<c:url value="/logout" />"><spring:message code="user.pulldown.logout" /></a></li>
......
<!DOCTYPE html>
<%@include file="/WEB-INF/jsp/init.jsp"%>
<html>
<head>
<title><spring:message code="user.page.list.title" /></title>
</head>
<body>
<h1>
<spring:message code="user.page.list.title" />
</h1>
<div class="nav-header">
<spring:message code="paged.totalElements" arguments="${pagedData.totalElements}" />
<br />
<spring:message code="paged.pageOfPages" arguments="${pagedData.number+1},${pagedData.totalPages}" />
<a class="${pagedData.number eq 0 ? 'disabled' :''}" href="?page=${pagedData.number eq 0 ? 1 : pagedData.number}"><spring:message code="pagination.previous-page" /></a> <a href="?page=${pagedData.number + 2}"><spring:message code="pagination.next-page" /></a>
</div>
<table class="funny-list">
<c:forEach items="${pagedData.content}" var="user" varStatus="status">
<tr class="clearfix ${status.count % 2 == 0 ? 'even' : 'odd'}">
<td><c:if test="${not user.systemAccount}"><a href="<c:url value="/profile/${user.uuid}" />"><c:out value="${user.name}" /></a></c:if></td>
<td>${user.uuid}</td>
<td>${user.email}</td>
<td>${user.systemAccount ? 'SYSTEM' : ''}</td>
</tr>
</c:forEach>
</table>
</body>
</html>
\ No newline at end of file
......@@ -12,7 +12,7 @@
</h1>
<security:authorize access="hasRole('ADMINISTRATOR') || (isAuthenticated() && principal.user.id == #user.id)">
<a href="<c:url value="/profile/${user.email}/edit" />" class="close"> <spring:message code="edit" /></a>
<a href="<c:url value="/profile/${user.uuid}/edit" />" class="close"> <spring:message code="edit" /></a>
</security:authorize>
<div class="form-horizontal">
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment