use of org.eclipse.hono.util.TenantObject in project hono by eclipse.
the class FileBasedTenantService method add.
/**
* Adds a tenant.
*
* @param tenantId The identifier of the tenant.
* @param tenantSpec The information to register for the tenant.
* @return The outcome of the operation indicating success or failure.
* @throws NullPointerException if any of the parameters are {@code null}.
*/
public TenantResult<JsonObject> add(final String tenantId, final JsonObject tenantSpec) {
Objects.requireNonNull(tenantId);
Objects.requireNonNull(tenantSpec);
if (getConfig().isModificationEnabled()) {
if (tenants.containsKey(tenantId)) {
return TenantResult.from(HttpURLConnection.HTTP_CONFLICT);
} else {
try {
final TenantObject tenant = tenantSpec.mapTo(TenantObject.class);
tenant.setTenantId(tenantId);
tenants.put(tenantId, tenant);
dirty = true;
return TenantResult.from(HttpURLConnection.HTTP_CREATED);
} catch (IllegalArgumentException e) {
return TenantResult.from(HttpURLConnection.HTTP_BAD_REQUEST);
}
}
} else {
return TenantResult.from(HttpURLConnection.HTTP_FORBIDDEN);
}
}
use of org.eclipse.hono.util.TenantObject in project hono by eclipse.
the class AbstractVertxBasedMqttProtocolAdapter method uploadMessage.
private Future<Void> uploadMessage(final MqttContext ctx, final String tenant, final String deviceId, final Buffer payload, final Future<MessageSender> senderTracker, final String endpointName) {
if (payload.length() == 0) {
return Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST, "payload must not be empty"));
} else {
final Future<JsonObject> tokenTracker = getRegistrationAssertion(tenant, deviceId, ctx.authenticatedDevice());
final Future<TenantObject> tenantConfigTracker = getTenantConfiguration(tenant);
return CompositeFuture.all(tokenTracker, tenantConfigTracker, senderTracker).compose(ok -> {
if (tenantConfigTracker.result().isAdapterEnabled(getTypeName())) {
final Message downstreamMessage = newMessage(String.format("%s/%s", endpointName, tenant), deviceId, ctx.message().topicName(), ctx.contentType(), payload, tokenTracker.result());
customizeDownstreamMessage(downstreamMessage, ctx);
return senderTracker.result().send(downstreamMessage);
} else {
// this adapter is not enabled for the tenant
return Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_FORBIDDEN));
}
}).compose(delivery -> {
LOG.trace("successfully processed message [topic: {}, QoS: {}] for device [tenantId: {}, deviceId: {}]", ctx.message().topicName(), ctx.message().qosLevel(), tenant, deviceId);
metrics.incrementProcessedMqttMessages(endpointName, tenant);
onMessageSent(ctx);
// check that the remote MQTT client is still connected before sending PUBACK
if (ctx.deviceEndpoint().isConnected() && ctx.message().qosLevel() == MqttQoS.AT_LEAST_ONCE) {
ctx.deviceEndpoint().publishAcknowledge(ctx.message().messageId());
}
return Future.<Void>succeededFuture();
}).recover(t -> {
if (ClientErrorException.class.isInstance(t)) {
ClientErrorException e = (ClientErrorException) t;
LOG.debug("cannot process message for device [tenantId: {}, deviceId: {}, endpoint: {}]: {} - {}", tenant, deviceId, endpointName, e.getErrorCode(), e.getMessage());
} else {
LOG.debug("cannot process message for device [tenantId: {}, deviceId: {}, endpoint: {}]", tenant, deviceId, endpointName, t);
metrics.incrementUndeliverableMqttMessages(endpointName, tenant);
onMessageUndeliverable(ctx);
}
return Future.failedFuture(t);
});
}
}
use of org.eclipse.hono.util.TenantObject in project hono by eclipse.
the class AbstractVertxBasedMqttProtocolAdapterTest method testEndpointHandlerRejectsDeviceOfDisabledTenant.
/**
* Verifies that an adapter rejects a connection attempt from a device that
* belongs to a tenant for which the adapter is disabled.
*/
@Test
public void testEndpointHandlerRejectsDeviceOfDisabledTenant() {
// GIVEN an adapter
final MqttServer server = getMqttServer(false);
// which is disabled for tenant "my-tenant"
final TenantObject myTenantConfig = TenantObject.from("my-tenant", true);
myTenantConfig.addAdapterConfiguration(new JsonObject().put(TenantConstants.FIELD_ADAPTERS_TYPE, ADAPTER_TYPE).put(TenantConstants.FIELD_ENABLED, false));
when(tenantClient.get("my-tenant")).thenReturn(Future.succeededFuture(myTenantConfig));
final AbstractVertxBasedMqttProtocolAdapter<ProtocolAdapterProperties> adapter = getAdapter(server);
forceClientMocksToConnected();
// WHEN a device of "my-tenant" tries to connect
final MqttAuth deviceCredentials = new MqttAuth("device@my-tenant", "irrelevant");
final MqttEndpoint endpoint = mock(MqttEndpoint.class);
when(endpoint.auth()).thenReturn(deviceCredentials);
adapter.handleEndpointConnection(endpoint);
// THEN the connection is not established
verify(endpoint).reject(MqttConnectReturnCode.CONNECTION_REFUSED_NOT_AUTHORIZED);
}
use of org.eclipse.hono.util.TenantObject in project hono by eclipse.
the class AbstractVertxBasedMqttProtocolAdapterTest method testUploadTelemetryMessageFailsForDisabledTenant.
/**
* Verifies that the adapter does not forward a message published by a device
* if the device belongs to a tenant for which the adapter has been disabled.
*
* @param ctx The vert.x test context.
*/
@Test
public void testUploadTelemetryMessageFailsForDisabledTenant(final TestContext ctx) {
// GIVEN an adapter
final MqttServer server = getMqttServer(false);
// which is disabled for tenant "my-tenant"
final TenantObject myTenantConfig = TenantObject.from("my-tenant", true);
myTenantConfig.addAdapterConfiguration(new JsonObject().put(TenantConstants.FIELD_ADAPTERS_TYPE, ADAPTER_TYPE).put(TenantConstants.FIELD_ENABLED, false));
when(tenantClient.get("my-tenant")).thenReturn(Future.succeededFuture(myTenantConfig));
final AbstractVertxBasedMqttProtocolAdapter<ProtocolAdapterProperties> adapter = getAdapter(server);
forceClientMocksToConnected();
final MessageSender sender = mock(MessageSender.class);
when(messagingClient.getOrCreateTelemetrySender(anyString())).thenReturn(Future.succeededFuture(sender));
// WHEN a device of "my-tenant" publishes a telemetry message
adapter.uploadTelemetryMessage(new MqttContext(mock(MqttPublishMessage.class), mock(MqttEndpoint.class)), "my-tenant", "the-device", Buffer.buffer("test")).setHandler(ctx.asyncAssertFailure(t -> {
// THEN the message has not been sent downstream
verify(sender, never()).send(any(Message.class));
// because the tenant is not enabled
ctx.assertEquals(HttpURLConnection.HTTP_FORBIDDEN, ((ClientErrorException) t).getErrorCode());
}));
}
use of org.eclipse.hono.util.TenantObject in project hono by eclipse.
the class AbstractVertxBasedHttpProtocolAdapterTest method testUploadTelemetryFailsForDisabledTenant.
/**
* Verifies that the adapter fails the upload of an event with a 403
* result if the device belongs to a tenant for which the adapter is
* disabled.
*/
@Test
public void testUploadTelemetryFailsForDisabledTenant() {
// GIVEN an adapter
final HttpServer server = getHttpServer(false);
final MessageSender sender = mock(MessageSender.class);
when(messagingClient.getOrCreateTelemetrySender(anyString())).thenReturn(Future.succeededFuture(sender));
// which is disabled for tenant "my-tenant"
final TenantObject myTenantConfig = TenantObject.from("my-tenant", true);
myTenantConfig.addAdapterConfiguration(new JsonObject().put(TenantConstants.FIELD_ADAPTERS_TYPE, ADAPTER_TYPE).put(TenantConstants.FIELD_ENABLED, false));
when(tenantClient.get("my-tenant")).thenReturn(Future.succeededFuture(myTenantConfig));
final AbstractVertxBasedHttpProtocolAdapter<HttpProtocolAdapterProperties> adapter = getAdapter(server, null);
// WHEN a device that belongs to "my-tenant" publishes a telemetry message
final Buffer payload = Buffer.buffer("some payload");
final RoutingContext ctx = newRoutingContext(payload);
adapter.uploadTelemetryMessage(ctx, "my-tenant", "the-device", payload, "application/text");
// THEN the device gets a 403
verify(ctx).fail(HttpURLConnection.HTTP_FORBIDDEN);
// and the message has not been forwarded downstream
verify(sender, never()).send(any(Message.class));
}
Aggregations