From e57a01e3d83c7619d5b6306e26cf7df28238f84b Mon Sep 17 00:00:00 2001 From: shreelakshmijoshi Date: Fri, 3 Nov 2023 12:58:07 +0530 Subject: [PATCH 01/22] Refactor initiateTransactions --- .../notification/UpdateNotification.java | 856 ++++++++++++++++-- .../server/notification/util/Constants.java | 6 +- 2 files changed, 803 insertions(+), 59 deletions(-) diff --git a/src/main/java/iudx/apd/acl/server/notification/UpdateNotification.java b/src/main/java/iudx/apd/acl/server/notification/UpdateNotification.java index 0c2c0a93..da94948b 100644 --- a/src/main/java/iudx/apd/acl/server/notification/UpdateNotification.java +++ b/src/main/java/iudx/apd/acl/server/notification/UpdateNotification.java @@ -6,10 +6,7 @@ import static iudx.apd.acl.server.common.ResponseUrn.RESOURCE_NOT_FOUND_URN; import static iudx.apd.acl.server.notification.util.Constants.*; -import io.vertx.core.AsyncResult; -import io.vertx.core.Future; -import io.vertx.core.Handler; -import io.vertx.core.Promise; +import io.vertx.core.*; import io.vertx.core.json.JsonArray; import io.vertx.core.json.JsonObject; import io.vertx.pgclient.PgPool; @@ -24,6 +21,7 @@ import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; +import java.util.ArrayList; import java.util.List; import java.util.UUID; import java.util.stream.Collector; @@ -119,6 +117,7 @@ public Future initiateUpdateNotification(JsonObject notification, Us } return Future.failedFuture(ownershipCheckFuture.cause().getMessage()); }); + LOG.info("What is approvedRequestFuture : " + approvedRequestFuture); return approvedRequestFuture; default: JsonObject failureMessage = @@ -140,44 +139,90 @@ public Future initiateUpdateNotification(JsonObject notification, Us * @param sqlConnection connection made to the DB to execute queries using transactions * @return Success response or Failure response as Future JsonObject */ + /*public Future approveNotification( + JsonObject notification, String query, SqlConnection sqlConnection) throws Exception { + LOG.trace("inside approveNotification method"); + Promise promise = Promise.promise(); + UUID notificationId = UUID.fromString(notification.getString("requestId")); + JsonObject constraints = notification.getJsonObject("constraints"); + + Tuple tuple = Tuple.of(getExpiryAt(), constraints, notificationId, getOwnerId()); + executeQuery( + sqlConnection, + query, + tuple, + handler -> { + if (handler.succeeded()) { + JsonArray result = handler.result().getJsonArray(RESULT); + boolean isResponseEmpty = result.isEmpty(); + */ + /* if the id is not returned back after execution, then record is not inserted*/ + /* + if (isResponseEmpty) { + LOG.error("Could not update request table while approving the request"); + JsonObject failureMessage = + new JsonObject() + .put(TYPE, HttpStatusCode.INTERNAL_SERVER_ERROR.getValue()) + .put(TITLE, ResponseUrn.DB_ERROR_URN.getUrn()) + .put(DETAIL, "Failure while executing query"); + promise.fail(failureMessage.encode()); + } else { + JsonObject successResponse = + new JsonObject() + .put(TYPE, ResponseUrn.SUCCESS_URN.getUrn()) + .put(TITLE, ResponseUrn.SUCCESS_URN.getMessage()) + .put(DETAIL, "Request updated successfully") + .put(STATUS_CODE, SUCCESS.getValue()); + promise.complete(successResponse); + } + } else { + promise.fail(handler.cause().getMessage()); + } + }); + return promise.future(); + } + */ + public Future approveNotification( JsonObject notification, String query, SqlConnection sqlConnection) throws Exception { + Collector> rowListCollector = + Collectors.mapping(row -> row.toJson(), Collectors.toList()); LOG.trace("inside approveNotification method"); Promise promise = Promise.promise(); UUID notificationId = UUID.fromString(notification.getString("requestId")); JsonObject constraints = notification.getJsonObject("constraints"); - - Tuple tuple = Tuple.of(getExpiryAt(), constraints, notificationId, getOwnerId()); - executeQuery( - sqlConnection, - query, - tuple, - handler -> { - if (handler.succeeded()) { - JsonArray result = handler.result().getJsonArray(RESULT); - boolean isResponseEmpty = result.isEmpty(); - /* if the id is not returned back after execution, then record is not inserted*/ - if (isResponseEmpty) { - LOG.error("Could not update request table while approving the request"); - JsonObject failureMessage = - new JsonObject() - .put(TYPE, HttpStatusCode.INTERNAL_SERVER_ERROR.getValue()) - .put(TITLE, ResponseUrn.DB_ERROR_URN.getUrn()) - .put(DETAIL, "Failure while executing query"); - promise.fail(failureMessage.encode()); - } else { - JsonObject successResponse = - new JsonObject() - .put(TYPE, ResponseUrn.SUCCESS_URN.getUrn()) - .put(TITLE, ResponseUrn.SUCCESS_URN.getMessage()) - .put(DETAIL, "Request updated successfully") - .put(STATUS_CODE, SUCCESS.getValue()); - promise.complete(successResponse); - } - } else { - promise.fail(handler.cause().getMessage()); - } - }); + final Tuple updateAccessRequestTuple = + Tuple.of(getExpiryAt(), constraints, notificationId, getOwnerId()); + sqlConnection + .preparedQuery(APPROVE_REQUEST_QUERY) + .collecting(rowListCollector) + .execute(updateAccessRequestTuple) + .map(rows -> rows.value()) + .onSuccess( + approveAccessRequestSuccess -> { + boolean isListEmpty = approveAccessRequestSuccess.isEmpty(); + if (isListEmpty) { + LOG.error("list is empty while updating notification"); + promise.fail("Something went wrong while approving access request"); + } else { + LOG.debug( + "Approving Notification successfully done : {}", approveAccessRequestSuccess); + JsonObject successResponse = + new JsonObject() + .put(TYPE, ResponseUrn.SUCCESS_URN.getUrn()) + .put(TITLE, ResponseUrn.SUCCESS_URN.getMessage()) + .put(DETAIL, "Request updated successfully") + .put(STATUS_CODE, SUCCESS.getValue()); + LOG.info("before promise is completed"); + promise.complete(successResponse); + LOG.info("Success response is : " + successResponse.toString()); + } + }) + .onFailure( + updateNotificationFailure -> { + LOG.error("Error while updating notification: " + updateNotificationFailure); + promise.fail("Something went wrong while approving access request"); + }); return promise.future(); } @@ -191,7 +236,14 @@ public Future approveNotification( * @param notification Request body from PUT notification API of type JsonObject * @return Final Success or Failure response to be presented to the user of type Future */ - public Future initiateTransactions(JsonObject notification) { + + // TODO : refactor the initiateTransactions method by doing the following steps + // do not call any method + // use compose blocks + // do not return primary key from the query, make the primary key + // maybe even complete the transaction from here + + /* public Future initiateTransactions(JsonObject notification) { LOG.trace("inside initiateTransactions method"); pool = postgresService.getPool(); Future transactionResponseFuture = @@ -255,8 +307,596 @@ public Future initiateTransactions(JsonObject notification) { return approvedNotificationFuture; }); return transactionResponseFuture; + }*/ + + // public Future initiateTransactions(JsonObject notification) { + // Promise promise = Promise.promise(); + // LOG.trace("inside initiateTransactions method"); + // Collector> rowListCollector = + // Collectors.mapping(row -> row.toJson(), Collectors.toList()); + // + // pool = postgresService.getPool(); + // Future transactionResponseFuture = + // pool.withTransaction( + // sqlConnection -> { + // JsonObject constraints = null; + // try { + // + // constraints = notification.getJsonObject("constraints"); + // LOG.debug("constraints : {}", constraints); + // if (constraints == null) { + // throw new NullPointerException("Invalid or null constraints in the request + // body"); + // } + // } catch (Exception exception) { + // LOG.error("Error : {}", exception.getMessage()); + // failPromise(promise, "Invalid or null constraints in the request body"); + // return promise.future(); + // } + // UUID policyId = UUID.randomUUID(); + // setPolicyId(policyId); + // + // Tuple tuple = + // Tuple.of( + // policyId, + // getConsumerEmailId(), + // getItemId(), + // getOwnerId(), + // "ACTIVE", + // getExpiryAt(), + // constraints); + // + // sqlConnection + // .preparedQuery(CREATE_POLICY_QUERY) + // .collecting(rowListCollector) + // .execute(tuple) + // .map(rows -> rows.value()) + // .onSuccess( + // createPolicySuccess -> { + // boolean isListEmpty = createPolicySuccess.isEmpty(); + // if (isListEmpty) { + // failPromise(promise, "Something went wrong while creating the + // policy"); + // + // } else { + // LOG.debug("Create Policy successful : {}", createPolicySuccess); + // // promise.complete(new + // JsonObject().put(RESULT, + // // createPolicySuccess)); + // } + // }) + // .onFailure( + // createPolicyFailed -> { + // LOG.error("Error while creating policy : " + createPolicyFailed); + // failPromise(promise, "Something went wrong while creating the policy"); + // }) + // .compose( + // insertionHandler -> { + // Promise promise2 = Promise.promise(); + // final UUID notificationId = + // UUID.fromString(notification.getString("requestId")); + // UUID uuid = UUID.randomUUID(); + // + // + // Tuple approvedAccessRequestInsertionTuple = + // Tuple.of(uuid, notificationId, getPolicyId()); + // sqlConnection + // .preparedQuery(INSERT_IN_APPROVED_ACCESS_REQUESTS_QUERY) + // .collecting(rowListCollector) + // .execute(approvedAccessRequestInsertionTuple) + // .map(rows -> rows.value()) + // .onSuccess( + // approvedAccessRequestInsertionSuccess -> { + // boolean isListEmpty = + // approvedAccessRequestInsertionSuccess.isEmpty(); + // if (isListEmpty) { + // LOG.error( + // "list is empty while inserting + // approved_access_request"); + // failPromise( + // promise2, + // "Something went wrong while approving the access + // request"); + // } else { + // LOG.info( + // "Insertion in approved_access_request successfully done + // : {}", + // approvedAccessRequestInsertionSuccess); + // // promise.complete(new + // // + // JsonObject().put(RESULT,approvedAccessRequestInsertionSuccess)); + // } + // }) + // .onFailure( + // insertionFailed -> { + // LOG.error( + // "Error while inserting in approved_access_request : " + // + insertionFailed); + // failPromise( + // promise2, + // "Something went wrong while approving access request"); + // }) + // .compose( + // updateNotificationHandler -> { + // Promise promise3 = Promise.promise(); + // final JsonObject constraints1 = + // notification.getJsonObject("constraints"); + // + // final Tuple updateAccessRequestTuple = + // Tuple.of( + // getExpiryAt(), + // constraints1, + // notificationId, + // getOwnerId()); + // + // sqlConnection + // .preparedQuery(APPROVE_REQUEST_QUERY) + // .collecting(rowListCollector) + // .execute(updateAccessRequestTuple) + // .map(rows -> rows.value()) + // .onSuccess( + // approveAccessRequestSuccess -> { + // boolean isListEmpty = + // approveAccessRequestSuccess.isEmpty(); + // if (isListEmpty) { + // LOG.error( + // "list is empty while updating notification"); + // failPromise( + // promise3, + // "Something went wrong while approving access + // request"); + // } else { + // LOG.debug( + // "Approving Notification successfully done : + // {}", + // approveAccessRequestSuccess); + // JsonObject successResponse = + // new JsonObject() + // .put(TYPE, + // ResponseUrn.SUCCESS_URN.getUrn()) + // .put( + // TITLE, + // ResponseUrn.SUCCESS_URN.getMessage()) + // .put(DETAIL, "Request updated + // successfully") + // .put(STATUS_CODE, SUCCESS.getValue()); + // LOG.info("before promise is completed"); + // promise3.complete(successResponse); + // LOG.info("Success response is : " + + // successResponse.toString()); + // } + // }) + // .onFailure( + // updateNotificationFailure -> { + // LOG.error( + // "Error while updating notification: " + // + updateNotificationFailure); + // failPromise( + // promise3, + // "Something went wrong while approving access + // request"); + // }); + // LOG.info("this is the actual promise : promise3" ); + // return promise3.future(); + // }); + // LOG.info("this is 2nd promise"); + // return promise2.future(); + // }); + // LOG.info("promise is here"); + // return promise.future(); // this future is being returned + // }); + // LOG.info("it is not returned"); + // return transactionResponseFuture; // here + // } + + public Future initiateTransactions(JsonObject notification) { + LOG.trace("inside initiateTransactions method"); + Collector> rowListCollector1 = + Collectors.mapping(row -> row.toJson(), Collectors.toList()); + Collector> rowListCollector2 = + Collectors.mapping(row -> row.toJson(), Collectors.toList()); + Collector> rowListCollector3 = + Collectors.mapping(row -> row.toJson(), Collectors.toList()); + pool = postgresService.getPool(); + Future transactionResponseFuture = + pool.withTransaction( + sqlConnection -> { + // LOG.trace("inside createPolicy method"); + Promise promise1 = Promise.promise(); + JsonObject constraints = null; + try { + + constraints = notification.getJsonObject("constraints"); + LOG.debug("constraints : {}", constraints); + if (constraints == null) { + throw new NullPointerException("Invalid or null constraints in the request body"); + } + } catch (Exception exception) { + LOG.error("Error : {}", exception.getMessage()); + JsonObject failureMessage = + new JsonObject() + .put(TYPE, BAD_REQUEST.getValue()) + .put(TITLE, BAD_REQUEST.getUrn()) + .put(DETAIL, "Invalid or null constraints in the request body"); + return Future.failedFuture(failureMessage.encode()); + } + UUID policyId = UUID.randomUUID(); + setPolicyId(policyId); + // + Tuple tuple = + Tuple.of( + policyId, + getConsumerEmailId(), + getItemId(), + getOwnerId(), + "ACTIVE", + getExpiryAt(), + constraints); + // + // + // var one = sqlConnection + // .preparedQuery(CREATE_POLICY_QUERY) + // .collecting(rowListCollector) + // .execute(tuple) + // .map(rows -> rows.value()) + // .onSuccess( + // createPolicySuccess -> { + // boolean isListEmpty = + // createPolicySuccess.isEmpty(); + // if (isListEmpty) { + // promise1.fail("Something went wrong + // while creating the policy"); + // + // } else { + // LOG.debug("Create Policy successful : + // {}", createPolicySuccess); + // promise1.complete(true); + // } + // }) + // .onFailure( + // createPolicyFailed -> { + // LOG.error("Error while creating policy : " + + // createPolicyFailed); + // promise1.fail("Something went wrong while + // creating the policy"); + // }); + // + // + // LOG.trace("inside insertInApprovedAccessRequest method"); + UUID notificationId = UUID.fromString(notification.getString("requestId")); + tuple = Tuple.of(notificationId, getPolicyId()); + // + UUID uuid = UUID.randomUUID(); + Tuple approvedAccessRequestInsertionTuple = + Tuple.of(uuid, notificationId, getPolicyId()); + Promise promise2 = Promise.promise(); + // + // var two = sqlConnection + // .preparedQuery(INSERT_IN_APPROVED_ACCESS_REQUESTS_QUERY) + // .collecting(rowListCollector) + // .execute(approvedAccessRequestInsertionTuple) + // .map(rows -> rows.value()) + // .onSuccess( + // approvedAccessRequestInsertionSuccess -> { + // boolean isListEmpty = + // approvedAccessRequestInsertionSuccess.isEmpty(); + // if (isListEmpty) { + // LOG.error("list is empty while inserting + // approved_access_request"); + // promise2.fail("Something went wrong + // while approving the access request"); + // } else { + // LOG.info( + // "Insertion in + // approved_access_request successfully done : {}", + // + // approvedAccessRequestInsertionSuccess); + // promise2.complete(true); + // } + // }) + // .onFailure( + // insertionFailed -> { + // LOG.error("Error while inserting in + // approved_access_request : " + insertionFailed); + // promise2.fail("Something went wrong while + // approving access request"); + // }); + // + // + Promise promise3 = Promise.promise(); + // LOG.trace("inside approveNotification method"); + notificationId = UUID.fromString(notification.getString("requestId")); + constraints = notification.getJsonObject("constraints"); + final Tuple updateAccessRequestTuple = + Tuple.of(getExpiryAt(), constraints, notificationId, getOwnerId()); + // var three = sqlConnection + // .preparedQuery(APPROVE_REQUEST_QUERY) + // .collecting(rowListCollector) + // .execute(updateAccessRequestTuple) + // .map(rows -> rows.value()) + // .onSuccess( + // approveAccessRequestSuccess -> { + // boolean isListEmpty = + // approveAccessRequestSuccess.isEmpty(); + // if (isListEmpty) { + // LOG.error("list is empty while updating + // notification"); + // promise3.fail("Something went wrong + // while approving access request"); + // } else { + // LOG.debug( + // "Approving Notification + // successfully done : {}", approveAccessRequestSuccess); + // JsonObject successResponse = + // new JsonObject() + // .put(TYPE, + // ResponseUrn.SUCCESS_URN.getUrn()) + // .put(TITLE, + // ResponseUrn.SUCCESS_URN.getMessage()) + // .put(DETAIL, "Request + // updated successfully") + // .put(STATUS_CODE, + // SUCCESS.getValue()); + // LOG.info("before promise is completed"); + // promise3.complete(successResponse); + // LOG.info("Success response is : " + + // successResponse.toString()); + // } + // }) + // .onFailure( + // updateNotificationFailure -> { + // LOG.error("Error while updating + // notification: " + updateNotificationFailure); + // promise3.fail("Something went wrong while + // approving access request"); + // }); + // var four = CompositeFuture.all(one, two, three) + // .compose(response -> + // { + // sqlConnection.close(); + // return promise3.future(); + // } + // ); + // + // _______________________________________________________________________________________ + + // var five = sqlConnection + // .preparedQuery(APPROVE_REQUEST_QUERY) + // .collecting(rowListCollector) + // .execute(updateAccessRequestTuple) + // .map(rows -> rows.value()) + // .compose(response1 -> { + // return sqlConnection + // .preparedQuery(APPROVE_REQUEST_QUERY) + // .collecting(rowListCollector) + // .execute(updateAccessRequestTuple) + // .map(rows -> rows.value()) + // .compose(response2 -> { + // return sqlConnection + // + // .preparedQuery(APPROVE_REQUEST_QUERY) + // .collecting(rowListCollector) + // .execute(updateAccessRequestTuple) + // .map(rows -> rows.value()) + // .onComplete(response3 -> { + // sqlConnection + // + // .preparedQuery(APPROVE_REQUEST_QUERY) + // + // .collecting(rowListCollector) + // + // .execute(updateAccessRequestTuple) + // .map(rows -> + // rows.value()) + // .onComplete(handler -> { + // boolean + // isResponse1Valid = !(response1.isEmpty()); + // boolean + // isResponse2Valid = !(response2.isEmpty()); + // if(isResponse1Valid + // && isResponse2Valid && response3.succeeded()) + // { + // + // sqlConnection.close(); + // JsonObject + // successResponse = + // new + // JsonObject() + // + // .put(TYPE, ResponseUrn.SUCCESS_URN.getUrn()) + // + // .put(TITLE, ResponseUrn.SUCCESS_URN.getMessage()) + // + // .put(DETAIL, "Request updated successfully") + // + // .put(STATUS_CODE, SUCCESS.getValue()); + // + // promise3.complete(successResponse); + // } + // }); + // + // }); + // }); + // }); + + // + // ------------------------------------------------------------------------------------- + // var six = sqlConnection + // .preparedQuery(APPROVE_REQUEST_QUERY) + // .execute(updateAccessRequestTuple) + // .compose(response1 -> { + // return sqlConnection + // .preparedQuery(APPROVE_REQUEST_QUERY) + // .execute(updateAccessRequestTuple) + // .compose(response2 -> { + // return sqlConnection + // + // .preparedQuery(APPROVE_REQUEST_QUERY) + // .execute(updateAccessRequestTuple) + // .onComplete(response3 -> { + // sqlConnection + // + // .preparedQuery(APPROVE_REQUEST_QUERY) + // + // .execute(updateAccessRequestTuple) + // .onComplete(handler -> { + // + // if(response3.succeeded()) + // { + // JsonObject + // successResponse = + // new + // JsonObject() + // + // .put(TYPE, ResponseUrn.SUCCESS_URN.getUrn()) + // + // .put(TITLE, ResponseUrn.SUCCESS_URN.getMessage()) + // + // .put(DETAIL, "Request updated successfully") + // + // .put(STATUS_CODE, SUCCESS.getValue()); + // + // promise3.complete(successResponse); + // } + // else + // { + // + // LOG.error("Something went wrong : ", handler.cause()); + // + // LOG.error("Failure : {}", handler.cause().getMessage()); + // + // failPromise(promise3, "Something went wrong while updating access request"); + // } + // }); + // + // }); + // }); + // }); + + // + // -------------------------------------------------------------------------------------------- + +// var seven = +// sqlConnection +// .preparedQuery(CREATE_POLICY_QUERY) +// .collecting(rowListCollector1) +// .execute(tuple) +// .map(row -> row.value()) +// .compose( +// response1 -> { +// LOG.info("Response 1 : {}", response1); +// return sqlConnection +// .preparedQuery(INSERT_IN_APPROVED_ACCESS_REQUESTS_QUERY) +// .collecting(rowListCollector2) +// .execute(approvedAccessRequestInsertionTuple) +// .map(row -> row.value()) +// .compose( +// response2 -> { +// LOG.info("Response 2 : {}", response2); +// return sqlConnection +// .preparedQuery(APPROVE_REQUEST_QUERY) +// .collecting(rowListCollector2) +// .execute(updateAccessRequestTuple) +// .map(row -> row.value()) +// .onComplete( +// response3 -> { +// sqlConnection +// .preparedQuery(APPROVE_REQUEST_QUERY) +// .collecting(rowListCollector3) +// .execute(updateAccessRequestTuple) +// .map(row -> row.value()) +// .onComplete( +// handler -> { +// if (response3.succeeded()) { +// LOG.info( +// "Response 3 : {}", +// handler.result()); +// JsonObject successResponse = +// new JsonObject() +// .put( +// TYPE, +// ResponseUrn.SUCCESS_URN +// .getUrn()) +// .put( +// TITLE, +// ResponseUrn.SUCCESS_URN +// .getMessage()) +// .put( +// DETAIL, +// "Request updated successfully") +// .put( +// STATUS_CODE, +// SUCCESS.getValue()); +// promise3.complete(successResponse); +// } else { +// LOG.error( +// "Something went wrong : ", +// handler.cause()); +// LOG.error( +// "Failure : {}", +// handler.cause().getMessage()); +// failPromise( +// promise3, +// "Something went wrong while updating access request"); +// } +// }); +// }); +// }); +// }); + + var eight = + sqlConnection + .preparedQuery(CREATE_POLICY_QUERY) + .collecting(rowListCollector1) + .execute(tuple) + .map(row -> row.value()) + .compose( + response1 -> { + LOG.info("Response 1 : {}", response1); + return sqlConnection + .preparedQuery(INSERT_IN_APPROVED_ACCESS_REQUESTS_QUERY) + .collecting(rowListCollector2) + .execute(approvedAccessRequestInsertionTuple) + .map(row -> row.value()) + .compose( + response2 -> { + LOG.info("Response 2 : {}", response2); + return sqlConnection + .preparedQuery(APPROVE_REQUEST_QUERY) + .collecting(rowListCollector2) + .execute(updateAccessRequestTuple) + .map(row -> row.value()) + .onComplete( + response3 -> { + LOG.info("Response 3 : {}", response3); + JsonObject successResponse = + new JsonObject() + .put(TYPE, ResponseUrn.SUCCESS_URN.getUrn()) + .put( + TITLE, + ResponseUrn.SUCCESS_URN.getMessage()) + .put(DETAIL, "Request updated successfully") + .put(STATUS_CODE, SUCCESS.getValue()); + promise3.complete(successResponse); + }); + }); + }); + + return promise3.future(); + // return four; + }); + return transactionResponseFuture; } + private void failPromise(Promise promise, String failureMessage) { + promise.fail( + getFailureMessage( + INTERNAL_SERVER_ERROR.getValue(), + ResponseUrn.BACKING_SERVICE_FORMAT_URN, + failureMessage)); + } + + /** * Inserts a record in approved_access_request table by inserting the notificationId and policyId *
@@ -267,22 +907,24 @@ public Future initiateTransactions(JsonObject notification) { * @param sqlConnection connection made to the DB to execute the query * @return True, if the record is successfully inserted, failure if any in the form of Future */ - public Future insertInApprovedAccessRequest( - JsonObject notification, String query, SqlConnection sqlConnection) throws Exception { - LOG.trace("inside insertInApprovedAccessRequest method"); - Promise promise = Promise.promise(); + /* public Future insertInApprovedAccessRequest( + JsonObject notification, String query, SqlConnection sqlConnection) throws Exception { + LOG.trace("inside insertInApprovedAccessRequest method"); + Promise promise = Promise.promise(); - UUID notificationId = UUID.fromString(notification.getString("requestId")); - Tuple tuple = Tuple.of(notificationId, getPolicyId()); - executeQuery( - sqlConnection, - query, - tuple, - handler -> { - if (handler.succeeded()) { - JsonObject result = handler.result().getJsonArray(RESULT).getJsonObject(0); - boolean isResponseEmpty = result.isEmpty(); - /* if the id is not returned back after execution, then record is not inserted*/ + UUID notificationId = UUID.fromString(notification.getString("requestId")); + Tuple tuple = Tuple.of(notificationId, getPolicyId()); + executeQuery( + sqlConnection, + query, + tuple, + handler -> { + if (handler.succeeded()) { + JsonObject result = handler.result().getJsonArray(RESULT).getJsonObject(0); + boolean isResponseEmpty = result.isEmpty(); + */ + /* if the id is not returned back after execution, then record is not inserted*/ + /* if (isResponseEmpty) { LOG.error("Could not insert in approved request access table"); JsonObject failureMessage = @@ -302,9 +944,49 @@ public Future insertInApprovedAccessRequest( } }); return promise.future(); + }*/ + + public Future insertInApprovedAccessRequest( + JsonObject notification, String query, SqlConnection sqlConnection) throws Exception { + LOG.trace("inside insertInApprovedAccessRequest method"); + Promise promise = Promise.promise(); + Collector> rowListCollector = + Collectors.mapping(row -> row.toJson(), Collectors.toList()); + UUID notificationId = UUID.fromString(notification.getString("requestId")); + Tuple tuple = Tuple.of(notificationId, getPolicyId()); + + UUID uuid = UUID.randomUUID(); + Tuple approvedAccessRequestInsertionTuple = Tuple.of(uuid, notificationId, getPolicyId()); + + sqlConnection + .preparedQuery(INSERT_IN_APPROVED_ACCESS_REQUESTS_QUERY) + .collecting(rowListCollector) + .execute(approvedAccessRequestInsertionTuple) + .map(rows -> rows.value()) + .onSuccess( + approvedAccessRequestInsertionSuccess -> { + boolean isListEmpty = approvedAccessRequestInsertionSuccess.isEmpty(); + if (isListEmpty) { + LOG.error("list is empty while inserting approved_access_request"); + promise.fail("Something went wrong while approving the access request"); + } else { + LOG.info( + "Insertion in approved_access_request successfully done : {}", + approvedAccessRequestInsertionSuccess); + promise.complete(true); + // promise.complete(new + // JsonObject().put(RESULT,approvedAccessRequestInsertionSuccess)); + } + }) + .onFailure( + insertionFailed -> { + LOG.error("Error while inserting in approved_access_request : " + insertionFailed); + promise.fail("Something went wrong while approving access request"); + }); + return promise.future(); } - /** + /** * Checks if the given user who is requesting to approve the notification of the consumer is * owning the resource * @@ -352,7 +1034,7 @@ public Future checkOwner4GivenResource(String query) { * @param sqlConnection object for executing the query by connecting to the DB * @return True, if a policy is successfully created, or failure if of type Future */ - public Future createPolicy( +/* public Future createPolicy( JsonObject notification, String query, SqlConnection sqlConnection) throws Exception { LOG.trace("inside createPolicy method"); Promise promise = Promise.promise(); @@ -385,9 +1067,9 @@ public Future createPolicy( handler -> { if (handler.succeeded()) { JsonObject result = handler.result().getJsonArray(RESULT).getJsonObject(0); - /*policy is created successfully and the policy id is returned */ + *//*policy is created successfully and the policy id is returned *//* if (!result.isEmpty()) { - /* set policyId */ + *//* set policyId *//* UUID policyId = UUID.fromString(result.getString("_id")); setPolicyId(policyId); LOG.trace("Policy created successfully with policyId: {}", result.getString("_id")); @@ -407,6 +1089,68 @@ public Future createPolicy( } }); return promise.future(); + }*/ + + public Future createPolicy( + JsonObject notification, String query, SqlConnection sqlConnection) throws Exception { + Collector> rowListCollector = + Collectors.mapping(row -> row.toJson(), Collectors.toList()); + + LOG.trace("inside createPolicy method"); + Promise promise = Promise.promise(); + JsonObject constraints = null; + try { + + constraints = notification.getJsonObject("constraints"); + LOG.debug("constraints : {}", constraints); + if (constraints == null) { + throw new NullPointerException("Invalid or null constraints in the request body"); + } + } catch (Exception exception) { + LOG.error("Error : {}", exception.getMessage()); + JsonObject failureMessage = + new JsonObject() + .put(TYPE, BAD_REQUEST.getValue()) + .put(TITLE, BAD_REQUEST.getUrn()) + .put(DETAIL, "Invalid or null constraints in the request body"); + return Future.failedFuture(failureMessage.encode()); + } + UUID policyId = UUID.randomUUID(); + setPolicyId(policyId); + + Tuple tuple = + Tuple.of( + policyId, + getConsumerEmailId(), + getItemId(), + getOwnerId(), + "ACTIVE", + getExpiryAt(), + constraints); + + + sqlConnection + .preparedQuery(query) + .collecting(rowListCollector) + .execute(tuple) + .map(rows -> rows.value()) + .onSuccess( + createPolicySuccess -> { + boolean isListEmpty = createPolicySuccess.isEmpty(); + if (isListEmpty) { + promise.fail("Something went wrong while creating the policy"); + + } else { + LOG.debug("Create Policy successful : {}", createPolicySuccess); + promise.complete(true); + } + }) + .onFailure( + createPolicyFailed -> { + LOG.error("Error while creating policy : " + createPolicyFailed); + promise.fail("Something went wrong while creating the policy"); + }); + return promise.future(); } /** diff --git a/src/main/java/iudx/apd/acl/server/notification/util/Constants.java b/src/main/java/iudx/apd/acl/server/notification/util/Constants.java index 9702d20d..94d00ab5 100644 --- a/src/main/java/iudx/apd/acl/server/notification/util/Constants.java +++ b/src/main/java/iudx/apd/acl/server/notification/util/Constants.java @@ -34,10 +34,10 @@ public class Constants { public static final String OWNERSHIP_CHECK_QUERY = "SELECT * FROM resource_entity WHERE _id = $1::uuid AND provider_id = $2::uuid"; public static final String CREATE_POLICY_QUERY = "INSERT INTO policy" - + "(user_emailid, item_id, owner_id, status, expiry_at, constraints)" - + " VALUES ($1, $2, $3, $4, $5,$6) RETURNING _id;"; + + "(_id, user_emailid, item_id, owner_id, status, expiry_at, constraints)" + + " VALUES ($1, $2, $3, $4, $5,$6, $7) RETURNING _id;"; public static final String INSERT_IN_APPROVED_ACCESS_REQUESTS_QUERY = - "INSERT INTO approved_access_requests(request_id, policy_id) VALUES ($1, $2) RETURNING _id"; + "INSERT INTO approved_access_requests(_id, request_id, policy_id) VALUES ($1, $2, $3) RETURNING _id"; public static final String APPROVE_REQUEST_QUERY = "UPDATE request SET status = 'GRANTED', expiry_at = $1," + "constraints = $2 WHERE _id = $3 AND owner_id = $4 RETURNING _id"; public static final String INSERT_USER_INFO_QUERY = "INSERT INTO user_table (_id, email_id, first_name, last_name)" From 0f40829932b916008f81278a6195565c3c3392c9 Mon Sep 17 00:00:00 2001 From: shreelakshmijoshi Date: Fri, 3 Nov 2023 16:25:23 +0530 Subject: [PATCH 02/22] Update file --- .../notification/UpdateNotification.java | 418 +++++------------- 1 file changed, 109 insertions(+), 309 deletions(-) diff --git a/src/main/java/iudx/apd/acl/server/notification/UpdateNotification.java b/src/main/java/iudx/apd/acl/server/notification/UpdateNotification.java index da94948b..12e0611a 100644 --- a/src/main/java/iudx/apd/acl/server/notification/UpdateNotification.java +++ b/src/main/java/iudx/apd/acl/server/notification/UpdateNotification.java @@ -491,17 +491,20 @@ public Future approveNotification( public Future initiateTransactions(JsonObject notification) { LOG.trace("inside initiateTransactions method"); - Collector> rowListCollector1 = - Collectors.mapping(row -> row.toJson(), Collectors.toList()); - Collector> rowListCollector2 = - Collectors.mapping(row -> row.toJson(), Collectors.toList()); - Collector> rowListCollector3 = - Collectors.mapping(row -> row.toJson(), Collectors.toList()); + + Collector> rowListCollector = + Collectors.mapping(row -> row.toJson(), Collectors.toList()); + Collector> rowListCollector1 = + Collectors.mapping(row -> row.toJson(), Collectors.toList()); + Collector> rowListCollector2 = + Collectors.mapping(row -> row.toJson(), Collectors.toList()); + Collector> rowListCollector3 = + Collectors.mapping(row -> row.toJson(), Collectors.toList()); pool = postgresService.getPool(); Future transactionResponseFuture = pool.withTransaction( sqlConnection -> { - // LOG.trace("inside createPolicy method"); + LOG.trace("createPolicy"); Promise promise1 = Promise.promise(); JsonObject constraints = null; try { @@ -522,7 +525,7 @@ public Future initiateTransactions(JsonObject notification) { } UUID policyId = UUID.randomUUID(); setPolicyId(policyId); - // + Tuple tuple = Tuple.of( policyId, @@ -532,37 +535,31 @@ public Future initiateTransactions(JsonObject notification) { "ACTIVE", getExpiryAt(), constraints); - // - // - // var one = sqlConnection - // .preparedQuery(CREATE_POLICY_QUERY) - // .collecting(rowListCollector) - // .execute(tuple) - // .map(rows -> rows.value()) - // .onSuccess( - // createPolicySuccess -> { - // boolean isListEmpty = - // createPolicySuccess.isEmpty(); - // if (isListEmpty) { - // promise1.fail("Something went wrong - // while creating the policy"); - // - // } else { - // LOG.debug("Create Policy successful : - // {}", createPolicySuccess); - // promise1.complete(true); - // } - // }) - // .onFailure( - // createPolicyFailed -> { - // LOG.error("Error while creating policy : " + - // createPolicyFailed); - // promise1.fail("Something went wrong while - // creating the policy"); - // }); - // - // - // LOG.trace("inside insertInApprovedAccessRequest method"); + + var one = + sqlConnection + .preparedQuery(CREATE_POLICY_QUERY) + .collecting(rowListCollector) + .execute(tuple) + .map(rows -> rows.value()) + .onSuccess( + createPolicySuccess -> { + boolean isListEmpty = createPolicySuccess.isEmpty(); + if (isListEmpty) { + promise1.fail("Something went wrong while creating the policy"); + + } else { + LOG.debug("Create Policy successful : {}", createPolicySuccess); + promise1.complete(true); + } + }) + .onFailure( + createPolicyFailed -> { + LOG.error("Error while creating policy : " + createPolicyFailed); + promise1.fail("Something went wrong while creating the policy"); + }); + + LOG.trace(" insertInApprovedAccessRequest "); UUID notificationId = UUID.fromString(notification.getString("requestId")); tuple = Tuple.of(notificationId, getPolicyId()); // @@ -570,280 +567,83 @@ public Future initiateTransactions(JsonObject notification) { Tuple approvedAccessRequestInsertionTuple = Tuple.of(uuid, notificationId, getPolicyId()); Promise promise2 = Promise.promise(); - // - // var two = sqlConnection - // .preparedQuery(INSERT_IN_APPROVED_ACCESS_REQUESTS_QUERY) - // .collecting(rowListCollector) - // .execute(approvedAccessRequestInsertionTuple) - // .map(rows -> rows.value()) - // .onSuccess( - // approvedAccessRequestInsertionSuccess -> { - // boolean isListEmpty = - // approvedAccessRequestInsertionSuccess.isEmpty(); - // if (isListEmpty) { - // LOG.error("list is empty while inserting - // approved_access_request"); - // promise2.fail("Something went wrong - // while approving the access request"); - // } else { - // LOG.info( - // "Insertion in - // approved_access_request successfully done : {}", - // - // approvedAccessRequestInsertionSuccess); - // promise2.complete(true); - // } - // }) - // .onFailure( - // insertionFailed -> { - // LOG.error("Error while inserting in - // approved_access_request : " + insertionFailed); - // promise2.fail("Something went wrong while - // approving access request"); - // }); - // - // + + var two = + sqlConnection + .preparedQuery(INSERT_IN_APPROVED_ACCESS_REQUESTS_QUERY) + .collecting(rowListCollector) + .execute(approvedAccessRequestInsertionTuple) + .map(rows -> rows.value()) + .onSuccess( + approvedAccessRequestInsertionSuccess -> { + boolean isListEmpty = approvedAccessRequestInsertionSuccess.isEmpty(); + if (isListEmpty) { + LOG.error("list is empty while inserting approved_access_request"); + promise2.fail( + "Something went wrong while approving the access request"); + } else { + LOG.info( + "Insertion in approved_access_request successfully done : {}", + approvedAccessRequestInsertionSuccess); + promise2.complete(true); + } + }) + .onFailure( + insertionFailed -> { + LOG.error( + "Error while inserting in approved_access_request : " + + insertionFailed); + promise2.fail("Something went wrong while approving access request"); + }); + Promise promise3 = Promise.promise(); - // LOG.trace("inside approveNotification method"); + LOG.trace("inside approveNotification method"); notificationId = UUID.fromString(notification.getString("requestId")); constraints = notification.getJsonObject("constraints"); final Tuple updateAccessRequestTuple = Tuple.of(getExpiryAt(), constraints, notificationId, getOwnerId()); - // var three = sqlConnection - // .preparedQuery(APPROVE_REQUEST_QUERY) - // .collecting(rowListCollector) - // .execute(updateAccessRequestTuple) - // .map(rows -> rows.value()) - // .onSuccess( - // approveAccessRequestSuccess -> { - // boolean isListEmpty = - // approveAccessRequestSuccess.isEmpty(); - // if (isListEmpty) { - // LOG.error("list is empty while updating - // notification"); - // promise3.fail("Something went wrong - // while approving access request"); - // } else { - // LOG.debug( - // "Approving Notification - // successfully done : {}", approveAccessRequestSuccess); - // JsonObject successResponse = - // new JsonObject() - // .put(TYPE, - // ResponseUrn.SUCCESS_URN.getUrn()) - // .put(TITLE, - // ResponseUrn.SUCCESS_URN.getMessage()) - // .put(DETAIL, "Request - // updated successfully") - // .put(STATUS_CODE, - // SUCCESS.getValue()); - // LOG.info("before promise is completed"); - // promise3.complete(successResponse); - // LOG.info("Success response is : " + - // successResponse.toString()); - // } - // }) - // .onFailure( - // updateNotificationFailure -> { - // LOG.error("Error while updating - // notification: " + updateNotificationFailure); - // promise3.fail("Something went wrong while - // approving access request"); - // }); - // var four = CompositeFuture.all(one, two, three) - // .compose(response -> - // { - // sqlConnection.close(); - // return promise3.future(); - // } - // ); - // - // _______________________________________________________________________________________ - - // var five = sqlConnection - // .preparedQuery(APPROVE_REQUEST_QUERY) - // .collecting(rowListCollector) - // .execute(updateAccessRequestTuple) - // .map(rows -> rows.value()) - // .compose(response1 -> { - // return sqlConnection - // .preparedQuery(APPROVE_REQUEST_QUERY) - // .collecting(rowListCollector) - // .execute(updateAccessRequestTuple) - // .map(rows -> rows.value()) - // .compose(response2 -> { - // return sqlConnection - // - // .preparedQuery(APPROVE_REQUEST_QUERY) - // .collecting(rowListCollector) - // .execute(updateAccessRequestTuple) - // .map(rows -> rows.value()) - // .onComplete(response3 -> { - // sqlConnection - // - // .preparedQuery(APPROVE_REQUEST_QUERY) - // - // .collecting(rowListCollector) - // - // .execute(updateAccessRequestTuple) - // .map(rows -> - // rows.value()) - // .onComplete(handler -> { - // boolean - // isResponse1Valid = !(response1.isEmpty()); - // boolean - // isResponse2Valid = !(response2.isEmpty()); - // if(isResponse1Valid - // && isResponse2Valid && response3.succeeded()) - // { - // - // sqlConnection.close(); - // JsonObject - // successResponse = - // new - // JsonObject() - // - // .put(TYPE, ResponseUrn.SUCCESS_URN.getUrn()) - // - // .put(TITLE, ResponseUrn.SUCCESS_URN.getMessage()) - // - // .put(DETAIL, "Request updated successfully") - // - // .put(STATUS_CODE, SUCCESS.getValue()); - // - // promise3.complete(successResponse); - // } - // }); - // - // }); - // }); - // }); - - // - // ------------------------------------------------------------------------------------- - // var six = sqlConnection - // .preparedQuery(APPROVE_REQUEST_QUERY) - // .execute(updateAccessRequestTuple) - // .compose(response1 -> { - // return sqlConnection - // .preparedQuery(APPROVE_REQUEST_QUERY) - // .execute(updateAccessRequestTuple) - // .compose(response2 -> { - // return sqlConnection - // - // .preparedQuery(APPROVE_REQUEST_QUERY) - // .execute(updateAccessRequestTuple) - // .onComplete(response3 -> { - // sqlConnection - // - // .preparedQuery(APPROVE_REQUEST_QUERY) - // - // .execute(updateAccessRequestTuple) - // .onComplete(handler -> { - // - // if(response3.succeeded()) - // { - // JsonObject - // successResponse = - // new - // JsonObject() - // - // .put(TYPE, ResponseUrn.SUCCESS_URN.getUrn()) - // - // .put(TITLE, ResponseUrn.SUCCESS_URN.getMessage()) - // - // .put(DETAIL, "Request updated successfully") - // - // .put(STATUS_CODE, SUCCESS.getValue()); - // - // promise3.complete(successResponse); - // } - // else - // { - // - // LOG.error("Something went wrong : ", handler.cause()); - // - // LOG.error("Failure : {}", handler.cause().getMessage()); - // - // failPromise(promise3, "Something went wrong while updating access request"); - // } - // }); - // - // }); - // }); - // }); - - // - // -------------------------------------------------------------------------------------------- - -// var seven = -// sqlConnection -// .preparedQuery(CREATE_POLICY_QUERY) -// .collecting(rowListCollector1) -// .execute(tuple) -// .map(row -> row.value()) -// .compose( -// response1 -> { -// LOG.info("Response 1 : {}", response1); -// return sqlConnection -// .preparedQuery(INSERT_IN_APPROVED_ACCESS_REQUESTS_QUERY) -// .collecting(rowListCollector2) -// .execute(approvedAccessRequestInsertionTuple) -// .map(row -> row.value()) -// .compose( -// response2 -> { -// LOG.info("Response 2 : {}", response2); -// return sqlConnection -// .preparedQuery(APPROVE_REQUEST_QUERY) -// .collecting(rowListCollector2) -// .execute(updateAccessRequestTuple) -// .map(row -> row.value()) -// .onComplete( -// response3 -> { -// sqlConnection -// .preparedQuery(APPROVE_REQUEST_QUERY) -// .collecting(rowListCollector3) -// .execute(updateAccessRequestTuple) -// .map(row -> row.value()) -// .onComplete( -// handler -> { -// if (response3.succeeded()) { -// LOG.info( -// "Response 3 : {}", -// handler.result()); -// JsonObject successResponse = -// new JsonObject() -// .put( -// TYPE, -// ResponseUrn.SUCCESS_URN -// .getUrn()) -// .put( -// TITLE, -// ResponseUrn.SUCCESS_URN -// .getMessage()) -// .put( -// DETAIL, -// "Request updated successfully") -// .put( -// STATUS_CODE, -// SUCCESS.getValue()); -// promise3.complete(successResponse); -// } else { -// LOG.error( -// "Something went wrong : ", -// handler.cause()); -// LOG.error( -// "Failure : {}", -// handler.cause().getMessage()); -// failPromise( -// promise3, -// "Something went wrong while updating access request"); -// } -// }); -// }); -// }); -// }); + var three = + sqlConnection + .preparedQuery(APPROVE_REQUEST_QUERY) + .collecting(rowListCollector) + .execute(updateAccessRequestTuple) + .map(rows -> rows.value()) + .onSuccess( + approveAccessRequestSuccess -> { + boolean isListEmpty = approveAccessRequestSuccess.isEmpty(); + if (isListEmpty) { + LOG.error("list is empty while updating notification"); + promise3.fail("Something went wrong while approving access request"); + } else { + LOG.debug( + "Approving Notification successfully done : {}", + approveAccessRequestSuccess); + JsonObject successResponse = + new JsonObject() + .put(TYPE, ResponseUrn.SUCCESS_URN.getUrn()) + .put(TITLE, ResponseUrn.SUCCESS_URN.getMessage()) + .put(DETAIL, "Request updated successfully") + .put(STATUS_CODE, SUCCESS.getValue()); + LOG.info("before promise is completed"); + promise3.complete(successResponse); + LOG.info("Success response is : " + successResponse.toString()); + } + }) + .onFailure( + updateNotificationFailure -> { + LOG.error( + "Error while updating notification: " + updateNotificationFailure); + promise3.fail("Something went wrong while approving access request"); + }); + var four = + CompositeFuture.all(one, two, three) + .compose( + response -> { + sqlConnection.close(); + return promise3.future(); + }); + // ------------------------------------------------------------------------------------------------------- var eight = sqlConnection .preparedQuery(CREATE_POLICY_QUERY) @@ -882,8 +682,8 @@ public Future initiateTransactions(JsonObject notification) { }); }); - return promise3.future(); - // return four; + // return promise3.future(); + return four; }); return transactionResponseFuture; } From 53dd7204fd91954c8b76a018a30c09fd441fc917 Mon Sep 17 00:00:00 2001 From: shreelakshmijoshi Date: Wed, 8 Nov 2023 13:54:51 +0530 Subject: [PATCH 03/22] Refactor UpdateNotification --- .../notification/UpdateNotification.java | 867 ++---------------- .../notification/TestUpdateNotifications.java | 259 ++---- 2 files changed, 144 insertions(+), 982 deletions(-) diff --git a/src/main/java/iudx/apd/acl/server/notification/UpdateNotification.java b/src/main/java/iudx/apd/acl/server/notification/UpdateNotification.java index 12e0611a..b82864e2 100644 --- a/src/main/java/iudx/apd/acl/server/notification/UpdateNotification.java +++ b/src/main/java/iudx/apd/acl/server/notification/UpdateNotification.java @@ -117,7 +117,7 @@ public Future initiateUpdateNotification(JsonObject notification, Us } return Future.failedFuture(ownershipCheckFuture.cause().getMessage()); }); - LOG.info("What is approvedRequestFuture : " + approvedRequestFuture); + return approvedRequestFuture; default: JsonObject failureMessage = @@ -129,103 +129,6 @@ public Future initiateUpdateNotification(JsonObject notification, Us } } - /** - * Approves the notification or request by changing the status field to GRANTED, updating - * the constraints and expiry given
- * by the Provider or provider delegate - * - * @param notification Request body from PUT notification API of type JsonObject - * @param query UPDATE query - * @param sqlConnection connection made to the DB to execute queries using transactions - * @return Success response or Failure response as Future JsonObject - */ - /*public Future approveNotification( - JsonObject notification, String query, SqlConnection sqlConnection) throws Exception { - LOG.trace("inside approveNotification method"); - Promise promise = Promise.promise(); - UUID notificationId = UUID.fromString(notification.getString("requestId")); - JsonObject constraints = notification.getJsonObject("constraints"); - - Tuple tuple = Tuple.of(getExpiryAt(), constraints, notificationId, getOwnerId()); - executeQuery( - sqlConnection, - query, - tuple, - handler -> { - if (handler.succeeded()) { - JsonArray result = handler.result().getJsonArray(RESULT); - boolean isResponseEmpty = result.isEmpty(); - */ - /* if the id is not returned back after execution, then record is not inserted*/ - /* - if (isResponseEmpty) { - LOG.error("Could not update request table while approving the request"); - JsonObject failureMessage = - new JsonObject() - .put(TYPE, HttpStatusCode.INTERNAL_SERVER_ERROR.getValue()) - .put(TITLE, ResponseUrn.DB_ERROR_URN.getUrn()) - .put(DETAIL, "Failure while executing query"); - promise.fail(failureMessage.encode()); - } else { - JsonObject successResponse = - new JsonObject() - .put(TYPE, ResponseUrn.SUCCESS_URN.getUrn()) - .put(TITLE, ResponseUrn.SUCCESS_URN.getMessage()) - .put(DETAIL, "Request updated successfully") - .put(STATUS_CODE, SUCCESS.getValue()); - promise.complete(successResponse); - } - } else { - promise.fail(handler.cause().getMessage()); - } - }); - return promise.future(); - } - */ - - public Future approveNotification( - JsonObject notification, String query, SqlConnection sqlConnection) throws Exception { - Collector> rowListCollector = - Collectors.mapping(row -> row.toJson(), Collectors.toList()); - LOG.trace("inside approveNotification method"); - Promise promise = Promise.promise(); - UUID notificationId = UUID.fromString(notification.getString("requestId")); - JsonObject constraints = notification.getJsonObject("constraints"); - final Tuple updateAccessRequestTuple = - Tuple.of(getExpiryAt(), constraints, notificationId, getOwnerId()); - sqlConnection - .preparedQuery(APPROVE_REQUEST_QUERY) - .collecting(rowListCollector) - .execute(updateAccessRequestTuple) - .map(rows -> rows.value()) - .onSuccess( - approveAccessRequestSuccess -> { - boolean isListEmpty = approveAccessRequestSuccess.isEmpty(); - if (isListEmpty) { - LOG.error("list is empty while updating notification"); - promise.fail("Something went wrong while approving access request"); - } else { - LOG.debug( - "Approving Notification successfully done : {}", approveAccessRequestSuccess); - JsonObject successResponse = - new JsonObject() - .put(TYPE, ResponseUrn.SUCCESS_URN.getUrn()) - .put(TITLE, ResponseUrn.SUCCESS_URN.getMessage()) - .put(DETAIL, "Request updated successfully") - .put(STATUS_CODE, SUCCESS.getValue()); - LOG.info("before promise is completed"); - promise.complete(successResponse); - LOG.info("Success response is : " + successResponse.toString()); - } - }) - .onFailure( - updateNotificationFailure -> { - LOG.error("Error while updating notification: " + updateNotificationFailure); - promise.fail("Something went wrong while approving access request"); - }); - return promise.future(); - } - /** * This method is used to initiate policy creation, inserting approved request and updating the * approved request
@@ -234,299 +137,21 @@ public Future approveNotification( * using vert.x pool.withTransaction method * * @param notification Request body from PUT notification API of type JsonObject - * @return Final Success or Failure response to be presented to the user of type Future + * @return Final Success or Failure response to be presented as Future of Boolean with it being + * true when the transaction is successful and failure message in the Future if some failure + * occurs */ - - // TODO : refactor the initiateTransactions method by doing the following steps - // do not call any method - // use compose blocks - // do not return primary key from the query, make the primary key - // maybe even complete the transaction from here - - /* public Future initiateTransactions(JsonObject notification) { - LOG.trace("inside initiateTransactions method"); - pool = postgresService.getPool(); - Future transactionResponseFuture = - pool.withTransaction( - sqlConnection -> { - Future createPolicyFuture = null; - try { - createPolicyFuture = createPolicy(notification, CREATE_POLICY_QUERY, sqlConnection); - } catch (Exception e) { - LOG.error("Error while creating policy: {}", e.getMessage()); - return Future.failedFuture( - getFailureMessage( - INTERNAL_SERVER_ERROR.getValue(), - ResponseUrn.BACKING_SERVICE_FORMAT_URN, - "Something went wrong while creating the policy")); - } - - Future finalCreatePolicyFuture = createPolicyFuture; - Future approvedAccessRequestsInsertionFuture = - createPolicyFuture.compose( - isPolicySuccessFullyCreated -> { - if (isPolicySuccessFullyCreated) { - try { - return insertInApprovedAccessRequest( - notification, - INSERT_IN_APPROVED_ACCESS_REQUESTS_QUERY, - sqlConnection); - } catch (Exception e) { - LOG.error( - "Error while inserting record in approved access request: {}", - e.getMessage()); - return Future.failedFuture( - getFailureMessage( - INTERNAL_SERVER_ERROR.getValue(), - ResponseUrn.BACKING_SERVICE_FORMAT_URN, - "Something went wrong while approving access request")); - } - } - return Future.failedFuture(finalCreatePolicyFuture.cause().getMessage()); - }); - - Future approvedNotificationFuture = - approvedAccessRequestsInsertionFuture.compose( - isSuccessFullyInserted -> { - if (isSuccessFullyInserted) { - try { - return approveNotification( - notification, APPROVE_REQUEST_QUERY, sqlConnection); - } catch (Exception e) { - LOG.error("Error while updating notification: {}", e.getMessage()); - return Future.failedFuture( - getFailureMessage( - INTERNAL_SERVER_ERROR.getValue(), - ResponseUrn.BACKING_SERVICE_FORMAT_URN, - "Something went wrong while approving access request")); - } - } - return Future.failedFuture( - approvedAccessRequestsInsertionFuture.cause().getMessage()); - }); - return approvedNotificationFuture; - }); - return transactionResponseFuture; - }*/ - - // public Future initiateTransactions(JsonObject notification) { - // Promise promise = Promise.promise(); - // LOG.trace("inside initiateTransactions method"); - // Collector> rowListCollector = - // Collectors.mapping(row -> row.toJson(), Collectors.toList()); - // - // pool = postgresService.getPool(); - // Future transactionResponseFuture = - // pool.withTransaction( - // sqlConnection -> { - // JsonObject constraints = null; - // try { - // - // constraints = notification.getJsonObject("constraints"); - // LOG.debug("constraints : {}", constraints); - // if (constraints == null) { - // throw new NullPointerException("Invalid or null constraints in the request - // body"); - // } - // } catch (Exception exception) { - // LOG.error("Error : {}", exception.getMessage()); - // failPromise(promise, "Invalid or null constraints in the request body"); - // return promise.future(); - // } - // UUID policyId = UUID.randomUUID(); - // setPolicyId(policyId); - // - // Tuple tuple = - // Tuple.of( - // policyId, - // getConsumerEmailId(), - // getItemId(), - // getOwnerId(), - // "ACTIVE", - // getExpiryAt(), - // constraints); - // - // sqlConnection - // .preparedQuery(CREATE_POLICY_QUERY) - // .collecting(rowListCollector) - // .execute(tuple) - // .map(rows -> rows.value()) - // .onSuccess( - // createPolicySuccess -> { - // boolean isListEmpty = createPolicySuccess.isEmpty(); - // if (isListEmpty) { - // failPromise(promise, "Something went wrong while creating the - // policy"); - // - // } else { - // LOG.debug("Create Policy successful : {}", createPolicySuccess); - // // promise.complete(new - // JsonObject().put(RESULT, - // // createPolicySuccess)); - // } - // }) - // .onFailure( - // createPolicyFailed -> { - // LOG.error("Error while creating policy : " + createPolicyFailed); - // failPromise(promise, "Something went wrong while creating the policy"); - // }) - // .compose( - // insertionHandler -> { - // Promise promise2 = Promise.promise(); - // final UUID notificationId = - // UUID.fromString(notification.getString("requestId")); - // UUID uuid = UUID.randomUUID(); - // - // - // Tuple approvedAccessRequestInsertionTuple = - // Tuple.of(uuid, notificationId, getPolicyId()); - // sqlConnection - // .preparedQuery(INSERT_IN_APPROVED_ACCESS_REQUESTS_QUERY) - // .collecting(rowListCollector) - // .execute(approvedAccessRequestInsertionTuple) - // .map(rows -> rows.value()) - // .onSuccess( - // approvedAccessRequestInsertionSuccess -> { - // boolean isListEmpty = - // approvedAccessRequestInsertionSuccess.isEmpty(); - // if (isListEmpty) { - // LOG.error( - // "list is empty while inserting - // approved_access_request"); - // failPromise( - // promise2, - // "Something went wrong while approving the access - // request"); - // } else { - // LOG.info( - // "Insertion in approved_access_request successfully done - // : {}", - // approvedAccessRequestInsertionSuccess); - // // promise.complete(new - // // - // JsonObject().put(RESULT,approvedAccessRequestInsertionSuccess)); - // } - // }) - // .onFailure( - // insertionFailed -> { - // LOG.error( - // "Error while inserting in approved_access_request : " - // + insertionFailed); - // failPromise( - // promise2, - // "Something went wrong while approving access request"); - // }) - // .compose( - // updateNotificationHandler -> { - // Promise promise3 = Promise.promise(); - // final JsonObject constraints1 = - // notification.getJsonObject("constraints"); - // - // final Tuple updateAccessRequestTuple = - // Tuple.of( - // getExpiryAt(), - // constraints1, - // notificationId, - // getOwnerId()); - // - // sqlConnection - // .preparedQuery(APPROVE_REQUEST_QUERY) - // .collecting(rowListCollector) - // .execute(updateAccessRequestTuple) - // .map(rows -> rows.value()) - // .onSuccess( - // approveAccessRequestSuccess -> { - // boolean isListEmpty = - // approveAccessRequestSuccess.isEmpty(); - // if (isListEmpty) { - // LOG.error( - // "list is empty while updating notification"); - // failPromise( - // promise3, - // "Something went wrong while approving access - // request"); - // } else { - // LOG.debug( - // "Approving Notification successfully done : - // {}", - // approveAccessRequestSuccess); - // JsonObject successResponse = - // new JsonObject() - // .put(TYPE, - // ResponseUrn.SUCCESS_URN.getUrn()) - // .put( - // TITLE, - // ResponseUrn.SUCCESS_URN.getMessage()) - // .put(DETAIL, "Request updated - // successfully") - // .put(STATUS_CODE, SUCCESS.getValue()); - // LOG.info("before promise is completed"); - // promise3.complete(successResponse); - // LOG.info("Success response is : " + - // successResponse.toString()); - // } - // }) - // .onFailure( - // updateNotificationFailure -> { - // LOG.error( - // "Error while updating notification: " - // + updateNotificationFailure); - // failPromise( - // promise3, - // "Something went wrong while approving access - // request"); - // }); - // LOG.info("this is the actual promise : promise3" ); - // return promise3.future(); - // }); - // LOG.info("this is 2nd promise"); - // return promise2.future(); - // }); - // LOG.info("promise is here"); - // return promise.future(); // this future is being returned - // }); - // LOG.info("it is not returned"); - // return transactionResponseFuture; // here - // } - public Future initiateTransactions(JsonObject notification) { LOG.trace("inside initiateTransactions method"); - - Collector> rowListCollector = - Collectors.mapping(row -> row.toJson(), Collectors.toList()); - Collector> rowListCollector1 = - Collectors.mapping(row -> row.toJson(), Collectors.toList()); - Collector> rowListCollector2 = - Collectors.mapping(row -> row.toJson(), Collectors.toList()); - Collector> rowListCollector3 = - Collectors.mapping(row -> row.toJson(), Collectors.toList()); pool = postgresService.getPool(); Future transactionResponseFuture = pool.withTransaction( sqlConnection -> { - LOG.trace("createPolicy"); - Promise promise1 = Promise.promise(); - JsonObject constraints = null; - try { - - constraints = notification.getJsonObject("constraints"); - LOG.debug("constraints : {}", constraints); - if (constraints == null) { - throw new NullPointerException("Invalid or null constraints in the request body"); - } - } catch (Exception exception) { - LOG.error("Error : {}", exception.getMessage()); - JsonObject failureMessage = - new JsonObject() - .put(TYPE, BAD_REQUEST.getValue()) - .put(TITLE, BAD_REQUEST.getUrn()) - .put(DETAIL, "Invalid or null constraints in the request body"); - return Future.failedFuture(failureMessage.encode()); - } + JsonObject constraints = notification.getJsonObject("constraints"); UUID policyId = UUID.randomUUID(); setPolicyId(policyId); - Tuple tuple = + Tuple createPolicyTuple = Tuple.of( policyId, getConsumerEmailId(), @@ -536,257 +161,79 @@ public Future initiateTransactions(JsonObject notification) { getExpiryAt(), constraints); - var one = + var response = sqlConnection .preparedQuery(CREATE_POLICY_QUERY) - .collecting(rowListCollector) - .execute(tuple) - .map(rows -> rows.value()) - .onSuccess( - createPolicySuccess -> { - boolean isListEmpty = createPolicySuccess.isEmpty(); - if (isListEmpty) { - promise1.fail("Something went wrong while creating the policy"); - - } else { - LOG.debug("Create Policy successful : {}", createPolicySuccess); - promise1.complete(true); - } - }) - .onFailure( - createPolicyFailed -> { - LOG.error("Error while creating policy : " + createPolicyFailed); - promise1.fail("Something went wrong while creating the policy"); - }); - - LOG.trace(" insertInApprovedAccessRequest "); - UUID notificationId = UUID.fromString(notification.getString("requestId")); - tuple = Tuple.of(notificationId, getPolicyId()); - // - UUID uuid = UUID.randomUUID(); - Tuple approvedAccessRequestInsertionTuple = - Tuple.of(uuid, notificationId, getPolicyId()); - Promise promise2 = Promise.promise(); - - var two = - sqlConnection - .preparedQuery(INSERT_IN_APPROVED_ACCESS_REQUESTS_QUERY) - .collecting(rowListCollector) - .execute(approvedAccessRequestInsertionTuple) - .map(rows -> rows.value()) - .onSuccess( - approvedAccessRequestInsertionSuccess -> { - boolean isListEmpty = approvedAccessRequestInsertionSuccess.isEmpty(); - if (isListEmpty) { - LOG.error("list is empty while inserting approved_access_request"); - promise2.fail( - "Something went wrong while approving the access request"); - } else { - LOG.info( - "Insertion in approved_access_request successfully done : {}", - approvedAccessRequestInsertionSuccess); - promise2.complete(true); - } - }) - .onFailure( - insertionFailed -> { - LOG.error( - "Error while inserting in approved_access_request : " - + insertionFailed); - promise2.fail("Something went wrong while approving access request"); - }); - - Promise promise3 = Promise.promise(); - LOG.trace("inside approveNotification method"); - notificationId = UUID.fromString(notification.getString("requestId")); - constraints = notification.getJsonObject("constraints"); - final Tuple updateAccessRequestTuple = - Tuple.of(getExpiryAt(), constraints, notificationId, getOwnerId()); - var three = - sqlConnection - .preparedQuery(APPROVE_REQUEST_QUERY) - .collecting(rowListCollector) - .execute(updateAccessRequestTuple) - .map(rows -> rows.value()) - .onSuccess( - approveAccessRequestSuccess -> { - boolean isListEmpty = approveAccessRequestSuccess.isEmpty(); - if (isListEmpty) { - LOG.error("list is empty while updating notification"); - promise3.fail("Something went wrong while approving access request"); - } else { - LOG.debug( - "Approving Notification successfully done : {}", - approveAccessRequestSuccess); - JsonObject successResponse = - new JsonObject() - .put(TYPE, ResponseUrn.SUCCESS_URN.getUrn()) - .put(TITLE, ResponseUrn.SUCCESS_URN.getMessage()) - .put(DETAIL, "Request updated successfully") - .put(STATUS_CODE, SUCCESS.getValue()); - LOG.info("before promise is completed"); - promise3.complete(successResponse); - LOG.info("Success response is : " + successResponse.toString()); - } - }) - .onFailure( - updateNotificationFailure -> { - LOG.error( - "Error while updating notification: " + updateNotificationFailure); - promise3.fail("Something went wrong while approving access request"); - }); - var four = - CompositeFuture.all(one, two, three) - .compose( - response -> { - sqlConnection.close(); - return promise3.future(); - }); - - // ------------------------------------------------------------------------------------------------------- - var eight = - sqlConnection - .preparedQuery(CREATE_POLICY_QUERY) - .collecting(rowListCollector1) - .execute(tuple) - .map(row -> row.value()) + .execute(createPolicyTuple) .compose( - response1 -> { - LOG.info("Response 1 : {}", response1); + policyCreatedSuccessfully -> { + LOG.info("Policy created successfully"); + UUID notificationId = + UUID.fromString(notification.getString("requestId")); + UUID uuid = UUID.randomUUID(); + + Tuple approvedAccessRequestInsertionTuple = + Tuple.of(uuid, notificationId, getPolicyId()); return sqlConnection .preparedQuery(INSERT_IN_APPROVED_ACCESS_REQUESTS_QUERY) - .collecting(rowListCollector2) - .execute(approvedAccessRequestInsertionTuple) - .map(row -> row.value()) - .compose( - response2 -> { - LOG.info("Response 2 : {}", response2); - return sqlConnection - .preparedQuery(APPROVE_REQUEST_QUERY) - .collecting(rowListCollector2) - .execute(updateAccessRequestTuple) - .map(row -> row.value()) - .onComplete( - response3 -> { - LOG.info("Response 3 : {}", response3); - JsonObject successResponse = - new JsonObject() - .put(TYPE, ResponseUrn.SUCCESS_URN.getUrn()) - .put( - TITLE, - ResponseUrn.SUCCESS_URN.getMessage()) - .put(DETAIL, "Request updated successfully") - .put(STATUS_CODE, SUCCESS.getValue()); - promise3.complete(successResponse); - }); - }); + .execute(approvedAccessRequestInsertionTuple); + }) + .compose( + approvedAccessRequestInsertion -> { + LOG.info( + "Inserted record successfully in approved access request : " + + notification.getString("requestId")); + UUID notificationId = + UUID.fromString(notification.getString("requestId")); + Tuple updateAccessRequestTuple = + Tuple.of(getExpiryAt(), constraints, notificationId, getOwnerId()); + return sqlConnection + .preparedQuery(APPROVE_REQUEST_QUERY) + .execute(updateAccessRequestTuple); + }) + .compose( + updatedNotificationSuccessful -> { + LOG.info("Updated Notification successfully"); + JsonObject successResponse = + new JsonObject() + .put(TYPE, ResponseUrn.SUCCESS_URN.getUrn()) + .put(TITLE, ResponseUrn.SUCCESS_URN.getMessage()) + .put(DETAIL, "Request updated successfully") + .put(STATUS_CODE, SUCCESS.getValue()); + return Future.succeededFuture(successResponse); }); - // return promise3.future(); - return four; + return response; }); - return transactionResponseFuture; - } - - private void failPromise(Promise promise, String failureMessage) { - promise.fail( - getFailureMessage( - INTERNAL_SERVER_ERROR.getValue(), - ResponseUrn.BACKING_SERVICE_FORMAT_URN, - failureMessage)); - } - - /** - * Inserts a record in approved_access_request table by inserting the notificationId and policyId - *
- * when the notification is successfully approved or granted by the provider or provider delegate - * - * @param notification Request body from PUT notification API of type JsonObject - * @param query Insertion query - * @param sqlConnection connection made to the DB to execute the query - * @return True, if the record is successfully inserted, failure if any in the form of Future - */ - /* public Future insertInApprovedAccessRequest( - JsonObject notification, String query, SqlConnection sqlConnection) throws Exception { - LOG.trace("inside insertInApprovedAccessRequest method"); - Promise promise = Promise.promise(); - - UUID notificationId = UUID.fromString(notification.getString("requestId")); - Tuple tuple = Tuple.of(notificationId, getPolicyId()); - executeQuery( - sqlConnection, - query, - tuple, - handler -> { - if (handler.succeeded()) { - JsonObject result = handler.result().getJsonArray(RESULT).getJsonObject(0); - boolean isResponseEmpty = result.isEmpty(); - */ - /* if the id is not returned back after execution, then record is not inserted*/ - /* - if (isResponseEmpty) { - LOG.error("Could not insert in approved request access table"); - JsonObject failureMessage = - new JsonObject() - .put(TYPE, HttpStatusCode.INTERNAL_SERVER_ERROR.getValue()) - .put(TITLE, ResponseUrn.DB_ERROR_URN.getUrn()) - .put(DETAIL, "Failure while executing query"); - promise.fail(failureMessage.encode()); - } else { - LOG.debug( - "Successfully inserted in approved_access_request with id {}", - result.getString("_id")); - promise.complete(true); + transactionResponseFuture = transactionResponseFuture.recover( + /* some exception occurred while fetching constraints */ + failure -> { + LOG.error("Error : " + failure); + if(failure instanceof ClassCastException) + { + JsonObject failureMessage = + new JsonObject() + .put(TYPE, BAD_REQUEST.getValue()) + .put(TITLE, ResponseUrn.BAD_REQUEST_URN.getUrn()) + .put(DETAIL, "Invalid or null constraint"); + return Future.failedFuture(failureMessage.encode()); } - } else { - promise.fail(handler.cause().getMessage()); - } + /* something went wrong while creating a policy + or while inserting a record in approved access request + or while updating the notification*/ + JsonObject failureMessage = + new JsonObject() + .put(TYPE, INTERNAL_SERVER_ERROR.getValue()) + .put(TITLE, ResponseUrn.DB_ERROR_URN.getUrn()) + .put(DETAIL, + "Something went wrong while approving access request"); + return Future.failedFuture(failureMessage.encode()); }); - return promise.future(); - }*/ - - public Future insertInApprovedAccessRequest( - JsonObject notification, String query, SqlConnection sqlConnection) throws Exception { - LOG.trace("inside insertInApprovedAccessRequest method"); - Promise promise = Promise.promise(); - Collector> rowListCollector = - Collectors.mapping(row -> row.toJson(), Collectors.toList()); - UUID notificationId = UUID.fromString(notification.getString("requestId")); - Tuple tuple = Tuple.of(notificationId, getPolicyId()); - - UUID uuid = UUID.randomUUID(); - Tuple approvedAccessRequestInsertionTuple = Tuple.of(uuid, notificationId, getPolicyId()); - - sqlConnection - .preparedQuery(INSERT_IN_APPROVED_ACCESS_REQUESTS_QUERY) - .collecting(rowListCollector) - .execute(approvedAccessRequestInsertionTuple) - .map(rows -> rows.value()) - .onSuccess( - approvedAccessRequestInsertionSuccess -> { - boolean isListEmpty = approvedAccessRequestInsertionSuccess.isEmpty(); - if (isListEmpty) { - LOG.error("list is empty while inserting approved_access_request"); - promise.fail("Something went wrong while approving the access request"); - } else { - LOG.info( - "Insertion in approved_access_request successfully done : {}", - approvedAccessRequestInsertionSuccess); - promise.complete(true); - // promise.complete(new - // JsonObject().put(RESULT,approvedAccessRequestInsertionSuccess)); - } - }) - .onFailure( - insertionFailed -> { - LOG.error("Error while inserting in approved_access_request : " + insertionFailed); - promise.fail("Something went wrong while approving access request"); - }); - return promise.future(); + return transactionResponseFuture; } - /** + /** * Checks if the given user who is requesting to approve the notification of the consumer is * owning the resource * @@ -825,134 +272,6 @@ public Future checkOwner4GivenResource(String query) { return promise.future(); } - /** - * Creates a policy by giving the information about consumer, owner, resource and expiry of the - * policy - * - * @param notification Request body as JsonObject - * @param query INSERT query to insert a new record for policy table - * @param sqlConnection object for executing the query by connecting to the DB - * @return True, if a policy is successfully created, or failure if of type Future - */ -/* public Future createPolicy( - JsonObject notification, String query, SqlConnection sqlConnection) throws Exception { - LOG.trace("inside createPolicy method"); - Promise promise = Promise.promise(); - JsonObject constraints = null; - try { - - constraints = notification.getJsonObject("constraints"); - LOG.debug("constraints : {}", constraints); - if (constraints == null) { - throw new NullPointerException("Invalid or null constraints in the request body"); - } - } catch (Exception exception) { - LOG.error("Error : {}", exception.getMessage()); - JsonObject failureMessage = - new JsonObject() - .put(TYPE, BAD_REQUEST.getValue()) - .put(TITLE, BAD_REQUEST.getUrn()) - .put(DETAIL, "Invalid or null constraints in the request body"); - return Future.failedFuture(failureMessage.encode()); - } - - Tuple tuple = - Tuple.of( - getConsumerEmailId(), getItemId(), getOwnerId(), "ACTIVE", getExpiryAt(), constraints); - - executeQuery( - sqlConnection, - query, - tuple, - handler -> { - if (handler.succeeded()) { - JsonObject result = handler.result().getJsonArray(RESULT).getJsonObject(0); - *//*policy is created successfully and the policy id is returned *//* - if (!result.isEmpty()) { - *//* set policyId *//* - UUID policyId = UUID.fromString(result.getString("_id")); - setPolicyId(policyId); - LOG.trace("Policy created successfully with policyId: {}", result.getString("_id")); - promise.complete(true); - } else { - LOG.error("Could not create policy : {}", handler.cause().getMessage()); - JsonObject failureMessage = - new JsonObject() - .put(TYPE, HttpStatusCode.INTERNAL_SERVER_ERROR.getValue()) - .put(TITLE, ResponseUrn.DB_ERROR_URN.getUrn()) - .put(DETAIL, "Failure while executing query"); - - promise.fail(failureMessage.encode()); - } - } else { - promise.fail(handler.cause().getMessage()); - } - }); - return promise.future(); - }*/ - - public Future createPolicy( - JsonObject notification, String query, SqlConnection sqlConnection) throws Exception { - Collector> rowListCollector = - Collectors.mapping(row -> row.toJson(), Collectors.toList()); - - LOG.trace("inside createPolicy method"); - Promise promise = Promise.promise(); - JsonObject constraints = null; - try { - - constraints = notification.getJsonObject("constraints"); - LOG.debug("constraints : {}", constraints); - if (constraints == null) { - throw new NullPointerException("Invalid or null constraints in the request body"); - } - } catch (Exception exception) { - LOG.error("Error : {}", exception.getMessage()); - JsonObject failureMessage = - new JsonObject() - .put(TYPE, BAD_REQUEST.getValue()) - .put(TITLE, BAD_REQUEST.getUrn()) - .put(DETAIL, "Invalid or null constraints in the request body"); - return Future.failedFuture(failureMessage.encode()); - } - UUID policyId = UUID.randomUUID(); - setPolicyId(policyId); - - Tuple tuple = - Tuple.of( - policyId, - getConsumerEmailId(), - getItemId(), - getOwnerId(), - "ACTIVE", - getExpiryAt(), - constraints); - - - sqlConnection - .preparedQuery(query) - .collecting(rowListCollector) - .execute(tuple) - .map(rows -> rows.value()) - .onSuccess( - createPolicySuccess -> { - boolean isListEmpty = createPolicySuccess.isEmpty(); - if (isListEmpty) { - promise.fail("Something went wrong while creating the policy"); - - } else { - LOG.debug("Create Policy successful : {}", createPolicySuccess); - promise.complete(true); - } - }) - .onFailure( - createPolicyFailed -> { - LOG.error("Error while creating policy : " + createPolicyFailed); - promise.fail("Something went wrong while creating the policy"); - }); - return promise.future(); - } - /** * Checks if the expiryAt value given the request body of the PUT Notification, is greater than * the present time @@ -1208,60 +527,6 @@ public void executeQuery(String query, Tuple tuple, Handler - * the transaction which gives the sql connection rolls back
- * to the original state - * - * @param query to be executes - * @param tuple exchangeable values to be added in the query - * @param handler AsyncResult JsonObject handler - * @param sqlConnection is a connection to the database to execute transaction using a single - * connection
- */ - public void executeQuery( - SqlConnection sqlConnection, - String query, - Tuple tuple, - Handler> handler) { - LOG.trace("inside executeQuery method"); - Collector> rowListCollector = - Collectors.mapping(row -> row.toJson(), Collectors.toList()); - sqlConnection - .preparedQuery(query) - .collecting(rowListCollector) - .execute(tuple) - .map(rows -> rows.value()) - .onSuccess( - successHandler -> { - JsonArray response = new JsonArray(successHandler); - JsonObject responseJson = - new JsonObject() - .put(TYPE, ResponseUrn.SUCCESS_URN.getUrn()) - .put(TITLE, ResponseUrn.SUCCESS_URN.getMessage()) - .put(RESULT, response); - handler.handle(Future.succeededFuture(responseJson)); - }) - .onFailure( - failureHandler -> { - LOG.error( - "Failure while executing the transaction : {},{}", - failureHandler.getMessage(), - query); - JsonObject response = - new JsonObject() - .put(TYPE, HttpStatusCode.INTERNAL_SERVER_ERROR.getValue()) - .put(TITLE, ResponseUrn.DB_ERROR_URN.getUrn()) - .put(DETAIL, "Failure while executing transaction"); - handler.handle(Future.failedFuture(response.encode())); - }); - } - - public String getFailureMessage(int type, ResponseUrn title, String detail) { - return new JsonObject().put(TYPE, type).put(TITLE, title.getUrn()).put(DETAIL, detail).encode(); - } - public UUID getOwnerId() { return ownerId; } diff --git a/src/test/java/iudx/apd/acl/server/notification/TestUpdateNotifications.java b/src/test/java/iudx/apd/acl/server/notification/TestUpdateNotifications.java index 98376469..88108e3d 100644 --- a/src/test/java/iudx/apd/acl/server/notification/TestUpdateNotifications.java +++ b/src/test/java/iudx/apd/acl/server/notification/TestUpdateNotifications.java @@ -5,16 +5,18 @@ import static iudx.apd.acl.server.apiserver.util.Constants.*; import static iudx.apd.acl.server.common.HttpStatusCode.*; import static iudx.apd.acl.server.common.HttpStatusCode.INTERNAL_SERVER_ERROR; -import static iudx.apd.acl.server.common.ResponseUrn.FORBIDDEN_URN; -import static iudx.apd.acl.server.common.ResponseUrn.POLICY_ALREADY_EXIST_URN; +import static iudx.apd.acl.server.common.ResponseUrn.*; import static iudx.apd.acl.server.notification.util.Constants.*; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.*; +import io.vertx.core.AsyncResult; import io.vertx.core.Future; +import io.vertx.core.Handler; import io.vertx.core.json.JsonArray; import io.vertx.core.json.JsonObject; +import io.vertx.ext.web.client.HttpResponse; import io.vertx.junit5.VertxExtension; import io.vertx.junit5.VertxTestContext; import io.vertx.pgclient.PgPool; @@ -24,6 +26,8 @@ import iudx.apd.acl.server.common.HttpStatusCode; import iudx.apd.acl.server.common.ResponseUrn; import iudx.apd.acl.server.policy.PostgresService; + +import java.nio.Buffer; import java.time.LocalDateTime; import java.util.List; import java.util.UUID; @@ -31,7 +35,9 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.invocation.InvocationOnMock; import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.stubbing.Answer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testcontainers.containers.PostgreSQLContainer; @@ -646,10 +652,8 @@ public void testApproveNotificationWithPolicyAlreadyCreated(VertxTestContext ver } @Test - @DisplayName("Test createPolicy method with invalid constraints") - public void testCreatePolicyWithInvalidConstraint(VertxTestContext vertxTestContext) - throws Exception { - SqlConnection sqlConnection = mock(SqlConnection.class); + @DisplayName("Test initiateTransactions with invalid constraints") + public void testInitiateTransactionsWithInvalidConstraint(VertxTestContext vertxTestContext) { JsonObject approveNotification = new JsonObject() @@ -658,7 +662,7 @@ public void testCreatePolicyWithInvalidConstraint(VertxTestContext vertxTestCont .put("expiryAt", expiryTime) .put("constraints", "constraints"); updateNotification - .createPolicy(approveNotification, CREATE_POLICY_QUERY, sqlConnection) + .initiateTransactions(approveNotification) .onComplete( handler -> { if (handler.succeeded()) { @@ -668,7 +672,7 @@ public void testCreatePolicyWithInvalidConstraint(VertxTestContext vertxTestCont new JsonObject() .put(TYPE, BAD_REQUEST.getValue()) .put(TITLE, ResponseUrn.BAD_REQUEST_URN.getUrn()) - .put(DETAIL, "Invalid or null constraints in the request body"); + .put(DETAIL, "Invalid or null constraint"); assertEquals(failure.encode(), handler.cause().getMessage()); vertxTestContext.completeNow(); } @@ -762,150 +766,7 @@ public void testCheckOwner4GivenResource(VertxTestContext vertxTestContext) { }); } - @Test - @DisplayName("Test insertInApprovedAccessRequest method when the response from the DB is empty") - public void testInsertInApprovedAccessRequest(VertxTestContext vertxTestContext) - throws Exception { - container.start(); - Utility utility = new Utility(); - PostgresService postgresService = utility.setUp(container); - utility.testInsert(); - UUID policyId = UUID.randomUUID(); - UUID requestId = UUID.randomUUID(); - - JsonObject failureMessage = - new JsonObject() - .put(TYPE, HttpStatusCode.INTERNAL_SERVER_ERROR.getValue()) - .put(TITLE, ResponseUrn.DB_ERROR_URN.getUrn()) - .put(DETAIL, "Failure while executing transaction"); - JsonObject approveNotification = - new JsonObject() - .put("requestId", requestId) - .put("status", "granted") - .put("expiryAt", expiryTime) - .put("constraints", "constraints"); - UpdateNotification updateNotification = new UpdateNotification(postgresService); - - updateNotification.setPolicyId(policyId); - - PgPool pool = postgresService.getPool(); - pool.withTransaction( - sqlConnection -> { - try { - return updateNotification - .insertInApprovedAccessRequest( - approveNotification, INSERT_IN_APPROVED_ACCESS_REQUESTS_QUERY, sqlConnection) - .onComplete( - handler -> { - if (handler.succeeded()) { - vertxTestContext.failNow( - "Succeeded with invalid requestId and while Database throws an error"); - } else { - assertEquals(failureMessage.encode(), handler.cause().getMessage()); - vertxTestContext.completeNow(); - } - }); - } catch (Exception e) { - throw new RuntimeException(e); - } - }); - } - - @Test - @DisplayName("Test approveNotification method when the response from the DB is empty") - public void testApproveNotification(VertxTestContext vertxTestContext) throws Exception { - container.start(); - Utility utility = new Utility(); - PostgresService postgresService = utility.setUp(container); - utility.testInsert(); - UUID requestId = UUID.randomUUID(); - JsonObject failureMessage = - new JsonObject() - .put(TYPE, HttpStatusCode.INTERNAL_SERVER_ERROR.getValue()) - .put(TITLE, ResponseUrn.DB_ERROR_URN.getUrn()) - .put(DETAIL, "Failure while executing query"); - - JsonObject approveNotification = - new JsonObject() - .put("requestId", requestId) - .put("status", "granted") - .put("expiryAt", expiryTime) - .put("constraints", constraints); - PgPool pool = postgresService.getPool(); - UpdateNotification updateNotification = new UpdateNotification(postgresService); - - pool.withTransaction( - sqlConnection -> { - try { - return updateNotification - .approveNotification(approveNotification, APPROVE_REQUEST_QUERY, sqlConnection) - .onComplete( - handler -> { - if (handler.succeeded()) { - vertxTestContext.failNow( - "Succeeded with invalid requestId and while Database throws an error"); - } else { - assertEquals(failureMessage.encode(), handler.cause().getMessage()); - vertxTestContext.completeNow(); - } - }); - } catch (Exception e) { - vertxTestContext.failNow("something went wrong"); - throw new RuntimeException(e); - } - }); - } - - @Test - @DisplayName("Test createPolicy method when there is failure response from DB ") - public void testCreatePolicy(VertxTestContext vertxTestContext) throws Exception { - container.start(); - Utility utility = new Utility(); - PostgresService postgresService = utility.setUp(container); - utility.testInsert(); - UUID requestId = UUID.randomUUID(); - JsonObject failureMessage = - new JsonObject() - .put(TYPE, HttpStatusCode.INTERNAL_SERVER_ERROR.getValue()) - .put(TITLE, ResponseUrn.DB_ERROR_URN.getUrn()) - .put(DETAIL, "Failure while executing transaction"); - JsonObject createPolicyJson = - new JsonObject() - .put("requestId", requestId) - .put("status", "granted") - .put("expiryAt", expiryTime) - .put("constraints", constraints); - - PgPool pool = postgresService.getPool(); - UpdateNotification updateNotification = new UpdateNotification(postgresService); - - updateNotification.setOwnerId(consumerId); - - pool.withTransaction( - sqlConnection -> { - try { - return updateNotification - .createPolicy(createPolicyJson, CREATE_POLICY_QUERY, sqlConnection) - .onComplete( - handler -> { - if (handler.succeeded()) { - vertxTestContext.failNow( - "Succeeded with invalid ownerId and while Database throws an error"); - } else { - - assertNull(updateNotification.getConsumerEmailId()); - assertNull(updateNotification.getItemId()); - assertEquals(failureMessage.encode(), handler.cause().getMessage()); - vertxTestContext.completeNow(); - } - }); - } catch (Exception e) { - vertxTestContext.failNow("something went wrong"); - throw new RuntimeException(e); - } - }); - } @Test @DisplayName( @@ -915,32 +776,37 @@ public void testInitiateTransactionFailure(VertxTestContext vertxTestContext) { new JsonObject() .put(TYPE, 500) .put(TITLE, ResponseUrn.DB_ERROR_URN.getUrn()) - .put(DETAIL, "Failure while executing transaction"); + .put(DETAIL, "Something went wrong while approving access request"); Utility util = new Utility(); container.start(); PostgresService postgresService = util.setUp(container); - UpdateNotification updateNotification = new UpdateNotification(postgresService); - - updateNotification - .initiateTransactions( - new JsonObject() - .put("constraints", new JsonObject().put("something", "someDummyValue"))) + util.testInsert() .onComplete( - handler -> { - if (handler.succeeded()) { - vertxTestContext.failNow( - "Succeeded when userEmailId given to create policy is null"); - - } else { - assertNull(updateNotification.getConsumerEmailId()); - assertNull(updateNotification.getItemId()); - assertNull(updateNotification.getOwnerId()); - assertNull(updateNotification.getExpiryAt()); + vertxTestContext.succeeding( + testSetUpSuccessful -> { + UpdateNotification updateNotification = new UpdateNotification(postgresService); + updateNotification + .initiateTransactions( + new JsonObject() + .put( + "constraints", + new JsonObject().put("something", "someDummyValue"))) + .onComplete( + handler -> { + if (handler.succeeded()) { + vertxTestContext.failNow( + "Succeeded when userEmailId, requestId given to create policy is null"); + } else { + assertNull(updateNotification.getConsumerEmailId()); + assertNull(updateNotification.getItemId()); + assertNull(updateNotification.getOwnerId()); + assertNull(updateNotification.getExpiryAt()); - assertEquals(failureMessage.encode(), handler.cause().getMessage()); - vertxTestContext.completeNow(); - } - }); + assertEquals(failureMessage.encode(), handler.cause().getMessage()); + vertxTestContext.completeNow(); + } + }); + })); } @Test @@ -953,8 +819,8 @@ public void testWithFailedInsertionInApprovedAccessRequest(VertxTestContext vert JsonObject failureMessage = new JsonObject() - .put(TYPE, 500) - .put(TITLE, ResponseUrn.BACKING_SERVICE_FORMAT_URN.getUrn()) + .put(TYPE, INTERNAL_SERVER_ERROR.getValue()) + .put(TITLE, ResponseUrn.DB_ERROR_URN.getUrn()) .put(DETAIL, "Something went wrong while approving access request"); JsonObject notification = new JsonObject(); updateNotification.setConsumerEmailId(emailId); @@ -972,7 +838,7 @@ public void testWithFailedInsertionInApprovedAccessRequest(VertxTestContext vert "Succeeded when there was a failure when inserting a record in approved_access_request table"); } else { - /* check if the policy with given consumer emailId, resourceId and ownerId is present */ + /* check if the policy with given consumer emailId, resourceId and ownerId is present or not */ utility .executeQuery( Tuple.of(emailId, itemId, ownerId), @@ -984,7 +850,7 @@ public void testWithFailedInsertionInApprovedAccessRequest(VertxTestContext vert policyHandler.result().getJsonArray("response").getJsonObject(0); assertTrue(policyResponse.isEmpty()); - /* check if the policy with the given policyId set while executing the transaction is present */ + /* check if the policy with the given policyId set while executing the transaction is present or not */ utility .executeQuery( Tuple.of(updateNotification.getPolicyId()), @@ -1036,7 +902,7 @@ public void testWithFailedInsertionInApprovedAccessRequest(VertxTestContext vert @Test @DisplayName( - "Test initiateTransaction method when there is a failure while updating notification: Failure") + "Test initiateTransaction method when there is a failure while creating notification: Failure") public void testWithFailureInApprovingNotification(VertxTestContext vertxTestContext) { container.start(); @@ -1057,10 +923,11 @@ public void testWithFailureInApprovingNotification(VertxTestContext vertxTestCon JsonObject failureMessage = new JsonObject() .put(TYPE, 500) - .put(TITLE, ResponseUrn.BACKING_SERVICE_FORMAT_URN.getUrn()) + .put(TITLE, ResponseUrn.DB_ERROR_URN.getUrn()) .put(DETAIL, "Something went wrong while approving access request"); JsonObject notification = mock(JsonObject.class); updateNotification.setConsumerEmailId("someEmailId"); + updateNotification.setItemId(itemId); updateNotification.setPolicyId(somePolicyId); updateNotification.setOwnerId(ownerId); @@ -1074,6 +941,8 @@ public void testWithFailureInApprovingNotification(VertxTestContext vertxTestCon .onComplete( handler -> { if (handler.succeeded()) { + System.out.println( + "handler.result().encode()" + handler.result().encode()); vertxTestContext.failNow( "Succeeded when there was a failure in approve notification"); @@ -1152,9 +1021,37 @@ public void testWithFailureInApprovingNotification(VertxTestContext vertxTestCon }); } }); - })).onFailure(failed -> { - LOG.error("Failed during set up: {}",failed.getCause().getMessage()); - vertxTestContext.failNow("Failed during setup"); + })) + .onFailure( + failed -> { + LOG.error("Failed during set up: {}", failed.getCause().getMessage()); + vertxTestContext.failNow("Failed during setup"); + }); + } + + @Test + @DisplayName("Test initiateTransactions method when the constraints is null : Failure") + public void testInitiateTransactionsWithNullConstraints(VertxTestContext vertxTestContext) { + JsonObject failureMessage = + new JsonObject() + .put(TYPE, INTERNAL_SERVER_ERROR.getValue()) + .put(TITLE, ResponseUrn.DB_ERROR_URN.getUrn()) + .put(DETAIL, "Something went wrong while approving access request"); + + updateNotification + .initiateTransactions(new JsonObject()) + .onComplete( + handler -> { + if (handler.succeeded()) { + LOG.error("Succeeded when the constraints in the notification is null"); + vertxTestContext.failNow( + "Failed : as it succeeded when the constraints " + + "in the notifications" + + " JsonObject is null"); + } else { + assertEquals(failureMessage.encode(), handler.cause().getMessage()); + vertxTestContext.completeNow(); + } }); } } From 02a9dbecabd2bfa282d5cef77f02dda850912d6b Mon Sep 17 00:00:00 2001 From: shreelakshmijoshi Date: Wed, 8 Nov 2023 15:31:05 +0530 Subject: [PATCH 04/22] Refactor Update notification --- .../notification/UpdateNotification.java | 14 ++-------- .../notification/TestUpdateNotifications.java | 28 ------------------- 2 files changed, 2 insertions(+), 40 deletions(-) diff --git a/src/main/java/iudx/apd/acl/server/notification/UpdateNotification.java b/src/main/java/iudx/apd/acl/server/notification/UpdateNotification.java index b82864e2..58dda082 100644 --- a/src/main/java/iudx/apd/acl/server/notification/UpdateNotification.java +++ b/src/main/java/iudx/apd/acl/server/notification/UpdateNotification.java @@ -147,7 +147,7 @@ public Future initiateTransactions(JsonObject notification) { Future transactionResponseFuture = pool.withTransaction( sqlConnection -> { - JsonObject constraints = notification.getJsonObject("constraints"); + JsonObject constraints = notification.getJsonObject("constraints", new JsonObject()); UUID policyId = UUID.randomUUID(); setPolicyId(policyId); @@ -207,21 +207,11 @@ public Future initiateTransactions(JsonObject notification) { }); transactionResponseFuture = transactionResponseFuture.recover( - /* some exception occurred while fetching constraints */ failure -> { - LOG.error("Error : " + failure); - if(failure instanceof ClassCastException) - { - JsonObject failureMessage = - new JsonObject() - .put(TYPE, BAD_REQUEST.getValue()) - .put(TITLE, ResponseUrn.BAD_REQUEST_URN.getUrn()) - .put(DETAIL, "Invalid or null constraint"); - return Future.failedFuture(failureMessage.encode()); - } /* something went wrong while creating a policy or while inserting a record in approved access request or while updating the notification*/ + LOG.error("Failed : " + failure); JsonObject failureMessage = new JsonObject() .put(TYPE, INTERNAL_SERVER_ERROR.getValue()) diff --git a/src/test/java/iudx/apd/acl/server/notification/TestUpdateNotifications.java b/src/test/java/iudx/apd/acl/server/notification/TestUpdateNotifications.java index 88108e3d..ebe3a86b 100644 --- a/src/test/java/iudx/apd/acl/server/notification/TestUpdateNotifications.java +++ b/src/test/java/iudx/apd/acl/server/notification/TestUpdateNotifications.java @@ -651,34 +651,6 @@ public void testApproveNotificationWithPolicyAlreadyCreated(VertxTestContext ver }); } - @Test - @DisplayName("Test initiateTransactions with invalid constraints") - public void testInitiateTransactionsWithInvalidConstraint(VertxTestContext vertxTestContext) { - - JsonObject approveNotification = - new JsonObject() - .put("requestId", requestId) - .put("status", "granted") - .put("expiryAt", expiryTime) - .put("constraints", "constraints"); - updateNotification - .initiateTransactions(approveNotification) - .onComplete( - handler -> { - if (handler.succeeded()) { - vertxTestContext.failNow("Succeeded for invalid constraint"); - } else { - JsonObject failure = - new JsonObject() - .put(TYPE, BAD_REQUEST.getValue()) - .put(TITLE, ResponseUrn.BAD_REQUEST_URN.getUrn()) - .put(DETAIL, "Invalid or null constraint"); - assertEquals(failure.encode(), handler.cause().getMessage()); - vertxTestContext.completeNow(); - } - }); - } - @Test @DisplayName("Test initiateUpdateNotification with error while creating database connection") public void testWithDatabaseConnectionError(VertxTestContext vertxTestContext) { From e21860c2a771d4f085bd79790283a8eda2a8fb8a Mon Sep 17 00:00:00 2001 From: shreelakshmijoshi Date: Wed, 8 Nov 2023 16:41:30 +0530 Subject: [PATCH 05/22] Update PUT notification payload schema --- docs/openapi.yaml | 53 ++++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 94b1c460..aa1faa3b 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -778,26 +778,41 @@ paths: content: application/json: schema: - type: object - properties: - requestId: - type: string - format: uuid - pattern: '^[0-9a-f]{8}\b-[0-9a-f]{4}\b-[0-9a-f]{4}\b-[0-9a-f]{4}\b-[0-9a-f]{12}$' - minLength: 36 - - status: - enum: - - granted - - rejected - minLength: 1 - expiryAt: - type: string - constraints: + oneOf: + - title: approve access request type: object - required: - - requestId - - status + properties: + requestId: + type: string + format: uuid + pattern: '^[0-9a-f]{8}\b-[0-9a-f]{4}\b-[0-9a-f]{4}\b-[0-9a-f]{4}\b-[0-9a-f]{12}$' + status: + type: string + default: granted + expiryAt: + type: string + constraints: + type: object + required: + - requestId + - status + - expiryAt + - constraints + + - title : reject access request + type: object + properties: + requestId: + type: string + format: uuid + pattern: '^[0-9a-f]{8}\b-[0-9a-f]{4}\b-[0-9a-f]{4}\b-[0-9a-f]{4}\b-[0-9a-f]{12}$' + status: + type: string + default: rejected + required: + - requestId + - status + x-examples: example-1: requestId: bca11712-f381-46a5-afa3-a29b00568ace From b6091f34742f05ac1081078e88c36804658e597f Mon Sep 17 00:00:00 2001 From: shreelakshmijoshi Date: Wed, 8 Nov 2023 17:54:15 +0530 Subject: [PATCH 06/22] Update POST notification --- docs/openapi.yaml | 33 ++++++++++--------- .../server/apiserver/ApiServerVerticle.java | 2 +- .../acl/server/validation/FailureHandler.java | 26 ++++++++++++++- 3 files changed, 44 insertions(+), 17 deletions(-) diff --git a/docs/openapi.yaml b/docs/openapi.yaml index aa1faa3b..7fed5e8e 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -603,9 +603,10 @@ paths: - Access Request APIs summary: Create Access Request description: |- - Access requests are made by consumers to request a provider to grant access to the provider's resources. Providers or their associated delegates may choose to approve or reject the request. On approval, a policy is written for the consumer for said resource. On rejection, no policy is written. + Access requests are made by consumer/consumer delegate to request a provider to grant access to the provider's resources. + A provider will be notified whenever the consumer creates an access request. - Users with the `consumer` role can request access for a resource/resource group + Users with the consumer/consumer delegate role can request access for a resource/resource group operationId: post-auth-v1-policies-requests parameters: - name: Authorization @@ -619,20 +620,20 @@ paths: pattern: '^[a-zA-Z0-9_*\-*\.\/]+$' requestBody: description: | - - `itemId` : The catalogue ID of the item for which the request is to be created.(UUID) + - `itemId` : The catalogue ID of the item for which the request is to be created - `itemType` : The type of the resource being requested for, it could be either RESOURCE or RESOURCE_GROUP required: true content: application/json: schema: type: object + additionalProperties: false properties: itemId: type: string format: uuid pattern: '^[0-9a-f]{8}\b-[0-9a-f]{4}\b-[0-9a-f]{4}\b-[0-9a-f]{4}\b-[0-9a-f]{12}$' - minLength: 36 - + itemType: enum: - RESOURCE_GROUP @@ -746,7 +747,7 @@ paths: - Access Request APIs summary: Update Access Request description: | - Providers or delegates can choose to approve or reject **pending** access requests associated with their resources. + Providers or provider delegates can choose to approve or reject **pending** access requests associated with their resources. If the request is approved - The request is modified to the `approved` state @@ -755,8 +756,7 @@ paths: If the request is rejected - The request is modified to the `rejected` state - ## Delegate - A delegate may use the API to view policies on behalf of their provider. This is done by passing the userInfo of the delegator which must be present in the token issued by the AAA. + operationId: put-auth-v1-policies-requests parameters: - name: Authorization @@ -770,16 +770,17 @@ paths: pattern: '^[a-zA-Z0-9_*\-*\.\/]+$' requestBody: description: |- - - `requestId` : ID of the request. Can get this `id` by using the list policy API. - - `status` : The `provider` or `Auth delegate` can update the status to `granted` or `rejected`. + - `requestId` : ID of the request. Can get this `id` by using the GET Access request API. + - `status` : The `provider` or `provider delegate` can update the status to `granted` or `rejected`. - `expiryAt` : expiration time stamp of the policy that will be created (Only present for the granted requests). - - `constraints` : constraints for the policy if request is granted. + - `constraints` : constraints for the access request if it is granted. required: true content: application/json: schema: oneOf: - title: approve access request + additionalProperties: false type: object properties: requestId: @@ -800,6 +801,7 @@ paths: - constraints - title : reject access request + additionalProperties: false type: object properties: requestId: @@ -892,7 +894,7 @@ paths: '403': description: |- Forbidden - - User does not own the policy or is not a delegate to the owner of the policy + - User does not own the resource for which a policy is to be created content: application/json: schema: @@ -1071,7 +1073,8 @@ components: example: type: urn:dx:acl:forbidden title: Forbidden - detail: Request could not be updated, as it doesn't belong to the user + detail: "Access Denied: You do not have ownership rights for this resource." + updateNotificationNotFound: title: Update notification not found @@ -1137,7 +1140,7 @@ components: example: type: urn:dx:acl:conflict title: Conflict - detail: Request could not be approved, as policy is already created + detail: Request could not be approved as, policy is already created UpdateAccessRequest: title: Delete notification forbidden @@ -1223,7 +1226,7 @@ components: example: type: urn:dx:acl:resourceNotFound title: Not Found - detail: Request could not be created, as resource is not found + detail: Request could not be created, as resource was not found createNotificationConflictResponse: title: Create notification conflict response diff --git a/src/main/java/iudx/apd/acl/server/apiserver/ApiServerVerticle.java b/src/main/java/iudx/apd/acl/server/apiserver/ApiServerVerticle.java index 3c3d3de8..68f79e3c 100644 --- a/src/main/java/iudx/apd/acl/server/apiserver/ApiServerVerticle.java +++ b/src/main/java/iudx/apd/acl/server/apiserver/ApiServerVerticle.java @@ -164,7 +164,7 @@ public void start() throws Exception { routerBuilder.rootHandler(TimeoutHandler.create(100000, 408)); configureCorsHandler(routerBuilder); - routerBuilder.rootHandler(BodyHandler.create()); + routerBuilder.rootHandler(BodyHandler.create().setHandleFileUploads(false)); router = routerBuilder.createRouter(); putCommonResponseHeaders(); configureErrorHandlers(router); diff --git a/src/main/java/iudx/apd/acl/server/validation/FailureHandler.java b/src/main/java/iudx/apd/acl/server/validation/FailureHandler.java index 7c548e4f..655b3860 100644 --- a/src/main/java/iudx/apd/acl/server/validation/FailureHandler.java +++ b/src/main/java/iudx/apd/acl/server/validation/FailureHandler.java @@ -5,8 +5,15 @@ import io.vertx.core.Handler; import io.vertx.core.json.JsonObject; import io.vertx.ext.web.RoutingContext; +import io.vertx.ext.web.validation.BadRequestException; +import io.vertx.ext.web.validation.BodyProcessorException; +import io.vertx.ext.web.validation.ParameterProcessorException; +import io.vertx.ext.web.validation.RequestPredicateException; +import io.vertx.json.schema.ValidationException; +import iudx.apd.acl.server.apiserver.response.ResponseUtil; import iudx.apd.acl.server.apiserver.response.RestResponse; import iudx.apd.acl.server.common.HttpStatusCode; +import iudx.apd.acl.server.common.ResponseUrn; import iudx.apd.acl.server.validation.exceptions.DxRuntimeException; import org.apache.http.HttpStatus; import org.apache.logging.log4j.LogManager; @@ -40,7 +47,24 @@ public void handle(RoutingContext routingContext) { .setStatusCode(exception.getStatusCode()) .end(response.encode()); } - //TODO: add statements to catch multiple types of failures + // TODO: add statements to catch multiple types of failures + + /* exceptions from OpenAPI specification*/ + if (failure instanceof ValidationException + || failure instanceof BodyProcessorException + || failure instanceof RequestPredicateException + || failure instanceof ParameterProcessorException) { + routingContext + .response() + .putHeader(CONTENT_TYPE, APPLICATION_JSON) + .setStatusCode(HttpStatus.SC_BAD_REQUEST) + .end( + ResponseUtil.generateResponse( + HttpStatusCode.BAD_REQUEST, + ResponseUrn.BAD_REQUEST_URN, + "Missing or malformed request") + .toString()); + } if (failure instanceof RuntimeException) { From 509e7eebe1805e4c071c9dcc8b0df5fbbb29d821 Mon Sep 17 00:00:00 2001 From: shreelakshmijoshi Date: Wed, 8 Nov 2023 18:20:38 +0530 Subject: [PATCH 07/22] Update GET Notification --- docs/openapi.yaml | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 7fed5e8e..784a839e 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -505,18 +505,15 @@ paths: - Access Request APIs summary: List Access Requests description: |- - Lists all the access requests of the user calling the API. The response depends on the roles the user has + Lists all the access requests of the user calling the API regardless of the state of the access requests. The response depends on the roles the user has - - `provider` : The requests that are present for the items owned by a provider are returned. - - `consumer` : The requests which are created by the consumer are returned. + - `provider` : The requests that are present for the items owned by a provider/provider delegate are returned. + - `consumer` : The requests which are created by the consumer/consumer delegate are returned.

`Note:` The response displays the requests of / for a user with respect to a particular server. - - ## Delegate - A delegate may use the API to view policies on behalf of their provider. The user info of the delegator must be present in the token issued by the Data Exchange AAA operationId: get-auth-v1-policies-requests parameters: - name: Authorization @@ -544,9 +541,9 @@ paths: title: Success results: - requestId: ea48d233-5d3b-4bdb-9545-691680c99cee - itemId: pune-env-flood-FWR056" + itemId: sf50d232-5d3y-rbds-4758-691680c99defa itemType: RESOURCE - status: pending + status: PENDING expiryAt: '2024-03-05T20:00:19' constraints: access: @@ -1839,15 +1836,18 @@ components: itemType: type: string minLength: 1 + resourceServerUrl: + type: string + minLength: 1 status: type: string minLength: 1 - expiryDuration: + expiryAt: type: string minLength: 1 constraints: type: object - user: + consumer: type: object properties: id: @@ -1872,7 +1872,7 @@ components: - id - email - name - owner: + provider: type: object properties: id: @@ -1902,7 +1902,11 @@ components: - itemId - itemType - status - - expiryDuration + - expiryAt + - resourceServerUrl + - constraints + - consumer + - provider required: - type - title From d74b5de4de56463c52ece9ff6c416158c38a09f5 Mon Sep 17 00:00:00 2001 From: shreelakshmijoshi Date: Wed, 8 Nov 2023 19:34:16 +0530 Subject: [PATCH 08/22] Update DELETE Notification --- docs/openapi.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 784a839e..84bf85d8 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -920,7 +920,7 @@ paths: description: |- A consumer may choose to withdraw access requests they have created, **as long as they are still in the pending state**. A withdrawn request cannot be approved or rejected by the concerned provider. - Only users with `consumer` role can call this API. + Only users with consumer/consumer delegate role can call this API. operationId: delete-auth-v1-policies-requests parameters: - name: Authorization @@ -942,13 +942,13 @@ paths: application/json: schema: type: object + additionalProperties: false properties: id: type: string format: uuid pattern: '^[0-9a-f]{8}\b-[0-9a-f]{4}\b-[0-9a-f]{4}\b-[0-9a-f]{4}\b-[0-9a-f]{12}$' - minLength: 36 - + required: - id examples: @@ -967,7 +967,7 @@ paths: description: |- Bad Request - Errors or exceptions - - The ID is no longer in the `PENDING` status or has already been withdrawn earlier + - The access request is no longer in the `PENDING` status or has already been withdrawn earlier content: application/json: schema: @@ -983,7 +983,7 @@ paths: '403': description: |- Forbidden - - User does not own the policy or is not a delegate to the owner of the policy + - User did not create the access request or is not a delegator to the consumer who created the access request content: application/json: schema: From 7eb814677f5c0091c916c76842caf456ee8f7782 Mon Sep 17 00:00:00 2001 From: shreelakshmijoshi Date: Wed, 8 Nov 2023 19:38:58 +0530 Subject: [PATCH 09/22] Update POST verify API description --- docs/openapi.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 84bf85d8..26ae3287 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -422,6 +422,8 @@ paths: - Verify API summary: Verify Policy description: | + `This API is not meant to be called by any user and is used by Data Exchange AAA server.` +
Verify the policy for a given item and owner. This endpoint checks if a policy exists for the specified item and owner in the APD server. It returns the policy constraints if a policy is found. operationId: get-auth-v1-verify parameters: From 8f449df59e77ade5625cb2e28c603b52bd218dfc Mon Sep 17 00:00:00 2001 From: shreelakshmijoshi Date: Wed, 8 Nov 2023 19:44:53 +0530 Subject: [PATCH 10/22] Update token description --- docs/openapi.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 26ae3287..97f4cb2d 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -520,7 +520,7 @@ paths: parameters: - name: Authorization in: header - description: AAA issued token + description: AAA issued Identity token required: true schema: type: string @@ -610,7 +610,7 @@ paths: parameters: - name: Authorization in: header - description: AAA Issued token + description: AAA Issued Identity token required: true schema: type: string @@ -760,7 +760,7 @@ paths: parameters: - name: Authorization in: header - description: AAA Issued token + description: AAA Issued Identity token required: true schema: type: string @@ -927,7 +927,7 @@ paths: parameters: - name: Authorization in: header - description: AAA Issued token + description: AAA Issued Identity token required: true schema: type: string From ae19927fa7c5425addf5e38986cd22a28358d696 Mon Sep 17 00:00:00 2001 From: shreelakshmijoshi Date: Thu, 9 Nov 2023 11:07:32 +0530 Subject: [PATCH 11/22] Update oneOf properties --- docs/openapi.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 97f4cb2d..55f0acec 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -788,7 +788,8 @@ paths: pattern: '^[0-9a-f]{8}\b-[0-9a-f]{4}\b-[0-9a-f]{4}\b-[0-9a-f]{4}\b-[0-9a-f]{12}$' status: type: string - default: granted + enum: + - granted expiryAt: type: string constraints: @@ -809,7 +810,8 @@ paths: pattern: '^[0-9a-f]{8}\b-[0-9a-f]{4}\b-[0-9a-f]{4}\b-[0-9a-f]{4}\b-[0-9a-f]{12}$' status: type: string - default: rejected + enum: + - rejected required: - requestId - status From db28c292f156453d6acc538482acc16720a6d914 Mon Sep 17 00:00:00 2001 From: shreelakshmijoshi Date: Thu, 9 Nov 2023 11:19:55 +0530 Subject: [PATCH 12/22] Update GET Notification response --- docs/openapi.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 55f0acec..2e3323ad 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -545,6 +545,7 @@ paths: - requestId: ea48d233-5d3b-4bdb-9545-691680c99cee itemId: sf50d232-5d3y-rbds-4758-691680c99defa itemType: RESOURCE + resourceServerUrl: rs.iudx.io status: PENDING expiryAt: '2024-03-05T20:00:19' constraints: From 919ae30cd649591e2f14c86a4e404826f0e179e9 Mon Sep 17 00:00:00 2001 From: shreelakshmijoshi Date: Thu, 9 Nov 2023 11:48:26 +0530 Subject: [PATCH 13/22] Update open api specs --- docs/openapi.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 2e3323ad..6f264e2c 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -923,7 +923,7 @@ paths: - Access Request APIs summary: Withdraw Access Request description: |- - A consumer may choose to withdraw access requests they have created, **as long as they are still in the pending state**. A withdrawn request cannot be approved or rejected by the concerned provider. + A consumer/consumer may choose to withdraw access requests they have created, **as long as they are still in the pending state**. A withdrawn request cannot be approved or rejected by the concerned provider. Only users with consumer/consumer delegate role can call this API. operationId: delete-auth-v1-policies-requests From 88ff9e6aa628552a439feb79f41d774d3294fbfc Mon Sep 17 00:00:00 2001 From: shreelakshmijoshi Date: Thu, 9 Nov 2023 12:31:00 +0530 Subject: [PATCH 14/22] Get ID from DB --- .../notification/UpdateNotification.java | 56 ++++++++++--------- .../server/notification/util/Constants.java | 6 +- 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/src/main/java/iudx/apd/acl/server/notification/UpdateNotification.java b/src/main/java/iudx/apd/acl/server/notification/UpdateNotification.java index 58dda082..482d96ac 100644 --- a/src/main/java/iudx/apd/acl/server/notification/UpdateNotification.java +++ b/src/main/java/iudx/apd/acl/server/notification/UpdateNotification.java @@ -143,17 +143,16 @@ public Future initiateUpdateNotification(JsonObject notification, Us */ public Future initiateTransactions(JsonObject notification) { LOG.trace("inside initiateTransactions method"); + Collector> rowListCollector = + Collectors.mapping(row -> row.toJson(), Collectors.toList()); pool = postgresService.getPool(); Future transactionResponseFuture = pool.withTransaction( sqlConnection -> { JsonObject constraints = notification.getJsonObject("constraints", new JsonObject()); - UUID policyId = UUID.randomUUID(); - setPolicyId(policyId); Tuple createPolicyTuple = Tuple.of( - policyId, getConsumerEmailId(), getItemId(), getOwnerId(), @@ -164,32 +163,39 @@ public Future initiateTransactions(JsonObject notification) { var response = sqlConnection .preparedQuery(CREATE_POLICY_QUERY) + .collecting(rowListCollector) .execute(createPolicyTuple) + .map(row -> row.value()) .compose( policyCreatedSuccessfully -> { - LOG.info("Policy created successfully"); + UUID policyId = UUID.fromString(policyCreatedSuccessfully.get(0).getString(ID)); + setPolicyId(policyId); + LOG.info("Policy created successfully with ID : {}", policyId); UUID notificationId = UUID.fromString(notification.getString("requestId")); - UUID uuid = UUID.randomUUID(); Tuple approvedAccessRequestInsertionTuple = - Tuple.of(uuid, notificationId, getPolicyId()); + Tuple.of(notificationId, getPolicyId()); return sqlConnection .preparedQuery(INSERT_IN_APPROVED_ACCESS_REQUESTS_QUERY) - .execute(approvedAccessRequestInsertionTuple); + .collecting(rowListCollector) + .execute(approvedAccessRequestInsertionTuple) + .map(row -> row.value()); }) .compose( approvedAccessRequestInsertion -> { + UUID uuid = UUID.fromString(approvedAccessRequestInsertion.get(0).getString(ID)); LOG.info( - "Inserted record successfully in approved access request : " - + notification.getString("requestId")); + "Inserted record successfully in approved access request with ID : {}", uuid); UUID notificationId = UUID.fromString(notification.getString("requestId")); Tuple updateAccessRequestTuple = Tuple.of(getExpiryAt(), constraints, notificationId, getOwnerId()); return sqlConnection .preparedQuery(APPROVE_REQUEST_QUERY) - .execute(updateAccessRequestTuple); + .collecting(rowListCollector) + .execute(updateAccessRequestTuple) + .map(row -> row.value()); }) .compose( updatedNotificationSuccessful -> { @@ -206,21 +212,21 @@ public Future initiateTransactions(JsonObject notification) { return response; }); - transactionResponseFuture = transactionResponseFuture.recover( - failure -> { - /* something went wrong while creating a policy - or while inserting a record in approved access request - or while updating the notification*/ - LOG.error("Failed : " + failure); - JsonObject failureMessage = - new JsonObject() - .put(TYPE, INTERNAL_SERVER_ERROR.getValue()) - .put(TITLE, ResponseUrn.DB_ERROR_URN.getUrn()) - .put(DETAIL, - "Something went wrong while approving access request"); - return Future.failedFuture(failureMessage.encode()); - }); - return transactionResponseFuture; + transactionResponseFuture = + transactionResponseFuture.recover( + failure -> { + /* something went wrong while creating a policy + or while inserting a record in approved access request + or while updating the notification*/ + LOG.error("Failed : " + failure); + JsonObject failureMessage = + new JsonObject() + .put(TYPE, INTERNAL_SERVER_ERROR.getValue()) + .put(TITLE, ResponseUrn.DB_ERROR_URN.getUrn()) + .put(DETAIL, "Something went wrong while approving access request"); + return Future.failedFuture(failureMessage.encode()); + }); + return transactionResponseFuture; } /** diff --git a/src/main/java/iudx/apd/acl/server/notification/util/Constants.java b/src/main/java/iudx/apd/acl/server/notification/util/Constants.java index 94d00ab5..9702d20d 100644 --- a/src/main/java/iudx/apd/acl/server/notification/util/Constants.java +++ b/src/main/java/iudx/apd/acl/server/notification/util/Constants.java @@ -34,10 +34,10 @@ public class Constants { public static final String OWNERSHIP_CHECK_QUERY = "SELECT * FROM resource_entity WHERE _id = $1::uuid AND provider_id = $2::uuid"; public static final String CREATE_POLICY_QUERY = "INSERT INTO policy" - + "(_id, user_emailid, item_id, owner_id, status, expiry_at, constraints)" - + " VALUES ($1, $2, $3, $4, $5,$6, $7) RETURNING _id;"; + + "(user_emailid, item_id, owner_id, status, expiry_at, constraints)" + + " VALUES ($1, $2, $3, $4, $5,$6) RETURNING _id;"; public static final String INSERT_IN_APPROVED_ACCESS_REQUESTS_QUERY = - "INSERT INTO approved_access_requests(_id, request_id, policy_id) VALUES ($1, $2, $3) RETURNING _id"; + "INSERT INTO approved_access_requests(request_id, policy_id) VALUES ($1, $2) RETURNING _id"; public static final String APPROVE_REQUEST_QUERY = "UPDATE request SET status = 'GRANTED', expiry_at = $1," + "constraints = $2 WHERE _id = $3 AND owner_id = $4 RETURNING _id"; public static final String INSERT_USER_INFO_QUERY = "INSERT INTO user_table (_id, email_id, first_name, last_name)" From ca25cb205bf680444527cfcadb7436e1ae3f9fa8 Mon Sep 17 00:00:00 2001 From: shreelakshmijoshi Date: Thu, 9 Nov 2023 12:36:49 +0530 Subject: [PATCH 15/22] Update notification --- .../server/notification/UpdateNotification.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main/java/iudx/apd/acl/server/notification/UpdateNotification.java b/src/main/java/iudx/apd/acl/server/notification/UpdateNotification.java index 482d96ac..53fb511f 100644 --- a/src/main/java/iudx/apd/acl/server/notification/UpdateNotification.java +++ b/src/main/java/iudx/apd/acl/server/notification/UpdateNotification.java @@ -168,9 +168,10 @@ public Future initiateTransactions(JsonObject notification) { .map(row -> row.value()) .compose( policyCreatedSuccessfully -> { - UUID policyId = UUID.fromString(policyCreatedSuccessfully.get(0).getString(ID)); - setPolicyId(policyId); - LOG.info("Policy created successfully with ID : {}", policyId); + UUID policyId = + UUID.fromString(policyCreatedSuccessfully.get(0).getString("_id")); + setPolicyId(policyId); + LOG.info("Policy created successfully with ID : {}", policyId); UUID notificationId = UUID.fromString(notification.getString("requestId")); @@ -184,9 +185,12 @@ public Future initiateTransactions(JsonObject notification) { }) .compose( approvedAccessRequestInsertion -> { - UUID uuid = UUID.fromString(approvedAccessRequestInsertion.get(0).getString(ID)); + UUID uuid = + UUID.fromString( + approvedAccessRequestInsertion.get(0).getString("_id")); LOG.info( - "Inserted record successfully in approved access request with ID : {}", uuid); + "Inserted record successfully in approved access request with ID : {}", + uuid); UUID notificationId = UUID.fromString(notification.getString("requestId")); Tuple updateAccessRequestTuple = @@ -215,6 +219,7 @@ public Future initiateTransactions(JsonObject notification) { transactionResponseFuture = transactionResponseFuture.recover( failure -> { + failure.printStackTrace(); /* something went wrong while creating a policy or while inserting a record in approved access request or while updating the notification*/ From 1c0c1ab136aa56d881d58dd35572650e5fe6f6de Mon Sep 17 00:00:00 2001 From: shreelakshmijoshi Date: Thu, 9 Nov 2023 12:47:36 +0530 Subject: [PATCH 16/22] Remove forbidden response --- docs/openapi.yaml | 14 ----- .../notification/CreateNotification.java | 7 ++- .../notification/TestCreateNotification.java | 6 +- .../IUDX-ACL-APD-APIs.postman_collection.json | 60 ------------------- 4 files changed, 7 insertions(+), 80 deletions(-) diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 6f264e2c..445e4855 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -696,20 +696,6 @@ paths: schema: type: string description: application/json - '403': - description: |- - Forbidden - - Resource being requested for is forbidden to access - - Consumer trying to access a resource not belonging to the same server - content: - application/json: - schema: - $ref: '#/components/schemas/createNotificationForbiddenResponse' - headers: - Content-Type: - schema: - type: string - description: application/json '404': description: |- diff --git a/src/main/java/iudx/apd/acl/server/notification/CreateNotification.java b/src/main/java/iudx/apd/acl/server/notification/CreateNotification.java index ea9187b0..34ad798f 100644 --- a/src/main/java/iudx/apd/acl/server/notification/CreateNotification.java +++ b/src/main/java/iudx/apd/acl/server/notification/CreateNotification.java @@ -420,13 +420,14 @@ public Future isItemPresentInCatalogue(UUID resourceId, String itemType } }); } else { + LOG.debug("user does not have access to create notification as they're belonging to a different server w.r.t to the resource"); JsonObject failureMessage = new JsonObject() - .put(TYPE, HttpStatusCode.FORBIDDEN.getValue()) - .put(TITLE, ResponseUrn.FORBIDDEN_URN.getUrn()) + .put(TYPE, HttpStatusCode.NOT_FOUND.getValue()) + .put(TITLE, ResponseUrn.RESOURCE_NOT_FOUND_URN.getUrn()) .put( DETAIL, - "Access Denied: You do not have ownership rights for this resource"); + "Access request could not be created, as resource is not found"); promise.fail(failureMessage.encode()); } } else { diff --git a/src/test/java/iudx/apd/acl/server/notification/TestCreateNotification.java b/src/test/java/iudx/apd/acl/server/notification/TestCreateNotification.java index d8e3f585..dc9d1397 100644 --- a/src/test/java/iudx/apd/acl/server/notification/TestCreateNotification.java +++ b/src/test/java/iudx/apd/acl/server/notification/TestCreateNotification.java @@ -294,11 +294,11 @@ public AsyncResult> answer(InvocationOnMock arg0) throws Throw } else { JsonObject failureMessage = new JsonObject() - .put(TYPE, HttpStatusCode.FORBIDDEN.getValue()) - .put(TITLE, ResponseUrn.FORBIDDEN_URN.getUrn()) + .put(TYPE, HttpStatusCode.NOT_FOUND.getValue()) + .put(TITLE, ResponseUrn.RESOURCE_NOT_FOUND_URN.getUrn()) .put( DETAIL, - "Access Denied: You do not have ownership rights for this resource"); + "Access request could not be created, as resource is not found"); assertEquals(failureMessage.encode(), handler.cause().getMessage()); vertxTestContext.completeNow(); } diff --git a/src/test/resources/IUDX-ACL-APD-APIs.postman_collection.json b/src/test/resources/IUDX-ACL-APD-APIs.postman_collection.json index da65356f..1204d258 100644 --- a/src/test/resources/IUDX-ACL-APD-APIs.postman_collection.json +++ b/src/test/resources/IUDX-ACL-APD-APIs.postman_collection.json @@ -2288,66 +2288,6 @@ }, "response": [] }, - { - "name": "403 Create Access Request: Forbidden", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "// Test the response code", - "pm.test(\"response is 403 (Forbidden)\", function () {", - " pm.response.to.have.status(403);", - "});", - "", - "// Test the response header", - "pm.test(\"Check response header\", function () {", - " pm.response.to.have.header(\"Content-Type\",\"application/json\");", - "});", - "", - "// Test the response", - "pm.test(\"Check response body\", function () { ", - " const body = pm.response.json();", - " pm.expect(body).to.have.property(\"type\", \"urn:dx:acl:forbidden\");", - " pm.expect(body).to.have.property(\"title\", \"Forbidden\");", - " }", - ");" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "Authorization", - "value": "{{consumerTokenForbidden}}", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "{\n\"itemId\": \"83c2e5c2-3574-4e11-9530-2b1fbdfce832\",\n\"itemType\": \"RESOURCE\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}{{basePath}}/policies/requests", - "host": [ - "{{baseUrl}}{{basePath}}" - ], - "path": [ - "policies", - "requests" - ] - } - }, - "response": [] - }, { "name": "404 Create Access Request: Not Found", "event": [ From 2fc51bc0a880d3aabb040488d718d2b757f537cd Mon Sep 17 00:00:00 2001 From: shreelakshmijoshi Date: Thu, 9 Nov 2023 12:59:39 +0530 Subject: [PATCH 17/22] Remove Forbiddenn response --- docs/openapi.yaml | 8 --- .../notification/CreateNotification.java | 2 +- .../notification/DeleteNotification.java | 12 ++-- .../notification/TestCreateNotification.java | 2 +- .../notification/TestDeleteNotifications.java | 21 +++--- .../IUDX-ACL-APD-APIs.postman_collection.json | 67 ------------------- 6 files changed, 18 insertions(+), 94 deletions(-) diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 445e4855..ed91eaa6 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -971,14 +971,6 @@ paths: application/json: schema: $ref: '#/components/schemas/deleteNotificationNotFound' - '403': - description: |- - Forbidden - - User did not create the access request or is not a delegator to the consumer who created the access request - content: - application/json: - schema: - $ref: '#/components/schemas/deleteNotificationForbiddenResponse' '401': description: |- Unauthorized diff --git a/src/main/java/iudx/apd/acl/server/notification/CreateNotification.java b/src/main/java/iudx/apd/acl/server/notification/CreateNotification.java index 34ad798f..4b84ef96 100644 --- a/src/main/java/iudx/apd/acl/server/notification/CreateNotification.java +++ b/src/main/java/iudx/apd/acl/server/notification/CreateNotification.java @@ -427,7 +427,7 @@ public Future isItemPresentInCatalogue(UUID resourceId, String itemType .put(TITLE, ResponseUrn.RESOURCE_NOT_FOUND_URN.getUrn()) .put( DETAIL, - "Access request could not be created, as resource is not found"); + "Access request could not be created, as resource was not found"); promise.fail(failureMessage.encode()); } } else { diff --git a/src/main/java/iudx/apd/acl/server/notification/DeleteNotification.java b/src/main/java/iudx/apd/acl/server/notification/DeleteNotification.java index d90e97c6..af421405 100644 --- a/src/main/java/iudx/apd/acl/server/notification/DeleteNotification.java +++ b/src/main/java/iudx/apd/acl/server/notification/DeleteNotification.java @@ -111,10 +111,10 @@ public Future verifyRequest(String query, UUID requestUuid, User user) promise.complete(true); } else { JsonObject failureResponse = new JsonObject(); - failureResponse.put(TYPE, FORBIDDEN.getValue()); - failureResponse.put(TITLE, FORBIDDEN.getUrn()); + failureResponse.put(TYPE, NOT_FOUND.getValue()); + failureResponse.put(TITLE, ResponseUrn.RESOURCE_NOT_FOUND_URN.getUrn()); failureResponse.put( - DETAIL, "Access Denied: You do not have ownership rights for this resource."); + DETAIL, "Request could not be withdrawn, as it is not found"); promise.fail(failureResponse.encode()); } } else { @@ -127,10 +127,10 @@ public Future verifyRequest(String query, UUID requestUuid, User user) } } else { JsonObject failureResponse = new JsonObject(); - failureResponse.put(TYPE, FORBIDDEN.getValue()); - failureResponse.put(TITLE, FORBIDDEN.getUrn()); + failureResponse.put(TYPE, NOT_FOUND.getValue()); + failureResponse.put(TITLE, ResponseUrn.RESOURCE_NOT_FOUND_URN.getUrn()); failureResponse.put( - DETAIL, "Access Denied: You do not have ownership rights for this resource."); + DETAIL, "Request could not be withdrawn, as it is not found"); promise.fail(failureResponse.encode()); } } diff --git a/src/test/java/iudx/apd/acl/server/notification/TestCreateNotification.java b/src/test/java/iudx/apd/acl/server/notification/TestCreateNotification.java index dc9d1397..3ae4cab4 100644 --- a/src/test/java/iudx/apd/acl/server/notification/TestCreateNotification.java +++ b/src/test/java/iudx/apd/acl/server/notification/TestCreateNotification.java @@ -298,7 +298,7 @@ public AsyncResult> answer(InvocationOnMock arg0) throws Throw .put(TITLE, ResponseUrn.RESOURCE_NOT_FOUND_URN.getUrn()) .put( DETAIL, - "Access request could not be created, as resource is not found"); + "Access request could not be created, as resource was not found"); assertEquals(failureMessage.encode(), handler.cause().getMessage()); vertxTestContext.completeNow(); } diff --git a/src/test/java/iudx/apd/acl/server/notification/TestDeleteNotifications.java b/src/test/java/iudx/apd/acl/server/notification/TestDeleteNotifications.java index cd9af74b..c0ab9492 100644 --- a/src/test/java/iudx/apd/acl/server/notification/TestDeleteNotifications.java +++ b/src/test/java/iudx/apd/acl/server/notification/TestDeleteNotifications.java @@ -2,8 +2,7 @@ import static iudx.apd.acl.server.Utility.*; import static iudx.apd.acl.server.apiserver.util.Constants.*; -import static iudx.apd.acl.server.common.HttpStatusCode.BAD_REQUEST; -import static iudx.apd.acl.server.common.HttpStatusCode.FORBIDDEN; +import static iudx.apd.acl.server.common.HttpStatusCode.*; import static iudx.apd.acl.server.notification.util.Constants.GET_REQUEST; import static iudx.apd.acl.server.notification.util.Constants.WITHDRAW_REQUEST; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -123,10 +122,10 @@ public void testInitiateDeleteNotificationWithRsUrlMismatch(VertxTestContext ver handler -> { if (handler.failed()) { JsonObject result = new JsonObject(handler.cause().getMessage()); - assertEquals(HttpStatusCode.FORBIDDEN.getValue(), result.getInteger(TYPE)); - assertEquals(HttpStatusCode.FORBIDDEN.getUrn(), result.getString(TITLE)); + assertEquals(HttpStatusCode.NOT_FOUND.getValue(), result.getInteger(TYPE)); + assertEquals(ResponseUrn.RESOURCE_NOT_FOUND_URN.getUrn(), result.getString(TITLE)); assertEquals( - "Access Denied: You do not have ownership rights for this resource.", + "Request could not be withdrawn, as it is not found", result.getString(DETAIL)); vertxTestContext.completeNow(); @@ -146,10 +145,10 @@ public void testInitiateDeleteNotification4InvalidUser(VertxTestContext vertxTes handler -> { if (handler.failed()) { JsonObject result = new JsonObject(handler.cause().getMessage()); - assertEquals(HttpStatusCode.FORBIDDEN.getValue(), result.getInteger(TYPE)); - assertEquals(HttpStatusCode.FORBIDDEN.getUrn(), result.getString(TITLE)); + assertEquals(HttpStatusCode.NOT_FOUND.getValue(), result.getInteger(TYPE)); + assertEquals(ResponseUrn.RESOURCE_NOT_FOUND_URN.getUrn(), result.getString(TITLE)); assertEquals( - "Access Denied: You do not have ownership rights for this resource.", + "Request could not be withdrawn, as it is not found", result.getString(DETAIL)); vertxTestContext.completeNow(); @@ -215,10 +214,10 @@ public void testInitiateDeleteNotification4UserId(VertxTestContext vertxTestCont vertxTestContext.failNow("Succeeded with an invalid user id"); } else { JsonObject result = new JsonObject(handler.cause().getMessage()); - assertEquals(FORBIDDEN.getValue(), result.getInteger(TYPE)); - assertEquals(FORBIDDEN.getUrn(), result.getString(TITLE)); + assertEquals(NOT_FOUND.getValue(), result.getInteger(TYPE)); + assertEquals(ResponseUrn.RESOURCE_NOT_FOUND_URN.getUrn(), result.getString(TITLE)); assertEquals( - "Access Denied: You do not have ownership rights for this resource.", + "Request could not be withdrawn, as it is not found", result.getString(DETAIL)); vertxTestContext.completeNow(); } diff --git a/src/test/resources/IUDX-ACL-APD-APIs.postman_collection.json b/src/test/resources/IUDX-ACL-APD-APIs.postman_collection.json index 1204d258..d1efbc84 100644 --- a/src/test/resources/IUDX-ACL-APD-APIs.postman_collection.json +++ b/src/test/resources/IUDX-ACL-APD-APIs.postman_collection.json @@ -1962,73 +1962,6 @@ }, "response": [] }, - { - "name": "403 Delete Access Request: Forbidden", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "// Test the response code", - "pm.test(\"response is 403 (Forbidden)\", function () {", - " pm.response.to.have.status(403);", - "});", - "", - "// Test the response header", - "pm.test(\"Check response header\", function () {", - " pm.response.to.have.header(\"Content-Type\",\"application/json\");", - "});", - "", - "// Test the response", - "pm.test(\"Check response body\", function () { ", - " const body = pm.response.json();", - " pm.expect(body).to.have.property(\"type\", \"urn:dx:acl:forbidden\");", - " pm.expect(body).to.have.property(\"title\", \"Forbidden\");", - " pm.expect(body).to.have.property(\"detail\", \"Access Denied: You do not have ownership rights for this resource.\");", - " }", - ");" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "DELETE", - "header": [ - { - "key": "Authorization", - "value": "{{consumerToken}}", - "type": "text", - "disabled": true - }, - { - "key": "Authorization", - "value": "{{consumerTokenForbidden}}", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "{\n\"id\": \"b1a16834-f238-4458-b468-887c2955e3cb\"\n}\n", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{baseUrl}}{{basePath}}/policies/requests", - "host": [ - "{{baseUrl}}{{basePath}}" - ], - "path": [ - "policies", - "requests" - ] - } - }, - "response": [] - }, { "name": "404 Delete Access Request: Not Found", "event": [ From a9af5f0ce929cea8fad6704c5f9696c50c2e0d35 Mon Sep 17 00:00:00 2001 From: shreelakshmijoshi Date: Thu, 9 Nov 2023 13:13:41 +0530 Subject: [PATCH 18/22] Update Server Description --- docs/openapi.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/openapi.yaml b/docs/openapi.yaml index ed91eaa6..ad25b32f 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -2,7 +2,10 @@ openapi: 3.0.0 info: version: 1.0.0 title: Data-Exchange-ACL-APD - description: API specification for ACL APD. These APIs are used by users manage policy. These APIs requires valid token for authentication. + description: | + **Data Exchange (DX) Access Control layer (ACL) and Access Policy Domain (APD)** is meant to create and manage the + policies created for consumer/consumer delegate so that a provider/provider delegate can regulate the access of their resources by consumers/ consumer delegates. + API specification for ACL APD. These APIs requires valid identity token from **Data Exchange(DX) Authentication Authorization and Accounting (AAA) Server** for authentication. contact: name: For support contact IUDX Team at email: support@iudx.org.in From 4e0f64a440cf686f1b01bb44c67bc1588cb1597a Mon Sep 17 00:00:00 2001 From: shreelakshmijoshi Date: Thu, 9 Nov 2023 13:20:04 +0530 Subject: [PATCH 19/22] Resolve checkstyle issue --- .../iudx/apd/acl/server/notification/UpdateNotification.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/iudx/apd/acl/server/notification/UpdateNotification.java b/src/main/java/iudx/apd/acl/server/notification/UpdateNotification.java index 53fb511f..3e311059 100644 --- a/src/main/java/iudx/apd/acl/server/notification/UpdateNotification.java +++ b/src/main/java/iudx/apd/acl/server/notification/UpdateNotification.java @@ -219,7 +219,7 @@ public Future initiateTransactions(JsonObject notification) { transactionResponseFuture = transactionResponseFuture.recover( failure -> { - failure.printStackTrace(); + failure.printStackTrace(); /* something went wrong while creating a policy or while inserting a record in approved access request or while updating the notification*/ @@ -528,6 +528,7 @@ public void executeQuery(String query, Tuple tuple, Handler Date: Thu, 9 Nov 2023 13:24:47 +0530 Subject: [PATCH 20/22] Resolve checkstyle issue --- .../iudx/apd/acl/server/notification/CreateNotification.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/iudx/apd/acl/server/notification/CreateNotification.java b/src/main/java/iudx/apd/acl/server/notification/CreateNotification.java index 4b84ef96..d1587be5 100644 --- a/src/main/java/iudx/apd/acl/server/notification/CreateNotification.java +++ b/src/main/java/iudx/apd/acl/server/notification/CreateNotification.java @@ -420,7 +420,9 @@ public Future isItemPresentInCatalogue(UUID resourceId, String itemType } }); } else { - LOG.debug("user does not have access to create notification as they're belonging to a different server w.r.t to the resource"); + LOG.debug( + "user does not have access to create notification as they're belonging " + + "to a different server w.r.t to the resource"); JsonObject failureMessage = new JsonObject() .put(TYPE, HttpStatusCode.NOT_FOUND.getValue()) From 52a1c852a67e8817edd0e4eb45ae6fa7b6aab8b4 Mon Sep 17 00:00:00 2001 From: shreelakshmijoshi Date: Thu, 9 Nov 2023 14:02:21 +0530 Subject: [PATCH 21/22] Update Introduction --- docs/openapi.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/openapi.yaml b/docs/openapi.yaml index ad25b32f..337be855 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -3,6 +3,10 @@ info: version: 1.0.0 title: Data-Exchange-ACL-APD description: | + + # Introduction + + **Data Exchange (DX) Access Control layer (ACL) and Access Policy Domain (APD)** is meant to create and manage the policies created for consumer/consumer delegate so that a provider/provider delegate can regulate the access of their resources by consumers/ consumer delegates. API specification for ACL APD. These APIs requires valid identity token from **Data Exchange(DX) Authentication Authorization and Accounting (AAA) Server** for authentication. From f1ca8b908ac59435aeaf2d13b5da3564685fcc5e Mon Sep 17 00:00:00 2001 From: shreelakshmijoshi Date: Thu, 9 Nov 2023 14:39:04 +0530 Subject: [PATCH 22/22] Update Introduction --- docs/openapi.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 337be855..e0d8e697 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -6,10 +6,10 @@ info: # Introduction - - **Data Exchange (DX) Access Control layer (ACL) and Access Policy Domain (APD)** is meant to create and manage the - policies created for consumer/consumer delegate so that a provider/provider delegate can regulate the access of their resources by consumers/ consumer delegates. - API specification for ACL APD. These APIs requires valid identity token from **Data Exchange(DX) Authentication Authorization and Accounting (AAA) Server** for authentication. + **Data Exchange (DX) Access Control Layer (ACL) and Access Policy Domain (APD)** are designed for creating and managing policies for consumers and consumer delegates. + This allows providers and provider delegates to control access to their resources by consumers and consumer delegates. + This API specification for ACL APD requires a valid identity token from the **Data Exchange (DX) Authentication Authorization and Accounting (AAA) Server** for authentication purposes. + contact: name: For support contact IUDX Team at email: support@iudx.org.in