Package org.candlepin.resource

Source Code of org.candlepin.resource.EntitlementResource

/**
* Copyright (c) 2009 - 2012 Red Hat, Inc.
*
* This software is licensed to you under the GNU General Public License,
* version 2 (GPLv2). There is NO WARRANTY for this software, express or
* implied, including the implied warranties of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
* along with this software; if not, see
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* Red Hat trademarks are not licensed under GPLv2. No permission is
* granted to use or replicate Red Hat trademarks that are incorporated
* in this software or its documentation.
*/
package org.candlepin.resource;

import static org.quartz.JobBuilder.*;

import org.candlepin.auth.interceptor.Verify;
import org.candlepin.common.exceptions.BadRequestException;
import org.candlepin.common.exceptions.NotFoundException;
import org.candlepin.controller.Entitler;
import org.candlepin.controller.PoolManager;
import org.candlepin.model.Cdn;
import org.candlepin.model.Consumer;
import org.candlepin.model.ConsumerCurator;
import org.candlepin.model.Entitlement;
import org.candlepin.model.EntitlementCurator;
import org.candlepin.model.Pool;
import org.candlepin.paging.Page;
import org.candlepin.paging.PageRequest;
import org.candlepin.paging.Paginate;
import org.candlepin.pinsetter.tasks.RegenProductEntitlementCertsJob;
import org.candlepin.policy.ValidationResult;
import org.candlepin.policy.js.entitlement.Enforcer;
import org.candlepin.policy.js.entitlement.Enforcer.CallerType;
import org.candlepin.policy.js.entitlement.EntitlementRulesTranslator;
import org.candlepin.service.ProductServiceAdapter;
import org.candlepin.util.Util;

import com.google.inject.Inject;

import org.apache.commons.lang.StringUtils;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xnap.commons.i18n.I18n;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

/**
* REST api gateway for the User object.
*/
@Path("/entitlements")
public class EntitlementResource {
    private static Logger log = LoggerFactory.getLogger(EntitlementResource.class);
    private final ConsumerCurator consumerCurator;
    private PoolManager poolManager;
    private final EntitlementCurator entitlementCurator;
    private I18n i18n;
    private ProductServiceAdapter prodAdapter;
    private Entitler entitler;
    private SubscriptionResource subResource;
    private Enforcer enforcer;
    private EntitlementRulesTranslator messageTranslator;

    @Inject
    public EntitlementResource(ProductServiceAdapter prodAdapter,
            EntitlementCurator entitlementCurator,
            ConsumerCurator consumerCurator,
            PoolManager poolManager,
            I18n i18n, Entitler entitler, SubscriptionResource subResource,
            Enforcer enforcer, EntitlementRulesTranslator messageTranslator) {

        this.entitlementCurator = entitlementCurator;
        this.consumerCurator = consumerCurator;
        this.i18n = i18n;
        this.prodAdapter = prodAdapter;
        this.poolManager = poolManager;
        this.entitler = entitler;
        this.subResource = subResource;
        this.enforcer = enforcer;
        this.messageTranslator = messageTranslator;
    }

    private void verifyExistence(Object o, String id) {
        if (o == null) {
            throw new RuntimeException(
                i18n.tr("Object with ID ''{0}'' could not found.", id));
        }
    }

    /**
     * Checks Consumer for Product Entitlement
     *
     * @param consumerUuid consumerUuid to check if entitled or not
     * @param productId productLabel to check if entitled or not
     * @return a boolean
     * @httpcode 404
     * @httpcode 200
     */
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("consumer/{consumer_uuid}/product/{product_id}")
    public Entitlement hasEntitlement(@PathParam("consumer_uuid") String consumerUuid,
            @PathParam("product_id") String productId) {

        Consumer consumer = consumerCurator.findByUuid(consumerUuid);
        verifyExistence(consumer, consumerUuid);

        for (Entitlement e : consumer.getEntitlements()) {
            if (e.getProductId().equals(productId)) {
                return e;
            }
        }

        throw new NotFoundException(i18n.tr(
            "Unit ''{0}'' has no subscription for product ''{1}''.",
                consumerUuid, productId));
    }

    /**
     * Retrieves list of Entitlements
     *
     * @return a list of Entitlement objects
     * @httpcode 400
     * @httpcode 200
     */
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Paginate
    public List<Entitlement> listAllForConsumer(
        @QueryParam("consumer") String consumerUuid,
        @Context PageRequest pageRequest) {

        Page<List<Entitlement>> p;
        if (consumerUuid != null) {

            Consumer consumer = consumerCurator.findByUuid(consumerUuid);
            if (consumer == null) {
                throw new BadRequestException(
                    i18n.tr("Unit with ID ''{0}'' could not be found.", consumerUuid));
            }

            p = entitlementCurator.listByConsumer(consumer, pageRequest);
        }
        else {
            p = entitlementCurator.listAll(pageRequest);
        }

        // Store the page for the LinkHeaderPostInterceptor
        ResteasyProviderFactory.pushContext(Page.class, p);
        return p.getPageData();
    }

