EntitlementResource { @ApiOperation(notes = "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.", value = "migrateEntitlement") @ApiResponses({ @ApiResponse(code = 404, message = "") }) @PUT @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.WILDCARD) @Path("{entitlement_id}/migrate") @Transactional public Response migrateEntitlement( @PathParam("entitlement_id") @Verify(Entitlement.class) String id, @QueryParam("to_consumer") @Verify(Consumer.class) String uuid, @QueryParam("quantity") Integer quantity) { Entitlement entitlement = entitlementCurator.get(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); ConsumerType scType = this.consumerTypeCurator.getConsumerType(sourceConsumer); ConsumerType dcType = this.consumerTypeCurator.getConsumerType(destinationConsumer); if (!scType.isManifest()) { throw new BadRequestException(i18n.tr( "Entitlement migration is not permissible for units of type \"{0}\"", scType.getLabel())); } if (!dcType.isManifest()) { throw new BadRequestException(i18n.tr( "Entitlement migration is not permissible for units of type \"{0}\"", dcType.getLabel())); } if (!sourceConsumer.getOwnerId().equals(destinationConsumer.getOwnerId())) { throw new BadRequestException(i18n.tr( "Source and destination units must belong to the same organization")); } 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.bindByPoolQuantity(destinationConsumer, pool.getId(), quantity)); 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)); } List<EntitlementDTO> entitlementDTOs = new ArrayList<>(); for (Entitlement entitlementModel : entitlements) { entitlementDTOs.add(this.translator.translate(entitlementModel, EntitlementDTO.class)); } return Response.status(Response.Status.OK) .type(MediaType.APPLICATION_JSON).entity(entitlementDTOs).build(); } @Inject  EntitlementResource(EntitlementCurator entitlementCurator,
        ConsumerCurator consumerCurator,
        ConsumerTypeCurator consumerTypeCurator,
        PoolManager poolManager,
        I18n i18n,
        Entitler entitler,
        Enforcer enforcer,
        EntitlementRulesTranslator messageTranslator,
        JobManager jobManager,
        ModelTranslator translator); @ApiOperation(notes = "Checks Consumer for Product Entitlement", value = "hasEntitlement") @ApiResponses({ @ApiResponse(code = 404, message = "") }) @GET @Produces(MediaType.APPLICATION_JSON) @Path("consumer/{consumer_uuid}/product/{product_id}") EntitlementDTO hasEntitlement(@PathParam("consumer_uuid") String consumerUuid,
        @PathParam("product_id") String productId); @ApiOperation(notes = "Retrieves list of Entitlements", value = "listAllForConsumer") @ApiResponses({ @ApiResponse(code = 400, message = "") }) @GET @Produces(MediaType.APPLICATION_JSON) List<EntitlementDTO> listAllForConsumer(
        @QueryParam("consumer") String consumerUuid,
        @QueryParam("matches") String matches,
        @QueryParam("attribute") List<KeyValueParameter> attrFilters,
        @Context PageRequest pageRequest); @ApiOperation(notes = "Retrieves a single Entitlement", value = "getEntitlement") @ApiResponses({ @ApiResponse(code = 404, message = "") }) @GET @Produces(MediaType.APPLICATION_JSON) @Path("{entitlement_id}") EntitlementDTO getEntitlement(
        @PathParam("entitlement_id") @Verify(Entitlement.class) String entitlementId); @ApiOperation(notes = "Updates an Entitlement. This only works for the quantity.", value = "updateEntitlement") @ApiResponses({ @ApiResponse(code = 404, message = "") }) @PUT @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @Path("{entitlement_id}") void updateEntitlement(
        @PathParam("entitlement_id") @Verify(Entitlement.class) String id,
        @ApiParam(name = "update", required = true) EntitlementDTO update); @ApiOperation(notes = "Retrieves a Subscription Certificate. 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. will also" + " @Produces(MediaType.APPLICATION_JSON)", value = "getUpstreamCert") @ApiResponses({ @ApiResponse(code = 404, message = "") }) @GET @Produces(MediaType.TEXT_PLAIN) @Path("{dbid}/upstream_cert") String getUpstreamCert(
        @PathParam("dbid") String entitlementId); @ApiOperation(notes = "Deletes an Entitlement", value = "unbind") @ApiResponses({ @ApiResponse(code = 403, message = ""), @ApiResponse(code = 404, message = "") }) @DELETE @Produces(MediaType.WILDCARD) @Path("/{dbid}") void unbind(@PathParam("dbid") String dbid); @ApiOperation(notes = "Regenerates the Entitlement Certificates for a Product", value = "regenerateEntitlementCertificatesForProduct") @ApiResponses({ @ApiResponse(code = 202, message = "") }) @PUT @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.WILDCARD) @Path("product/{product_id}") AsyncJobStatusDTO regenerateEntitlementCertificatesForProduct(
        @PathParam("product_id") String productId,
        @QueryParam("lazy_regen") @DefaultValue("true") boolean lazyRegen); @ApiOperation(notes = "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.", value = "migrateEntitlement") @ApiResponses({ @ApiResponse(code = 404, message = "") }) @PUT @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.WILDCARD) @Path("{entitlement_id}/migrate") @Transactional Response migrateEntitlement(
        @PathParam("entitlement_id") @Verify(Entitlement.class) String id,
        @QueryParam("to_consumer") @Verify(Consumer.class) String uuid,
        @QueryParam("quantity") Integer quantity);  }
