1515import org .eclipse .biscuit .token .format .SerializedBiscuit ;
1616
1717public 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 }
0 commit comments