Skip to content

Commit 76548ce

Browse files
authored
feat: support actions in CEL expr (#5529)
1 parent f344552 commit 76548ce

18 files changed

Lines changed: 211 additions & 8 deletions

File tree

core/common/cel-core/src/main/java/org/eclipse/edc/policy/cel/engine/CelExpressionEngineImpl.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import java.util.Map;
4040
import java.util.Set;
4141
import java.util.stream.Collectors;
42+
import java.util.stream.Stream;
4243

4344
public class CelExpressionEngineImpl implements CelExpressionEngine {
4445

@@ -77,8 +78,7 @@ public boolean canEvaluate(String leftOperand) {
7778

7879
@Override
7980
public Set<String> evaluationScopes(String leftOperand) {
80-
return fetch(leftOperand)
81-
.stream()
81+
return Stream.concat(fetch(leftOperand).stream(), fetchByAction(leftOperand).stream())
8282
.flatMap(expr -> expr.getScopes().stream())
8383
.collect(Collectors.toSet());
8484
}
@@ -147,6 +147,13 @@ private List<CelExpression> fetch(String leftOperand) {
147147

148148
}
149149

150+
private List<CelExpression> fetchByAction(String action) {
151+
return ctx.execute(() -> store.query(QuerySpec.Builder.newInstance()
152+
.filter(Criterion.criterion("actions", "contains", action))
153+
.build()));
154+
155+
}
156+
150157
private Result<CelAbstractSyntaxTree> compile(String expression) {
151158
CelAbstractSyntaxTree ast;
152159
try {

core/common/cel-core/src/test/java/org/eclipse/edc/policy/cel/engine/CelExpressionEngineImplTest.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
import java.util.List;
3131
import java.util.Map;
32+
import java.util.Set;
3233
import java.util.stream.Stream;
3334

3435
import static org.assertj.core.api.Assertions.assertThat;
@@ -228,12 +229,25 @@ void canEvaluate_noMatching() {
228229
assertThat(result).isFalse();
229230
}
230231

232+
@Test
233+
void evaluationScopes() {
234+
var expr = expressionBuilder("empty").scopes(Set.of("scope1", "scope2")).build();
235+
when(store.query(any())).thenReturn(List.of(expr));
236+
237+
var result = registry.evaluationScopes("leftOperand");
238+
239+
assertThat(result).containsAll(expr.getScopes());
240+
}
241+
231242
private CelExpression expression(String expr) {
243+
return expressionBuilder(expr).build();
244+
}
245+
246+
private CelExpression.Builder expressionBuilder(String expr) {
232247
return CelExpression.Builder.newInstance().id("id")
233248
.leftOperand("test")
234249
.expression(expr)
235-
.description("description")
236-
.build();
250+
.description("description");
237251
}
238252

239253
private @NotNull Map<String, Object> credential() {

core/common/lib/json-ld-lib/src/main/resources/document/management-context-v2.jsonld

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,10 @@
497497
"@id": "edc:scopes",
498498
"@container": "@set"
499499
},
500+
"actions": {
501+
"@id": "edc:actions",
502+
"@container": "@set"
503+
},
500504
"expression": "edc:expression",
501505
"description": "edc:description"
502506
}

core/control-plane/control-plane-transform/src/main/java/org/eclipse/edc/connector/controlplane/transform/edc/cel/from/JsonObjectFromCelExpressionTransformer.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID;
2727
import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE;
28+
import static org.eclipse.edc.policy.cel.model.CelExpression.CEL_EXPRESSION_ACTIONS_IRI;
2829
import static org.eclipse.edc.policy.cel.model.CelExpression.CEL_EXPRESSION_DESCRIPTION_IRI;
2930
import static org.eclipse.edc.policy.cel.model.CelExpression.CEL_EXPRESSION_EXPRESSION_IRI;
3031
import static org.eclipse.edc.policy.cel.model.CelExpression.CEL_EXPRESSION_LEFT_OPERAND_IRI;
@@ -49,6 +50,7 @@ public JsonObjectFromCelExpressionTransformer(JsonBuilderFactory factory) {
4950
.add(CEL_EXPRESSION_EXPRESSION_IRI, celExpression.getExpression())
5051
.add(CEL_EXPRESSION_DESCRIPTION_IRI, celExpression.getDescription())
5152
.add(CEL_EXPRESSION_SCOPES_IRI, Json.createArrayBuilder(celExpression.getScopes()))
53+
.add(CEL_EXPRESSION_ACTIONS_IRI, Json.createArrayBuilder(celExpression.getActions()))
5254
.build();
5355
}
5456
}

core/control-plane/control-plane-transform/src/main/java/org/eclipse/edc/connector/controlplane/transform/edc/cel/to/JsonObjectToCelExpressionTransformer.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.util.UUID;
2626

2727
import static java.util.Optional.ofNullable;
28+
import static org.eclipse.edc.policy.cel.model.CelExpression.CEL_EXPRESSION_ACTIONS_IRI;
2829
import static org.eclipse.edc.policy.cel.model.CelExpression.CEL_EXPRESSION_DESCRIPTION_IRI;
2930
import static org.eclipse.edc.policy.cel.model.CelExpression.CEL_EXPRESSION_EXPRESSION_IRI;
3031
import static org.eclipse.edc.policy.cel.model.CelExpression.CEL_EXPRESSION_LEFT_OPERAND_IRI;
@@ -45,6 +46,7 @@ public JsonObjectToCelExpressionTransformer() {
4546
id = UUID.randomUUID().toString();
4647
}
4748
var scopes = new HashSet<String>();
49+
var actions = new HashSet<String>();
4850

4951
var operandLeft = transformString(object.get(CEL_EXPRESSION_LEFT_OPERAND_IRI), context);
5052
var expression = transformString(object.get(CEL_EXPRESSION_EXPRESSION_IRI), context);
@@ -53,12 +55,16 @@ public JsonObjectToCelExpressionTransformer() {
5355
ofNullable(object.getJsonArray(CEL_EXPRESSION_SCOPES_IRI))
5456
.ifPresent(ja -> scopes.addAll(ja.stream().map(this::nodeValue).toList()));
5557

58+
ofNullable(object.getJsonArray(CEL_EXPRESSION_ACTIONS_IRI))
59+
.ifPresent(ja -> actions.addAll(ja.stream().map(this::nodeValue).toList()));
60+
5661
return CelExpression.Builder.newInstance()
5762
.id(id)
5863
.scopes(scopes)
5964
.leftOperand(operandLeft)
6065
.expression(expression)
6166
.description(description)
67+
.actions(actions)
6268
.build();
6369
}
6470
}

core/control-plane/control-plane-transform/src/test/java/org/eclipse/edc/connector/controlplane/transform/edc/cel/from/JsonObjectFromCelExpressionTransformerTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import static org.assertj.core.api.Assertions.assertThat;
2626
import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID;
2727
import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.TYPE;
28+
import static org.eclipse.edc.policy.cel.model.CelExpression.CEL_EXPRESSION_ACTIONS_IRI;
2829
import static org.eclipse.edc.policy.cel.model.CelExpression.CEL_EXPRESSION_DESCRIPTION_IRI;
2930
import static org.eclipse.edc.policy.cel.model.CelExpression.CEL_EXPRESSION_EXPRESSION_IRI;
3031
import static org.eclipse.edc.policy.cel.model.CelExpression.CEL_EXPRESSION_LEFT_OPERAND_IRI;
@@ -52,6 +53,7 @@ void transform_shouldConvertCelExpressionToJsonObject() {
5253
.expression("== 'admin'")
5354
.description("Check if user is admin")
5455
.scopes(Set.of("read", "write"))
56+
.actions(Set.of("use", "access"))
5557
.build();
5658

5759
var result = transformer.transform(celExpression, context);
@@ -65,6 +67,10 @@ void transform_shouldConvertCelExpressionToJsonObject() {
6567
assertThat(result.getJsonArray(CEL_EXPRESSION_SCOPES_IRI))
6668
.hasSize(2)
6769
.containsExactlyInAnyOrder(Json.createValue("read"), Json.createValue("write"));
70+
71+
assertThat(result.getJsonArray(CEL_EXPRESSION_ACTIONS_IRI))
72+
.hasSize(2)
73+
.containsExactlyInAnyOrder(Json.createValue("use"), Json.createValue("access"));
6874
}
6975

7076
@Test

core/control-plane/control-plane-transform/src/test/java/org/eclipse/edc/connector/controlplane/transform/edc/cel/to/JsonObjectToCelExpressionTransformerTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import static org.assertj.core.api.Assertions.assertThat;
2323
import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.ID;
2424
import static org.eclipse.edc.jsonld.spi.JsonLdKeywords.VALUE;
25+
import static org.eclipse.edc.policy.cel.model.CelExpression.CEL_EXPRESSION_ACTIONS_IRI;
2526
import static org.eclipse.edc.policy.cel.model.CelExpression.CEL_EXPRESSION_DESCRIPTION_IRI;
2627
import static org.eclipse.edc.policy.cel.model.CelExpression.CEL_EXPRESSION_EXPRESSION_IRI;
2728
import static org.eclipse.edc.policy.cel.model.CelExpression.CEL_EXPRESSION_LEFT_OPERAND_IRI;
@@ -50,6 +51,9 @@ void transform_shouldConvertJsonObjectToCelExpression() {
5051
.add(CEL_EXPRESSION_SCOPES_IRI, Json.createArrayBuilder()
5152
.add(Json.createObjectBuilder().add(VALUE, "read"))
5253
.add(Json.createObjectBuilder().add(VALUE, "write")))
54+
.add(CEL_EXPRESSION_ACTIONS_IRI, Json.createArrayBuilder()
55+
.add(Json.createObjectBuilder().add(VALUE, "use"))
56+
.add(Json.createObjectBuilder().add(VALUE, "access")))
5357
.build();
5458

5559
var result = transformer.transform(json, context);
@@ -60,6 +64,7 @@ void transform_shouldConvertJsonObjectToCelExpression() {
6064
assertThat(result.getExpression()).isEqualTo("== 'admin'");
6165
assertThat(result.getDescription()).isEqualTo("Check if user is admin");
6266
assertThat(result.getScopes()).containsExactlyInAnyOrder("read", "write");
67+
assertThat(result.getActions()).containsExactlyInAnyOrder("use", "access");
6368
}
6469

6570
@Test

extensions/common/api/management-api-schema-validator/src/main/resources/schema/management/v4/cel-expression-schema.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@
3737
"type": "string"
3838
},
3939
"uniqueItems": true
40+
},
41+
"actions": {
42+
"type": "array",
43+
"items": {
44+
"type": "string"
45+
},
46+
"uniqueItems": true
4047
}
4148
},
4249
"required": [

extensions/common/store/sql/cel-store-sql/src/main/java/org/eclipse/edc/policy/cel/store/sql/BaseSqlDialectStatementsConfig.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public String getInsertTemplate() {
3131
.column(getExpressionColumn())
3232
.column(getDescriptionColumn())
3333
.jsonColumn(getScopesColumn())
34+
.jsonColumn(getActionsColumn())
3435
.column(getCreateTimestampColumn())
3536
.column(getLastModifiedTimestampColumn())
3637
.insertInto(getCelExpressionTable());
@@ -43,6 +44,7 @@ public String getUpdateTemplate() {
4344
.column(getExpressionColumn())
4445
.column(getDescriptionColumn())
4546
.jsonColumn(getScopesColumn())
47+
.jsonColumn(getActionsColumn())
4648
.column(getCreateTimestampColumn())
4749
.column(getLastModifiedTimestampColumn())
4850
.update(getCelExpressionTable(), getIdColumn());

extensions/common/store/sql/cel-store-sql/src/main/java/org/eclipse/edc/policy/cel/store/sql/CelExpressionStoreStatements.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ default String getScopesColumn() {
4444
return "scopes";
4545
}
4646

47+
default String getActionsColumn() {
48+
return "actions";
49+
}
50+
4751
default String getLeftOperandColumn() {
4852
return "left_operand";
4953
}

0 commit comments

Comments
 (0)