Skip to content

Commit 01dc4c2

Browse files
committed
Compatibility error messages should match rust version.
1 parent 124370f commit 01dc4c2

4 files changed

Lines changed: 88 additions & 96 deletions

File tree

src/main/java/org/eclipse/biscuit/datalog/SchemaVersion.java

Lines changed: 82 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -15,111 +15,98 @@
1515
import org.eclipse.biscuit.token.format.SerializedBiscuit;
1616

1717
public final class SchemaVersion {
18-
public static int version(
18+
private final boolean containsScopes;
19+
private final boolean containsV31;
20+
private final boolean containsCheckAll;
21+
private final boolean containsV33;
22+
private final boolean containsExternalKey;
23+
24+
public SchemaVersion(
1925
List<Fact> facts,
2026
List<Rule> rules,
2127
List<Check> checks,
2228
List<Scope> scopes,
2329
Optional<PublicKey> externalKey) {
24-
if (containsV6(facts, rules, checks)) {
30+
containsScopes =
31+
!scopes.isEmpty()
32+
|| rules.stream().anyMatch(r -> !r.scopes().isEmpty())
33+
|| checks.stream()
34+
.anyMatch(c -> c.queries().stream().anyMatch(q -> !q.scopes().isEmpty()));
35+
36+
containsCheckAll = checks.stream().anyMatch(c -> c.kind() == Check.Kind.ALL);
37+
38+
containsV31 =
39+
rules.stream().anyMatch(r -> containsV31Op(r.expressions()))
40+
|| checks.stream()
41+
.anyMatch(c -> c.queries().stream().anyMatch(q -> containsV31Op(q.expressions())));
42+
43+
containsV33 =
44+
checks.stream().anyMatch(c -> c.kind() == Check.Kind.REJECT)
45+
|| rules.stream()
46+
.anyMatch(
47+
r ->
48+
containsV33Predicate(r.head())
49+
|| r.body().stream().anyMatch(SchemaVersion::containsV33Predicate)
50+
|| containsV33Op(r.expressions()))
51+
|| checks.stream()
52+
.anyMatch(
53+
c ->
54+
c.queries().stream()
55+
.anyMatch(
56+
q ->
57+
q.body().stream().anyMatch(SchemaVersion::containsV33Predicate)
58+
|| containsV33Op(q.expressions())))
59+
|| facts.stream().anyMatch(f -> containsV33Predicate(f.predicate()));
60+
61+
containsExternalKey = externalKey.isPresent();
62+
}
63+
64+
public int version() {
65+
if (containsV33) {
2566
return SerializedBiscuit.DATALOG_3_3;
2667
}
27-
if (containsV5(externalKey)) {
68+
if (containsExternalKey) {
2869
return SerializedBiscuit.DATALOG_3_2;
2970
}
30-
if (containsV4(rules, checks, scopes)) {
71+
if (containsScopes || containsV31 || containsCheckAll) {
3172
return SerializedBiscuit.DATALOG_3_1;
3273
}
3374
return SerializedBiscuit.MIN_SCHEMA_VERSION;
3475
}
3576

36-
public static Result<Void, Error.FormatError> checkCompatibility(
37-
int version,
38-
List<Fact> facts,
39-
List<Rule> rules,
40-
List<Check> checks,
41-
List<Scope> scopes,
42-
Optional<PublicKey> externalKey) {
43-
if (version < SerializedBiscuit.DATALOG_3_1 && containsV4(rules, checks, scopes)) {
44-
return Result.err(
45-
new Error.FormatError.DeserializationError(
46-
"v" + version + " blocks must not have v4 features"));
77+
public Result<Void, Error.FormatError> checkCompatibility(int version) {
78+
if (version < SerializedBiscuit.DATALOG_3_1) {
79+
if (containsScopes) {
80+
return Result.err(
81+
new Error.FormatError.DeserializationError(
82+
"scopes are only supported in datalog v3.1+"));
83+
}
84+
if (containsV31) {
85+
return Result.err(
86+
new Error.FormatError.DeserializationError(
87+
"bitwise operators and != are only supported in datalog v3.1+"));
88+
}
89+
if (containsCheckAll) {
90+
return Result.err(
91+
new Error.FormatError.DeserializationError(
92+
"check all is only supported in datalog v3.1+"));
93+
}
4794
}
48-
if (version < SerializedBiscuit.DATALOG_3_2 && containsV5(externalKey)) {
95+
if (version < SerializedBiscuit.DATALOG_3_2 && containsExternalKey) {
4996
return Result.err(
5097
new Error.FormatError.DeserializationError(
51-
"v" + version + " blocks must not have v5 features"));
98+
"third-party blocks are only supported in datalog v3.2+"));
5299
}
53-
if (version < SerializedBiscuit.DATALOG_3_3 && containsV6(facts, rules, checks)) {
100+
101+
if (version < SerializedBiscuit.DATALOG_3_3 && containsV33) {
54102
return Result.err(
55103
new Error.FormatError.DeserializationError(
56-
"v" + version + " blocks must not have v6 features"));
104+
"maps, arrays, null, closures are only supported in datalog v3.3+"));
57105
}
58106
return Result.ok(null);
59107
}
60108

61-
private static boolean containsV4(List<Rule> rules, List<Check> checks, List<Scope> scopes) {
62-
if (!scopes.isEmpty()) {
63-
return true;
64-
}
65-
for (Rule rule : rules) {
66-
if (!rule.scopes().isEmpty()) {
67-
return true;
68-
}
69-
if (containsV4Ops(rule.expressions())) {
70-
return true;
71-
}
72-
}
73-
74-
for (Check check : checks) {
75-
if (check.kind() == Check.Kind.ALL) {
76-
return true;
77-
}
78-
for (Rule query : check.queries()) {
79-
if (!query.scopes().isEmpty()) {
80-
return true;
81-
}
82-
if (containsV4Ops(query.expressions())) {
83-
return true;
84-
}
85-
}
86-
}
87-
88-
return false;
89-
}
90-
91-
private static boolean containsV5(Optional<PublicKey> externalKey) {
92-
return externalKey.isPresent();
93-
}
94-
95-
private static boolean containsV6(List<Fact> facts, List<Rule> rules, List<Check> checks) {
96-
for (Fact fact : facts) {
97-
if (containsV6Terms(fact.predicate().terms())) {
98-
return true;
99-
}
100-
}
101-
102-
for (Rule rule : rules) {
103-
if (containsV6Ops(rule.expressions())) {
104-
return true;
105-
}
106-
}
107-
108-
for (Check check : checks) {
109-
if (check.kind() == Check.Kind.REJECT) {
110-
return true;
111-
}
112-
for (Rule query : check.queries()) {
113-
if (containsV6Ops(query.expressions())) {
114-
return true;
115-
}
116-
}
117-
}
118-
119-
return false;
120-
}
121-
122-
private static boolean containsV4Ops(List<Expression> expressions) {
109+
private static boolean containsV31Op(List<Expression> expressions) {
123110
for (Expression e : expressions) {
124111
for (Op op : e.getOps()) {
125112
if (op instanceof Op.Binary) {
@@ -138,7 +125,7 @@ private static boolean containsV4Ops(List<Expression> expressions) {
138125
return false;
139126
}
140127

141-
private static boolean containsV6Ops(List<Expression> expressions) {
128+
private static boolean containsV33Op(List<Expression> expressions) {
142129
for (Expression e : expressions) {
143130
for (Op op : e.getOps()) {
144131
if (op instanceof Op.Unary) {
@@ -176,15 +163,19 @@ private static boolean containsV6Ops(List<Expression> expressions) {
176163
return false;
177164
}
178165

179-
private static boolean containsV6Terms(List<Term> terms) {
180-
for (Term term : terms) {
181-
if (term instanceof Term.Null) {
182-
return true;
183-
} else if (term instanceof Term.Array) {
184-
return true;
185-
} else if (term instanceof Term.Map) {
186-
return true;
187-
}
166+
private static boolean containsV33Predicate(Predicate predicate) {
167+
return predicate.terms().stream().anyMatch(SchemaVersion::containsV33Term);
168+
}
169+
170+
private static boolean containsV33Term(Term term) {
171+
if (term instanceof Term.Null) {
172+
return true;
173+
}
174+
if (term instanceof Term.Array) {
175+
return true;
176+
}
177+
if (term instanceof Term.Map) {
178+
return true;
188179
}
189180
return false;
190181
}

src/main/java/org/eclipse/biscuit/token/Block.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public final class Block {
3535
private final List<Scope> scopes;
3636
private final List<PublicKey> publicKeys;
3737
private Optional<PublicKey> externalKey;
38-
private long version;
38+
private int version;
3939

4040
/**
4141
* creates a new block
@@ -222,7 +222,7 @@ public Schema.Block serialize() {
222222
b.addPublicKeys(pk.serialize());
223223
}
224224

225-
b.setVersion(SchemaVersion.version(facts, rules, checks, scopes, externalKey));
225+
b.setVersion(version);
226226
return b.build();
227227
}
228228

@@ -299,7 +299,8 @@ public static Result<Block, Error.FormatError> deserialize(
299299
}
300300
}
301301

302-
var res = SchemaVersion.checkCompatibility(version, facts, rules, checks, scopes, externalKey);
302+
var schemaVersion = new SchemaVersion(facts, rules, checks, scopes, externalKey);
303+
var res = schemaVersion.checkCompatibility(version);
303304
if (res.isErr()) {
304305
Error.FormatError e = res.getErr();
305306
return Result.err(e);

src/main/java/org/eclipse/biscuit/token/builder/Biscuit.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ private org.eclipse.biscuit.token.Biscuit build(SymbolTable symbolTable) throws
148148
for (Scope s : this.scopes) {
149149
scopes.add(s.convert(symbolTable));
150150
}
151-
int version = SchemaVersion.version(facts, rules, checks, scopes, Optional.empty());
151+
var version = new SchemaVersion(facts, rules, checks, scopes, Optional.empty()).version();
152152

153153
SymbolTable blockSymbols = new SymbolTable();
154154

src/main/java/org/eclipse/biscuit/token/builder/Block.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ public org.eclipse.biscuit.token.Block build(
142142
for (Scope s : this.scopes) {
143143
scopes.add(s.convert(symbolTable));
144144
}
145-
int version = SchemaVersion.version(facts, rules, checks, scopes, externalKey);
145+
var version = new SchemaVersion(facts, rules, checks, scopes, externalKey).version();
146146

147147
SymbolTable blockSymbols = new SymbolTable();
148148

0 commit comments

Comments
 (0)