/**
*
*/
package net.conselldemallorca.helium.core.helperv26;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import net.conselldemallorca.helium.core.util.GlobalProperties;
import net.conselldemallorca.helium.v3.core.api.dto.PermisDto;
import net.conselldemallorca.helium.v3.core.api.dto.PrincipalTipusEnumDto;
import org.springframework.security.acls.domain.BasePermission;
import org.springframework.security.acls.domain.GrantedAuthoritySid;
import org.springframework.security.acls.domain.ObjectIdentityImpl;
import org.springframework.security.acls.domain.PrincipalSid;
import org.springframework.security.acls.jdbc.LookupStrategy;
import org.springframework.security.acls.model.AccessControlEntry;
import org.springframework.security.acls.model.Acl;
import org.springframework.security.acls.model.MutableAcl;
import org.springframework.security.acls.model.MutableAclService;
import org.springframework.security.acls.model.NotFoundException;
import org.springframework.security.acls.model.ObjectIdentity;
import org.springframework.security.acls.model.Permission;
import org.springframework.security.acls.model.Sid;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
/**
* Helper per a la gestiĆ³ de permisos dins les ACLs.
*
* @author Limit Tecnologies <limit@limit.es>
*/
@Component
public class PermisosHelper {
@Resource
private LookupStrategy lookupStrategy;
@Resource
private MutableAclService aclService;
public List<AccessControlEntry> findAclsByOid(
ObjectIdentity oid) {
try {
return getAclSids(
Class.forName(oid.getType()),
(Long)oid.getIdentifier());
} catch (ClassNotFoundException e) {
return null;
}
}
public void assignarPermisUsuari(
String userName,
Class<?> objectClass,
Long objectIdentifier,
Permission permission) {
assignarPermisos(
new PrincipalSid(userName),
objectClass,
objectIdentifier,
new Permission[] {permission});
}
public void assignarPermisRol(
String roleName,
Class<?> objectClass,
Long objectIdentifier,
Permission permission) {
assignarPermisos(
new GrantedAuthoritySid(getMapeigRol(roleName)),
objectClass,
objectIdentifier,
new Permission[] {permission});
}
public void revocarPermisUsuari(
String userName,
Class<?> objectClass,
Long objectIdentifier,
Permission permission) {
revocarPermisos(
new PrincipalSid(userName),
objectClass,
objectIdentifier,
new Permission[] {permission});
}
public void revocarPermisRol(
String roleName,
Class<?> objectClass,
Long objectIdentifier,
Permission permission) {
revocarPermisos(
new GrantedAuthoritySid(getMapeigRol(roleName)),
objectClass,
objectIdentifier,
new Permission[] {permission});
}
public void mourePermisUsuari(
String sourceUserName,
String targetUserName,
Class<?> objectClass,
Long objectIdentifier,
Permission permission) {
assignarPermisos(
new PrincipalSid(targetUserName),
objectClass,
objectIdentifier,
new Permission[] {permission});
revocarPermisos(
new PrincipalSid(sourceUserName),
objectClass,
objectIdentifier,
new Permission[] {permission});
}
public void mourePermisRol(
String sourceRoleName,
String targetRoleName,
Class<?> objectClass,
Long objectIdentifier,
Permission permission) {
assignarPermisos(
new GrantedAuthoritySid(getMapeigRol(targetRoleName)),
objectClass,
objectIdentifier,
new Permission[] {permission});
revocarPermisos(
new GrantedAuthoritySid(getMapeigRol(sourceRoleName)),
objectClass,
objectIdentifier,
new Permission[] {permission});
}
public List<AccessControlEntry> getAclSids(
Class<?> objectClass,
Long objectIdentifier) {
try {
ObjectIdentity oid = new ObjectIdentityImpl(objectClass, objectIdentifier);
MutableAcl acl = (MutableAcl)aclService.readAclById(oid);
return acl.getEntries();
} catch (NotFoundException nfex) {
return null;
}
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public boolean filterGrantedAny(
Collection<?> objects,
ObjectIdentifierExtractor objectIdentifierExtractor,
Class<?> clazz,
Permission[] permissions) {
Iterator<?> it = objects.iterator();
while (it.hasNext()) {
Long objectIdentifier = objectIdentifierExtractor.getObjectIdentifier(
it.next());
if (!isGrantedAny(
objectIdentifier,
clazz,
permissions))
it.remove();
}
return !objects.isEmpty();
}
public boolean isGrantedAny(
Long objectIdentifier,
Class<?> clazz,
Permission[] permissions) {
boolean[] granted = verificarPermisos(
objectIdentifier,
clazz,
permissions);
for (int i = 0; i < granted.length; i++) {
if (granted[i])
return true;
}
return false;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public void filterGrantedAll(
Collection<?> objects,
ObjectIdentifierExtractor objectIdentifierExtractor,
Class<?> clazz,
Permission[] permissions,
Authentication auth) {
Iterator<?> it = objects.iterator();
while (it.hasNext()) {
Long objectIdentifier = objectIdentifierExtractor.getObjectIdentifier(
it.next());
if (!isGrantedAll(
objectIdentifier,
clazz,
permissions,
auth))
it.remove();
}
}
public boolean isGrantedAll(
Long objectIdentifier,
Class<?> clazz,
Permission[] permissions,
Authentication auth) {
boolean[] granted = verificarPermisos(
objectIdentifier,
clazz,
permissions);
boolean result = true;
for (int i = 0; i < granted.length; i++) {
if (!granted[i]) {
result = false;
break;
}
}
return result;
}
public boolean isGrantedAny(
Long objectIdentifier,
Class<?> clazz,
Permission[] permissions,
Authentication auth) {
boolean[] granted = verificarPermisos(
objectIdentifier,
clazz,
permissions);
for (int i = 0; i < granted.length; i++) {
if (granted[i])
return true;
}
return false;
}
public List<PermisDto> findPermisos(
Long objectIdentifier,
Class<?> objectClass) {
Acl acl = null;
try {
ObjectIdentity oid = new ObjectIdentityImpl(objectClass, objectIdentifier);
acl = aclService.readAclById(oid);
} catch (NotFoundException nfex) {
return new ArrayList<PermisDto>();
}
return findPermisosPerAcl(acl);
}
public Map<Long, List<PermisDto>> findPermisos(
List<Long> objectIdentifiers,
Class<?> objectClass) {
try {
Map<Long, List<PermisDto>> resposta = new HashMap<Long, List<PermisDto>>();
List<ObjectIdentity> oids = new ArrayList<ObjectIdentity>();
for (Long objectIdentifier: objectIdentifiers) {
ObjectIdentity oid = new ObjectIdentityImpl(
objectClass,
objectIdentifier);
oids.add(oid);
}
if (!oids.isEmpty()) {
Map<ObjectIdentity, Acl> acls = lookupStrategy.readAclsById(oids, null);
for (ObjectIdentity oid: acls.keySet()) {
resposta.put(
(Long)oid.getIdentifier(),
findPermisosPerAcl(acls.get(oid)));
}
}
return resposta;
} catch (NotFoundException nfex) {
return new HashMap<Long, List<PermisDto>>();
}
}
private void assignarPermisos(
Sid sid,
Class<?> objectClass,
Serializable objectIdentifier,
Permission[] permissions) {
ObjectIdentity oid = new ObjectIdentityImpl(objectClass, objectIdentifier);
MutableAcl acl = null;
try {
acl = (MutableAcl)aclService.readAclById(oid);
} catch (NotFoundException nfex) {
nfex.printStackTrace();
acl = aclService.createAcl(oid);
}
for (Permission permission: permissions) {
boolean insertar;
try {
List<Permission> permisos = new ArrayList<Permission>();
List<Sid> sids = new ArrayList<Sid>();
permisos.add(permission);
sids.add(sid);
insertar = !acl.isGranted(
permisos,
sids,
true);
} catch (Exception ignored) {
insertar = true;
}
if (insertar)
acl.insertAce(
acl.getEntries().size(),
permission,
sid,
true);
}
aclService.updateAcl(acl);
}
private void revocarPermisos(
Sid sid,
Class<?> objectClass,
Serializable objectIdentifier,
Permission[] permissions) throws NotFoundException {
ObjectIdentity oid = new ObjectIdentityImpl(objectClass, objectIdentifier);
try {
MutableAcl acl = (MutableAcl)aclService.readAclById(oid);
List<Integer> indexosPerEsborrar = new ArrayList<Integer>();
int aceIndex = 0;
for (AccessControlEntry ace: acl.getEntries()) {
if (ace.getSid().equals(sid)) {
for (Permission p: permissions) {
if (p.equals(ace.getPermission()))
indexosPerEsborrar.add(aceIndex);
}
}
aceIndex++;
}
for (Integer index: indexosPerEsborrar)
acl.deleteAce(index);
aclService.updateAcl(acl);
} catch (NotFoundException nfex) {
// Si no troba l'ACL no fa res
}
}
private boolean[] verificarPermisos(
Long objectIdentifier,
Class<?> clazz,
Permission[] permissions) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
List<Sid> sids = new ArrayList<Sid>();
sids.add(new PrincipalSid(auth.getName()));
if (auth.getAuthorities() != null) {
for (GrantedAuthority ga: auth.getAuthorities())
sids.add(new GrantedAuthoritySid(ga.getAuthority()));
}
boolean[] granted = new boolean[permissions.length];
for (int i = 0; i < permissions.length; i++)
granted[i] = false;
try {
ObjectIdentity oid = new ObjectIdentityImpl(
clazz,
objectIdentifier);
Acl acl = aclService.readAclById(oid);
List<Permission> ps = new ArrayList<Permission>();
for (int i = 0; i < permissions.length; i++) {
try {
ps.add(permissions[i]);
granted[i] = acl.isGranted(
ps,
sids,
true);
ps.clear();
} catch (NotFoundException ex) {}
}
} catch (NotFoundException ex) {}
return granted;
}
private String getMapeigRol(String rol) {
String propertyMapeig =
(String)GlobalProperties.getInstance().get(
"es.caib.helium.mapeig.rol." + rol);
if (propertyMapeig != null)
return propertyMapeig;
else
return rol;
}
private List<PermisDto> findPermisosPerAcl(Acl acl) {
List<PermisDto> resposta = new ArrayList<PermisDto>();
if (acl != null) {
Map<String, PermisDto> permisosUsuari = new HashMap<String, PermisDto>();
Map<String, PermisDto> permisosRol = new HashMap<String, PermisDto>();
for (AccessControlEntry ace: acl.getEntries()) {
PermisDto permis = null;
if (ace.getSid() instanceof PrincipalSid) {
String principal = ((PrincipalSid)ace.getSid()).getPrincipal();
permis = permisosUsuari.get(principal);
if (permis == null) {
permis = new PermisDto();
permis.setId((Long)ace.getId());
permis.setPrincipalNom(principal);
permis.setPrincipalTipus(PrincipalTipusEnumDto.USUARI);
permisosUsuari.put(principal, permis);
}
} else if (ace.getSid() instanceof GrantedAuthoritySid) {
String grantedAuthority = ((GrantedAuthoritySid)ace.getSid()).getGrantedAuthority();
permis = permisosUsuari.get(grantedAuthority);
if (permis == null) {
permis = new PermisDto();
permis.setId((Long)ace.getId());
permis.setPrincipalNom(grantedAuthority);
permis.setPrincipalTipus(PrincipalTipusEnumDto.ROL);
permisosRol.put(grantedAuthority, permis);
}
}
if (permis != null) {
if (BasePermission.READ.equals(ace.getPermission()))
permis.setRead(true);
if (BasePermission.WRITE.equals(ace.getPermission()))
permis.setWrite(true);
if (BasePermission.CREATE.equals(ace.getPermission()))
permis.setCreate(true);
if (BasePermission.DELETE.equals(ace.getPermission()))
permis.setDelete(true);
if (BasePermission.ADMINISTRATION.equals(ace.getPermission()))
permis.setAdministration(true);
}
}
resposta.addAll(permisosUsuari.values());
resposta.addAll(permisosRol.values());
}
return resposta;
}
public interface ObjectIdentifierExtractor<T> {
public Long getObjectIdentifier(T object);
}
}