blob: 39ac45455f73674ecbe7cc7bcd3454574b219c67 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013-2016 LAAS-CNRS (www.laas.fr)
* 7 Colonel Roche 31077 Toulouse - France
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Initial Contributors:
* Thierry Monteil : Project manager, technical co-manager
* Mahdi Ben Alaya : Technical co-manager
* Samir Medjiah : Technical co-manager
* Khalil Drira : Strategy expert
* Guillaume Garzone : Developer
* François Aïssaoui : Developer
*
* New contributors :
*******************************************************************************/
package org.eclipse.om2m.core.controller;
import java.util.List;
import org.eclipse.om2m.commons.constants.Constants;
import org.eclipse.om2m.commons.constants.MimeMediaType;
import org.eclipse.om2m.commons.constants.Operation;
import org.eclipse.om2m.commons.constants.ResourceStatus;
import org.eclipse.om2m.commons.constants.ResourceType;
import org.eclipse.om2m.commons.constants.ResponseStatusCode;
import org.eclipse.om2m.commons.constants.ShortName;
import org.eclipse.om2m.commons.entities.AccessControlPolicyEntity;
import org.eclipse.om2m.commons.entities.AccessControlRuleEntity;
import org.eclipse.om2m.commons.entities.AeEntity;
import org.eclipse.om2m.commons.entities.CSEBaseEntity;
import org.eclipse.om2m.commons.entities.RemoteCSEEntity;
import org.eclipse.om2m.commons.entities.ResourceEntity;
import org.eclipse.om2m.commons.entities.SubscriptionEntity;
import org.eclipse.om2m.commons.exceptions.BadRequestException;
import org.eclipse.om2m.commons.exceptions.ConflictException;
import org.eclipse.om2m.commons.exceptions.ResourceNotFoundException;
import org.eclipse.om2m.commons.resource.AccessControlPolicy;
import org.eclipse.om2m.commons.resource.RequestPrimitive;
import org.eclipse.om2m.commons.resource.ResponsePrimitive;
import org.eclipse.om2m.commons.utils.AcpUtils;
import org.eclipse.om2m.commons.utils.Util.DateUtil;
import org.eclipse.om2m.core.datamapper.DataMapperSelector;
import org.eclipse.om2m.core.entitymapper.EntityMapperFactory;
import org.eclipse.om2m.core.notifier.Notifier;
import org.eclipse.om2m.core.router.Patterns;
import org.eclipse.om2m.core.urimapper.UriMapper;
import org.eclipse.om2m.core.util.ControllerUtil;
import org.eclipse.om2m.core.util.ControllerUtil.UpdateUtil;
import org.eclipse.om2m.persistence.service.DAO;
/**
* Controller for Access Control policy
*
*/
public class AccessControlPolicyController extends Controller {
/*
* Generic create procedure
*
* Req
* @resourceName NP
* resourceType NP
* resourceID NP
* parentID NP
* expirationTime O
* labels O
* creationTime NP
* lastModifiedTime NP
* announceTo O
* announcedAttribute O
* privileges M
* selfPrivileges M
*/
@Override
public ResponsePrimitive doCreate(RequestPrimitive request) {
ResponsePrimitive response = new ResponsePrimitive(request);
Patterns patterns = new Patterns();
// Get the DAO of the parent
DAO<ResourceEntity> dao = (DAO<ResourceEntity>) patterns.getDAO(request.getTargetId(), dbs);
if (dao == null){
throw new ResourceNotFoundException("Cannot find parent resource");
}
// Get the parent entity
ResourceEntity parentEntity = (ResourceEntity)dao.find(transaction, request.getTargetId());
// Check the parent existence
if (parentEntity == null){
throw new ResourceNotFoundException("Cannot find parent resource");
}
// lock parent database entity
transaction.lock(parentEntity);
// Get lists to change in the method corresponding to specific object
List<AccessControlPolicyEntity> acpsToCheck = null;
List<AccessControlPolicyEntity> childAcps = null;
List<SubscriptionEntity> subscriptions = null;
// Case of CSEBase parent
if (parentEntity.getResourceType().intValue() == (ResourceType.CSE_BASE)){
CSEBaseEntity cseBase= (CSEBaseEntity) parentEntity ;
acpsToCheck = cseBase.getAccessControlPolicies();
childAcps = cseBase.getChildAccessControlPolicies();
subscriptions = cseBase.getSubscriptions();
}
// Case of AE parent
if (parentEntity.getResourceType().intValue() == (ResourceType.AE)){
AeEntity ae = (AeEntity) parentEntity;
acpsToCheck = ae.getAccessControlPolicies();
childAcps = ae.getChildAccessControlPolicies();
subscriptions = ae.getSubscriptions();
}
// case of Remote CSE
if (parentEntity.getResourceType().intValue() == (ResourceType.REMOTE_CSE)) {
RemoteCSEEntity csr = (RemoteCSEEntity) parentEntity;
acpsToCheck = csr.getAccessControlPolicies();
childAcps = csr.getChildAcps();
subscriptions = csr.getSubscriptions();
}
// TODO complete list of parents
// Check access control policy of the originator
checkACP(acpsToCheck, request.getFrom(), Operation.CREATE);
// Check if content is present
if (request.getContent() == null){
throw new BadRequestException("A content is requiered for AccessControlPolicy creation");
}
// Get the java object from the representation
AccessControlPolicy acp = null;
try{
if (request.getRequestContentType().equals(MimeMediaType.OBJ)){
acp = (AccessControlPolicy) request.getContent();
} else {
acp = (AccessControlPolicy)DataMapperSelector.getDataMapperList()
.get(request.getRequestContentType()).stringToObj((String)request.getContent());
}
} catch (ClassCastException e){
LOGGER.debug("ClassCastException: Incorrect resource type in object conversion.",e);
throw new BadRequestException("Incorrect resource representation in content", e);
}
if (acp == null){
throw new BadRequestException("Error in provided content");
}
AccessControlPolicyEntity acpEntity = new AccessControlPolicyEntity();
// Check attributes
// @resourceName NP
// Resource Type NP
// resourceID NP
// parentID NP
// lastModifiedTime NP
// creationTime NP
// labels O
ControllerUtil.CreateUtil.fillEntityFromGenericResource(acp, acpEntity);
// privileges M
if (acp.getPrivileges() == null){
throw new BadRequestException("Prilileges is Mandatory");
}
// selfPrivileges M
if (acp.getSelfPrivileges() == null){
throw new BadRequestException("SelfPrivileges is Mandatory");
}
String generatedId = generateId();
// Creating the corresponding entity
if (acp.getName() != null){
if (!patterns.checkResourceName(acp.getName())){
throw new BadRequestException("Name provided is incorrect. Must be:" + patterns.ID_STRING);
}
acpEntity.setName(acp.getName());
} else {
acpEntity.setName(ShortName.ACP + "_" + generatedId);
}
acpEntity.setHierarchicalURI(parentEntity.getHierarchicalURI() + "/" + acpEntity.getName());
acpEntity.setResourceID("/" + Constants.CSE_ID + "/" + ShortName.ACP + Constants.PREFIX_SEPERATOR + generatedId);
if(!UriMapper.addNewUri(acpEntity.getHierarchicalURI(), acpEntity.getResourceID(), ResourceType.ACCESS_CONTROL_POLICY)){
throw new ConflictException("Name already present in the parent collection.");
}
acpEntity.setCreationTime(DateUtil.now());
acpEntity.setLastModifiedTime(DateUtil.now());
acpEntity.setParentID(parentEntity.getResourceID());
acpEntity.setResourceType(ResourceType.ACCESS_CONTROL_POLICY);
switch(parentEntity.getResourceType().intValue()) {
case ResourceType.AE:
acpEntity.setParentAE((AeEntity) parentEntity);
break;
case ResourceType.REMOTE_CSE:
acpEntity.setParentCsr((RemoteCSEEntity) parentEntity);
break;
case ResourceType.CSE_BASE:
acpEntity.setParentCse((CSEBaseEntity) parentEntity);
break;
}
// expirationTime O
if (acp.getExpirationTime() != null){
acpEntity.setExpirationTime(acp.getExpirationTime());
}
// announceTo O
acpEntity.getAnnounceTo().addAll(acp.getAnnounceTo());
// announcedAttribute O
acpEntity.getAnnouncedAttribute().addAll(acp.getAnnouncedAttribute());
acpEntity.setPrivileges(AcpUtils.getACREntityFromSetOfArcs(acp.getPrivileges()));
acpEntity.setSelfPrivileges(AcpUtils.getACREntityFromSetOfArcs(acp.getSelfPrivileges()));
// Create ACP in database
dbs.getDAOFactory().getAccessControlPolicyDAO().create(transaction, acpEntity);
// Get the managed object from db
AccessControlPolicyEntity acpDB = dbs.getDAOFactory().getAccessControlPolicyDAO().find(transaction, acpEntity.getResourceID());
// Add the ACP to the parentEntity list
childAcps.add(acpDB);
dao.update(transaction, parentEntity);
// Commit the DB transaction & release lock
transaction.commit();
Notifier.notify(subscriptions, acpDB, ResourceStatus.CHILD_CREATED);
// Create the response
response.setResponseStatusCode(ResponseStatusCode.CREATED);
// Set the location of the resource
setLocationAndCreationContent(request, response, acpDB);
return response;
}
/*
* Generic retrieve procedure
*/
@Override
public ResponsePrimitive doRetrieve(RequestPrimitive request) {
ResponsePrimitive response = new ResponsePrimitive(request);
// Check existence of the resource
AccessControlPolicyEntity acpEntity = dbs.getDAOFactory()
.getAccessControlPolicyDAO().find(transaction, request.getTargetId());
if (acpEntity == null) {
throw new ResourceNotFoundException("Resource " + request.getTargetId() + " not found.");
}
// Check authorization
checkSelfACP(acpEntity, request.getFrom(),
Operation.RETRIEVE);
// Create the object used to create the representation of the resource
AccessControlPolicy acpResource = EntityMapperFactory.getAcpMapper().mapEntityToResource(acpEntity, request);
response.setContent(acpResource);
response.setResponseStatusCode(ResponseStatusCode.OK);
return response;
}
/*
* Generic update procedure
*
* Req
* @resourceName NP
* resourceType NP
* resourceID NP
* parentID NP
* expirationTime O
* labels O
* creationTime NP
* lastModifiedTime NP
* announceTo O
* announcedAttribute O
* privileges O
* selfPrivileges O
*/
@Override
public ResponsePrimitive doUpdate(RequestPrimitive request) {
ResponsePrimitive response = new ResponsePrimitive(request);
// Retrieve the resource from DB
AccessControlPolicyEntity acpEntity = dbs.getDAOFactory().
getAccessControlPolicyDAO().find(transaction, request.getTargetId());
// Check resource existence
if (acpEntity == null){
throw new ResourceNotFoundException("Resource " + request.getTargetId() + " not found.");
}
// lock entity
transaction.lock(acpEntity);
// Check self ACP
checkSelfACP(acpEntity, request.getFrom(), Operation.UPDATE);
// Check if content is present
if (request.getContent() == null){
throw new BadRequestException("A content is requiered for ACP update");
}
// Create the java object from the resource representation
AccessControlPolicy acp = null;
try{
if (request.getRequestContentType().equals(MimeMediaType.OBJ)){
acp = (AccessControlPolicy) request.getContent();
} else {
acp = (AccessControlPolicy)DataMapperSelector.getDataMapperList()
.get(request.getRequestContentType()).stringToObj((String)request.getContent());
}
} catch (ClassCastException e){
LOGGER.debug("ClassCastException: Incorrect resource type in object conversion.",e);
throw new BadRequestException("Incorrect resource representation in content", e);
}
if (acp == null){
throw new BadRequestException("Error in provided content");
}
AccessControlPolicy modifiedAttributes = new AccessControlPolicy();
// NP attributes
// @resourceName NP
// resourceType NP
// resourceID NP
// parentID NP
// creationTime NP
// lastModifiedTime NP
UpdateUtil.checkNotPermittedParameters(acp);
// expirationTime O
if(acp.getExpirationTime() != null){
acpEntity.setExpirationTime(acp.getExpirationTime());
modifiedAttributes.setExpirationTime(acp.getExpirationTime());
}
// labels O
if(!acp.getLabels().isEmpty()){
acpEntity.setLabelsEntitiesFromSring(acp.getLabels());
modifiedAttributes.getLabels().addAll(acp.getLabels());
}
// announceTo O
if(!acp.getAnnounceTo().isEmpty()){
acpEntity.getAnnounceTo().clear();
acpEntity.getAnnounceTo().addAll(acp.getAnnounceTo());
// TODO Announcement in ACP update
modifiedAttributes.getAnnounceTo().addAll(acp.getAnnounceTo());
}
// announcedAttribute O
if(!acp.getAnnouncedAttribute().isEmpty()){
acpEntity.getAnnouncedAttribute().clear();
acpEntity.getAnnouncedAttribute().addAll(acp.getAnnouncedAttribute());
modifiedAttributes.getAnnouncedAttribute().addAll(acp.getAnnouncedAttribute());
}
// privileges O
if(acp.getPrivileges() != null){
List<AccessControlRuleEntity> rules = AcpUtils.getACREntityFromSetOfArcs(acp.getPrivileges());
acpEntity.getPrivileges().clear();
acpEntity.getPrivileges().addAll(rules);
modifiedAttributes.setPrivileges(acp.getPrivileges());
}
// selfPrivileges O
if(acp.getSelfPrivileges() != null){
List<AccessControlRuleEntity> rules = AcpUtils.getACREntityFromSetOfArcs(acp.getSelfPrivileges());
acpEntity.getSelfPrivileges().clear();
acpEntity.getSelfPrivileges().addAll(rules);
modifiedAttributes.setSelfPrivileges(acp.getSelfPrivileges());
}
acpEntity.setLastModifiedTime(DateUtil.now());
modifiedAttributes.setLastModifiedTime(acpEntity.getLastModifiedTime());
response.setContent(modifiedAttributes);
dbs.getDAOFactory().getAccessControlPolicyDAO().update(transaction, acpEntity);
// commit transaction & unlock
transaction.commit();
Notifier.notify(acpEntity.getChildSubscriptions(), acpEntity, ResourceStatus.UPDATED);
response.setResponseStatusCode(ResponseStatusCode.UPDATED);
return response;
}
/*
* Generic Delete procedure
*/
@Override
public ResponsePrimitive doDelete(RequestPrimitive request) {
ResponsePrimitive response = new ResponsePrimitive(request);
// Retrieve the resource from database
AccessControlPolicyEntity acpEntity = dbs.getDAOFactory()
.getAccessControlPolicyDAO().find(transaction, request.getTargetId());
// Check resource existence
if (acpEntity == null){
throw new ResourceNotFoundException("Resource not found");
}
// transaction lock
transaction.lock(acpEntity);
// Check this acp is not a generated acp for an AE to avoid inconsistency
// for(RegularResourceEntity regularResourceEntity : acpEntity.getLinkedRegularResources()) {
// if (regularResourceEntity instanceof AeEntity) {
// AeEntity ae = (AeEntity) regularResourceEntity;
// if (ae.getGeneratedAcp() != null) {
// if(ae.getGeneratedAcp().getResourceID().equals(acpEntity.getResourceID())){
// throw new BadRequestException("Delete the linked ae(s) to avoid acp inconsistency.");
// }
// }
// }
// }
for(AeEntity ae : acpEntity.getLinkedAes()){
if (ae.getGeneratedAcp() != null) {
if(ae.getGeneratedAcp().getResourceID().equals(acpEntity.getResourceID())){
throw new BadRequestException("Delete the linked ae(s) to avoid acp inconsistency.");
}
}
}
// Check self access control policy
checkSelfACP(acpEntity, request.getFrom(), Operation.DELETE);
// TODO Notify doDelete
// TODO De-announce doDelete
UriMapper.deleteUri(acpEntity.getHierarchicalURI());
Notifier.notifyDeletion(acpEntity.getChildSubscriptions(), acpEntity);
// Delete the resource
dbs.getDAOFactory().getAccessControlPolicyDAO().delete(transaction, acpEntity);
// commit & unlock
transaction.commit();
// Close transaction and return
response.setResponseStatusCode(ResponseStatusCode.DELETED);
return response;
}
}