/**
*
* geo-platform
* Rich webgis framework
* http://geo-platform.org
* ====================================================================
*
* Copyright (C) 2008-2017 geoSDI Group (CNR IMAA - Potenza - ITALY).
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. This program is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License
* for more details. You should have received a copy of the GNU General
* Public License along with this program. If not, see http://www.gnu.org/licenses/
*
* ====================================================================
*
* Linking this library statically or dynamically with other modules is
* making a combined work based on this library. Thus, the terms and
* conditions of the GNU General Public License cover the whole combination.
*
* As a special exception, the copyright holders of this library give you permission
* to link this library with independent modules to produce an executable, regardless
* of the license terms of these independent modules, and to copy and distribute
* the resulting executable under terms of your choice, provided that you also meet,
* for each linked independent module, the terms and conditions of the license of
* that module. An independent module is a module which is not derived from or
* based on this library. If you modify this library, you may extend this exception
* to your version of the library, but you are not obligated to do so. If you do not
* wish to do so, delete this exception statement from your version.
*/
package org.geosdi.geoplatform.core.delegate.impl.acl;
import java.util.List;
import java.util.Map;
import org.geosdi.geoplatform.core.acl.AclClass;
import org.geosdi.geoplatform.core.acl.AclEntry;
import org.geosdi.geoplatform.core.acl.AclObjectIdentity;
import org.geosdi.geoplatform.core.acl.AclSid;
import org.geosdi.geoplatform.core.acl.GeoPlatformPermission;
import org.geosdi.geoplatform.core.acl.GuiComponent;
import org.geosdi.geoplatform.core.acl.dao.AclClassDAO;
import org.geosdi.geoplatform.core.acl.dao.AclEntryDAO;
import org.geosdi.geoplatform.core.acl.dao.AclObjectIdentityDAO;
import org.geosdi.geoplatform.core.acl.dao.AclSidDAO;
import org.geosdi.geoplatform.core.acl.dao.GuiComponentDAO;
import org.geosdi.geoplatform.core.dao.GPAccountDAO;
import org.geosdi.geoplatform.core.dao.GPAuthorityDAO;
import org.geosdi.geoplatform.core.dao.GPOrganizationDAO;
import org.geosdi.geoplatform.core.delegate.api.acl.AclDelegate;
import org.geosdi.geoplatform.core.model.GPAccount;
import org.geosdi.geoplatform.core.model.GPApplication;
import org.geosdi.geoplatform.core.model.GPAuthority;
import org.geosdi.geoplatform.core.model.GPOrganization;
import org.geosdi.geoplatform.exception.IllegalParameterFault;
import org.geosdi.geoplatform.exception.ResourceNotFoundFault;
import org.geosdi.geoplatform.request.organization.WSPutRolePermissionRequest;
import org.geosdi.geoplatform.request.organization.WSSaveRoleRequest;
import org.geosdi.geoplatform.response.collection.GuiComponentsPermissionMapData;
import org.geosdi.geoplatform.response.role.WSGetRoleResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.acls.model.Permission;
import org.springframework.stereotype.Component;
/**
* ACL service delegate.
*
* @author Vincenzo Monteverde <vincenzo.monteverde@geosdi.org>
*/
@Component(value = "gpAclDelegate")
public class GPAclDelegate implements AclDelegate {
private static final Logger logger = LoggerFactory.getLogger(
GPAclDelegate.class);
//
@Autowired
private GPAccountDAO accountDao;
@Autowired
private GPAuthorityDAO authorityDao;
@Autowired
private GPOrganizationDAO organizationDao;
@Autowired
private AclClassDAO classDao;
@Autowired
private AclSidDAO sidDao;
@Autowired
private AclObjectIdentityDAO objectIdentityDao;
@Autowired
private AclEntryDAO entryDao;
@Autowired
private GuiComponentDAO guiComponentDao;
@Override
public WSGetRoleResponse getAllRoles(String organization) throws
ResourceNotFoundFault {
List<AclSid> sids = sidDao.findByPrincipal(false, organization);
WSGetRoleResponse getRoles = new WSGetRoleResponse();
for (AclSid sid : sids) {
getRoles.addRole(sid.getSid());
}
return getRoles;
}
@Override
public List<String> getAllGuiComponentIDs() {
return guiComponentDao.findAllGuiComponentIDs();
}
@Override
public GuiComponentsPermissionMapData getApplicationPermission(String appID)
throws ResourceNotFoundFault {
// Retrieve the account
GPApplication application = accountDao.findByAppID(appID);
if (application == null) {
throw new ResourceNotFoundFault(
"Application not found with appID \"" + appID + "\"");
}
GuiComponentsPermissionMapData mapComponentPermission = new GuiComponentsPermissionMapData();
Map<String, Boolean> permissionMap = mapComponentPermission.getPermissionMap();
// Retrieve the Sid corresponding to the Application ID
AclSid sid = this.findSid(appID, true, null);
// Retrieve the ACEs of the Sid
List<AclEntry> entries = entryDao.findBySid(sid.getId());
logger.trace("\n*** #Entries: {} ***", entries.size());
// For each ACEs
// (ACL has a single ACE for Role+GuiComponent,
// because there is a singe Permission)
for (AclEntry entry : entries) {
logger.trace("\n*** AclEntry:\n{}\n***", entry);
if (entry.getMask().equals(GeoPlatformPermission.ENABLE.getMask())) {
AclObjectIdentity objectIdentity = entry.getAclObject();
logger.trace("\n*** AclObjectIdentity:\n{}\n***", objectIdentity);
GuiComponent gc = guiComponentDao.find(
objectIdentity.getObjectId());
logger.trace("\n*** GuiComponent:\n{}\n***", gc);
logger.debug("\n*** ComponentId: {} ***\n*** Granting: {} ***",
gc.getComponentId(), entry.isGranting());
permissionMap.put(gc.getComponentId(), entry.isGranting());
}
}
return mapComponentPermission;
}
@Override
public GuiComponentsPermissionMapData getAccountPermission(Long accountID)
throws ResourceNotFoundFault {
// Retrieve the account
GPAccount account = accountDao.find(accountID);
if (account == null) {
throw new ResourceNotFoundFault("Account not found", accountID);
}
GuiComponentsPermissionMapData mapComponentPermission = new GuiComponentsPermissionMapData();
// Retrieve the Authorities of the Account
List<GPAuthority> authorities = authorityDao.findByAccountNaturalID(
account.getNaturalID());
logger.trace("\n*** #Authorities: {} ***", authorities.size());
// For each Autorities (disjoined)
for (GPAuthority authority : authorities) {
String nameAuthority = authority.getAuthority();
logger.trace("\n*** nameAuthority: {} ***", nameAuthority);
this.elaborateGuiComponentACEs(nameAuthority,
account.getOrganization().getName(),
mapComponentPermission.getPermissionMap());
}
return mapComponentPermission;
}
@Override
public GuiComponentsPermissionMapData getRolePermission(String role,
String organization)
throws ResourceNotFoundFault {
GuiComponentsPermissionMapData mapComponentPermission = new GuiComponentsPermissionMapData();
this.elaborateGuiComponentACEs(role, organization,
mapComponentPermission.getPermissionMap());
return mapComponentPermission;
}
@Override
public Boolean updateRolePermission(
WSPutRolePermissionRequest putRolePermissionReq)
throws ResourceNotFoundFault {
if (putRolePermissionReq == null) {
throw new IllegalArgumentException("The WSPutRolePermissionRequest "
+ "must not be null.");
}
String role = putRolePermissionReq.getRole();
String organization = putRolePermissionReq.getOrganization();
GuiComponentsPermissionMapData mapComponentPermission = putRolePermissionReq.getMapComponentPermission();
logger.debug("\n*** Role: {} ***", role);
// Retrieve the Sid corresponding to the Role (Authority) name
AclSid sid = this.findSid(role, false, organization);
AclClass clazz = classDao.findByClass(GuiComponent.class.getName());
Permission permission = GeoPlatformPermission.ENABLE;
Map<String, Boolean> permissionMap = mapComponentPermission.getPermissionMap();
for (Map.Entry<String, Boolean> entry : permissionMap.entrySet()) {
String componentId = entry.getKey();
Boolean granting = entry.getValue();
logger.debug("\n*** Entry to manage: {} - {} ***", componentId,
granting);
GuiComponent gc = guiComponentDao.findByComponentId(componentId);
if (gc == null) {
throw new ResourceNotFoundFault(
"GuiComponent \"" + componentId + "\" not found");
}
logger.trace("\n*** GuiComponent:\n{}\n***", gc);
AclObjectIdentity obj = objectIdentityDao.findByObjectId(
clazz.getId(), gc.getId());
List<AclEntry> aces = entryDao.findByObjectIdentity(obj.getId());
boolean managed = this.manageExistingEntry(aces, sid, permission,
granting); // UPDATE or DELETE the entry
if (!managed) { // ADD new entry
Integer aceOrder = ((aces != null) && (aces.size() > 0))
? (aces.get(aces.size() - 1).getAceOrder() + 1) : 0;
AclEntry e = new AclEntry(obj, aceOrder, sid,
permission.getMask(), granting);
entryDao.persist(e);
logger.debug("\n*** ACE added ***");
}
}
return true;
}
@Override
public Boolean saveRole(WSSaveRoleRequest saveRoleReq) throws
IllegalParameterFault {
if (saveRoleReq == null) {
throw new IllegalParameterFault("The WSSaveRoleRequest must not "
+ "be null.");
}
String organization = saveRoleReq.getOrganization();
String role = saveRoleReq.getRole();
AclSid sid = sidDao.findBySid(role, false, organization);
if (sid != null) {
throw new IllegalParameterFault(
"Authority (Role) \"" + role + "\" already exist");
}
GPOrganization org = organizationDao.findByName(organization);
if (org == null) {
throw new IllegalParameterFault(
"Organization \"" + organization + "\" not found");
}
sid = new AclSid(false, role, org);
sidDao.persist(sid);
return true;
}
private void elaborateGuiComponentACEs(String sidName, String organization,
Map<String, Boolean> permissionMap)
throws ResourceNotFoundFault {
// Retrieve the Sid corresponding to the Role (Authority) name and the relative organization
AclSid sid = this.findSid(sidName, false, organization);
// Retrieve the ACEs of the Sid
List<AclEntry> entries = entryDao.findBySid(sid.getId());
logger.trace("\n*** #Entries: {} ***", entries.size());
// For each ACEs
// (ACL has a single ACE for Role+GuiComponent,
// because there is a singe Permission)
for (AclEntry entry : entries) {
logger.trace("\n*** AclEntry:\n{}\n***", entry);
if (entry.getMask().equals(GeoPlatformPermission.ENABLE.getMask())) {
AclObjectIdentity objectIdentity = entry.getAclObject();
logger.trace("\n*** AclObjectIdentity:\n{}\n***", objectIdentity);
GuiComponent gc = guiComponentDao.find(
objectIdentity.getObjectId());
logger.trace("\n*** GuiComponent:\n{}\n***", gc);
logger.debug("\n*** ComponentId: {} ***\n*** Granting: {} ***",
gc.getComponentId(), entry.isGranting());
permissionMap.put(gc.getComponentId(), entry.isGranting());
}
}
// for (String componentID : GuiComponentIDs.LIST_ALL) {
// if (!permissionMap.containsKey(componentID)) {
// logger.debug("\n*** NONE added: {} ***", componentID);
// permissionMap.put(componentID, null);
// }
// }
}
private boolean manageExistingEntry(List<AclEntry> aces, AclSid sid,
Permission permission, Boolean granting) {
for (AclEntry ace : aces) {
if (ace.getAclSid().equals(sid)
&& ace.getMask().equals(permission.getMask())) {
if (granting == null) {
entryDao.remove(ace);
logger.debug("\n*** ACE deleted ***");
return true;
} else {
ace.setGranting(granting);
entryDao.merge(ace);
logger.debug("\n*** ACE updated ***");
return true;
}
}
}
return false;
}
private AclSid findSid(String sidName, boolean principal,
String organization)
throws ResourceNotFoundFault {
AclSid sid;
if (organization == null) {
sid = sidDao.findBySid(sidName, principal);
} else {
sid = sidDao.findBySid(sidName, principal, organization);
}
if (sid == null) {
throw new ResourceNotFoundFault(
"Authority (Role) \"" + sidName + "\" not found");
}
logger.trace("\n*** AclSid:\n{}\n***", sid);
return sid;
}
}