edu.kit.dama.rest.sharing.services.impl.SharingRestServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for edu.kit.dama.rest.sharing.services.impl.SharingRestServiceImpl.java

Source

/*
 * Copyright 2014 Karlsruhe Institute of Technology.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package edu.kit.dama.rest.sharing.services.impl;

import com.sun.jersey.api.core.HttpContext;
import edu.kit.dama.authorization.entities.GroupId;
import edu.kit.dama.authorization.entities.IAuthorizationContext;
import edu.kit.dama.authorization.entities.IDefaultGrant;
import edu.kit.dama.authorization.entities.IDefaultGrantSet;
import edu.kit.dama.authorization.entities.IDefaultReferenceId;
import edu.kit.dama.authorization.entities.ISimpleGroupId;
import edu.kit.dama.authorization.entities.ISimpleUserId;
import edu.kit.dama.authorization.entities.ReferenceId;
import edu.kit.dama.authorization.entities.Role;
import edu.kit.dama.authorization.entities.SecurableResourceId;
import edu.kit.dama.authorization.entities.UserId;
import edu.kit.dama.authorization.entities.impl.Grant;
import edu.kit.dama.authorization.entities.impl.GrantSet;
import edu.kit.dama.authorization.entities.impl.SecurableResource;
import edu.kit.dama.authorization.entities.impl.User;
import edu.kit.dama.authorization.entities.util.FindUtil;
import edu.kit.dama.authorization.entities.util.PU;
import edu.kit.dama.authorization.exceptions.EntityAlreadyExistsException;
import edu.kit.dama.authorization.exceptions.EntityNotFoundException;
import edu.kit.dama.authorization.exceptions.UnauthorizedAccessAttemptException;
import edu.kit.dama.authorization.services.administration.ResourceServiceLocal;
import edu.kit.dama.rest.base.IEntityWrapper;
import edu.kit.dama.rest.base.types.CheckServiceResponse;
import edu.kit.dama.rest.base.types.ServiceStatus;
import edu.kit.dama.rest.util.RestUtils;
import edu.kit.dama.rest.sharing.services.interfaces.ISharingService;
import edu.kit.dama.rest.sharing.types.GrantSetWrapper;
import edu.kit.dama.rest.sharing.types.GrantWrapper;
import edu.kit.dama.rest.sharing.types.GroupIdWrapper;
import edu.kit.dama.rest.sharing.types.ReferenceIdWrapper;
import edu.kit.dama.rest.sharing.types.UserIdWrapper;
import edu.kit.dama.util.Constants;
import java.util.List;
import javax.persistence.EntityManager;
import javax.ws.rs.Path;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author mf6319
 */
@Path("/")
public final class SharingRestServiceImpl implements ISharingService {

    private static final Class[] IMPL_CLASSES = new Class[] { GrantSetWrapper.class, ReferenceIdWrapper.class,
            GrantSet.class, Grant.class, SecurableResource.class, ReferenceId.class, Role.class, User.class };
    private static final Logger LOGGER = LoggerFactory.getLogger(SharingRestServiceImpl.class);

    @Override
    public IEntityWrapper<? extends IDefaultReferenceId> createReference(String pDomain, String pDomainUniqueId,
            String pReferenceGroupId, String pRole, String pGroupId, HttpContext hc) {
        IAuthorizationContext ctx = RestUtils.authorize(hc, new GroupId(pGroupId));
        LOGGER.debug("Creating referenceId for domain {}, uniqueId {} and reference group {}", pDomain,
                pDomainUniqueId, pReferenceGroupId);
        ReferenceId refId = factoryReferenceId(pDomain, pDomainUniqueId, pReferenceGroupId);

        try {
            LOGGER.debug("Try creating reference {}", refId);
            ResourceServiceLocal.getSingleton().createReference(refId, Role.valueOf(pRole), ctx);
            LOGGER.debug("Reference successfully created.");
            // return RestUtils.transformObject(IMPL_CLASSES, Constants.REST_DEFAULT_OBJECT_GRAPH, new ReferenceIdWrapper(refId));
            return new ReferenceIdWrapper(refId);
        } catch (UnauthorizedAccessAttemptException ex) {
            LOGGER.error("Failed to create reference for resource " + refId, ex);
            throw new WebApplicationException(401);
        } catch (EntityNotFoundException ex) {
            LOGGER.error(
                    "EntityNotFoundException caught while creating a ResourceReference. Probably, the resource "
                            + factoryResourceId(pDomain, pDomainUniqueId) + " was not registered before.",
                    ex);
            throw new WebApplicationException(404);
        } catch (EntityAlreadyExistsException ex) {
            LOGGER.error("Failed to create resource reference for resource "
                    + factoryResourceId(pDomain, pDomainUniqueId) + " and group " + pGroupId
                    + " . Reference already exists.", ex);
            throw new WebApplicationException(409);
        }
    }

