From 2d5078d53dba95b3e2960116edcc29c0d6146a16 Mon Sep 17 00:00:00 2001 From: Stefan Wiedemann Date: Mon, 27 May 2024 15:39:23 +0200 Subject: [PATCH 01/11] add some basic ngsi-ld support --- doc/REGO.md | 10 +++++ src/main/resources/mapping.json | 6 +++ src/main/resources/rego-resources.txt | 12 ++++++ .../resources/rego/ngsi-ld/leftOperand.rego | 43 +++++++++++++++++++ 4 files changed, 71 insertions(+) create mode 100644 src/main/resources/rego/ngsi-ld/leftOperand.rego diff --git a/doc/REGO.md b/doc/REGO.md index d55bf13..1318e6a 100644 --- a/doc/REGO.md +++ b/doc/REGO.md @@ -61,3 +61,13 @@ | helper | ## | token | the unprefixed bearer token | | helper | ## | entity | the entity provided as http-body | | helper | ## | target | the target of the request, found as the last part of the path | + +## ngsild + +| ODRL Class | ODRL Key | Rego-Method | Description | +| --- | --- | --- | --- | +| leftOperand | ngsi-ld:entityType | entity_type(http_part) | retrieves the type from an entity, either from the request path or from the body | +| leftOperand | ngsi-ld: | # | retrieves the value of the property, only applies to properties of type "Property". The method should be concretized in the mapping.json, to match a concrete property. | +| leftOperand | ngsi-ld:_observedAt | # | retrieves the observedAt of the property The method should be concretized in the mapping.json, to match a concrete property. | +| leftOperand | ngsi-ld:_modifiedAt | # | retrieves the modifiedAt of the property The method should be concretized in the mapping.json, to match a concrete property. | +| leftOperand | ngsi-ld: | # | retrieves the object of the relationship, only applies to properties of type "Relationship". The method should be concretized in the mapping.json, to match a concrete property. | diff --git a/src/main/resources/mapping.json b/src/main/resources/mapping.json index 9a5fcaf..1c23535 100644 --- a/src/main/resources/mapping.json +++ b/src/main/resources/mapping.json @@ -124,6 +124,12 @@ } }, "leftOperand": { + "ngsi-ld": { + "entityType": { + "regoPackage": "ngsild.leftOperand as ngsild_lo", + "regoMethod": "odrl_lo.entity_type(helper.http_part)" + } + }, "odrl": { "dateTime": { "regoPackage": "odrl.leftOperand as odrl_lo", diff --git a/src/main/resources/rego-resources.txt b/src/main/resources/rego-resources.txt index 634c2ff..5e60c70 100644 --- a/src/main/resources/rego-resources.txt +++ b/src/main/resources/rego-resources.txt @@ -19,3 +19,15 @@ rego/odrl/action.rego rego/odrl/assignee.rego rego/utils/kong.rego rego/utils/apisix.rego +rego/dome/leftOperand.rego +rego/dome/action.rego +rego/odrl/operand.rego +rego/odrl/rightOperand.rego +rego/odrl/operator.rego +rego/odrl/leftOperand.rego +rego/odrl/target.rego +rego/odrl/action.rego +rego/odrl/assignee.rego +rego/utils/kong.rego +rego/utils/apisix.rego +rego/ngsi-ld/leftOperand.rego diff --git a/src/main/resources/rego/ngsi-ld/leftOperand.rego b/src/main/resources/rego/ngsi-ld/leftOperand.rego new file mode 100644 index 0000000..1b59afa --- /dev/null +++ b/src/main/resources/rego/ngsi-ld/leftOperand.rego @@ -0,0 +1,43 @@ +package ngsild.leftOperand + +import rego.v1 + +# helper method to retrieve the type from the path +type_from_path(path) := type if { + path_without_query := split(path, "?")[0] + path_elements := split(path_without_query, "/") + id_elements := split(path_elements[count(path_elements) - 1], ":") + type = id_elements[2] +} + +# helper to retrieve the type from the body +type_from_body(body) := body.type + +## ngsi-ld:entityType +# retrieves the type from an entity, either from the request path or from the body +entity_type(http_part) := tfp if { + tfp = type_from_path(http_part.path) +} else := tfb if { + tfb = type_from_body(http_part.body) +} + +## ngsi-ld: +# retrieves the value of the property, only applies to properties of type "Property". The method should be concretized in the mapping.json, to match a concrete property. +# F.e.: ngsi-ld:brandName = property_value("brandName", http_part.body) +property_value(property_name, body) := body[property_name].value + +## ngsi-ld:_observedAt +# retrieves the observedAt of the property The method should be concretized in the mapping.json, to match a concrete property. +# F.e.: ngsi-ld:brandName_observedAt = property_value("brandName", http_part.body) +property_observed_at(property_name,body) := body[property_name].observedAt + +## ngsi-ld:_modifiedAt +# retrieves the modifiedAt of the property The method should be concretized in the mapping.json, to match a concrete property. +# F.e.: ngsi-ld:brandName_modifiedAt= property_value("brandName", http_part.body) +property_observed_at(property_name,body) := body[property_name].modifiedAt + +## ngsi-ld: +# retrieves the object of the relationship, only applies to properties of type "Relationship". The method should be concretized in the mapping.json, to match a concrete property. +# F.e.: ngsi-ld:owningCompany = relationship_object("owningCompany", http_part.body) +relationship_object(relationship_name, body):= body[relationship_name].object + From 759e9858a2514ae10b08577ea306286ec0f2077e Mon Sep 17 00:00:00 2001 From: Stefan Wiedemann Date: Mon, 27 May 2024 16:23:28 +0200 Subject: [PATCH 02/11] add vc funcs --- doc/REGO.md | 7 +++++++ src/main/resources/mapping.json | 12 +++++++++++- src/main/resources/rego-resources.txt | 13 +++++++++++++ src/main/resources/rego/utils/apisix.rego | 6 +++++- src/main/resources/rego/vc/leftOperand.rego | 15 +++++++++++++++ .../resources/examples/dome/1001/_1001.json | Bin 3478 -> 3482 bytes 6 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 src/main/resources/rego/vc/leftOperand.rego diff --git a/doc/REGO.md b/doc/REGO.md index 1318e6a..28c5625 100644 --- a/doc/REGO.md +++ b/doc/REGO.md @@ -62,6 +62,13 @@ | helper | ## | entity | the entity provided as http-body | | helper | ## | target | the target of the request, found as the last part of the path | +## vc + +| ODRL Class | ODRL Key | Rego-Method | Description | +| --- | --- | --- | --- | +| leftOperand | vc:role | role(verifiable_credential,organization_id) | retrieves the roles from the credential, that target the current organization | +| leftOperand | vc:currentParty | current_party(credential) | the current (organization)party, | + ## ngsild | ODRL Class | ODRL Key | Rego-Method | Description | diff --git a/src/main/resources/mapping.json b/src/main/resources/mapping.json index 1c23535..8c7e16d 100644 --- a/src/main/resources/mapping.json +++ b/src/main/resources/mapping.json @@ -124,10 +124,20 @@ } }, "leftOperand": { + "vc": { + "role": { + "regoPackage": "vc.leftOperand as vc_lo", + "regoMethod": "vc_lo.role(helper.verifiable_credential, helper.organization_did)" + }, + "currentParty": { + "regoPackage": "vc.leftOperand as vc_lo", + "regoMethod": "vc_lo.current_party(helper.verifiable_credential)" + } + }, "ngsi-ld": { "entityType": { "regoPackage": "ngsild.leftOperand as ngsild_lo", - "regoMethod": "odrl_lo.entity_type(helper.http_part)" + "regoMethod": "ngsild_lo.entity_type(helper.http_part)" } }, "odrl": { diff --git a/src/main/resources/rego-resources.txt b/src/main/resources/rego-resources.txt index 5e60c70..07d3f1f 100644 --- a/src/main/resources/rego-resources.txt +++ b/src/main/resources/rego-resources.txt @@ -31,3 +31,16 @@ rego/odrl/assignee.rego rego/utils/kong.rego rego/utils/apisix.rego rego/ngsi-ld/leftOperand.rego +rego/dome/leftOperand.rego +rego/dome/action.rego +rego/odrl/operand.rego +rego/odrl/rightOperand.rego +rego/odrl/operator.rego +rego/odrl/leftOperand.rego +rego/odrl/target.rego +rego/odrl/action.rego +rego/odrl/assignee.rego +rego/utils/kong.rego +rego/utils/apisix.rego +rego/vc/leftOperand.rego +rego/ngsi-ld/leftOperand.rego diff --git a/src/main/resources/rego/utils/apisix.rego b/src/main/resources/rego/utils/apisix.rego index a466054..b68481b 100644 --- a/src/main/resources/rego/utils/apisix.rego +++ b/src/main/resources/rego/utils/apisix.rego @@ -36,7 +36,11 @@ decoded_token_payload := decoded_authorization[1] ## # the verifiable credential received as part of the token -verifiable_credential := decoded_token_payload.verifiableCredential +verifiable_credential := verfiableCredential if{ + verfiableCredential = decoded_token_payload.verifiableCredential +} else := vc if { + vc = decoded_token_payload.vc +} ## # the issuer of the credential diff --git a/src/main/resources/rego/vc/leftOperand.rego b/src/main/resources/rego/vc/leftOperand.rego new file mode 100644 index 0000000..c088b03 --- /dev/null +++ b/src/main/resources/rego/vc/leftOperand.rego @@ -0,0 +1,15 @@ +package vc.leftOperand + +import rego.v1 + +## vc:role +# retrieves the roles from the credential, that target the current organization +role(verifiable_credential,organization_id) := r if { + roles := verifiable_credential.credentialSubject.roles + role := [rad | some rad in roles; rad.target = organization_id ] + r = role[_].names; trace(organization_id) +} + +## vc:currentParty +# the current (organization)party, +current_party(credential) := credential.issuer \ No newline at end of file diff --git a/src/test/resources/examples/dome/1001/_1001.json b/src/test/resources/examples/dome/1001/_1001.json index b2cb54d3230b87cd671678c0082538fa22883807..dc97c4b0832b76054d295cdc481026628dde5db5 100644 GIT binary patch delta 20 ccmbOxJxhASE;eQ*2Bpb{jN+RwupMIq07GB~PXGV_ delta 20 ccmbOwJxzMUF1E=&oIH~c@bGQE!FGrZ08riskpKVy From cc7d7e7887841e66548fc44c0323723b6ff142c4 Mon Sep 17 00:00:00 2001 From: Stefan Wiedemann Date: Tue, 28 May 2024 07:56:26 +0200 Subject: [PATCH 03/11] try to rebuild --- src/main/resources/rego-resources.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/resources/rego-resources.txt b/src/main/resources/rego-resources.txt index 07d3f1f..c80b3de 100644 --- a/src/main/resources/rego-resources.txt +++ b/src/main/resources/rego-resources.txt @@ -44,3 +44,16 @@ rego/utils/kong.rego rego/utils/apisix.rego rego/vc/leftOperand.rego rego/ngsi-ld/leftOperand.rego +rego/dome/leftOperand.rego +rego/dome/action.rego +rego/odrl/operand.rego +rego/odrl/rightOperand.rego +rego/odrl/operator.rego +rego/odrl/leftOperand.rego +rego/odrl/target.rego +rego/odrl/action.rego +rego/odrl/assignee.rego +rego/utils/kong.rego +rego/utils/apisix.rego +rego/vc/leftOperand.rego +rego/ngsi-ld/leftOperand.rego From a5471492c16b8aeabd475dd4c928a76751cebd66 Mon Sep 17 00:00:00 2001 From: Stefan Wiedemann Date: Tue, 28 May 2024 08:07:19 +0200 Subject: [PATCH 04/11] fix test policy --- .../resources/examples/dome/1001/_1001.json | Bin 3482 -> 3478 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/test/resources/examples/dome/1001/_1001.json b/src/test/resources/examples/dome/1001/_1001.json index dc97c4b0832b76054d295cdc481026628dde5db5..b2cb54d3230b87cd671678c0082538fa22883807 100644 GIT binary patch delta 20 ccmbOwJxzMUF1E=&oIH~c@bGQE!FGrZ08riskpKVy delta 20 ccmbOxJxhASE;eQ*2Bpb{jN+RwupMIq07GB~PXGV_ From fea27e225dc78b2506a5a8f948fd0f31f01f9246 Mon Sep 17 00:00:00 2001 From: Stefan Wiedemann Date: Tue, 28 May 2024 08:49:22 +0200 Subject: [PATCH 05/11] temp log --- src/main/java/org/fiware/odrl/PolicyResource.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/org/fiware/odrl/PolicyResource.java b/src/main/java/org/fiware/odrl/PolicyResource.java index c57be44..9d385dd 100644 --- a/src/main/java/org/fiware/odrl/PolicyResource.java +++ b/src/main/java/org/fiware/odrl/PolicyResource.java @@ -43,6 +43,11 @@ public Response createPolicyWithId(String id, Map policy) { if (id.equals("main")) { return Response.status(HttpStatus.SC_CONFLICT).entity("Policy `main` cannot be manually modified.").build(); } + try { + log.warn("The config: {}", new ObjectMapper().writer().writeValueAsString(mappingConfiguration)); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } OdrlMapper odrlMapper = new OdrlMapper(objectMapper, mappingConfiguration); MappingResult mappingResult = odrlMapper.mapOdrl(policy); if (mappingResult.isFailed()) { From 8fae7e7a8107feea6f5cc0e8048499091d35d737 Mon Sep 17 00:00:00 2001 From: Stefan Wiedemann Date: Tue, 28 May 2024 11:25:15 +0200 Subject: [PATCH 06/11] clean up temp --- src/main/java/org/fiware/odrl/PolicyResource.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/main/java/org/fiware/odrl/PolicyResource.java b/src/main/java/org/fiware/odrl/PolicyResource.java index 9d385dd..c57be44 100644 --- a/src/main/java/org/fiware/odrl/PolicyResource.java +++ b/src/main/java/org/fiware/odrl/PolicyResource.java @@ -43,11 +43,6 @@ public Response createPolicyWithId(String id, Map policy) { if (id.equals("main")) { return Response.status(HttpStatus.SC_CONFLICT).entity("Policy `main` cannot be manually modified.").build(); } - try { - log.warn("The config: {}", new ObjectMapper().writer().writeValueAsString(mappingConfiguration)); - } catch (JsonProcessingException e) { - throw new RuntimeException(e); - } OdrlMapper odrlMapper = new OdrlMapper(objectMapper, mappingConfiguration); MappingResult mappingResult = odrlMapper.mapOdrl(policy); if (mappingResult.isFailed()) { From 8ad3b3c9ccc771b6dd492b6119233cae00db47da Mon Sep 17 00:00:00 2001 From: Stefan Wiedemann Date: Tue, 28 May 2024 15:51:55 +0200 Subject: [PATCH 07/11] add traces --- src/main/resources/rego/ngsi-ld/leftOperand.rego | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/resources/rego/ngsi-ld/leftOperand.rego b/src/main/resources/rego/ngsi-ld/leftOperand.rego index 1b59afa..0b22f05 100644 --- a/src/main/resources/rego/ngsi-ld/leftOperand.rego +++ b/src/main/resources/rego/ngsi-ld/leftOperand.rego @@ -7,7 +7,7 @@ type_from_path(path) := type if { path_without_query := split(path, "?")[0] path_elements := split(path_without_query, "/") id_elements := split(path_elements[count(path_elements) - 1], ":") - type = id_elements[2] + type = id_elements[2]; trace(id_elements) } # helper to retrieve the type from the body @@ -16,9 +16,9 @@ type_from_body(body) := body.type ## ngsi-ld:entityType # retrieves the type from an entity, either from the request path or from the body entity_type(http_part) := tfp if { - tfp = type_from_path(http_part.path) + tfp = type_from_path(http_part.path); trace(tfp) } else := tfb if { - tfb = type_from_body(http_part.body) + tfb = type_from_body(http_part.body); trace(tfb) } ## ngsi-ld: From 0d547a0715b88cc3823ad86d86be217d7a5a5fa5 Mon Sep 17 00:00:00 2001 From: Stefan Wiedemann Date: Wed, 29 May 2024 09:05:56 +0200 Subject: [PATCH 08/11] support odrl any --- .../org/fiware/odrl/mapping/OdrlMapper.java | 7 +++- src/main/resources/mapping.json | 4 ++ .../resources/rego/ngsi-ld/leftOperand.rego | 6 +-- src/main/resources/rego/odrl/assignee.rego | 7 +++- src/test/java/org/fiware/odrl/OdrlTest.java | 8 +++- .../examples/ngsi-ld/types/types.json | 39 +++++++++++++++++++ 6 files changed, 65 insertions(+), 6 deletions(-) create mode 100644 src/test/resources/examples/ngsi-ld/types/types.json diff --git a/src/main/java/org/fiware/odrl/mapping/OdrlMapper.java b/src/main/java/org/fiware/odrl/mapping/OdrlMapper.java index fab9b64..c82609e 100644 --- a/src/main/java/org/fiware/odrl/mapping/OdrlMapper.java +++ b/src/main/java/org/fiware/odrl/mapping/OdrlMapper.java @@ -156,7 +156,12 @@ private void mapAssignee(Object theAssignee) throws MappingException { NamespacedValue assignee = getNamespaced(ASSIGNEE_KEY); try { - mapStringAssignee(assignee, getStringOrByKey(theAssignee, ID_KEY)); + String assigneeString = getStringOrByKey(theAssignee, ID_KEY); + if(isNamespaced(assigneeString)) { + assignee = getNamespaced(assigneeString); + } + + mapStringAssignee(assignee, assigneeString); return; } catch (MappingException e) { // no-op, its a map diff --git a/src/main/resources/mapping.json b/src/main/resources/mapping.json index 8c7e16d..844147e 100644 --- a/src/main/resources/mapping.json +++ b/src/main/resources/mapping.json @@ -192,6 +192,10 @@ "assignee": { "regoPackage": "odrl.assignee as odrl_assignee", "regoMethod": "odrl_assignee.is_user(helper.issuer,%s)" + }, + "any": { + "regoPackage": "odrl.assignee as odrl_assignee", + "regoMethod": "odrl_assignee.is_any" } } }, diff --git a/src/main/resources/rego/ngsi-ld/leftOperand.rego b/src/main/resources/rego/ngsi-ld/leftOperand.rego index 0b22f05..1b59afa 100644 --- a/src/main/resources/rego/ngsi-ld/leftOperand.rego +++ b/src/main/resources/rego/ngsi-ld/leftOperand.rego @@ -7,7 +7,7 @@ type_from_path(path) := type if { path_without_query := split(path, "?")[0] path_elements := split(path_without_query, "/") id_elements := split(path_elements[count(path_elements) - 1], ":") - type = id_elements[2]; trace(id_elements) + type = id_elements[2] } # helper to retrieve the type from the body @@ -16,9 +16,9 @@ type_from_body(body) := body.type ## ngsi-ld:entityType # retrieves the type from an entity, either from the request path or from the body entity_type(http_part) := tfp if { - tfp = type_from_path(http_part.path); trace(tfp) + tfp = type_from_path(http_part.path) } else := tfb if { - tfb = type_from_body(http_part.body); trace(tfb) + tfb = type_from_body(http_part.body) } ## ngsi-ld: diff --git a/src/main/resources/rego/odrl/assignee.rego b/src/main/resources/rego/odrl/assignee.rego index 1f2420f..cf03d72 100644 --- a/src/main/resources/rego/odrl/assignee.rego +++ b/src/main/resources/rego/odrl/assignee.rego @@ -4,4 +4,9 @@ import rego.v1 ## odrl:uid,odrl:assignee # is the given user id the same as the given uid -is_user(user,uid) if user == uid \ No newline at end of file +is_user(user,uid) if user == uid + +## odrl:any +# allows for any user +is_any := true + diff --git a/src/test/java/org/fiware/odrl/OdrlTest.java b/src/test/java/org/fiware/odrl/OdrlTest.java index 501601a..9a6b616 100644 --- a/src/test/java/org/fiware/odrl/OdrlTest.java +++ b/src/test/java/org/fiware/odrl/OdrlTest.java @@ -44,7 +44,6 @@ public abstract class OdrlTest { public void mockEntity(MockServerClient mockServerClient, MockEntity mockEntity) { - Map theOffering = Map.of("id", mockEntity.id(), "relatedParty", mockEntity.relatedParty()); mockServerClient @@ -62,6 +61,12 @@ public void mockEntity(MockServerClient mockServerClient, MockEntity mockEntity) public static Stream validCombinations() { return Stream.of( + Arguments.of( + List.of("/examples/ngsi-ld/types/types.json"), + getRequest("urn:ngsi-ld:participant:1", + "/ngsi-ld/v1/entities/urn:ngsi-ld:Marketplace:test", + "GET"), + new MockEntity().id("urn:ngsi-ld:organization:0b03975e-7ded-4fbd-9c3b-a5d6550df7e2").relatedParty(List.of(new RelatedParty()))), Arguments.of( List.of("/examples/dome/1000/_1000.json"), getRequest("urn:ngsi-ld:organization:0b03975e-7ded-4fbd-9c3b-a5d6550df7e2", @@ -155,6 +160,7 @@ public static Stream odrlPolicies() { public static Stream odrlPolicyPath() { return Stream.of( + Arguments.of("/examples/ngsi-ld/types/types.json"), Arguments.of("/examples/dome/1000/_1000.json"), Arguments.of("/examples/dome/1001/_1001.json"), Arguments.of("/examples/dome/1001-2/_1001-2.json"), diff --git a/src/test/resources/examples/ngsi-ld/types/types.json b/src/test/resources/examples/ngsi-ld/types/types.json new file mode 100644 index 0000000..4ae8ac6 --- /dev/null +++ b/src/test/resources/examples/ngsi-ld/types/types.json @@ -0,0 +1,39 @@ +{ + "@context": { + "dc": "http://purl.org/dc/elements/1.1/", + "dct": "http://purl.org/dc/terms/", + "owl": "http://www.w3.org/2002/07/owl#", + "odrl": "http://www.w3.org/ns/odrl/2/", + "rdfs": "http://www.w3.org/2000/01/rdf-schema#", + "skos": "http://www.w3.org/2004/02/skos/core#" + }, + "@id": "https://mp-operation.org/policy/common/type", + "@type": "odrl:Policy", + "odrl:permission": { + "odrl:assigner": { + "@id": "https://www.mp-operation.org/" + }, + "odrl:target": { + "@type": "odrl:AssetCollection", + "odrl:source": "urn:asset", + "odrl:refinement": [ + { + "@type": "odrl:Constraint", + "odrl:leftOperand": { + "@id": "ngsi-ld:entityType" + }, + "odrl:operator": { + "@id": "odrl:eq" + }, + "odrl:rightOperand": "Marketplace" + } + ] + }, + "odrl:assignee": { + "@id": "odrl:any" + }, + "odrl:action": { + "@id": "dome-op:read" + } + } +} From 67b00a9f3ca9b90ea7a9dcbca989cf21350424ec Mon Sep 17 00:00:00 2001 From: Stefan Wiedemann Date: Wed, 29 May 2024 10:57:58 +0200 Subject: [PATCH 09/11] fix mapper --- .../org/fiware/odrl/mapping/OdrlMapper.java | 53 +++++++++++++------ 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/fiware/odrl/mapping/OdrlMapper.java b/src/main/java/org/fiware/odrl/mapping/OdrlMapper.java index c82609e..bbdfaa7 100644 --- a/src/main/java/org/fiware/odrl/mapping/OdrlMapper.java +++ b/src/main/java/org/fiware/odrl/mapping/OdrlMapper.java @@ -151,20 +151,9 @@ private void mapTarget(Object theTarget) throws MappingException { } } - private void mapAssignee(Object theAssignee) throws MappingException { - NamespacedValue assignee = getNamespaced(ASSIGNEE_KEY); - - try { - String assigneeString = getStringOrByKey(theAssignee, ID_KEY); - if(isNamespaced(assigneeString)) { - assignee = getNamespaced(assigneeString); - } - - mapStringAssignee(assignee, assigneeString); + if (mapStringAssignee(theAssignee)) { return; - } catch (MappingException e) { - // no-op, its a map } Map assigneeMap = convertToMap(theAssignee); @@ -397,10 +386,40 @@ private String getStringOrByKey(Object theObject, String theKey) throws MappingE throw new MappingException(String.format("Was not able to extract a valid %s.", theKey)); } - private void mapStringAssignee(NamespacedValue assignee, String assigneeId) throws MappingException { - RegoMethod regoMethod = getFromConfig(OdrlAttribute.ASSIGNEE, assignee); - mappingResult.addImport(regoMethod.regoPackage()); - mappingResult.addRule(String.format(regoMethod.regoMethod(), String.format(STRING_ESCAPE_TEMPLATE, assigneeId))); + private boolean mapStringAssignee(Object theAssignee) throws MappingException { + boolean result = false; + var assigneeString = ""; + + if (theAssignee instanceof String theString) { + assigneeString = theString; + result = true; + } else { + Map assigneeMap = convertToMap(theAssignee); + if (assigneeMap.containsKey(VALUE_KEY) && assigneeMap.get(VALUE_KEY) instanceof String theString) { + assigneeString = theString; + result = true; + } else if (assigneeMap.containsKey(ID_KEY) && assigneeMap.get(ID_KEY) instanceof String theString) { + assigneeString = theString; + result = true; + } + } + + if (result) { + NamespacedValue namespacedAssignee = null; + var assigneeId = ""; + try { + getFromConfig(OdrlAttribute.ASSIGNEE, getNamespaced(assigneeString)); + namespacedAssignee = getNamespaced(assigneeString); + } catch (MappingException mappingException) { + namespacedAssignee = getNamespaced(ASSIGNEE_KEY); + assigneeId = assigneeString; + } + RegoMethod regoMethod = getFromConfig(OdrlAttribute.ASSIGNEE, namespacedAssignee); + mappingResult.addImport(regoMethod.regoPackage()); + mappingResult.addRule(String.format(regoMethod.regoMethod(), String.format(STRING_ESCAPE_TEMPLATE, assigneeId))); + } + + return result; } private void mapStringTarget(NamespacedValue target, String targetId) throws MappingException { @@ -413,7 +432,7 @@ private void mapStringTarget(NamespacedValue target, String targetId) throws Map private void mapAssigneeParty(Map theParty) throws MappingException { Optional optionalUid = Optional.ofNullable(theParty.get(UID_KEY)); if (optionalUid.isPresent() && optionalUid.get() instanceof String uid) { - mapStringAssignee(getNamespaced(ASSIGNEE_KEY), uid); + mapStringAssignee(uid); } else { mappingResult.addFailure("The party does not contain a valid uid."); } From d8cabcc572e20ab3025824989f7ddfb6ca4d8193 Mon Sep 17 00:00:00 2001 From: Stefan Wiedemann Date: Thu, 30 May 2024 14:21:50 +0200 Subject: [PATCH 10/11] support type query --- src/main/resources/rego/ngsi-ld/leftOperand.rego | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/main/resources/rego/ngsi-ld/leftOperand.rego b/src/main/resources/rego/ngsi-ld/leftOperand.rego index 1b59afa..3c2ca87 100644 --- a/src/main/resources/rego/ngsi-ld/leftOperand.rego +++ b/src/main/resources/rego/ngsi-ld/leftOperand.rego @@ -2,12 +2,18 @@ package ngsild.leftOperand import rego.v1 + # helper method to retrieve the type from the path -type_from_path(path) := type if { - path_without_query := split(path, "?")[0] +type_from_path(path) := tfe if { + path_without_query := split(path, "?")[0] path_elements := split(path_without_query, "/") id_elements := split(path_elements[count(path_elements) - 1], ":") - type = id_elements[2] + tfe = id_elements[2] +} else := tfq if { + query := split(path, "?")[1] + query_parts := split(query, "&") + type_query := [query_part | some query_part in query_parts; contains(query_part, "type=")] + tfq = split(type_query, "=")[1] } # helper to retrieve the type from the body From 60ef5fc229d85a7e0dedcccd9da5708aa2b32fc8 Mon Sep 17 00:00:00 2001 From: Stefan Wiedemann Date: Thu, 30 May 2024 14:44:48 +0200 Subject: [PATCH 11/11] fix input --- src/main/resources/rego/ngsi-ld/leftOperand.rego | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/rego/ngsi-ld/leftOperand.rego b/src/main/resources/rego/ngsi-ld/leftOperand.rego index 3c2ca87..3fb774b 100644 --- a/src/main/resources/rego/ngsi-ld/leftOperand.rego +++ b/src/main/resources/rego/ngsi-ld/leftOperand.rego @@ -13,7 +13,7 @@ type_from_path(path) := tfe if { query := split(path, "?")[1] query_parts := split(query, "&") type_query := [query_part | some query_part in query_parts; contains(query_part, "type=")] - tfq = split(type_query, "=")[1] + tfq = split(type_query[0], "=")[1] } # helper to retrieve the type from the body