TenantResult<JsonObject> removeTenant(final String tenantId) { Objects.requireNonNull(tenantId); if (getConfig().isModificationEnabled()) { if (tenants.remove(tenantId) != null) { dirty = true; return TenantResult.from(HttpURLConnection.HTTP_NO_CONTENT); } else { return TenantResult.from(HttpURLConnection.HTTP_NOT_FOUND); } } else { return TenantResult.from(HttpURLConnection.HTTP_FORBIDDEN); } }
/** * Creates a new result for a status code. * * @param status The status code indicating the outcome of the request. * @param <T> The type of the payload conveyed in the result. * @return The result. */ public static <T> TenantResult<T> from(final int status) { return new TenantResult<>(status, null, null); }
private Future<EventBusMessage> processGetByIdRequest(final EventBusMessage request, final String tenantId) { final Future<TenantResult<JsonObject>> getResult = Future.future(); get(tenantId, getResult.completer()); return getResult.map(tr -> { return request.getResponse(tr.getStatus()) .setJsonPayload(tr.getPayload()) .setTenant(tenantId) .setCacheDirective(tr.getCacheDirective()); }); }
private <T> Future<TenantObject> get( final TriTuple<TenantAction, T, Object> key, final Supplier<JsonObject> payloadSupplier, final Span currentSpan) { TracingHelper.TAG_CACHE_HIT.set(currentSpan, true); return getResponseFromCache(key).recover(cacheMiss -> { TracingHelper.TAG_CACHE_HIT.set(currentSpan, false); final Future<TenantResult<TenantObject>> tenantResult = Future.future(); createAndSendRequest( TenantConstants.TenantAction.get.toString(), customizeRequestApplicationProperties(), payloadSupplier.get().toBuffer(), RegistrationConstants.CONTENT_TYPE_APPLICATION_JSON, tenantResult.completer(), key, currentSpan); return tenantResult; }).map(tenantResult -> { switch(tenantResult.getStatus()) { case HttpURLConnection.HTTP_OK: return tenantResult.getPayload(); case HttpURLConnection.HTTP_NOT_FOUND: throw new ClientErrorException(tenantResult.getStatus(), "no such tenant"); default: throw StatusCodeMapper.from(tenantResult); } }); }
private Future<EventBusMessage> processGetByCaRequest(final EventBusMessage request, final String subjectDn) { try { final X500Principal dn = new X500Principal(subjectDn); log.debug("retrieving tenant [subject DN: {}]", subjectDn); final Future<TenantResult<JsonObject>> getResult = Future.future(); get(dn, getResult.completer()); return getResult.map(tr -> { final EventBusMessage response = request.getResponse(tr.getStatus()) .setJsonPayload(tr.getPayload()) .setCacheDirective(tr.getCacheDirective()); if (tr.isOk() && tr.getPayload() != null) { response.setTenant(getTypesafeValueForField(String.class, tr.getPayload(), TenantConstants.FIELD_PAYLOAD_TENANT_ID)); } return response; }); } catch (final IllegalArgumentException e) { // the given subject DN is invalid log.debug("cannot parse subject DN [{}] provided by client", subjectDn); return Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST)); } }
protected static void assertTenantExists(final TenantService svc, final String tenant, final TestContext ctx) { svc.get(tenant, null, ctx.asyncAssertSuccess(t -> { assertThat(t.getStatus(), is(HttpURLConnection.HTTP_OK)); })); }
private Future<EventBusMessage> processGetByIdRequest(final EventBusMessage request, final String tenantId, final Span span) { final Future<TenantResult<JsonObject>> getResult = Future.future(); get(tenantId, span, getResult.completer()); return getResult.map(tr -> { return request.getResponse(tr.getStatus()) .setJsonPayload(tr.getPayload()) .setTenant(tenantId) .setCacheDirective(tr.getCacheDirective()); }); }
/** * Verifies that the service returns an existing tenant. * * @param ctx The vert.x test context. */ @Test public void testGetTenantSucceedsForExistingTenants(final TestContext ctx) { addTenant("tenant").map(ok -> { getCompleteTenantService().get("tenant", null, ctx.asyncAssertSuccess(s -> { assertThat(s.getStatus(), is(HttpURLConnection.HTTP_OK)); assertThat(s.getPayload().getString(TenantConstants.FIELD_PAYLOAD_TENANT_ID), is("tenant")); assertThat(s.getPayload().getBoolean(TenantConstants.FIELD_ENABLED), is(Boolean.TRUE)); })); return null; }); }
private Future<EventBusMessage> processGetByCaRequest(final EventBusMessage request, final String subjectDn, final Span span) { try { final X500Principal dn = new X500Principal(subjectDn); log.debug("retrieving tenant [subject DN: {}]", subjectDn); final Future<TenantResult<JsonObject>> getResult = Future.future(); get(dn, span, getResult.completer()); return getResult.map(tr -> { final EventBusMessage response = request.getResponse(tr.getStatus()) .setJsonPayload(tr.getPayload()) .setCacheDirective(tr.getCacheDirective()); if (tr.isOk() && tr.getPayload() != null) { final String tenantId = getTypesafeValueForField(String.class, tr.getPayload(), TenantConstants.FIELD_PAYLOAD_TENANT_ID); span.setTag(MessageHelper.APP_PROPERTY_TENANT_ID, tenantId); response.setTenant(tenantId); } return response; }); } catch (final IllegalArgumentException e) { TracingHelper.logError(span, "illegal subject DN provided by client: " + subjectDn); // the given subject DN is invalid log.debug("cannot parse subject DN [{}] provided by client", subjectDn); return Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST)); } }
protected static void assertTenantDoesNotExist(final TenantService svc, final String tenant, final TestContext ctx) { svc.get(tenant, null, ctx.asyncAssertSuccess(t -> { assertThat(t.getStatus(), is(HttpURLConnection.HTTP_NOT_FOUND)); })); }
private Future<EventBusMessage> processRemoveRequest(final EventBusMessage request) { final String tenantId = request.getTenant(); if (tenantId == null) { log.debug("request does not contain mandatory property [{}]", MessageHelper.APP_PROPERTY_TENANT_ID); return Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST)); } else { log.debug("deleting tenant [{}]", tenantId); final Future<TenantResult<JsonObject>> removeResult = Future.future(); remove(tenantId, removeResult.completer()); return removeResult.map(tr -> { return request.getResponse(tr.getStatus()) .setJsonPayload(tr.getPayload()) .setCacheDirective(tr.getCacheDirective()); }); } }
TenantResult<JsonObject> removeTenant(final String tenantId) { Objects.requireNonNull(tenantId); if (getConfig().isModificationEnabled()) { if (tenants.remove(tenantId) != null) { dirty = true; return TenantResult.from(HttpURLConnection.HTTP_NO_CONTENT); } else { return TenantResult.from(HttpURLConnection.HTTP_NOT_FOUND); } } else { return TenantResult.from(HttpURLConnection.HTTP_FORBIDDEN); } }
/** * Verifies that the service finds an existing tenant by the subject DN of * its configured trusted certificate authority. * * @param ctx The vert.x test context. */ @Test public void testGetForCertificateAuthoritySucceeds(final TestContext ctx) { final X500Principal subjectDn = new X500Principal("O=Eclipse, OU=Hono, CN=ca"); final JsonObject trustedCa = new JsonObject() .put(TenantConstants.FIELD_PAYLOAD_SUBJECT_DN, subjectDn.getName(X500Principal.RFC2253)) .put(TenantConstants.FIELD_PAYLOAD_PUBLIC_KEY, "NOTAPUBLICKEY"); final JsonObject tenant = buildTenantPayload("tenant") .put(TenantConstants.FIELD_PAYLOAD_TRUSTED_CA, trustedCa); addTenant("tenant", tenant).map(ok -> { getCompleteTenantService().get(subjectDn, null, ctx.asyncAssertSuccess(s -> { assertThat(s.getStatus(), is(HttpURLConnection.HTTP_OK)); final TenantObject obj = s.getPayload().mapTo(TenantObject.class); assertThat(obj.getTenantId(), is("tenant")); final JsonObject ca = obj.getProperty(TenantConstants.FIELD_PAYLOAD_TRUSTED_CA); assertThat(ca, is(trustedCa)); })); return null; }); }
/** * Verifies that the service does not find any tenant for an unknown subject DN. * * @param ctx The vert.x test context. */ @Test public void testGetForCertificateAuthorityFailsForUnknownSubjectDn(final TestContext ctx) { final X500Principal unknownSubjectDn = new X500Principal("O=Eclipse, OU=NotHono, CN=ca"); final X500Principal subjectDn = new X500Principal("O=Eclipse, OU=Hono, CN=ca"); final String publicKey = "NOTAPUBLICKEY"; final JsonObject trustedCa = new JsonObject() .put(TenantConstants.FIELD_PAYLOAD_SUBJECT_DN, subjectDn.getName(X500Principal.RFC2253)) .put(TenantConstants.FIELD_PAYLOAD_PUBLIC_KEY, publicKey); final JsonObject tenant = buildTenantPayload("tenant") .put(TenantConstants.FIELD_PAYLOAD_TRUSTED_CA, trustedCa); addTenant("tenant", tenant).map(ok -> { getCompleteTenantService().get(unknownSubjectDn, null, ctx.asyncAssertSuccess(s -> { assertThat(s.getStatus(), is(HttpURLConnection.HTTP_NOT_FOUND)); })); return null; }); }
/** * Creates a new result for a status code and payload. * * @param status The status code indicating the outcome of the request. * @param payload The payload to convey to the sender of the request. * @param <T> The type of the payload conveyed in the result. * @return The result. */ public static <T> TenantResult<T> from(final int status, final T payload) { return new TenantResult<>(status, payload, null); }
private Future<EventBusMessage> processRemoveRequest(final EventBusMessage request) { final String tenantId = request.getTenant(); if (tenantId == null) { log.debug("request does not contain mandatory property [{}]", MessageHelper.APP_PROPERTY_TENANT_ID); return Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST)); } else { log.debug("deleting tenant [{}]", tenantId); final Future<TenantResult<JsonObject>> removeResult = Future.future(); remove(tenantId, removeResult.completer()); return removeResult.map(tr -> { return request.getResponse(tr.getStatus()) .setJsonPayload(tr.getPayload()) .setCacheDirective(tr.getCacheDirective()); }); } }
private TenantResult<JsonObject> getForCertificateAuthority(final X500Principal subjectDn) { if (subjectDn == null) { return TenantResult.from(HttpURLConnection.HTTP_BAD_REQUEST); } else { final TenantObject tenant = getByCa(subjectDn); if (tenant == null) { return TenantResult.from(HttpURLConnection.HTTP_NOT_FOUND); } else { return TenantResult.from(HttpURLConnection.HTTP_OK, JsonObject.mapFrom(tenant), CacheDirective.maxAgeDirective(MAX_AGE_GET_TENANT)); } } }
/** * Verifies that the service updates tenants for a given tenantId. * * @param ctx The vert.x test context. */ @Test public void testUpdateTenantsSucceeds(final TestContext ctx) { final JsonObject updatedPayload = buildTenantPayload("tenant"); updatedPayload.put("custom-prop", "something"); addTenant("tenant").compose(ok -> { final Future<TenantResult<JsonObject>> updateResult = Future.future(); getCompleteTenantService().update("tenant", updatedPayload.copy(), updateResult.completer()); return updateResult; }).compose(updateResult -> { ctx.assertEquals(HttpURLConnection.HTTP_NO_CONTENT, updateResult.getStatus()); final Future<TenantResult<JsonObject>> getResult = Future.future(); getCompleteTenantService().get("tenant", null, getResult.completer()); return getResult; }).setHandler(ctx.asyncAssertSuccess(getResult -> { assertThat(getResult.getStatus(), is(HttpURLConnection.HTTP_OK)); assertThat(getResult.getPayload().getString("custom-prop"), is("something")); })); }
/** * Verifies that the service returns 404 if a client wants to retrieve a non-existing tenant. * * @param ctx The vert.x test context. */ @Test public void testGetTenantFailsForNonExistingTenant(final TestContext ctx) { getCompleteTenantService().get("notExistingTenant" , null, ctx.asyncAssertSuccess(s -> { assertThat(s.getStatus(), is(HttpURLConnection.HTTP_NOT_FOUND)); })); }
/** * Creates a new result for a status code. * * @param status The status code indicating the outcome of the request. * @param <T> The type of the payload conveyed in the result. * @return The result. */ public static <T> TenantResult<T> from(final int status) { return new TenantResult<>(status, null, null); }