    @Override
    public IEntityWrapper<? extends IDefaultReferenceId> getReferences(String pDomain, String pDomainUniqueId,
            String pGroupId, HttpContext hc) {
        IAuthorizationContext ctx = RestUtils.authorize(hc, new GroupId(pGroupId));
        SecurableResourceId resId = factoryResourceId(pDomain, pDomainUniqueId);
        try {
            // return RestUtils.transformObject(IMPL_CLASSES, Constants.REST_DEFAULT_OBJECT_GRAPH, new ReferenceIdWrapper(ResourceServiceLocal.getSingleton().getReferences(resId, ctx)));
            return new ReferenceIdWrapper(ResourceServiceLocal.getSingleton().getReferences(resId, ctx));
        } catch (UnauthorizedAccessAttemptException ex) {
            LOGGER.error("Failed to get references for resource " + resId, ex);
            throw new WebApplicationException(401);
        } catch (EntityNotFoundException ex) {
            LOGGER.error(
                    "EntityNotFoundException caught while obtaining ResourceReferences. Probably, the resource "
                            + new SecurableResourceId(pDomain, pDomainUniqueId) + " was not registered before.",
                    ex);
            throw new WebApplicationException(404);
        }
    }

    @Override
    public IEntityWrapper<? extends ISimpleGroupId> getReferencedGroups(String pDomain, String pDomainUniqueId,
            String pRole, String pGroupId, HttpContext hc) {
        IAuthorizationContext ctx = RestUtils.authorize(hc, new GroupId(pGroupId));
        SecurableResourceId resId = factoryResourceId(pDomain, pDomainUniqueId);
        try {
            LOGGER.debug("Try to obtain groups referencing resource {} with at least role {}", resId, pRole);
            return new GroupIdWrapper(
                    ResourceServiceLocal.getSingleton().getAuthorizedGroups(resId, Role.valueOf(pRole), ctx));
        } catch (UnauthorizedAccessAttemptException ex) {
            LOGGER.error("Failed to obtained referenced groups for resource " + resId, ex);
            throw new WebApplicationException(401);
        } catch (EntityNotFoundException ex) {
            LOGGER.error(
                    "EntityNotFoundException caught while obtaining ResourceReferences. Probably, the resource "
                            + new SecurableResourceId(pDomain, pDomainUniqueId) + " was not registered before.",
                    ex);
            throw new WebApplicationException(404);
        }
    }

    @Override
    public Response deleteReference(String pDomain, String pDomainUniqueId, String pGroupId, HttpContext hc) {
        IAuthorizationContext ctx = RestUtils.authorize(hc, new GroupId(pGroupId));
        ReferenceId refId = factoryReferenceId(pDomain, pDomainUniqueId, pGroupId);
        try {
            LOGGER.debug("Try to delete reference {}", refId);
            ResourceServiceLocal.getSingleton().deleteReference(refId, ctx);
            LOGGER.debug("Reference successfully deleted.");
            return Response.ok().build();
        } catch (UnauthorizedAccessAttemptException ex) {
            LOGGER.error("Failed to delete reference with id " + refId, ex);
            throw new WebApplicationException(401);
        } catch (EntityNotFoundException ex) {
            LOGGER.error(
                    "EntityNotFoundException caught while obtaining ResourceReferences. Probably, the resource "
                            + new SecurableResourceId(pDomain, pDomainUniqueId) + " was not registered before.",
                    ex);
            throw new WebApplicationException(404);
        }
    }

