@Override public void uploadOverdueConfig(final String overdueXML, final CallContext callContext) throws OverdueApiException { try { final InternalTenantContext internalTenantContext = createInternalTenantContext(callContext); final String tenantKey = TenantKey.OVERDUE_CONFIG.toString(); if (!tenantApi.getTenantValuesForKey(tenantKey, callContext).isEmpty()) { tenantApi.deleteTenantKey(tenantKey, callContext); } tenantApi.addTenantKeyValue(tenantKey, overdueXML, callContext); overdueConfigCache.clearOverdueConfig(internalTenantContext); } catch (final TenantApiException e) { throw new OverdueApiException(e); } }
@Test(groups = "slow") public void testTenant() throws Exception { final TenantData tenantdata = new DefaultTenant(UUID.randomUUID(), clock.getUTCNow(), clock.getUTCNow(), "er44TT-yy4r", "TTR445ee2", "dskjhfs^^54R"); tenantUserApi.createTenant(tenantdata, callContext); final Tenant tenant = tenantUserApi.getTenantByApiKey(tenantdata.getApiKey()); Assert.assertEquals(tenant.getApiKey(), tenantdata.getApiKey()); Assert.assertEquals(tenant.getExternalKey(), tenantdata.getExternalKey()); // The second time, the value is already in the cache so the TenantCacheLoader is not invoked final Tenant tenant2 = tenantUserApi.getTenantByApiKey(tenantdata.getApiKey()); Assert.assertEquals(tenant2.getApiKey(), tenantdata.getApiKey()); Assert.assertEquals(tenant2.getExternalKey(), tenantdata.getExternalKey()); }
@Test(groups = "slow", description = "https://github.com/killbill/killbill/issues/297") public void testVerifyCacheOnAbsentValues() throws Exception { final String tenantKey = TenantKey.PLUGIN_CONFIG_.toString() + "MyPluginName"; // Warm the cache with the empty value List<String> value = tenantUserApi.getTenantValuesForKey(tenantKey, callContext); Assert.assertEquals(value.size(), 0); // Update the DAO directly (caching is done at the API layer) tenantDao.addTenantKeyValue(tenantKey, "TheValue-hidden!", true, internalCallContext); // Verify we still hit the cache value = tenantUserApi.getTenantValuesForKey(tenantKey, callContext); Assert.assertEquals(value.size(), 0); // Update the cache tenantUserApi.addTenantKeyValue(tenantKey, "TheValue", callContext); // Verify the cache now has the right value value = tenantUserApi.getTenantValuesForKey(tenantKey, callContext); Assert.assertEquals(value.size(), 1); Assert.assertEquals(value.get(0), "TheValue"); }
@TimedResource @GET @Path("/" + USER_KEY_VALUE + "/{keyName:" + ANYTHING_PATTERN + "}") @Produces(APPLICATION_JSON) @ApiOperation(value = "Retrieve a per tenant user key/value", response = TenantKeyValueJson.class) @ApiResponses(value = {@ApiResponse(code = 400, message = "Invalid tenantId supplied")}) public Response getUserKeyValue(@PathParam("keyName") final String key, @javax.ws.rs.core.Context final HttpServletRequest request) throws TenantApiException { final TenantContext tenantContext = context.createTenantContextNoAccountId(request); final List<String> values = tenantApi.getTenantValuesForKey(key, tenantContext); final TenantKeyValueJson result = new TenantKeyValueJson(key, values); return Response.status(Status.OK).entity(result).build(); }
tenantApi.addTenantKeyValue(TenantKey.CATALOG.toString(), catalogXML, callContext); catalogCache.clearCatalog(internalTenantContext); } catch (final TenantApiException e) {
@Test(groups = "slow") public void testTenantKVChange() throws Exception { final TenantData tenantData = new DefaultTenant(null, clock.getUTCNow(), clock.getUTCNow(), "MY_TENANT", "key", "s3Cr3T"); final CallContext contextWithNoTenant = new DefaultCallContext(null, null, "loulou", CallOrigin.EXTERNAL, UserType.ADMIN, "no reason", "hum", UUID.randomUUID(), clock); final Tenant tenant = tenantUserApi.createTenant(tenantData, contextWithNoTenant); final CallContext contextWithTenant = new DefaultCallContext(null, tenant.getId(), "loulou", CallOrigin.EXTERNAL, UserType.ADMIN, "no reason", "hum", UUID.randomUUID(), clock); final String tenantKey = TenantKey.PLUGIN_CONFIG_ + "FOO"; tenantUserApi.addTenantKeyValue(tenantKey, "FOO", contextWithTenant); await().atMost(10, SECONDS).until(new Callable<Boolean>() { @Override public Boolean call() throws Exception { // expecting TENANT_CONFIG_CHANGE return externalBusCount.get() == 1; } }); }
@Override public void deleteCatalog(final CallContext callContext) throws CatalogApiException { final InternalTenantContext internalTenantContext = internalCallContextFactory.createInternalTenantContextWithoutAccountRecordId(callContext); try { tenantApi.deleteTenantKey(TenantKey.CATALOG.toString(), callContext); catalogCache.clearCatalog(internalTenantContext); createDefaultEmptyCatalog(callContext.getCreatedDate(), callContext); } catch (final TenantApiException e) { throw new CatalogApiException(e); } }
@Test(groups = "slow", description = "Test Tenant creation with External Key over limit") public void testCreateTenantWithExternalKeyOverLimit() throws Exception { final TenantData tenantdata = new DefaultTenant(UUID.randomUUID(), clock.getUTCNow(), clock.getUTCNow(), "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis,.", "TTR445ee2", "dskjhfs^^54R"); try { tenantUserApi.createTenant(tenantdata, callContext); Assert.fail(); } catch (final TenantApiException e) { Assert.assertEquals(e.getCode(), ErrorCode.EXTERNAL_KEY_LIMIT_EXCEEDED.getCode()); } } }
@TimedResource @GET @Produces(APPLICATION_JSON) @ApiOperation(value = "Retrieve a tenant by its API key", response = TenantJson.class) @ApiResponses(value = {@ApiResponse(code = 404, message = "Tenant not found")}) public Response getTenantByApiKey(@QueryParam(QUERY_API_KEY) final String externalKey) throws TenantApiException { final Tenant tenant = tenantApi.getTenantByApiKey(externalKey); return Response.status(Status.OK).entity(new TenantJson(tenant)).build(); }
@TimedResource @GET @Path("/{tenantId:" + UUID_PATTERN + "}") @Produces(APPLICATION_JSON) @ApiOperation(value = "Retrieve a tenant by id", response = TenantJson.class) @ApiResponses(value = {@ApiResponse(code = 400, message = "Invalid tenantId supplied"), @ApiResponse(code = 404, message = "Tenant not found")}) public Response getTenant(@PathParam("tenantId") final UUID tenantId) throws TenantApiException { final Tenant tenant = tenantApi.getTenantById(tenantId); return Response.status(Status.OK).entity(new TenantJson(tenant)).build(); }
@Test(groups = "slow", description = "https://github.com/killbill/killbill/issues/297") public void testVerifyCacheOnAbsentValues() throws Exception { final String tenantKey = TenantKey.PLUGIN_CONFIG_.toString() + "MyPluginName"; // Warm the cache with the empty value List<String> value = tenantUserApi.getTenantValuesForKey(tenantKey, callContext); Assert.assertEquals(value.size(), 0); // Update the DAO directly (caching is done at the API layer) tenantDao.addTenantKeyValue(tenantKey, "TheValue-hidden!", true, internalCallContext); // Verify we still hit the cache value = tenantUserApi.getTenantValuesForKey(tenantKey, callContext); Assert.assertEquals(value.size(), 0); // Update the cache tenantUserApi.addTenantKeyValue(tenantKey, "TheValue", callContext); // Verify the cache now has the right value value = tenantUserApi.getTenantValuesForKey(tenantKey, callContext); Assert.assertEquals(value.size(), 1); Assert.assertEquals(value.get(0), "TheValue"); }
private Response getTenantKey(final TenantKey key, @Nullable final String keyPostfix, final HttpServletRequest request) throws TenantApiException { final TenantContext tenantContext = context.createTenantContextNoAccountId(request); final String tenantKey = keyPostfix != null ? key.toString() + keyPostfix : key.toString(); final List<String> values = tenantApi.getTenantValuesForKey(tenantKey, tenantContext); final TenantKeyValueJson result = new TenantKeyValueJson(tenantKey, values); return Response.status(Status.OK).entity(result).build(); }
@TimedResource @POST @Path("/" + USER_KEY_VALUE + "/{keyName:" + ANYTHING_PATTERN + "}") @Consumes(TEXT_PLAIN) @Produces(APPLICATION_JSON) @ApiOperation(value = "Add a per tenant user key/value", response = TenantKeyValueJson.class) @ApiResponses(value = {@ApiResponse(code = 201, message = "Per tenant config uploaded successfully"), @ApiResponse(code = 400, message = "Invalid tenantId supplied")}) public Response insertUserKeyValue(@PathParam("keyName") final String key, final String value, @HeaderParam(HDR_CREATED_BY) final String createdBy, @HeaderParam(HDR_REASON) final String reason, @HeaderParam(HDR_COMMENT) final String comment, @javax.ws.rs.core.Context final HttpServletRequest request, @javax.ws.rs.core.Context final UriInfo uriInfo) throws TenantApiException { final CallContext callContext = context.createCallContextNoAccountId(createdBy, reason, comment, request); tenantApi.addTenantKeyValue(key, value, callContext); return uriBuilder.buildResponse(uriInfo, TenantResource.class, "getUserKeyValue", key, request); }
private Response deleteTenantKey(final TenantKey key, @Nullable final String keyPostfix, final String createdBy, final String reason, final String comment, final HttpServletRequest request) throws TenantApiException { final CallContext callContext = context.createCallContextNoAccountId(createdBy, reason, comment, request); final String tenantKey = keyPostfix != null ? key.toString() + keyPostfix : key.toString(); tenantApi.deleteTenantKey(tenantKey, callContext); return Response.status(Status.NO_CONTENT).build(); }
@TimedResource @POST @Consumes(APPLICATION_JSON) @Produces(APPLICATION_JSON) @ApiOperation(value = "Create a tenant", response = TenantJson.class) @ApiResponses(value = {@ApiResponse(code = 201, message = "Tenant created successfully"), @ApiResponse(code = 409, message = "Tenant already exists")}) public Response createTenant(final TenantJson json, @QueryParam(QUERY_TENANT_USE_GLOBAL_DEFAULT) @DefaultValue("false") final Boolean useGlobalDefault, @HeaderParam(HDR_CREATED_BY) final String createdBy, @HeaderParam(HDR_REASON) final String reason, @HeaderParam(HDR_COMMENT) final String comment, @javax.ws.rs.core.Context final HttpServletRequest request, @javax.ws.rs.core.Context final UriInfo uriInfo) throws TenantApiException, CatalogApiException { verifyNonNullOrEmpty(json, "TenantJson body should be specified"); verifyNonNullOrEmpty(json.getApiKey(), "TenantJson apiKey needs to be set", json.getApiSecret(), "TenantJson apiSecret needs to be set"); final TenantData data = json.toTenantData(); final Tenant tenant = tenantApi.createTenant(data, context.createCallContextNoAccountId(createdBy, reason, comment, request)); if (!useGlobalDefault) { final CallContext callContext = new DefaultCallContext(null, tenant.getId(), createdBy, CallOrigin.EXTERNAL, UserType.CUSTOMER, Context.getOrCreateUserToken(), clock); catalogUserApi.createDefaultEmptyCatalog(null, callContext); } return uriBuilder.buildResponse(uriInfo, TenantResource.class, "getTenant", tenant.getId(), request); }
final Tenant currentTenant = tenantApi.getTenantById(tenantContext.getTenantId());
@Test(groups = "slow") public void testUserKey() throws Exception { tenantUserApi.addTenantKeyValue("THE_KEY", "TheValue", callContext); List<String> value = tenantUserApi.getTenantValuesForKey("THE_KEY", callContext); Assert.assertEquals(value.size(), 1); Assert.assertEquals(value.get(0), "TheValue"); tenantUserApi.addTenantKeyValue("THE_KEY", "TheSecondValue", callContext); value = tenantUserApi.getTenantValuesForKey("THE_KEY", callContext); Assert.assertEquals(value.size(), 2); value = tenantUserApi.getTenantValuesForKey("THE_KEY", callContext); Assert.assertEquals(value.size(), 2); tenantUserApi.deleteTenantKey("THE_KEY", callContext); value = tenantUserApi.getTenantValuesForKey("THE_KEY", callContext); Assert.assertEquals(value.size(), 0); }
private Response getTemplateResource(@Nullable final String localeStr, final TenantKey tenantKey, final HttpServletRequest request) throws InvoiceApiException, TenantApiException { final TenantContext tenantContext = context.createTenantContextNoAccountId(request); final String tenantKeyStr = localeStr != null ? LocaleUtils.localeString(LocaleUtils.toLocale(localeStr), tenantKey.toString()) : tenantKey.toString(); final List<String> result = tenantApi.getTenantValuesForKey(tenantKeyStr, tenantContext); return result.isEmpty() ? Response.status(Status.NOT_FOUND).build() : Response.status(Status.OK).entity(result.get(0)).build(); }
private Response insertTenantKey(final TenantKey key, @Nullable final String keyPostfix, final String value, final UriInfo uriInfo, final String getMethodStr, final String createdBy, final String reason, final String comment, final HttpServletRequest request) throws TenantApiException { final CallContext callContext = context.createCallContextNoAccountId(createdBy, reason, comment, request); final String tenantKey = keyPostfix != null ? key.toString() + keyPostfix : key.toString(); tenantApi.addTenantKeyValue(tenantKey, value, callContext); return uriBuilder.buildResponse(uriInfo, TenantResource.class, getMethodStr, keyPostfix, request); }
@TimedResource @DELETE @Path("/" + USER_KEY_VALUE + "/{keyName:" + ANYTHING_PATTERN + "}") @ApiOperation(value = "Delete a per tenant user key/value") @ApiResponses(value = {@ApiResponse(code = 204, message = "Successful operation"), @ApiResponse(code = 400, message = "Invalid tenantId supplied")}) public Response deleteUserKeyValue(@PathParam("keyName") final String key, @HeaderParam(HDR_CREATED_BY) final String createdBy, @HeaderParam(HDR_REASON) final String reason, @HeaderParam(HDR_COMMENT) final String comment, @javax.ws.rs.core.Context final HttpServletRequest request) throws TenantApiException { final CallContext callContext = context.createCallContextNoAccountId(createdBy, reason, comment, request); tenantApi.deleteTenantKey(key, callContext); return Response.status(Status.NO_CONTENT).build(); }