    /**
     * Retrieves a single Entitlement
     * <p>
     * <pre>
     * {
     *   "id" : "database_id",
     *   "consumer" : {},
     *   "pool" : {},
     *   "certificates" : [ ],
     *   "quantity" : 1,
     *   "startDate" : [date],
     *   "endDate" : [date],
     *   "href" : "/entitlements/database_id",
     *   "created" : [date],
     *   "updated" : [date]
     * }
     * </pre>
     *
     * @param dbid entitlement id.
     * @return an Entitlement object
     * @httpcode 404
     * @httpcode 200
     */
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("{dbid}")
    public Entitlement getEntitlement(
        @PathParam("dbid") @Verify(Entitlement.class) String dbid) {
        Entitlement toReturn = entitlementCurator.find(dbid);
        List<Entitlement> tempList = Arrays.asList(toReturn);
        poolManager.regenerateDirtyEntitlements(tempList);
        if (toReturn != null) {
            return toReturn;
        }
        throw new NotFoundException(
            i18n.tr("Entitlement with ID ''{0}'' could not be found.", dbid));
    }

    /**
     * Updates an Entitlement
     * <p>
     * This only works for the quantity.
     *
     * @httpcode 404
     * @httpcode 200
     */
    @PUT
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    @Path("{entitlement_id}")
    public void updateEntitlement(
        @PathParam("entitlement_id") @Verify(Entitlement.class) String id,
        Entitlement update) {

        // Check that quantity param was set and is not 0:
        if (update.getQuantity() <= 0) {
            throw new BadRequestException(
                i18n.tr("Quantity value must be greater than 0."));
        }

        // Verify entitlement exists:
        Entitlement entitlement = entitlementCurator.find(id);
        if (entitlement != null) {
            // make sure that this will be a change
            if (!entitlement.getQuantity().equals(update.getQuantity())) {
                Consumer consumer = entitlement.getConsumer();
                entitler.adjustEntitlementQuantity(consumer, entitlement,
                    update.getQuantity());
            }
        }
        else {
            throw new NotFoundException(
                i18n.tr("Entitlement with ID ''{0}'' could not be found.", id));
        }
    }


    /**
     * Retrieves a Subscription Certificate
     * <p>
     * We can't return CdnInfo at this time, but when the time comes this
     * is the implementation we want to start from. It will require changes
     * to thumbslug.
     * <p>
     * public CdnInfo getEntitlementUpstreamCert
     * will also @Produces(MediaType.APPLICATION_JSON)
     *
     * @param entitlementId entitlement id.
     * @return a String object
     * @httpcode 404
     * @httpcode 200
     */
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    @Path("{dbid}/upstream_cert")
    public String getUpstreamCert(
        @PathParam("dbid") String entitlementId) {
        Entitlement ent = entitlementCurator.find(entitlementId);
        if (ent == null) {
            throw new NotFoundException(i18n.tr(
                "Entitlement with ID ''{0}'' could not be found.", entitlementId));
        }

        String subscriptionId = null;
        Pool entPool = ent.getPool();
        if (StringUtils.isBlank(entPool.getSourceStackId())) {
            subscriptionId = entPool.getSubscriptionId();
        }
        /*
         * A derived pool originating from a stacked parent pool will have no subscription
         * ID as the pool is technically from many subscriptions. (i.e. all the
         * entitlements in the stack) In this case we must look up an active entitlement
         * in the hosts stack, and use this as our upstream certificate.
         */
        else {
            log.debug("Entitlement is from a stack derived pool, searching for oldest " +
                "active entitlements in source stack.");
            Entitlement e = entitlementCurator.findUpstreamEntitlementForStack(
                entPool.getSourceConsumer(),
                entPool.getSourceStackId());
            if (e != null) {
                subscriptionId = e.getPool().getSubscriptionId();
            }
        }

        if (subscriptionId == null) {
            throw new NotFoundException(
                i18n.tr("Unable to find upstream certificate for entitlement: {0}",
                    entitlementId));
        }

        return subResource.getSubCertAsPem(subscriptionId);
        // Cdn cdn = subResource.getSubscription(subscriptionId).getCdn();
        // CdnInfo result = new CdnInfo(cdn, subResource.getSubCertAsPem(subscriptionId));
        // return result;
    }

    /**
     * Deletes an Entitlement
     *
     * @param dbid the entitlement to delete.
     * @httpcode 403
     * @httpcode 404
     * @httpcode 200
     */
    @DELETE
    @Path("/{dbid}")
    public void unbind(@PathParam("dbid") String dbid) {
        Entitlement toDelete = entitlementCurator.find(dbid);
        if (toDelete != null) {
            poolManager.revokeEntitlement(toDelete);
            return;
        }
        throw new NotFoundException(
            i18n.tr("Entitlement with ID ''{0}'' could not be found.", dbid));
    }

