diff --git a/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java b/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java index e2edf1333..596ef0da5 100644 --- a/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java +++ b/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java @@ -306,7 +306,7 @@ private void setUpEncryptedRoutes(Router mainRouter, BodyHandler bodyHandler) { mainRouter.post(V2_IDENTITY_BUCKETS.toString()).handler(bodyHandler).handler(auth.handleV1( rc -> encryptedPayloadHandler.handle(rc, this::handleBucketsV2), Role.MAPPER)); mainRouter.post(V2_IDENTITY_MAP.toString()).handler(bodyHandler).handler(auth.handleV1( - rc -> encryptedPayloadHandler.handle(rc, this::handleIdentityMapV2), Role.MAPPER)); + rc -> encryptedPayloadHandler.handleIdentityMap(rc, this::handleIdentityMapV2), Role.MAPPER)); mainRouter.post(V2_KEY_LATEST.toString()).handler(bodyHandler).handler(auth.handleV1( rc -> encryptedPayloadHandler.handle(rc, this::handleKeysRequestV2), Role.ID_READER)); mainRouter.post(V2_KEY_SHARING.toString()).handler(bodyHandler).handler(auth.handleV1( @@ -1663,7 +1663,8 @@ private boolean validateServiceLink(RoutingContext rc) { return false; } - private void handleIdentityMapV2(RoutingContext rc) { + private Future handleIdentityMapV2(RoutingContext rc) { + final Promise promise = Promise.promise(); try { final Integer siteId = RoutingContextUtil.getSiteId(rc); final String apiContact = RoutingContextUtil.getApiContact(rc, clientKeyProvider); @@ -1672,16 +1673,39 @@ private void handleIdentityMapV2(RoutingContext rc) { final InputUtil.InputVal[] inputList = getIdentityMapV2Input(rc); if (inputList == null) { ResponseUtil.LogInfoAndSend400Response(rc, this.phoneSupport ? ERROR_INVALID_INPUT_WITH_PHONE_SUPPORT : ERROR_INVALID_INPUT_EMAIL_MISSING); - return; + promise.complete(); + return promise.future(); } - if (!validateServiceLink(rc)) { return; } + if (!validateServiceLink(rc)) { + promise.complete(); + return promise.future(); + } - final JsonObject resp = handleIdentityMapCommon(rc, inputList); - ResponseUtil.SuccessV2(rc, resp); + vertx.executeBlocking( + blockingPromise -> { + try { + final JsonObject resp = handleIdentityMapCommon(rc, inputList); + blockingPromise.complete(resp); + } catch (Exception e) { + blockingPromise.fail(e); + }}, + false, + resp -> { + if (resp.succeeded()) { + if (!rc.response().ended()) { + ResponseUtil.SuccessV2(rc, resp.result()); + } + } else { + ResponseUtil.LogErrorAndSendResponse(ResponseStatus.UnknownError, 500, rc, "Unknown error while mapping identity v2", (Exception) resp.cause()); + } + promise.complete(); + }); } catch (Exception e) { ResponseUtil.LogErrorAndSendResponse(ResponseStatus.UnknownError, 500, rc, "Unknown error while mapping identity v2", e); + promise.fail(e); } + return promise.future(); } private InputUtil.InputVal[] getIdentityMapV2Input(RoutingContext rc) { diff --git a/src/main/java/com/uid2/operator/vertx/V2PayloadHandler.java b/src/main/java/com/uid2/operator/vertx/V2PayloadHandler.java index 10627ab10..88fd00255 100644 --- a/src/main/java/com/uid2/operator/vertx/V2PayloadHandler.java +++ b/src/main/java/com/uid2/operator/vertx/V2PayloadHandler.java @@ -43,6 +43,44 @@ public V2PayloadHandler(KeyManager keyManager, Boolean enableEncryption, Identit this.siteProvider = siteProvider; } + public void handleIdentityMap(RoutingContext rc, Function> apiHandler) { + if (!enableEncryption) { + passThroughIdentityMap(rc, apiHandler); + return; + } + + V2RequestUtil.V2Request request = V2RequestUtil.parseRequest(rc.body().asString(), AuthMiddleware.getAuthClient(ClientKey.class, rc), new InstantClock()); + if (!request.isValid()) { + ResponseUtil.LogInfoAndSend400Response(rc, request.errorMessage); + return; + } + rc.data().put("request", request.payload); + + Future apiHandlerFuture = apiHandler.apply(rc); + + apiHandlerFuture.onComplete(ar -> { + if (!rc.response().ended()) { + handleResponse(rc, request); + } + }); + } + + private void passThroughIdentityMap(RoutingContext rc, Function> apiHandler) { + rc.data().put("request", rc.body().asJsonObject()); + Future apiHandlerFuture = apiHandler.apply(rc); + + apiHandlerFuture.onComplete(ar -> { + if (ar.succeeded() && !rc.response().ended()) { + if (rc.response().getStatusCode() != 200) { + return; + } + JsonObject respJson = (JsonObject) rc.data().get("response"); + rc.response().putHeader(HttpHeaders.CONTENT_TYPE, "application/json") + .end(respJson.encode()); + } + }); + } + public void handle(RoutingContext rc, Handler apiHandler) { if (!enableEncryption) { passThrough(rc, apiHandler); diff --git a/src/test/java/com/uid2/operator/UIDOperatorVerticleTest.java b/src/test/java/com/uid2/operator/UIDOperatorVerticleTest.java index 5e4793497..15a3402ec 100644 --- a/src/test/java/com/uid2/operator/UIDOperatorVerticleTest.java +++ b/src/test/java/com/uid2/operator/UIDOperatorVerticleTest.java @@ -33,10 +33,7 @@ import com.uid2.shared.store.salt.ISaltProvider; import io.micrometer.core.instrument.Metrics; import io.micrometer.core.instrument.simple.SimpleMeterRegistry; -import io.vertx.core.AsyncResult; -import io.vertx.core.Future; -import io.vertx.core.Handler; -import io.vertx.core.Vertx; +import io.vertx.core.*; import io.vertx.core.buffer.Buffer; import io.vertx.core.json.JsonArray; import io.vertx.core.json.JsonObject; @@ -2346,8 +2343,12 @@ void identityMapBatchBothEmailAndHashEmpty(String apiVersion, Vertx vertx, Vertx req.put("email_hash", emailHashes); send(apiVersion, vertx, apiVersion + "/identity/map", false, null, req, 200, respJson -> { - checkIdentityMapResponse(respJson); - testContext.completeNow(); + try { + checkIdentityMapResponse(respJson); + testContext.completeNow(); + } catch (Throwable ex) { + testContext.failNow(ex); + } }); }