    @Override
    public IEntityWrapper<? extends IDefaultGrantSet> getGrantSetForResource(String pDomain, String pDomainUniqueId,
            String pGroupId, HttpContext hc) {
        IAuthorizationContext ctx = RestUtils.authorize(hc, new GroupId(pGroupId));
        SecurableResourceId resId = factoryResourceId(pDomain, pDomainUniqueId);
        try {
            LOGGER.debug("Try getting grantset for resource {}", resId);
            List<Grant> grants = ResourceServiceLocal.getSingleton().getGrants(resId, ctx);
            LOGGER.debug("Obtained {} grants.", (grants != null) ? grants.size() : 0);

            GrantSet grantSet = null;
            if (grants != null && !grants.isEmpty()) {
                //get grantSet from any grant...let's take the first.
                grantSet = grants.get(0).getGrants();
            }
            if (grantSet != null) {
                LOGGER.debug("Obtained grantset with id {}", grantSet.getId());
            } else {
                LOGGER.warn("Obtained no grantset. Returning empty result.");
            }

            // return RestUtils.transformObject(IMPL_CLASSES, Constants.REST_DEFAULT_OBJECT_GRAPH, new GrantSetWrapper(grantSet));
            return new GrantSetWrapper(grantSet);
        } catch (UnauthorizedAccessAttemptException ex) {
            LOGGER.error("Failed to obtain grantset for resource " + resId, ex);
            throw new WebApplicationException(401);
        } catch (EntityNotFoundException ex) {
            LOGGER.error(
                    "EntityNotFoundException caught while obtaining ResourceReferences. Probably, the resource "
                            + resId + " was not registered before.",
                    ex);
            throw new WebApplicationException(404);
        }
    }

    @Override
    public IEntityWrapper<? extends IDefaultGrant> getGrantById(Long pId, String pGroupId, HttpContext hc) {
        //@TODO Hack using EM directly...other way?
        EntityManager em = PU.entityManager();
        try {
            LOGGER.debug("Finding grant for id " + pId);
            Grant grant = FindUtil.findGrant(em, pId);
            // return RestUtils.transformObject(IMPL_CLASSES, Constants.REST_DEFAULT_OBJECT_GRAPH, new GrantWrapper(grant));
            return new GrantWrapper(grant);
        } catch (EntityNotFoundException ex) {
            LOGGER.error("EntityNotFoundException caught while obtaining Grant for id " + pId
                    + ". Probably, there is no grant for this id.", ex);
            throw new WebApplicationException(404);
        } finally {
            em.close();
        }
    }

