66package org .eclipse .biscuit .datalog ;
77
88import java .util .List ;
9+ import java .util .Optional ;
10+ import org .eclipse .biscuit .crypto .PublicKey ;
911import org .eclipse .biscuit .datalog .expressions .Expression ;
1012import org .eclipse .biscuit .datalog .expressions .Op ;
1113import org .eclipse .biscuit .error .Error ;
1214import org .eclipse .biscuit .error .Result ;
1315import org .eclipse .biscuit .token .format .SerializedBiscuit ;
1416
1517public final class SchemaVersion {
16- private boolean containsScopes ;
17- private boolean containsCheckAll ;
18- private boolean containsV4 ;
18+ public static int version (
19+ List <Fact > facts ,
20+ List <Rule > rules ,
21+ List <Check > checks ,
22+ List <Scope > scopes ,
23+ Optional <PublicKey > externalKey ) {
24+ if (containsV6 (facts , rules , checks )) {
25+ return SerializedBiscuit .DATALOG_3_3 ;
26+ }
27+ if (containsV5 (externalKey )) {
28+ return SerializedBiscuit .DATALOG_3_2 ;
29+ }
30+ if (containsV4 (rules , checks , scopes )) {
31+ return SerializedBiscuit .DATALOG_3_1 ;
32+ }
33+ return SerializedBiscuit .MIN_SCHEMA_VERSION ;
34+ }
1935
20- public SchemaVersion (List <Fact > facts , List <Rule > rules , List <Check > checks , List <Scope > scopes ) {
21- containsScopes = !scopes .isEmpty ();
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" ));
47+ }
48+ if (version < SerializedBiscuit .DATALOG_3_2 && containsV5 (externalKey )) {
49+ return Result .err (
50+ new Error .FormatError .DeserializationError (
51+ "v" + version + " blocks must not have v5 features" ));
52+ }
53+ if (version < SerializedBiscuit .DATALOG_3_3 && containsV6 (facts , rules , checks )) {
54+ return Result .err (
55+ new Error .FormatError .DeserializationError (
56+ "v" + version + " blocks must not have v6 features" ));
57+ }
58+ return Result .ok (null );
59+ }
2260
23- if (!containsScopes ) {
24- for (Rule r : rules ) {
25- if (!r .scopes ().isEmpty ()) {
26- containsScopes = true ;
27- break ;
28- }
29- }
61+ private static boolean containsV4 (List <Rule > rules , List <Check > checks , List <Scope > scopes ) {
62+ if (!scopes .isEmpty ()) {
63+ return true ;
3064 }
31- if (!containsScopes ) {
32- for (Check check : checks ) {
33- for (Rule query : check .queries ()) {
34- if (!query .scopes ().isEmpty ()) {
35- containsScopes = true ;
36- break ;
37- }
38- }
65+ for (Rule rule : rules ) {
66+ if (!rule .scopes ().isEmpty ()) {
67+ return true ;
68+ }
69+ if (containsV4Ops (rule .expressions ())) {
70+ return true ;
3971 }
4072 }
4173
42- containsCheckAll = false ;
4374 for (Check check : checks ) {
4475 if (check .kind () == Check .Kind .ALL ) {
45- containsCheckAll = true ;
46- break ;
76+ return true ;
4777 }
48- }
49-
50- containsV4 = false ;
51- for (Check check : checks ) {
5278 for (Rule query : check .queries ()) {
79+ if (!query .scopes ().isEmpty ()) {
80+ return true ;
81+ }
5382 if (containsV4Ops (query .expressions ())) {
54- containsV4 = true ;
55- break ;
83+ return true ;
5684 }
5785 }
5886 }
87+
88+ return false ;
5989 }
6090
61- public int version () {
62- if (containsScopes || containsV4 || containsCheckAll ) {
63- return 4 ;
64- } else {
65- return SerializedBiscuit .MIN_SCHEMA_VERSION ;
66- }
91+ private static boolean containsV5 (Optional <PublicKey > externalKey ) {
92+ return externalKey .isPresent ();
6793 }
6894
69- public Result <Void , Error .FormatError > checkCompatibility (int version ) {
70- if (version < 4 ) {
71- if (containsScopes ) {
72- return Result .err (
73- new Error .FormatError .DeserializationError ("v3 blocks must not have scopes" ));
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 ;
7499 }
75- if (containsV4 ) {
76- return Result .err (
77- new Error .FormatError .DeserializationError (
78- "v3 blocks must not have v4 operators (bitwise operators or !=" ));
100+ }
101+
102+ for (Rule rule : rules ) {
103+ if (containsV6Ops (rule .expressions ())) {
104+ return true ;
79105 }
80- if (containsCheckAll ) {
81- return Result .err (
82- new Error .FormatError .DeserializationError ("v3 blocks must not use check all" ));
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+ }
83116 }
84117 }
85118
86- return Result . ok ( null ) ;
119+ return false ;
87120 }
88121
89- public static boolean containsV4Ops (List <Expression > expressions ) {
122+ private static boolean containsV4Ops (List <Expression > expressions ) {
90123 for (Expression e : expressions ) {
91124 for (Op op : e .getOps ()) {
92125 if (op instanceof Op .Binary ) {
@@ -104,4 +137,55 @@ public static boolean containsV4Ops(List<Expression> expressions) {
104137 }
105138 return false ;
106139 }
140+
141+ private static boolean containsV6Ops (List <Expression > expressions ) {
142+ for (Expression e : expressions ) {
143+ for (Op op : e .getOps ()) {
144+ if (op instanceof Op .Unary ) {
145+ Op .Unary b = (Op .Unary ) op ;
146+ switch (b .getOp ()) {
147+ case TypeOf :
148+ return true ;
149+ default :
150+ }
151+ } else if (op instanceof Op .Binary ) {
152+ Op .Binary b = (Op .Binary ) op ;
153+ switch (b .getOp ()) {
154+ case HeterogeneousEqual :
155+ case HeterogeneousNotEqual :
156+ case LazyAnd :
157+ case LazyOr :
158+ case Get :
159+ case Any :
160+ case All :
161+ case TryOr :
162+ return true ;
163+ default :
164+ }
165+ } else if (op instanceof Op .Closure ) {
166+ return true ;
167+ } else if (op instanceof Term .Null ) {
168+ return true ;
169+ } else if (op instanceof Term .Array ) {
170+ return true ;
171+ } else if (op instanceof Term .Map ) {
172+ return true ;
173+ }
174+ }
175+ }
176+ return false ;
177+ }
178+
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+ }
188+ }
189+ return false ;
190+ }
107191}
0 commit comments