/** * Check, if reported error cause indicates a temporary error. * * @param cause reported error cause * @return {@code true}, if error is temporary and the client may retry its action, {@code false}, otherwise, when * the client should not repeat this action. */ public static boolean isTemporaryError(final Throwable cause) { if (ServiceInvocationException.class.isInstance(cause)) { return ((ServiceInvocationException) cause).getErrorCode() == HttpURLConnection.HTTP_UNAVAILABLE; } return false; }
/** * Extract the HTTP status code from an exception. * * @param t The exception to extract the code from. * @return The HTTP status code, or 500 if the exception is not of type {@link ServiceInvocationException}. */ public static int extractStatusCode(final Throwable t) { return Optional.of(t).map(cause -> { if (cause instanceof ServiceInvocationException) { return ((ServiceInvocationException) cause).getErrorCode(); } else { return null; } }).orElse(HttpURLConnection.HTTP_INTERNAL_ERROR); } }
private static MqttConnectReturnCode getConnectReturnCode(final Throwable e) { if (e instanceof MqttConnectionException) { return ((MqttConnectionException) e).code(); } else if (e instanceof ServiceInvocationException) { switch (((ServiceInvocationException) e).getErrorCode()) { case HttpURLConnection.HTTP_UNAUTHORIZED: case HttpURLConnection.HTTP_NOT_FOUND: return MqttConnectReturnCode.CONNECTION_REFUSED_BAD_USER_NAME_OR_PASSWORD; case HttpURLConnection.HTTP_UNAVAILABLE: return MqttConnectReturnCode.CONNECTION_REFUSED_SERVER_UNAVAILABLE; default: return MqttConnectReturnCode.CONNECTION_REFUSED_NOT_AUTHORIZED; } } else { return MqttConnectReturnCode.CONNECTION_REFUSED_NOT_AUTHORIZED; } } }
private static MqttConnectReturnCode getConnectReturnCode(final Throwable e) { if (e instanceof MqttConnectionException) { return ((MqttConnectionException) e).code(); } else if (e instanceof ServiceInvocationException) { switch (((ServiceInvocationException) e).getErrorCode()) { case HttpURLConnection.HTTP_UNAUTHORIZED: case HttpURLConnection.HTTP_NOT_FOUND: return MqttConnectReturnCode.CONNECTION_REFUSED_BAD_USER_NAME_OR_PASSWORD; case HttpURLConnection.HTTP_UNAVAILABLE: return MqttConnectReturnCode.CONNECTION_REFUSED_SERVER_UNAVAILABLE; default: return MqttConnectReturnCode.CONNECTION_REFUSED_NOT_AUTHORIZED; } } else { return MqttConnectReturnCode.CONNECTION_REFUSED_NOT_AUTHORIZED; } } }
/** * Marks an <em>OpenTracing</em> span as erroneous and logs an exception. * <p> * This method does <em>not</em> finish the span. * * @param span The span to mark. * @param error The exception that has occurred. If the exception is a * {@link ServiceInvocationException} then a {@link Tags#HTTP_STATUS} * tag is added containing the exception's error code property value. * @throws NullPointerException if error is {@code null}. */ protected final void logError(final Span span, final Throwable error) { if (span != null) { if (ServiceInvocationException.class.isInstance(error)) { final ServiceInvocationException e = (ServiceInvocationException) error; Tags.HTTP_STATUS.set(span, e.getErrorCode()); } TracingHelper.logError(span, error); } }
@Override public final void authenticate( final DeviceCredentials deviceCredentials, final Handler<AsyncResult<DeviceUser>> resultHandler) { Objects.requireNonNull(deviceCredentials); Objects.requireNonNull(resultHandler); getCredentialsForDevice(deviceCredentials) .recover(t -> { if (!(t instanceof ServiceInvocationException)) { return Future.failedFuture(t); } final ServiceInvocationException e = (ServiceInvocationException) t; if (e.getErrorCode() == HttpURLConnection.HTTP_NOT_FOUND) { return Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_UNAUTHORIZED, "bad credentials")); } else { return Future.failedFuture(t); } }).compose(credentialsOnRecord -> validateCredentials(deviceCredentials, credentialsOnRecord)) .compose(d -> Future.succeededFuture(new DeviceUser(d.getTenantId(), d.getDeviceId()))) .setHandler(resultHandler); }
/** * Verifies that the base service fails for a payload that defines a trusted CA * containing both a certificate and a public key. * * @param ctx The vert.x test context. */ @Test public void testAddFailsForTrustedCaWithCertAndPk(final TestContext ctx) { final JsonObject malformedTrustedCa = new JsonObject() .put(TenantConstants.FIELD_PAYLOAD_SUBJECT_DN, "CN=test") .put(TenantConstants.FIELD_PAYLOAD_CERT, "certificate") .put(TenantConstants.FIELD_PAYLOAD_PUBLIC_KEY, "key"); final JsonObject testPayload = createValidTenantPayload(); testPayload.put(TenantConstants.FIELD_PAYLOAD_TRUSTED_CA, malformedTrustedCa); final EventBusMessage msg = createRequest(TenantConstants.TenantAction.add, testPayload); tenantService.processRequest(msg).setHandler(ctx.asyncAssertFailure(t -> { ctx.assertEquals(HttpURLConnection.HTTP_BAD_REQUEST, ((ServiceInvocationException) t).getErrorCode()); })); }
/** * Verifies that the base service fails for a payload that defines a trusted CA * containing neither a certificate nor a public key. * * @param ctx The vert.x test context. */ @Test public void testAddFailsForTrustedCaWithoutCertOrPk(final TestContext ctx) { final JsonObject malformedTrustedCa = new JsonObject() .put(TenantConstants.FIELD_PAYLOAD_SUBJECT_DN, "CN=test"); final JsonObject testPayload = createValidTenantPayload(); testPayload.put(TenantConstants.FIELD_PAYLOAD_TRUSTED_CA, malformedTrustedCa); final EventBusMessage msg = createRequest(TenantConstants.TenantAction.add, testPayload); tenantService.processRequest(msg).setHandler(ctx.asyncAssertFailure(t -> { ctx.assertEquals(HttpURLConnection.HTTP_BAD_REQUEST, ((ServiceInvocationException) t).getErrorCode()); })); }
/** * Verifies that the base service fails for a payload that defines a trusted CA * without a Subject DN. * * @param ctx The vert.x test context. */ @Test public void testAddFailsForTrustedCaWithoutSubjectDn(final TestContext ctx) { final JsonObject malformedTrustedCa = new JsonObject() .put(TenantConstants.FIELD_PAYLOAD_CERT, "certificate"); final JsonObject testPayload = createValidTenantPayload(); testPayload.put(TenantConstants.FIELD_PAYLOAD_TRUSTED_CA, malformedTrustedCa); final EventBusMessage msg = createRequest(TenantConstants.TenantAction.add, testPayload); tenantService.processRequest(msg).setHandler(ctx.asyncAssertFailure(t -> { ctx.assertEquals(HttpURLConnection.HTTP_BAD_REQUEST, ((ServiceInvocationException) t).getErrorCode()); })); }
/** * Verifies that the base service rejects a request for adding * hashed password credentials containing a malformed bcrypt hash. * * @param ctx The vert.x test context. */ @Test public void testAddFailsForMalformedBcryptSecrets(final TestContext ctx) { final JsonObject malformedSecret = new JsonObject() .put(CredentialsConstants.FIELD_SECRETS_HASH_FUNCTION, CredentialsConstants.HASH_FUNCTION_BCRYPT) .put(CredentialsConstants.FIELD_SECRETS_PWD_HASH, "$2y$11$malformed"); final JsonObject credentials = createValidCredentialsObject(CredentialsConstants.SECRETS_TYPE_HASHED_PASSWORD, malformedSecret); final EventBusMessage msg = createRequestForPayload(CredentialsConstants.CredentialsAction.add, credentials); service.processRequest(msg).setHandler(ctx.asyncAssertFailure(t -> { ctx.assertEquals(HttpURLConnection.HTTP_BAD_REQUEST, ((ServiceInvocationException) t).getErrorCode()); })); }
/** * Verifies that the base service fails for a payload that defines an empty adapter array (must be null or has to * contain at least one element). * * @param ctx The vert.x test context. */ @Test public void testAddFailsForEmptyAdapterArray(final TestContext ctx) { final JsonObject testPayload = createValidTenantPayload(); testPayload.put(TenantConstants.FIELD_ADAPTERS, new JsonArray()); final EventBusMessage msg = createRequest(TenantConstants.TenantAction.add, testPayload); tenantService.processRequest(msg).setHandler(ctx.asyncAssertFailure(t -> { ctx.assertEquals(HttpURLConnection.HTTP_BAD_REQUEST, ((ServiceInvocationException) t).getErrorCode()); })); }
/** * Verifies that the base service rejects a request for adding * credentials that contain a secret with a malformed time stamp. * * @param ctx The vert.x test context. */ @Test public void testAddFailsForMalformedTimestamp(final TestContext ctx) { final JsonObject secret = new JsonObject() .put(CredentialsConstants.FIELD_SECRETS_NOT_BEFORE, "no-timestamp"); final JsonObject testData = createValidCredentialsObject(secret); final EventBusMessage msg = createRequestForPayload(CredentialsConstants.CredentialsAction.add, testData); service.processRequest(msg).setHandler(ctx.asyncAssertFailure(t -> { ctx.assertEquals(HttpURLConnection.HTTP_BAD_REQUEST, ((ServiceInvocationException) t).getErrorCode()); })); }
/** * Verifies that the base service fails for a payload that defines an adapter entry, but does not provide the * mandatory field {@link TenantConstants#FIELD_ADAPTERS_TYPE}. * * @param ctx The vert.x test context. */ @Test public void testAddFailsForAdapterConfigWithoutType(final TestContext ctx) { final JsonObject testPayload = createValidTenantPayload(); final JsonArray adapterArray = new JsonArray(); // no type specified (which is a violation of the API) adapterArray.add(new JsonObject()); testPayload.put(TenantConstants.FIELD_ADAPTERS, adapterArray); final EventBusMessage msg = createRequest(TenantConstants.TenantAction.add, testPayload); tenantService.processRequest(msg).setHandler(ctx.asyncAssertFailure(t -> { ctx.assertEquals(HttpURLConnection.HTTP_BAD_REQUEST, ((ServiceInvocationException) t).getErrorCode()); })); }
/** * Verifies that the base service rejects a request for adding * credentials that contains a secret with a time stamp that does * not include an offset. * * @param ctx The vert.x test context. */ @Test public void testAddFailsForShortTimestamp(final TestContext ctx) { final JsonObject secret = new JsonObject() .put(CredentialsConstants.FIELD_SECRETS_NOT_BEFORE, "2007-04-05T14:30"); final JsonObject testData = createValidCredentialsObject(secret); final EventBusMessage msg = createRequestForPayload(CredentialsConstants.CredentialsAction.add, testData); service.processRequest(msg).setHandler(ctx.asyncAssertFailure(t -> { ctx.assertEquals(HttpURLConnection.HTTP_BAD_REQUEST, ((ServiceInvocationException) t).getErrorCode()); })); }
/** * Verifies that the base service fails for an incomplete message that does not contain mandatory fields. * * @param ctx The vert.x test context. */ @Test public void testAddFailsForIncompleteMessage(final TestContext ctx) { final EventBusMessage msg = EventBusMessage.forOperation(TenantConstants.TenantAction.add.toString()); tenantService.processRequest(msg).setHandler(ctx.asyncAssertFailure(t -> { ctx.assertEquals(HttpURLConnection.HTTP_BAD_REQUEST, ((ServiceInvocationException) t).getErrorCode()); })); }
/** * Verifies that the base service rejects a request for adding * credentials containing an empty <em>secrets</em> array. * * @param ctx The vert.x test context. */ @Test public void testAddFailsForEmptySecrets(final TestContext ctx) { final JsonObject testData = createValidCredentialsObject(null); final EventBusMessage msg = createRequestForPayload(CredentialsConstants.CredentialsAction.add, testData); service.processRequest(msg).setHandler(ctx.asyncAssertFailure(t -> { ctx.assertEquals(HttpURLConnection.HTTP_BAD_REQUEST, ((ServiceInvocationException) t).getErrorCode()); })); }
/** * Verifies that the base service rejects a request for adding * credentials that do not contain a <em>secrets</em> array at all. * * @param ctx The vert.x test context. */ @Test public void testAddFailsForMissingSecrets(final TestContext ctx) { final JsonObject testData = createValidCredentialsObject(); testData.remove(CredentialsConstants.FIELD_SECRETS); final EventBusMessage msg = createRequestForPayload(CredentialsConstants.CredentialsAction.add, testData); service.processRequest(msg).setHandler(ctx.asyncAssertFailure(t -> { ctx.assertEquals(HttpURLConnection.HTTP_BAD_REQUEST, ((ServiceInvocationException) t).getErrorCode()); })); }
/** * Verifies that the registry returns 400 when issuing a request with an unsupported action. * * @param ctx The vert.x test context. */ @Test public void testProcessRequestFailsWithUnsupportedAction(final TestContext ctx) { // GIVEN an empty registry final CompleteBaseRegistrationService<ServiceConfigProperties> registrationService = newCompleteRegistrationService(); registrationService.setRegistrationAssertionFactory(RegistrationAssertionHelperImpl.forSigning(vertx, props)); registrationService .processRequest(EventBusMessage.forOperation("unknown-action")) .setHandler(ctx.asyncAssertFailure(t -> { ctx.assertEquals(HttpURLConnection.HTTP_BAD_REQUEST, ((ServiceInvocationException) t).getErrorCode()); })); }
/** * Verifies that the base service fails a request for getting credentials * with a 400 error code if the type is missing. * * @param ctx The vert.x test context. */ @Test public void testGetFailsForMissingType(final TestContext ctx) { // GIVEN a request for getting credentials that does not specify a type final CredentialsObject malformedPayload = new CredentialsObject() .setAuthId("bumlux") .addSecret(CredentialsObject.emptySecret(null, null)); final EventBusMessage request = createRequestForPayload( CredentialsConstants.CredentialsAction.get, JsonObject.mapFrom(malformedPayload)); // WHEN processing the request service.processRequest(request).setHandler(ctx.asyncAssertFailure(t -> { // THEN the response contains a 400 error code ctx.assertEquals(HttpURLConnection.HTTP_BAD_REQUEST, ((ServiceInvocationException) t).getErrorCode()); })); }
/** * Verifies that the base service fails a request for getting credentials * with a 400 error code if the authentication identifier is missing. * * @param ctx The vert.x test context. */ @Test public void testGetFailsForMissingAuthId(final TestContext ctx) { // GIVEN a request for getting credentials that does not specify an auth ID final CredentialsObject malformedPayload = new CredentialsObject() .setType("my-type") .addSecret(CredentialsObject.emptySecret(null, null)); final EventBusMessage request = createRequestForPayload( CredentialsConstants.CredentialsAction.get, JsonObject.mapFrom(malformedPayload)); // WHEN processing the request service.processRequest(request).setHandler(ctx.asyncAssertFailure(t -> { // THEN the response contains a 400 error code ctx.assertEquals(HttpURLConnection.HTTP_BAD_REQUEST, ((ServiceInvocationException) t).getErrorCode()); })); }