    @Override
    public IEntityWrapper<? extends IDefaultGrant> createGrant(String pDomain, String pDomainUniqueId,
            final String pUserId, String pGroupId, String pRole, HttpContext hc) {
        IAuthorizationContext ctx = RestUtils.authorize(hc, new GroupId(pGroupId));
        try {
            SecurableResourceId resId = factoryResourceId(pDomain, pDomainUniqueId);
            LOGGER.debug("Checking whether grants are allowed.");
            if (!ResourceServiceLocal.getSingleton().grantsAllowed(resId, ctx)) {
                LOGGER.debug("Grants are not allowed. Enabling grants with max. role MANAGER.");
                //allow grants with max. role MANAGER.
                //@TODO check whether this should be solved in a configurable way.
                ResourceServiceLocal.getSingleton().allowGrants(resId, Role.MANAGER, ctx);
                LOGGER.debug("Grants are now allowed.");
            } else {
                LOGGER.debug("Grants are already allowed.");
            }

            LOGGER.debug("Adding grant for user {} on resource {}", resId, pUserId);
            //add grant
            ResourceServiceLocal.getSingleton().addGrant(resId, new UserId(pUserId), Role.valueOf(pRole), ctx);
            LOGGER.debug("Obtaining grant information for resource {} from database.", resId);
            //get all grants as addGrant does not return anything.
            List<Grant> grants = ResourceServiceLocal.getSingleton().getGrants(resId, ctx);
            LOGGER.debug("Searching for grantee {}.", pUserId);
            //search for appropriate grant
            Grant grant = (Grant) CollectionUtils.find(grants, new Predicate() {

                @Override
                public boolean evaluate(Object o) {
                    return ((Grant) o).getGrantee().getUserId().equals(pUserId);
                }
            });
            if (grant != null) {
                LOGGER.debug("Grant information successfully obtained. Returning result.");
            } else {
                LOGGER.warn("No grant information obtained. Returning empty result.");
            }
            //return RestUtils.transformObject(IMPL_CLASSES, Constants.REST_DEFAULT_OBJECT_GRAPH, new GrantWrapper(grant));
            return new GrantWrapper(grant);
        } catch (UnauthorizedAccessAttemptException ex) {
            LOGGER.error("Failed to create grant", ex);
            throw new WebApplicationException(401);
        } catch (EntityNotFoundException ex) {
            LOGGER.error(
                    "EntityNotFoundException caught while adding Grant. Probably, the resource "
                            + new SecurableResourceId(pDomain, pDomainUniqueId) + " was not registered before.",
                    ex);
            throw new WebApplicationException(404);
        } catch (EntityAlreadyExistsException ex) {
            LOGGER.error(
                    "EntityAlreadyExistsException caught while adding Grant. Probably, there is already a grant for resource "
                            + new SecurableResourceId(pDomain, pDomainUniqueId) + " and user " + pUserId + ".",
                    ex);
            throw new WebApplicationException(409);
        }
    }

    @Override
    public Response revokeGrant(Long pId, String pGroupId, HttpContext hc) {
        IAuthorizationContext ctx = RestUtils.authorize(hc, new GroupId(pGroupId));
        //Hack using EM directly...other way?
        EntityManager em = PU.entityManager();
        try {
            LOGGER.debug("Finding grant for id " + pId);
            Grant grant = FindUtil.findGrant(em, pId);
            LOGGER.debug("Revoking grant for id " + pId);
            ResourceServiceLocal.getSingleton().revokeGrant(
                    grant.getGrants().getResource().getSecurableResourceId(),
                    new UserId(grant.getGrantee().getUserId()), ctx);
            return Response.ok().build();
        } catch (UnauthorizedAccessAttemptException ex) {
            LOGGER.error("Failed to revoke grant with id " + pId, ex);
            throw new WebApplicationException(401);
        } catch (EntityNotFoundException ex) {
            LOGGER.error("EntityNotFoundException caught while obtaining Grant for id " + pId
                    + ". Probably, there is no grant for this id.", ex);
            throw new WebApplicationException(404);
        } finally {
            em.close();
        }
    }

    @Override
    public Response revokeAllGrants(String pDomain, String pDomainUniqueId, String pGroupId, HttpContext hc) {
        IAuthorizationContext ctx = RestUtils.authorize(hc, new GroupId(pGroupId));
        SecurableResourceId resId = factoryResourceId(pDomain, pDomainUniqueId);

        try {
            ResourceServiceLocal.getSingleton().revokeAllAndDisallowGrants(resId, ctx);
            return Response.ok().build();
        } catch (UnauthorizedAccessAttemptException ex) {
            LOGGER.error("Failed to revoke all grants for resource " + resId, ex);
            throw new WebApplicationException(401);
        } catch (EntityNotFoundException ex) {
            LOGGER.error(
                    "EntityNotFoundException caught while revoking all grants. Probably, the resource "
                            + new SecurableResourceId(pDomain, pDomainUniqueId) + " was not registered before.",
                    ex);
            throw new WebApplicationException(404);
        }

    }

