Commit bd784bcf authored by Matija Obreza's avatar Matija Obreza

Merge branch 'acl-json-and-permission-checks' into 'master'

CustomAclService allowed for multiple entries per SID for object identity

See merge request genesys-pgr/application-blocks!29
parents dc4ba486 1b0006b2
......@@ -33,7 +33,8 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
* (through {@link AclObjectIdentity}).
*/
@Entity
@Table(name = "acl_entry", uniqueConstraints = @UniqueConstraint(columnNames = { "acl_object_identity", "ace_order" }))
@Table(name = "acl_entry", uniqueConstraints = { @UniqueConstraint(columnNames = { "acl_object_identity", "ace_order" }),
@UniqueConstraint(columnNames = { "acl_object_identity", "sid", "mask" }) })
public class AclEntry extends BasicModel {
/** The Constant serialVersionUID. */
......
......@@ -19,6 +19,8 @@ import static org.springframework.security.acls.domain.BasePermission.*;
import org.springframework.security.acls.domain.BasePermission;
import com.fasterxml.jackson.annotation.JsonIgnore;
/**
* A simple POJO for object permissions.
*/
......@@ -39,6 +41,9 @@ public class Permissions {
/** Allowed to admin/manage */
public boolean manage;
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
......@@ -73,6 +78,11 @@ public class Permissions {
}
}
/**
* Grant all.
*
* @return the permissions
*/
public Permissions grantAll() {
this.create = true;
this.read = true;
......@@ -82,6 +92,11 @@ public class Permissions {
return this;
}
/**
* Grant none.
*
* @return the permissions
*/
public Permissions grantNone() {
this.create = false;
this.read = false;
......@@ -90,4 +105,14 @@ public class Permissions {
this.manage = false;
return this;
}
/**
* Checks if is one granting.
*
* @return true, if is one granting
*/
@JsonIgnore
public boolean isOneGranting() {
return create || read || write || delete || manage;
}
}
......@@ -16,7 +16,6 @@
package org.genesys.blocks.security.service;
import java.util.List;
import java.util.Map;
import org.genesys.blocks.security.model.AclAwareModel;
import org.genesys.blocks.security.model.AclEntry;
......@@ -150,7 +149,7 @@ public interface CustomAclService {
* @return
*/
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(entity, 'ADMINISTRATION')")
List<AclEntry> updatePermissions(AclAwareModel entity, AclSid sid, final Permissions permissions);
AclObjectIdentity setPermissions(AclAwareModel entity, AclSid sid, final Permissions permissions);
/**
* Update permissions.
......@@ -161,7 +160,7 @@ public interface CustomAclService {
* @return
*/
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#objectIdentity.objectIdIdentity, #objectIdentity.aclClass.aclClass, 'ADMINISTRATION')")
List<AclEntry> updatePermissions(AclObjectIdentity objectIdentity, AclSid sid, final Permissions permissions);
AclObjectIdentity setPermissions(AclObjectIdentity objectIdentity, AclSid sid, final Permissions permissions);
/**
* Gets the acl entries.
......@@ -191,29 +190,6 @@ public interface CustomAclService {
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#entity, 'read')")
List<AclSid> getSids(AclAwareModel entity);
/**
* Adds the permissions.
*
* @param id the object id identity
* @param className the class name
* @param sid TODO
* @param permissions the permissions
* @return list of new ACL entries
*/
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#objectIdentity.objectIdIdentity, #objectIdentity.aclClass.aclClass, 'ADMINISTRATION')")
List<AclEntry> addPermissions(AclObjectIdentity objectIdentity, AclSid sid, final Permissions permissions);
/**
* Adds the permissions.
*
* @param entity the entity
* @param sid the sid
* @param permissions the permissions
* @return list of new ACL entries
*/
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#entity, 'ADMINISTRATION')")
List<AclEntry> addPermissions(AclAwareModel entity, AclSid sid, final Permissions permissions);
/**
* Ensure object identity.
*
......
......@@ -43,8 +43,6 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.google.common.collect.Lists;
/**
* The Class CustomAclServiceImpl.
*/
......@@ -89,6 +87,7 @@ public class CustomAclServiceImpl implements CustomAclService {
}
@Override
@Transactional(propagation = Propagation.REQUIRED)
public AclSid getAuthoritySid(String authority) {
return ensureSidForAuthority(authority);
}
......@@ -171,9 +170,17 @@ public class CustomAclServiceImpl implements CustomAclService {
* @param permissions the permissions
* @return the list
*/
@Override
@Transactional
public List<AclEntry> addPermissions(final AclObjectIdentity objectIdentity, final AclSid sid, final Permissions permissions) {
private AclObjectIdentity addPermissions(final AclObjectIdentity objectIdentity, final AclSid sid, final Permissions permissions) {
if (objectIdentity == null) {
throw new NullPointerException("AclObjectIdentity must be provided, was null.");
}
if (sid == null) {
throw new NullPointerException("AclSid must be provided, was null.");
}
if (permissions == null) {
throw new NullPointerException("Permissions must be provided, was null.");
}
try {
List<AclEntry> aclEntries = new ArrayList<>();
long nextAceOrder = getAceOrder(objectIdentity.getId());
......@@ -192,7 +199,8 @@ public class CustomAclServiceImpl implements CustomAclService {
aclEntries.add(aclEntry);
}
// save ACL
return aclEntryPersistence.save(aclEntries);
aclEntryPersistence.save(aclEntries);
return getObjectIdentity(objectIdentity.getId());
} finally {
clearAclCache();
}
......@@ -318,30 +326,64 @@ public class CustomAclServiceImpl implements CustomAclService {
return getPermissions(entity.getId(), entity.getClass().getName());
}
@Transactional(propagation = Propagation.REQUIRED)
@Override
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#entity, 'ADMINISTRATION')")
public List<AclEntry> updatePermissions(final AclAwareModel entity, final AclSid sid, final Permissions permissions) {
public AclObjectIdentity setPermissions(final AclAwareModel entity, final AclSid sid, final Permissions permissions) {
if (entity == null) {
throw new NullPointerException("AclAwareModel must be provided, was null.");
}
if (sid == null) {
throw new NullPointerException("AclSid must be provided, was null.");
}
if (permissions == null) {
throw new NullPointerException("Permissions must be provided, was null.");
}
final AclObjectIdentity objectIdentity = getObjectIdentity(entity);
return updatePermissions(objectIdentity, sid, permissions);
return setPermissions(objectIdentity, sid, permissions);
}
@Transactional(propagation = Propagation.REQUIRED)
@Override
@PreAuthorize("hasRole('ADMINISTRATOR') or hasPermission(#objectIdentity.objectIdIdentity, #objectIdentity.aclClass.aclClass, 'ADMINISTRATION')")
public List<AclEntry> updatePermissions(AclObjectIdentity objectIdentity, AclSid sid, final Permissions permissions) {
public AclObjectIdentity setPermissions(AclObjectIdentity objectIdentity, AclSid sid, final Permissions permissions) {
if (objectIdentity == null) {
throw new NullPointerException("AclObjectIdentity must be provided, was null.");
}
if (sid == null) {
throw new NullPointerException("AclSid must be provided, was null.");
}
if (permissions == null) {
throw new NullPointerException("Permissions must be provided, was null.");
}
try {
boolean oneGranting = false;
final List<AclEntry> aclEntries = aclEntryPersistence.findBySidAndObjectIdentity(sid, objectIdentity);
for (final AclEntry aclEntry : aclEntries) {
aclEntry.setGranting(permissions.isGranting(aclEntry.getMask()));
oneGranting |= aclEntry.isGranting();
}
if (oneGranting) {
LOG.info("Saving " + aclEntries);
return aclEntryPersistence.save(aclEntries);
if (permissions.isOneGranting()) {
// need to update or add permissions
final List<AclEntry> aclEntries = aclEntryPersistence.findBySidAndObjectIdentity(sid, objectIdentity);
if (aclEntries.isEmpty()) {
// add
return addPermissions(objectIdentity, sid, permissions);
} else {
// updarte
for (final AclEntry aclEntry : aclEntries) {
aclEntry.setGranting(permissions.isGranting(aclEntry.getMask()));
}
LOG.info("Saving " + aclEntries);
aclEntryPersistence.save(aclEntries);
return getObjectIdentity(objectIdentity.getId());
}
} else {
LOG.info("Deleting " + aclEntries);
aclEntryPersistence.delete(aclEntries);
return Lists.newArrayList();
// delete existing
final List<AclEntry> aclEntries = aclEntryPersistence.findBySidAndObjectIdentity(sid, objectIdentity);
if (!aclEntries.isEmpty()) {
LOG.info("Deleting " + aclEntries);
aclEntryPersistence.delete(aclEntries);
}
return getObjectIdentity(objectIdentity.getId());
}
} finally {
clearAclCache();
......@@ -394,11 +436,6 @@ public class CustomAclServiceImpl implements CustomAclService {
return aclEntryPersistence.getSids(getObjectIdentity(entity));
}
@Override
public List<AclEntry> addPermissions(AclAwareModel entity, AclSid sid, final Permissions permissions) {
return addPermissions(getObjectIdentity(entity), sid, permissions);
}
/**
* Ensure ACL SID entry for the specified authority name (role)
*/
......@@ -416,7 +453,8 @@ public class CustomAclServiceImpl implements CustomAclService {
return roleSid;
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.genesys.blocks.security.service.CustomAclService#listAuthoritySids()
*/
@Override
......@@ -432,7 +470,7 @@ public class CustomAclServiceImpl implements CustomAclService {
* java.lang.String, long)
*/
@Override
@Transactional
@Transactional(propagation = Propagation.REQUIRED)
public AclObjectIdentity ensureObjectIdentity(final long objectIdIdentity, final String className) {
AclObjectIdentity aoi = aclObjectIdentityPersistence.findByObjectIdAndClassname(objectIdIdentity, className);
if (aoi == null) {
......
......@@ -19,6 +19,8 @@ import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
import java.util.List;
......@@ -28,8 +30,10 @@ import org.genesys.blocks.security.UserException;
import org.genesys.blocks.security.model.AclEntity;
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.model.BasicUser.AccountType;
import org.genesys.blocks.security.model.TestUser;
import org.genesys.blocks.security.model.UserRole;
import org.genesys.blocks.security.serialization.Permissions;
import org.genesys.blocks.security.service.CustomAclService;
import org.genesys.blocks.security.service.PasswordPolicy.PasswordPolicyException;
......@@ -63,6 +67,20 @@ public class PermissionsTest extends ServiceTest {
SecurityContextHolder.getContext().setAuthentication(null);
}
@Test
public void testAuthoritySid() {
AclSid roleSid = aclService.getAuthoritySid(UserRole.EXTRAROLE.name());
assertThat(roleSid, not(nullValue()));
assertThat(roleSid.getId(), not(nullValue()));
roleSid = aclService.getAuthoritySid(UserRole.EXTRAROLE.name());
assertThat(roleSid, not(nullValue()));
assertThat(roleSid.getId(), not(nullValue()));
roleSid = aclService.getSid(roleSid.getId());
assertThat(roleSid, not(nullValue()));
}
@Test
public void testSave1() {
assertThat(aclEntryPersistence.count(), equalTo(0l));
......@@ -134,7 +152,7 @@ public class PermissionsTest extends ServiceTest {
Permissions permissions = new Permissions();
// one granted permission
permissions.create = true;
aclService.addPermissions(acl1, user2, permissions);
aclService.setPermissions(acl1, user2, permissions);
assertThat("ACL entries should be doubled!", aclService.getAclEntries(acl1), hasSize(entryCount * 2));
// Test listObjectIdentityIdsForSid
......
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