From 6e5c4fedfe6dbf6af8b902f0fea4b31536e43394 Mon Sep 17 00:00:00 2001 From: Suraj Shanbhag Date: Thu, 10 Mar 2022 10:50:25 +0530 Subject: [PATCH 1/9] Auto Raise Claim on Add or Update Entity effecting Attestation policy paths --- .../registry/middleware/util/JSONUtil.java | 7 +- .../controller/RegistryClaimsController.java | 4 +- .../controller/RegistryEntityController.java | 2 +- .../registry/helper/RegistryHelper.java | 89 ++++++++++++++++++- .../sunbirdrc/actors/ClaimPluginActor.java | 3 +- 5 files changed, 95 insertions(+), 10 deletions(-) diff --git a/java/middleware-commons/src/main/java/dev/sunbirdrc/registry/middleware/util/JSONUtil.java b/java/middleware-commons/src/main/java/dev/sunbirdrc/registry/middleware/util/JSONUtil.java index bdca18214..1c7d3fb94 100644 --- a/java/middleware-commons/src/main/java/dev/sunbirdrc/registry/middleware/util/JSONUtil.java +++ b/java/middleware-commons/src/main/java/dev/sunbirdrc/registry/middleware/util/JSONUtil.java @@ -269,6 +269,10 @@ public static void addField(ObjectNode parent, String childKey, List chi parent.set(childKey, arrayNode); } + public static String parseJsonTree(String path, JsonNode input) { + return JsonPath.parse(input.toString()).read(path).toString(); + } + /** * Remove a node of given key from parent's hierarchy(including nested objects) * @@ -483,8 +487,7 @@ public static String readValFromJsonTree(String path, JsonNode input) { List typeList = JsonPath.using(alwaysReturnListConfig).parse(input.toString()).read(path); return typeList.get(0); } - - public static String getOSIDFromArrNode(JsonNode resultNode, JsonNode requestBody, List fieldsToRemove) { + public static String getOSIDFromArrNode(JsonNode resultNode) { if (resultNode.isArray()) { ArrayNode arrayNode = (ArrayNode) resultNode; return arrayNode.get(arrayNode.size() - 1).get("osid").asText(); diff --git a/java/registry/src/main/java/dev/sunbirdrc/registry/controller/RegistryClaimsController.java b/java/registry/src/main/java/dev/sunbirdrc/registry/controller/RegistryClaimsController.java index a82e58b48..8eeed55ed 100644 --- a/java/registry/src/main/java/dev/sunbirdrc/registry/controller/RegistryClaimsController.java +++ b/java/registry/src/main/java/dev/sunbirdrc/registry/controller/RegistryClaimsController.java @@ -158,7 +158,7 @@ public ResponseEntity riseAttestation(HttpServletRequest request, @Reque ((ObjectNode)requestBody).put("propertyData", propertyData.toString()); } registryHelper.addAttestationProperty(entityName, entityId, attestationName, requestBody, request); - String attestationOSID = registryHelper.getAttestationOSID(requestBody, entityName, entityId, attestationName); + String attestationOSID = registryHelper.getAttestationOSID(entityName, entityId, attestationName); // Resolve condition for REQUESTER String condition = conditionResolverService.resolve(propertyData, "REQUESTER", attestationPolicy.getConditions(), Collections.emptyList()); updateGetFileUrl(additionalInput); @@ -180,7 +180,7 @@ public ResponseEntity riseAttestation(HttpServletRequest request, @Reque } else { try { registryHelper.addAttestationProperty(entityName, entityId, attestationName, requestBody, request); - String attestationOSID = registryHelper.getAttestationOSID(requestBody, entityName, entityId, attestationName); + String attestationOSID = registryHelper.getAttestationOSID(entityName, entityId, attestationName); PluginRequestMessage pluginRequestMessage = PluginRequestMessageCreator.create( "", "", attestationOSID, entityName, entityId, additionalInput, Action.RAISE_CLAIM.name(), attestationPolicy.getName(), diff --git a/java/registry/src/main/java/dev/sunbirdrc/registry/controller/RegistryEntityController.java b/java/registry/src/main/java/dev/sunbirdrc/registry/controller/RegistryEntityController.java index 201c18981..2e59545ea 100644 --- a/java/registry/src/main/java/dev/sunbirdrc/registry/controller/RegistryEntityController.java +++ b/java/registry/src/main/java/dev/sunbirdrc/registry/controller/RegistryEntityController.java @@ -182,7 +182,7 @@ public ResponseEntity putEntity( JsonNode existingNode = registryHelper.readEntity(newRootNode, userId); registryHelper.updateEntityAndState(newRootNode, userId); registryHelper.invalidateAttestation(entityName, entityId); - + registryHelper.autoRaiseClaim(entityName,entityId,existingNode,registryHelper.readEntity(newRootNode,entityId),userId); responseParams.setErrmsg(""); responseParams.setStatus(Response.Status.SUCCESSFUL); watch.stop(tag); diff --git a/java/registry/src/main/java/dev/sunbirdrc/registry/helper/RegistryHelper.java b/java/registry/src/main/java/dev/sunbirdrc/registry/helper/RegistryHelper.java index 9e78f7a99..ee4a2c18c 100644 --- a/java/registry/src/main/java/dev/sunbirdrc/registry/helper/RegistryHelper.java +++ b/java/registry/src/main/java/dev/sunbirdrc/registry/helper/RegistryHelper.java @@ -10,8 +10,10 @@ import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; import com.flipkart.zjsonpatch.JsonPatch; +import dev.sunbirdrc.actors.factory.PluginRouter; import dev.sunbirdrc.keycloak.KeycloakAdminUtil; import dev.sunbirdrc.pojos.PluginRequestMessage; +import dev.sunbirdrc.pojos.PluginRequestMessageCreator; import dev.sunbirdrc.pojos.PluginResponseMessage; import dev.sunbirdrc.pojos.SunbirdRCInstrumentation; import dev.sunbirdrc.pojos.attestation.Action; @@ -21,6 +23,7 @@ import dev.sunbirdrc.registry.exception.SignatureException; import dev.sunbirdrc.registry.exception.UnAuthorizedException; import dev.sunbirdrc.registry.middleware.MiddlewareHaltException; +import dev.sunbirdrc.registry.middleware.service.ConditionResolverService; import dev.sunbirdrc.registry.middleware.util.JSONUtil; import dev.sunbirdrc.registry.middleware.util.OSSystemFields; import dev.sunbirdrc.registry.model.DBConnectionInfoMgr; @@ -82,6 +85,9 @@ public class RegistryHelper { @Autowired IValidate validationService; + @Autowired + ConditionResolverService conditionResolverService; + @Autowired private ISearchService searchService; @@ -133,12 +139,11 @@ public class RegistryHelper { @Autowired private EntityTypeHandler entityTypeHandler; - public String getAttestationOSID(JsonNode requestBody, String entityName, String entityId, String propertyName) throws Exception { + public String getAttestationOSID(String entityName, String entityId, String propertyName) throws Exception { JsonNode resultNode = readEntity("", entityName, entityId, false, null, false) .get(entityName) .get(propertyName); - List fieldsToRemove = getFieldsToRemove(entityName); - return JSONUtil.getOSIDFromArrNode(resultNode, requestBody, fieldsToRemove); + return JSONUtil.getOSIDFromArrNode(resultNode); } @Autowired @@ -176,7 +181,7 @@ public String addEntityAndSign(JsonNode inputJson, String userId) throws Excepti } public String inviteEntity(JsonNode inputJson, String userId) throws Exception { - String entityId = addEntityHandler(inputJson, userId, true); + String entityId = newAddEntityHandler(inputJson, userId, true); sendInviteNotification(inputJson); return entityId; } @@ -194,6 +199,18 @@ private String addEntityHandler(JsonNode inputJson, String userId, boolean isInv return addEntity(inputJson, userId, entityType); } + private String newAddEntityHandler(JsonNode inputJson, String userId, boolean isInvite) throws Exception { + String entityType = inputJson.fields().next().getKey(); + validationService.validate(entityType, objectMapper.writeValueAsString(inputJson), isInvite); + String entityName = inputJson.fields().next().getKey(); + List attestationPolicies = getAttestationPolicies(entityName); + entityStateHelper.applyWorkflowTransitions(JSONUtil.convertStringJsonNode("{}"), inputJson, attestationPolicies); + String entityId = addEntity(inputJson, userId, entityType); + String keyCloakUserId = inputJson.fields().next().getValue().get("osOwner").get(0).asText(); + autoRaiseClaim(entityName,entityId,objectMapper.createObjectNode(),inputJson,keyCloakUserId); + return entityId; + } + private void sendInviteNotification(JsonNode inputJson) throws Exception { String entityType = inputJson.fields().next().getKey(); sendNotificationToOwners(inputJson, INVITE, String.format(INVITE_SUBJECT_TEMPLATE, entityType), String.format(INVITE_BODY_TEMPLATE, entityType)); @@ -411,6 +428,16 @@ public String addAttestationProperty(String entityName, String entityId, String return updateEntityAndState(existingEntityNode, nodeToUpdate, userId); } + public String newAddAttestationProperty(JsonNode existingEntityNode, String propertyName, JsonNode inputJson) throws Exception { + JsonNode nodeToUpdate = existingEntityNode.deepCopy(); + String entityName = existingEntityNode.fields().next().getKey(); + JsonNode parentNode = nodeToUpdate.get(entityName); + JsonNode propertyNode = parentNode.get(propertyName); + createOrUpdateProperty(entityName, inputJson, nodeToUpdate, propertyName, (ObjectNode) parentNode, propertyNode); + String userId = existingEntityNode.fields().next().getValue().get("osOwner").get(0).asText(); + return updateEntityAndState(existingEntityNode, nodeToUpdate,userId); + } + private void createOrUpdateProperty(String entityName, JsonNode inputJson, JsonNode updateNode, String propertyName, ObjectNode parentNode, JsonNode propertyNode) throws JsonProcessingException { if (propertyNode != null && !propertyNode.isMissingNode()) { updateProperty(inputJson, propertyName, parentNode, propertyNode); @@ -506,6 +533,60 @@ public void sendForAttestation(String entityName, String entityId, String notes, updateEntity(updatedNode, ""); } + private boolean hasPolicyPathChanged(AttestationPolicy policy, JsonNode existingNode, JsonNode updatedNode, String entityName){ + List paths = policy.getPaths(); + boolean result = false; + for (String path : paths) { + if (!StringUtils.isEmpty(path)) { + if (existingNode.isEmpty() || !JSONUtil.parseJsonTree(path, updatedNode.get(entityName)).equals(JSONUtil.parseJsonTree(path, existingNode.get(entityName)))){ + result = true; + } + } + } + return result; + } + + public void autoRaiseClaim(String entityName, String entityId, JsonNode existingNode, JsonNode updatedNode, String userId) throws Exception { + List attestationPolicies = getAttestationPolicies(entityName); + for (AttestationPolicy policy : + attestationPolicies) { + if(hasPolicyPathChanged(policy,existingNode,updatedNode,entityName)){ + logger.info("Calling auto attestation actor"); + String attestationName = policy.getName(); + ObjectNode claimProperties = objectMapper.createObjectNode(); + claimProperties.put("entityName",entityName); + claimProperties.put("entityId",entityId); + claimProperties.put("name",attestationName); + JsonNode entityNode = readEntity(userId, entityName, entityId, false, null, false); + if(policy.isInternal()) { + Map> propertyOSIDMapper = objectMapper.convertValue(claimProperties.get("propertiesOSID"), Map.class); + JsonNode propertyData = JSONUtil.extractPropertyDataFromEntity(entityNode.get(entityName), policy.getAttestationProperties(), propertyOSIDMapper); + if(!propertyData.isNull()) { + claimProperties.put("propertyData", propertyData.toString()); + } + newAddAttestationProperty(entityNode,attestationName, claimProperties); + String attestationOSID = getAttestationOSID(entityName, entityId, attestationName); + String condition = conditionResolverService.resolve(propertyData, "REQUESTER", policy.getConditions(), Collections.emptyList()); + PluginRequestMessage message = PluginRequestMessageCreator.create( + propertyData.toString(), condition, attestationOSID, + entityName, entityId, null, Action.RAISE_CLAIM.name(), policy.getName(), + policy.getAttestorPlugin(), policy.getAttestorEntity(), + policy.getAttestorSignin()); + PluginRouter.route(message); + } else { + newAddAttestationProperty(entityNode,attestationName, claimProperties); + String attestationOSID = getAttestationOSID(entityName, entityId, attestationName); + PluginRequestMessage pluginRequestMessage = PluginRequestMessageCreator.create( + "", "", attestationOSID, + entityName, entityId, null, Action.RAISE_CLAIM.name(), policy.getName(), + policy.getAttestorPlugin(), policy.getAttestorEntity(), + policy.getAttestorSignin()); + PluginRouter.route(pluginRequestMessage); + } + } + } + } + public void callPluginActor() throws JsonProcessingException { registryService.callPluginActors("CowinActor", PluginRequestMessage.builder().sourceEntity("Student").sourceOSID("234").policyName("education").attestationOSID("432").build()); } diff --git a/java/sunbirdrc-actors/src/main/java/dev/sunbirdrc/actors/ClaimPluginActor.java b/java/sunbirdrc-actors/src/main/java/dev/sunbirdrc/actors/ClaimPluginActor.java index 1b4d9f377..37cd020fd 100644 --- a/java/sunbirdrc-actors/src/main/java/dev/sunbirdrc/actors/ClaimPluginActor.java +++ b/java/sunbirdrc-actors/src/main/java/dev/sunbirdrc/actors/ClaimPluginActor.java @@ -27,7 +27,7 @@ public class ClaimPluginActor extends BaseActor { // TODO: read url from config - private final String claimRequestUrl = System.getenv("claims_url"); + private final String claimRequestUrl = System.getenv().getOrDefault("claims_url","http://localhost:8082"); private final String CLAIMS_PATH = "/api/v1/claims"; RestTemplate restTemplate = new RestTemplate(); @@ -78,6 +78,7 @@ private void attestClaim(PluginRequestMessage pluginRequestMessage) throws IOExc private String getClaimRequestUrl() { if (isBlank(claimRequestUrl)) { + logger.error("claims service url is not set but it seems to be in use."); } return claimRequestUrl; From a334ce85114d5bc7bb77dedd773b34b179ba58b9 Mon Sep 17 00:00:00 2001 From: Suraj Shanbhag Date: Thu, 10 Mar 2022 12:23:42 +0530 Subject: [PATCH 2/9] fixed failing test --- .../registry/entities/AttestationPolicy.java | 3 ++ .../registry/helper/RegistryHelper.java | 48 ++++++++++--------- .../registry/helper/RegistryHelperTest.java | 3 ++ 3 files changed, 31 insertions(+), 23 deletions(-) diff --git a/java/registry/src/main/java/dev/sunbirdrc/registry/entities/AttestationPolicy.java b/java/registry/src/main/java/dev/sunbirdrc/registry/entities/AttestationPolicy.java index 2c984f42c..a7498901a 100644 --- a/java/registry/src/main/java/dev/sunbirdrc/registry/entities/AttestationPolicy.java +++ b/java/registry/src/main/java/dev/sunbirdrc/registry/entities/AttestationPolicy.java @@ -90,6 +90,9 @@ public String getNodePath() { public boolean isInternal() { return this.attestorPlugin.split(PLUGIN_SPLITTER)[1].equals(AttestorPluginType.internal.name()); } + public boolean hasAttestationPlugin(){ + return this.attestorPlugin!=null; + } public Map getAttestationProperties() { try { diff --git a/java/registry/src/main/java/dev/sunbirdrc/registry/helper/RegistryHelper.java b/java/registry/src/main/java/dev/sunbirdrc/registry/helper/RegistryHelper.java index 0124d759c..02ba036d7 100644 --- a/java/registry/src/main/java/dev/sunbirdrc/registry/helper/RegistryHelper.java +++ b/java/registry/src/main/java/dev/sunbirdrc/registry/helper/RegistryHelper.java @@ -565,30 +565,32 @@ public void autoRaiseClaim(String entityName, String entityId, JsonNode existing claimProperties.put("entityId",entityId); claimProperties.put("name",attestationName); JsonNode entityNode = readEntity(userId, entityName, entityId, false, null, false); - if(policy.isInternal()) { - Map> propertyOSIDMapper = objectMapper.convertValue(claimProperties.get("propertiesOSID"), Map.class); - JsonNode propertyData = JSONUtil.extractPropertyDataFromEntity(entityNode.get(entityName), policy.getAttestationProperties(), propertyOSIDMapper); - if(!propertyData.isNull()) { - claimProperties.put("propertyData", propertyData.toString()); + if(policy.hasAttestationPlugin()){ + if(policy.isInternal()) { + Map> propertyOSIDMapper = objectMapper.convertValue(claimProperties.get("propertiesOSID"), Map.class); + JsonNode propertyData = JSONUtil.extractPropertyDataFromEntity(entityNode.get(entityName), policy.getAttestationProperties(), propertyOSIDMapper); + if(!propertyData.isNull()) { + claimProperties.put("propertyData", propertyData.toString()); + } + newAddAttestationProperty(entityNode,attestationName, claimProperties); + String attestationOSID = getAttestationOSID(entityName, entityId, attestationName); + String condition = conditionResolverService.resolve(propertyData, "REQUESTER", policy.getConditions(), Collections.emptyList()); + PluginRequestMessage message = PluginRequestMessageCreator.create( + propertyData.toString(), condition, attestationOSID, + entityName, entityId, null, Action.RAISE_CLAIM.name(), policy.getName(), + policy.getAttestorPlugin(), policy.getAttestorEntity(), + policy.getAttestorSignin()); + PluginRouter.route(message); + } else { + newAddAttestationProperty(entityNode,attestationName, claimProperties); + String attestationOSID = getAttestationOSID(entityName, entityId, attestationName); + PluginRequestMessage pluginRequestMessage = PluginRequestMessageCreator.create( + "", "", attestationOSID, + entityName, entityId, null, Action.RAISE_CLAIM.name(), policy.getName(), + policy.getAttestorPlugin(), policy.getAttestorEntity(), + policy.getAttestorSignin()); + PluginRouter.route(pluginRequestMessage); } - newAddAttestationProperty(entityNode,attestationName, claimProperties); - String attestationOSID = getAttestationOSID(entityName, entityId, attestationName); - String condition = conditionResolverService.resolve(propertyData, "REQUESTER", policy.getConditions(), Collections.emptyList()); - PluginRequestMessage message = PluginRequestMessageCreator.create( - propertyData.toString(), condition, attestationOSID, - entityName, entityId, null, Action.RAISE_CLAIM.name(), policy.getName(), - policy.getAttestorPlugin(), policy.getAttestorEntity(), - policy.getAttestorSignin()); - PluginRouter.route(message); - } else { - newAddAttestationProperty(entityNode,attestationName, claimProperties); - String attestationOSID = getAttestationOSID(entityName, entityId, attestationName); - PluginRequestMessage pluginRequestMessage = PluginRequestMessageCreator.create( - "", "", attestationOSID, - entityName, entityId, null, Action.RAISE_CLAIM.name(), policy.getName(), - policy.getAttestorPlugin(), policy.getAttestorEntity(), - policy.getAttestorSignin()); - PluginRouter.route(pluginRequestMessage); } } } diff --git a/java/registry/src/test/java/dev/sunbirdrc/registry/helper/RegistryHelperTest.java b/java/registry/src/test/java/dev/sunbirdrc/registry/helper/RegistryHelperTest.java index 5338314b5..fad3bdc6a 100644 --- a/java/registry/src/test/java/dev/sunbirdrc/registry/helper/RegistryHelperTest.java +++ b/java/registry/src/test/java/dev/sunbirdrc/registry/helper/RegistryHelperTest.java @@ -319,6 +319,7 @@ public void shouldCreateOwnersForInvite() throws Exception { when(keycloakAdminUtil.createUser(any(), any(), any(), any())).thenReturn(testUserId); when(registryService.addEntity(any(), any(), any())).thenReturn(UUID.randomUUID().toString()); when(shardManager.getShard(any())).thenReturn(new Shard()); + when(readService.getEntity(any(),any(),any(),any(),any())).thenReturn(inviteJson); registryHelper.inviteEntity(inviteJson, ""); Mockito.verify(registryService).addEntity(shardCapture.capture(), userIdCapture.capture(), inputJsonCapture.capture()); assertEquals("{\"Institute\":{\"email\":\"gecasu.ihises@tovinit.com\",\"instituteName\":\"gecasu\",\"osOwner\":[\"" + testUserId + "\"]}}", inputJsonCapture.getValue().toString()); @@ -332,6 +333,7 @@ public void shouldSendInviteInvitationsAfterCreatingOwners() throws Exception { when(keycloakAdminUtil.createUser(any(), any(), any(), any())).thenReturn(testUserId); when(registryService.addEntity(any(), any(), any())).thenReturn(UUID.randomUUID().toString()); when(shardManager.getShard(any())).thenReturn(new Shard()); + when(readService.getEntity(any(),any(),any(),any(),any())).thenReturn(inviteJson); registryHelper.inviteEntity(inviteJson, ""); Mockito.verify(registryService).addEntity(shardCapture.capture(), userIdCapture.capture(), inputJsonCapture.capture()); Mockito.verify(registryService, atLeastOnce()).callNotificationActors(operationCapture.capture(), toCapture.capture(), subjectCapture.capture(), messageCapture.capture()); @@ -362,6 +364,7 @@ public void shouldSendMultipleInviteInvitationsAfterCreatingOwners() throws Exce when(keycloakAdminUtil.createUser(any(), any(), any(), any())).thenReturn(testUserId); when(registryService.addEntity(any(), any(), any())).thenReturn(UUID.randomUUID().toString()); when(shardManager.getShard(any())).thenReturn(new Shard()); + when(readService.getEntity(any(),any(),any(),any(),any())).thenReturn(inviteJson); mockDefinitionManager(); registryHelper.inviteEntity(inviteJson, ""); Mockito.verify(registryService).addEntity(shardCapture.capture(), userIdCapture.capture(), inputJsonCapture.capture()); From e5e468fd3ac61704d63a277db9f8470886135bd6 Mon Sep 17 00:00:00 2001 From: suraj-shanbhag Date: Wed, 16 Mar 2022 15:49:30 +0530 Subject: [PATCH 3/9] Update RegistryEntityController.java --- .../sunbirdrc/registry/controller/RegistryEntityController.java | 1 + 1 file changed, 1 insertion(+) diff --git a/java/registry/src/main/java/dev/sunbirdrc/registry/controller/RegistryEntityController.java b/java/registry/src/main/java/dev/sunbirdrc/registry/controller/RegistryEntityController.java index 5acf7e110..19665570d 100644 --- a/java/registry/src/main/java/dev/sunbirdrc/registry/controller/RegistryEntityController.java +++ b/java/registry/src/main/java/dev/sunbirdrc/registry/controller/RegistryEntityController.java @@ -188,6 +188,7 @@ public ResponseEntity putEntity( String tag = "RegistryController.update " + entityName; watch.start(tag); // TODO: get userID from auth header + JsonNode existingNode = registryHelper.readEntity(newRootNode, userId); registryHelper.updateEntityAndState(newRootNode, userId); registryHelper.invalidateAttestation(entityName, entityId); registryHelper.autoRaiseClaim(entityName,entityId,existingNode,registryHelper.readEntity(newRootNode,entityId),userId); From 5f4524a4ae4d8f347e0e9f46a25850ac21434002 Mon Sep 17 00:00:00 2001 From: suraj-shanbhag Date: Wed, 16 Mar 2022 15:55:12 +0530 Subject: [PATCH 4/9] Update RegistryHelper.java --- .../registry/helper/RegistryHelper.java | 30 +------------------ 1 file changed, 1 insertion(+), 29 deletions(-) diff --git a/java/registry/src/main/java/dev/sunbirdrc/registry/helper/RegistryHelper.java b/java/registry/src/main/java/dev/sunbirdrc/registry/helper/RegistryHelper.java index 27a3935a3..cb5ecb1ee 100644 --- a/java/registry/src/main/java/dev/sunbirdrc/registry/helper/RegistryHelper.java +++ b/java/registry/src/main/java/dev/sunbirdrc/registry/helper/RegistryHelper.java @@ -519,17 +519,6 @@ public void attestEntity(String entityName, JsonNode node, String[] jsonPaths, S JsonPatch.applyInPlace(objectMapper.readTree(patch), node.get(entityName)); updateEntity(node, userId); } - - public void sendForAttestation(String entityName, String entityId, String notes, HttpServletRequest request, String propertyId) throws Exception { - String propertyURI = getPropertyURI(entityId, request); - if (!propertyId.isEmpty()) { - propertyURI = propertyURI + "/" + propertyId; - } - JsonNode entityNode = readEntity("", entityName, entityId, false, null, false); - List attestationPolicies = getAttestationPolicies(entityName); - JsonNode updatedNode = entityStateHelper.sendForAttestation(entityNode, propertyURI, notes, attestationPolicies); - updateEntity(updatedNode, ""); - } private boolean hasPolicyPathChanged(AttestationPolicy policy, JsonNode existingNode, JsonNode updatedNode, String entityName){ List paths = policy.getPaths(); @@ -586,24 +575,7 @@ public void autoRaiseClaim(String entityName, String entityId, JsonNode existing } } } - - public void callPluginActor() throws JsonProcessingException { - registryService.callPluginActors("CowinActor", PluginRequestMessage.builder().sourceEntity("Student").sourceOSID("234").policyName("education").attestationOSID("432").build()); - } - - public void attest(String entityName, String entityId, String uuidPath, JsonNode attestReq) throws Exception { - JsonNode entityNode = readEntity("", entityName, entityId, false, null, false); - JsonNode updatedNode; - if (attestReq.get("action").asText().equals(Action.GRANT_CLAIM.toString())) { - updatedNode = entityStateHelper.grantClaim(entityNode, uuidPath, attestReq.get("notes").asText(), getAttestationPolicies(entityName)); - sendNotificationToOwners(updatedNode, CLAIM_GRANTED, String.format(CLAIM_STATUS_SUBJECT_TEMPLATE, CLAIM_GRANTED), String.format(CLAIM_STATUS_BODY_TEMPLATE, CLAIM_GRANTED)); - } else { - updatedNode = entityStateHelper.rejectClaim(entityNode, uuidPath, attestReq.get("notes").asText(), getAttestationPolicies(entityName)); - sendNotificationToOwners(updatedNode, CLAIM_REJECTED, String.format(CLAIM_STATUS_SUBJECT_TEMPLATE, CLAIM_REJECTED), String.format(CLAIM_STATUS_BODY_TEMPLATE, CLAIM_REJECTED)); - } - updateEntity(updatedNode, ""); - } - + public void updateState(PluginResponseMessage pluginResponseMessage) throws Exception { String attestationName = pluginResponseMessage.getPolicyName(); String attestationOSID = pluginResponseMessage.getAttestationOSID(); From 71207cd6accf8eb041844968f5a931e4785d25de Mon Sep 17 00:00:00 2001 From: Suraj Shanbhag Date: Wed, 16 Mar 2022 16:23:47 +0530 Subject: [PATCH 5/9] Updated code to use Attestation policy property instead of paths --- .../registry/controller/RegistryEntityController.java | 2 +- .../java/dev/sunbirdrc/registry/helper/RegistryHelper.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/java/registry/src/main/java/dev/sunbirdrc/registry/controller/RegistryEntityController.java b/java/registry/src/main/java/dev/sunbirdrc/registry/controller/RegistryEntityController.java index 19665570d..8ce3f6740 100644 --- a/java/registry/src/main/java/dev/sunbirdrc/registry/controller/RegistryEntityController.java +++ b/java/registry/src/main/java/dev/sunbirdrc/registry/controller/RegistryEntityController.java @@ -190,7 +190,7 @@ public ResponseEntity putEntity( // TODO: get userID from auth header JsonNode existingNode = registryHelper.readEntity(newRootNode, userId); registryHelper.updateEntityAndState(newRootNode, userId); - registryHelper.invalidateAttestation(entityName, entityId); + registryHelper.invalidateAttestation(entityName, entityId,userId); registryHelper.autoRaiseClaim(entityName,entityId,existingNode,registryHelper.readEntity(newRootNode,entityId),userId); responseParams.setErrmsg(""); responseParams.setStatus(Response.Status.SUCCESSFUL); diff --git a/java/registry/src/main/java/dev/sunbirdrc/registry/helper/RegistryHelper.java b/java/registry/src/main/java/dev/sunbirdrc/registry/helper/RegistryHelper.java index cb5ecb1ee..9f4b6e27b 100644 --- a/java/registry/src/main/java/dev/sunbirdrc/registry/helper/RegistryHelper.java +++ b/java/registry/src/main/java/dev/sunbirdrc/registry/helper/RegistryHelper.java @@ -52,6 +52,7 @@ import javax.servlet.http.HttpServletRequest; import java.io.ByteArrayInputStream; import java.util.*; +import java.util.stream.Collectors; import static dev.sunbirdrc.registry.Constants.*; import static dev.sunbirdrc.registry.exception.ErrorMessages.*; @@ -521,7 +522,7 @@ public void attestEntity(String entityName, JsonNode node, String[] jsonPaths, S } private boolean hasPolicyPathChanged(AttestationPolicy policy, JsonNode existingNode, JsonNode updatedNode, String entityName){ - List paths = policy.getPaths(); + List paths = new ArrayList<>(policy.getAttestationProperties().values()); boolean result = false; for (String path : paths) { if (!StringUtils.isEmpty(path)) { From 2c1b8981763f6a2d0aabff1382a8f63adf1549e1 Mon Sep 17 00:00:00 2001 From: Suraj Shanbhag Date: Wed, 16 Mar 2022 17:11:57 +0530 Subject: [PATCH 6/9] Added Null checks for attestation property path --- .../main/java/dev/sunbirdrc/registry/helper/RegistryHelper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/registry/src/main/java/dev/sunbirdrc/registry/helper/RegistryHelper.java b/java/registry/src/main/java/dev/sunbirdrc/registry/helper/RegistryHelper.java index 9f4b6e27b..4cf1770a6 100644 --- a/java/registry/src/main/java/dev/sunbirdrc/registry/helper/RegistryHelper.java +++ b/java/registry/src/main/java/dev/sunbirdrc/registry/helper/RegistryHelper.java @@ -522,7 +522,7 @@ public void attestEntity(String entityName, JsonNode node, String[] jsonPaths, S } private boolean hasPolicyPathChanged(AttestationPolicy policy, JsonNode existingNode, JsonNode updatedNode, String entityName){ - List paths = new ArrayList<>(policy.getAttestationProperties().values()); + List paths = new ArrayList<>(policy.getAttestationProperties()==null?CollectionUtils.emptyCollection():policy.getAttestationProperties().values()); boolean result = false; for (String path : paths) { if (!StringUtils.isEmpty(path)) { From d45b4d66233385e90729d27074f14dffdf890a1e Mon Sep 17 00:00:00 2001 From: Suraj Shanbhag Date: Fri, 18 Mar 2022 16:42:36 +0530 Subject: [PATCH 7/9] Enable Keycloak Security on conditional --- .../java/dev/sunbirdrc/registry/app/SunbirdRCApplication.java | 3 ++- .../java/dev/sunbirdrc/registry/config/SecurityConfig.java | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/java/registry/src/main/java/dev/sunbirdrc/registry/app/SunbirdRCApplication.java b/java/registry/src/main/java/dev/sunbirdrc/registry/app/SunbirdRCApplication.java index 6aa10f41c..59661e94a 100644 --- a/java/registry/src/main/java/dev/sunbirdrc/registry/app/SunbirdRCApplication.java +++ b/java/registry/src/main/java/dev/sunbirdrc/registry/app/SunbirdRCApplication.java @@ -4,6 +4,7 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; @@ -12,7 +13,7 @@ import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; -@SpringBootApplication +@SpringBootApplication(exclude={SecurityAutoConfiguration.class}) @ComponentScan(basePackages = {"dev.sunbirdrc.registry", "dev.sunbirdrc.pojos", "dev.sunbirdrc.keycloak", "dev.sunbirdrc.workflow", "dev.sunbirdrc.plugin"}) public class SunbirdRCApplication { private static ApplicationContext context; diff --git a/java/registry/src/main/java/dev/sunbirdrc/registry/config/SecurityConfig.java b/java/registry/src/main/java/dev/sunbirdrc/registry/config/SecurityConfig.java index df2b5f714..7b3be31cb 100644 --- a/java/registry/src/main/java/dev/sunbirdrc/registry/config/SecurityConfig.java +++ b/java/registry/src/main/java/dev/sunbirdrc/registry/config/SecurityConfig.java @@ -6,6 +6,7 @@ import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @@ -20,6 +21,7 @@ @Configuration @EnableWebSecurity @ComponentScan(basePackageClasses = KeycloakSecurityComponents.class) +@ConditionalOnProperty(name = "authentication.enabled",havingValue = "true",matchIfMissing = false) public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter { @Value("${authentication.enabled:true}") boolean authenticationEnabled; From b97dc6b8966e5cd79151c0d367da8622f476f579 Mon Sep 17 00:00:00 2001 From: Suraj Shanbhag Date: Mon, 21 Mar 2022 18:07:38 +0530 Subject: [PATCH 8/9] Added safety check around the parsing key-cloak id --- .../java/dev/sunbirdrc/registry/helper/RegistryHelper.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/java/registry/src/main/java/dev/sunbirdrc/registry/helper/RegistryHelper.java b/java/registry/src/main/java/dev/sunbirdrc/registry/helper/RegistryHelper.java index 4cf1770a6..c0a1df725 100644 --- a/java/registry/src/main/java/dev/sunbirdrc/registry/helper/RegistryHelper.java +++ b/java/registry/src/main/java/dev/sunbirdrc/registry/helper/RegistryHelper.java @@ -211,8 +211,10 @@ private String newAddEntityHandler(JsonNode inputJson, String userId, boolean is List attestationPolicies = getAttestationPolicies(entityName); entityStateHelper.applyWorkflowTransitions(JSONUtil.convertStringJsonNode("{}"), inputJson, attestationPolicies); String entityId = addEntity(inputJson, userId, entityType); - String keyCloakUserId = inputJson.fields().next().getValue().get("osOwner").get(0).asText(); - autoRaiseClaim(entityName,entityId,objectMapper.createObjectNode(),inputJson,keyCloakUserId); + String keyCloakUserId = inputJson.fields().next().getValue().get("osOwner")!=null ?inputJson.fields().next().getValue().get("osOwner").get(0).asText():null; + if(keyCloakUserId!=null){ + autoRaiseClaim(entityName,entityId,objectMapper.createObjectNode(),inputJson,keyCloakUserId); + } return entityId; } From 570d64735813782edd4d61d7fbc6325d0d741788 Mon Sep 17 00:00:00 2001 From: Suraj Shanbhag Date: Fri, 29 Apr 2022 02:28:15 +0530 Subject: [PATCH 9/9] Updated auto claim to fetch email id of the requestor from entity --- .../registry/middleware/util/JSONUtil.java | 2 +- .../registry/helper/RegistryHelper.java | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/java/middleware-commons/src/main/java/dev/sunbirdrc/registry/middleware/util/JSONUtil.java b/java/middleware-commons/src/main/java/dev/sunbirdrc/registry/middleware/util/JSONUtil.java index 57455e2a0..bfb51b3b8 100644 --- a/java/middleware-commons/src/main/java/dev/sunbirdrc/registry/middleware/util/JSONUtil.java +++ b/java/middleware-commons/src/main/java/dev/sunbirdrc/registry/middleware/util/JSONUtil.java @@ -499,7 +499,7 @@ public static String getOSIDFromArrNode(JsonNode resultNode, JsonNode requestBod } private static JsonNode searchClaimOsIdFromRequestProperties(ArrayNode arrayNode, JsonNode requestBody) { - if (requestBody.get("propertiesOSID") != null) { + if (requestBody!=null && requestBody.get("propertiesOSID") != null) { Map> requestBodyProperty = objectMapper.convertValue(requestBody.get("propertiesOSID"), Map.class); Iterator claimIterator = arrayNode.elements(); while (claimIterator.hasNext()) { diff --git a/java/registry/src/main/java/dev/sunbirdrc/registry/helper/RegistryHelper.java b/java/registry/src/main/java/dev/sunbirdrc/registry/helper/RegistryHelper.java index 0299ca189..46ecf257d 100644 --- a/java/registry/src/main/java/dev/sunbirdrc/registry/helper/RegistryHelper.java +++ b/java/registry/src/main/java/dev/sunbirdrc/registry/helper/RegistryHelper.java @@ -12,6 +12,7 @@ import com.flipkart.zjsonpatch.JsonPatch; import dev.sunbirdrc.actors.factory.PluginRouter; import dev.sunbirdrc.keycloak.KeycloakAdminUtil; +import dev.sunbirdrc.pojos.OwnershipsAttributes; import dev.sunbirdrc.pojos.PluginRequestMessage; import dev.sunbirdrc.pojos.PluginRequestMessageCreator; import dev.sunbirdrc.pojos.PluginResponseMessage; @@ -565,7 +566,7 @@ public void autoRaiseClaim(String entityName, String entityId, JsonNode existing String condition = conditionResolverService.resolve(propertyData, "REQUESTER", policy.getConditions(), Collections.emptyList()); PluginRequestMessage message = PluginRequestMessageCreator.create( propertyData.toString(), condition, attestationOSID, - entityName,"", entityId, null, Action.RAISE_CLAIM.name(), policy.getName(), + entityName,fetchEmailIdFromEntity(entityNode,entityName), entityId, null, Action.RAISE_CLAIM.name(), policy.getName(), policy.getAttestorPlugin(), policy.getAttestorEntity(), policy.getAttestorSignin()); PluginRouter.route(message); @@ -574,7 +575,7 @@ public void autoRaiseClaim(String entityName, String entityId, JsonNode existing String attestationOSID = getAttestationOSID(null,entityName, entityId, attestationName); PluginRequestMessage pluginRequestMessage = PluginRequestMessageCreator.create( "", "", attestationOSID, - entityName,"", entityId, null, Action.RAISE_CLAIM.name(), policy.getName(), + entityName,fetchEmailIdFromEntity(entityNode,entityName), entityId, null, Action.RAISE_CLAIM.name(), policy.getName(), policy.getAttestorPlugin(), policy.getAttestorEntity(), policy.getAttestorSignin()); PluginRouter.route(pluginRequestMessage); @@ -711,6 +712,17 @@ private String fetchUserIdFromToken(HttpServletRequest request) throws Exception throw new Exception("Forbidden"); } + private String fetchEmailIdFromEntity(JsonNode entityNode,String entityName){ + List ownershipAttributes = definitionsManager.getOwnershipAttributes(entityName); + String entityEmail=""; + for (OwnershipsAttributes attributes:ownershipAttributes){ + String email = entityNode.at(String.format("/%s%s", entityName,attributes.getEmail())).asText(""); + if(StringUtils.isNotEmpty(email)){ + entityEmail = email; + } + } + return entityEmail; + } public String fetchEmailIdFromToken(HttpServletRequest request, String entityName) throws Exception { if (doesEntityContainOwnershipAttributes(entityName) || getManageRoles(entityName).size() > 0) { KeycloakAuthenticationToken principal = (KeycloakAuthenticationToken) request.getUserPrincipal();