    /**
     * Regenerates the Entitlement Certificates for a Product
     *
     * @return a JobDetail object
     * @httpcode 202
     */
    @PUT
    @Path("product/{product_id}")
    public JobDetail regenerateEntitlementCertificatesForProduct(
            @PathParam("product_id") String productId,
            @QueryParam("lazy_regen") @DefaultValue("true") boolean lazyRegen) {
        prodAdapter.purgeCache(Arrays.asList(productId));
        JobDataMap map = new JobDataMap();
        map.put(RegenProductEntitlementCertsJob.PROD_ID, productId);
        map.put(RegenProductEntitlementCertsJob.LAZY_REGEN, lazyRegen);

        JobDetail detail = newJob(RegenProductEntitlementCertsJob.class)
            .withIdentity("regen_entitlement_cert_of_prod" + Util.generateUUID())
            .usingJobData(map)
            .build();

        return detail;
    }

    /**
     *  Migrate entitlements from one distributor consumer to another
     *
     *  Can specify full or partial quantity. No specified quantity
     *   will lead to full migration of the entitlement.
     *
     * @return a Response object
     * @httpcode 404
     * @httpcode 200
     */
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    @Path("{entitlement_id}/migrate")
    public Response migrateEntitlement(
        @PathParam("entitlement_id") @Verify(Entitlement.class) String id,
        @QueryParam("to_consumer") @Verify(Consumer.class) String uuid,
        @QueryParam("quantity") Integer quantity) {
        // confirm entitlement
        Entitlement entitlement = entitlementCurator.find(id);
        List<Entitlement> entitlements = new ArrayList();

        if (entitlement != null) {
            if (quantity == null) {
                quantity = entitlement.getQuantity();
            }
            if (quantity > 0 && quantity <= entitlement.getQuantity()) {
                Consumer sourceConsumer = entitlement.getConsumer();
                Consumer destinationConsumer = consumerCurator.verifyAndLookupConsumer(
                        uuid);
                if (!sourceConsumer.getType().isManifest()) {
                    throw new BadRequestException(i18n.tr(
                        "Entitlement migration is not permissible for units of type ''{0}''",
                        sourceConsumer.getType().getLabel()));
                }
                if (!destinationConsumer.getType().isManifest()) {
                    throw new BadRequestException(i18n.tr(
                        "Entitlement migration is not permissible for units of type ''{0}''",
                        destinationConsumer.getType().getLabel()));
                }
                if (!sourceConsumer.getOwner().getKey().equals(destinationConsumer.getOwner().getKey())) {
                    throw new BadRequestException(i18n.tr(
                        "Source and destination units must belong to the same organization"));
                }
                // test to ensure destination can use the pool
                ValidationResult result = enforcer.preEntitlement(destinationConsumer,
                        entitlement.getPool(), 0, CallerType.BIND);
                if (!result.isSuccessful()) {
                    throw new BadRequestException(i18n.tr(
                        "The entitlement cannot be utilized by the destination unit: ") +
                        messageTranslator.poolErrorToMessage(entitlement.getPool(),
                            result.getErrors().get(0)));
                }
                if (quantity.intValue() == entitlement.getQuantity()) {
                    unbind(id);
                }
                else {
                    entitler.adjustEntitlementQuantity(sourceConsumer, entitlement,
                            entitlement.getQuantity() - quantity);
                }
                Pool pool = entitlement.getPool();
                entitlements.addAll(entitler.bindByPool(pool.getId(), destinationConsumer,
                        quantity));

                // Trigger events:
                entitler.sendEvents(entitlements);

            }
            else {
                throw new BadRequestException(i18n.tr(
                    "The quantity specified must be greater than zero " +
                    "and less than or equal to the total for this entitlement"));
            }
        }
        else {
            throw new NotFoundException(
                i18n.tr("Entitlement with ID ''{0}'' could not be found.", id));
        }
        return Response.status(Response.Status.OK)
                .type(MediaType.APPLICATION_JSON).entity(entitlements).build();

    }

    /**
     *
     * CdnInfo represents a container for subscription entitlement and cdn
     */
    public static class CdnInfo implements Serializable {
        private Cdn cdn;
        private String subCert;

        public CdnInfo() {
        }

        public CdnInfo(Cdn cdn, String subEntitlement) {
            this.cdn = cdn;
            this.subCert = subEntitlement;
        }

        public Cdn getCdn() {
            return this.cdn;
        }

        public void setCdn(Cdn cdn) {
            this.cdn = cdn;
        }

        public String getSubCert() {
            return this.subCert;
        }

        public void setSubCert(String subCert) {
            this.subCert = subCert;
        }
    }

}
TOP

Related Classes of org.candlepin.resource.EntitlementResource

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.