@Test public void migrateEntitlementQuantityFail() { ConsumerType ct = TestUtil.createConsumerType(); ct.setManifest(true); this.mockConsumerType(ct); Entitlement e = TestUtil.createEntitlement(); Consumer sourceConsumer = new Consumer("source-consumer", "bill", owner, ct) .setUuid(Util.generateUUID()); Consumer destConsumer = new Consumer("destination-consumer", "bill", owner, ct) .setUuid(Util.generateUUID()); e.setConsumer(sourceConsumer); e.setQuantity(25); when(entitlementCurator.get(eq(e.getId()))).thenReturn(e); when(consumerCurator.verifyAndLookupConsumer(eq(destConsumer.getUuid()))) .thenReturn(destConsumer); assertThrows(BadRequestException.class, () -> entResource.migrateEntitlement(e.getId(), destConsumer.getUuid(), 30) ); }
@Test public void migrateEntitlementSourceConsumerFail() { ConsumerType ct = TestUtil.createConsumerType(); ct.setManifest(true); this.mockConsumerType(ct); Entitlement e = TestUtil.createEntitlement(); Consumer destConsumer = new Consumer("destination-consumer", "bill", owner, ct) .setUuid(Util.generateUUID()); e.setConsumer(consumer); e.setQuantity(25); when(entitlementCurator.get(eq(e.getId()))).thenReturn(e); when(consumerCurator.verifyAndLookupConsumer(eq(destConsumer.getUuid()))).thenReturn(destConsumer); assertThrows(BadRequestException.class, () -> entResource.migrateEntitlement(e.getId(), destConsumer.getUuid(), 15) ); }
@Test public void migrateEntitlementDestinationConsumerFail() { ConsumerType ct = TestUtil.createConsumerType(); ct.setManifest(true); this.mockConsumerType(ct); Entitlement e = TestUtil.createEntitlement(); Consumer sourceConsumer = new Consumer("source-consumer", "bill", owner, ct) .setUuid(Util.generateUUID()); e.setConsumer(sourceConsumer); e.setQuantity(25); when(entitlementCurator.get(eq(e.getId()))).thenReturn(e); when(consumerCurator.verifyAndLookupConsumer(eq(consumer.getUuid()))).thenReturn(consumer); assertThrows(BadRequestException.class, () -> entResource.migrateEntitlement(e.getId(), consumer.getUuid(), 15) ); }
@Test public void migrateEntitlementSameOwnerFail() { ConsumerType ct = TestUtil.createConsumerType(); ct.setManifest(true); this.mockConsumerType(ct); Entitlement e = TestUtil.createEntitlement(); Owner owner2 = new Owner("admin2"); owner.setId(TestUtil.randomString()); owner2.setId(TestUtil.randomString()); Consumer sourceConsumer = new Consumer("source-consumer", "bill", owner, ct) .setUuid(Util.generateUUID()); Consumer destConsumer = new Consumer("destination-consumer", "bill", owner2, ct) .setUuid(Util.generateUUID()); e.setConsumer(sourceConsumer); e.setQuantity(25); when(entitlementCurator.get(eq(e.getId()))).thenReturn(e); when(consumerCurator.verifyAndLookupConsumer(eq(destConsumer.getUuid()))) .thenReturn(destConsumer); assertThrows(BadRequestException.class, () -> entResource.migrateEntitlement(e.getId(), destConsumer.getUuid(), 15) ); }