Skip to content

Commit 3c01e13

Browse files
committed
add datalog components parser and authorizer helper using it
1 parent 8923fb1 commit 3c01e13

File tree

2 files changed

+109
-50
lines changed

2 files changed

+109
-50
lines changed

src/main/java/org/biscuitsec/biscuit/token/Authorizer.java

+27
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import static io.vavr.API.Right;
55

66
import io.vavr.Tuple2;
7+
import io.vavr.Tuple4;
78
import io.vavr.control.Either;
89
import io.vavr.control.Option;
910
import java.time.Instant;
@@ -203,6 +204,32 @@ public Authorizer addToken(Biscuit token) throws Error.FailedLogic {
203204
return this;
204205
}
205206

207+
public Either<Map<Integer, List<Error>>, Authorizer> addDatalog(String s) {
208+
Either<Map<Integer, List<org.biscuitsec.biscuit.token.builder.parser.Error>>, Tuple4<List<org.biscuitsec.biscuit.token.builder.Fact>, List<org.biscuitsec.biscuit.token.builder.Rule>, List<org.biscuitsec.biscuit.token.builder.Check>, List<org.biscuitsec.biscuit.token.builder.Scope>>> result = Parser
209+
.datalogComponents(s);
210+
211+
if (result.isLeft()) {
212+
Map<Integer, List<org.biscuitsec.biscuit.token.builder.parser.Error>> errors = result.getLeft();
213+
Map<Integer, List<Error>> errorMap = new HashMap<>();
214+
for (Map.Entry<Integer, List<org.biscuitsec.biscuit.token.builder.parser.Error>> entry : errors.entrySet()) {
215+
List<Error> errorsList = new ArrayList<>();
216+
for (org.biscuitsec.biscuit.token.builder.parser.Error error : entry.getValue()) {
217+
errorsList.add(new Error.Parser(error));
218+
}
219+
errorMap.put(entry.getKey(), errorsList);
220+
}
221+
return Either.left(errorMap);
222+
}
223+
224+
Tuple4<List<org.biscuitsec.biscuit.token.builder.Fact>, List<org.biscuitsec.biscuit.token.builder.Rule>, List<org.biscuitsec.biscuit.token.builder.Check>, List<org.biscuitsec.biscuit.token.builder.Scope>> components = result
225+
.get();
226+
components._1.forEach(this::addFact);
227+
components._2.forEach(this::addRule);
228+
components._3.forEach(this::addCheck);
229+
230+
return Either.right(this);
231+
}
232+
206233
public Authorizer addFact(org.biscuitsec.biscuit.token.builder.Fact fact) {
207234
world.addFact(Origin.authorizer(), fact.convert(symbolTable));
208235
return this;

src/main/java/org/biscuitsec/biscuit/token/builder/parser/Parser.java

+82-50
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,19 @@ private Parser() {}
3434
*
3535
* <p>If one succeeds it returns Right(Block) else it returns a Map[lineNumber, List[Error]]
3636
*
37-
* @param index block index
3837
* @param s datalog string to parse
39-
* @return Either<Map<Integer, List<Error>>, Block>
38+
* @return Either<Map<Integer, List<Error>>, Tuple4<List<Fact>, List<Rule>,
39+
* List<Check>, List<Scope>>>
4040
*/
41-
public static Either<Map<Integer, List<Error>>, Block> datalog(long index, String s) {
42-
Block blockBuilder = new Block();
41+
public static Either<Map<Integer, List<Error>>, Tuple4<List<Fact>, List<Rule>, List<Check>, List<Scope>>> datalogComponents(
42+
String s) {
43+
List<Fact> facts = new ArrayList<>();
44+
List<Rule> rules = new ArrayList<>();
45+
List<Check> checks = new ArrayList<>();
46+
List<Scope> scopes = new ArrayList<>();
4347

44-
// empty block code
4548
if (s.isEmpty()) {
46-
return Either.right(blockBuilder);
49+
return Either.right(new Tuple4<>(facts, rules, checks, scopes));
4750
}
4851

4952
Map<Integer, List<Error>> errors = new HashMap<>();
@@ -61,58 +64,54 @@ public static Either<Map<Integer, List<Error>>, Block> datalog(long index, Strin
6164
List<Error> lineErrors = new ArrayList<>();
6265

6366
boolean parsed = false;
64-
parsed =
65-
rule(code)
66-
.fold(
67-
e -> {
68-
lineErrors.add(e);
69-
return false;
70-
},
71-
r -> {
72-
blockBuilder.addRule(r._2);
73-
return true;
74-
});
67+
parsed = rule(code)
68+
.fold(
69+
e -> {
70+
lineErrors.add(e);
71+
return false;
72+
},
73+
r -> {
74+
rules.add(r._2);
75+
return true;
76+
});
7577

7678
if (!parsed) {
77-
parsed =
78-
fact(code)
79-
.fold(
80-
e -> {
81-
lineErrors.add(e);
82-
return false;
83-
},
84-
r -> {
85-
blockBuilder.addFact(r._2);
86-
return true;
87-
});
79+
parsed = fact(code)
80+
.fold(
81+
e -> {
82+
lineErrors.add(e);
83+
return false;
84+
},
85+
r -> {
86+
facts.add(r._2);
87+
return true;
88+
});
8889
}
8990

9091
if (!parsed) {
91-
parsed =
92-
check(code)
93-
.fold(
94-
e -> {
95-
lineErrors.add(e);
96-
return false;
97-
},
98-
r -> {
99-
blockBuilder.addCheck(r._2);
100-
return true;
101-
});
92+
parsed = check(code)
93+
.fold(
94+
e -> {
95+
lineErrors.add(e);
96+
return false;
97+
},
98+
r -> {
99+
checks.add(r._2);
100+
return true;
101+
});
102102
}
103103

104104
if (!parsed) {
105-
parsed =
106-
scope(code)
107-
.fold(
108-
e -> {
109-
lineErrors.add(e);
110-
return false;
111-
},
112-
r -> {
113-
blockBuilder.addScope(r._2);
114-
return true;
115-
});
105+
parsed = scope(code)
106+
.fold(
107+
e -> {
108+
lineErrors.add(e);
109+
return false;
110+
},
111+
r -> {
112+
scopes.add(r._2);
113+
return true;
114+
});
116115
}
117116

118117
if (!parsed) {
@@ -127,6 +126,39 @@ public static Either<Map<Integer, List<Error>>, Block> datalog(long index, Strin
127126
return Either.left(errors);
128127
}
129128

129+
return Either.right(new Tuple4<>(facts, rules, checks, scopes));
130+
}
131+
132+
/**
133+
* Takes a datalog string with <code>\n</code> as datalog line separator. It
134+
* tries to parse each
135+
* line using fact, rule, check and scope sequentially.
136+
*
137+
* <p>
138+
* If one succeeds it returns Right(Block) else it returns a Map[lineNumber,
139+
* List[Error]]
140+
*
141+
* @param index block index
142+
* @param s datalog string to parse
143+
* @return Either<Map<Integer, List<Error>>, Block>
144+
*/
145+
public static Either<Map<Integer, List<Error>>, Block> datalog(long index, String s) {
146+
Block blockBuilder = new Block();
147+
148+
Either<Map<Integer, List<Error>>, Tuple4<List<Fact>, List<Rule>, List<Check>, List<Scope>>> result = datalogComponents(
149+
s);
150+
151+
if (result.isLeft()) {
152+
return Either.left(result.getLeft());
153+
}
154+
155+
Tuple4<List<Fact>, List<Rule>, List<Check>, List<Scope>> components = result.get();
156+
157+
components._1.forEach(blockBuilder::addFact);
158+
components._2.forEach(blockBuilder::addRule);
159+
components._3.forEach(blockBuilder::addCheck);
160+
components._4.forEach(blockBuilder::addScope);
161+
130162
return Either.right(blockBuilder);
131163
}
132164

0 commit comments

Comments
 (0)