    @Override
    public IEntityWrapper<? extends IDefaultGrant> updateGrant(Long pId, String pGroupId, String pRole,
            HttpContext hc) {
        IAuthorizationContext ctx = RestUtils.authorize(hc, new GroupId(pGroupId));
        //Hack using EM directly...other way?
        EntityManager em = PU.entityManager();
        try {
            LOGGER.debug("Finding grant for id " + pId);
            Grant grant = FindUtil.findGrant(em, pId);
            LOGGER.debug("Updating grant for id " + pId);
            Role newRole = Role.valueOf(pRole);
            ResourceServiceLocal.getSingleton().changeGrant(
                    grant.getGrants().getResource().getSecurableResourceId(),
                    new UserId(grant.getGrantee().getUserId()), newRole, ctx);
            grant.setGrantedRole(newRole);
            return new GrantWrapper(grant);
        } catch (UnauthorizedAccessAttemptException ex) {
            LOGGER.error("Failed to update grant with id " + pId, ex);
            throw new WebApplicationException(401);
        } catch (EntityNotFoundException ex) {
            LOGGER.error("EntityNotFoundException caught while obtaining Grant for id " + pId
                    + ". Probably, there is no grant for this id.", ex);
            throw new WebApplicationException(404);
        } finally {
            em.close();
        }
    }

    @Override
    public IEntityWrapper<? extends ISimpleUserId> getAuthorizedUsers(String pDomain, String pDomainUniqueId,
            String pRole, String pGroupId, HttpContext hc) {
        IAuthorizationContext ctx = RestUtils.authorize(hc, new GroupId(pGroupId));
        SecurableResourceId resId = factoryResourceId(pDomain, pDomainUniqueId);
        try {
            return new UserIdWrapper(
                    ResourceServiceLocal.getSingleton().getAuthorizedUsers(resId, Role.valueOf(pRole), ctx));
        } catch (UnauthorizedAccessAttemptException ex) {
            LOGGER.error("Failed to get a list of authorized users for resource " + resId, ex);
            throw new WebApplicationException(401);
        } catch (EntityNotFoundException ex) {
            LOGGER.error(
                    "EntityNotFoundException caught while obtaining authorized users. Probably, the resource "
                            + new SecurableResourceId(pDomain, pDomainUniqueId) + " was not registered before.",
                    ex);
            throw new WebApplicationException(404);
        }
    }

    @Override
    public Response checkService() {
        ServiceStatus status = ServiceStatus.UNKNOWN;
        return Response.status(200).entity(new CheckServiceResponse("Sharing", status)).build();
    }

    /**
     * Internal helper to create a ReferenceId for pDomain, pDomainUniqueId and
     * pGroupId.
     *
     * @param pDomain The resource domain.
     * @param pDomainUniqueId The domain unique id.
     * @param pGroupId The group id.
     *
     * @return The ReferenceId.
     */
    private ReferenceId factoryReferenceId(String pDomain, String pDomainUniqueId, String pGroupId) {
        SecurableResourceId resId = factoryResourceId(pDomain, pDomainUniqueId);
        String id = pGroupId;
        if (id == null) {
            LOGGER.info("Provided groupId is null. Using default group {} instead.", Constants.USERS_GROUP_ID);
            id = Constants.USERS_GROUP_ID;
        }

        return new ReferenceId(resId, new GroupId(id));
    }

    /**
     * Internal helper to create a SecurableResourceId for pDomain and
     * pDomainUniqueId.
     *
     * @param pDomain The resource domain.
     * @param pDomainUniqueId The domain unique id.
     *
     * @return The SecurableResourceId.
     */
    private SecurableResourceId factoryResourceId(String pDomain, String pDomainUniqueId) {
        if (pDomain == null || pDomainUniqueId == null) {
            LOGGER.error(
                    "Arguments pDomain and pDomainUniqueId must not be null. Returning HTTP-BAD REQUEST (400)");
            throw new WebApplicationException(Response.Status.BAD_REQUEST);
        }

        return new SecurableResourceId(pDomain, pDomainUniqueId);
    }

}