1pub mod error;
4pub mod eval;
5pub mod model;
6pub mod parser;
7pub mod store;
8
9use crate::error::ZanzibarError;
10use crate::model::{NamespaceConfig, Object, Relation, RelationTuple, User};
11use crate::store::{InMemoryTupleStore, TupleStore};
12use std::collections::{HashMap, HashSet};
13
14pub struct ZanzibarService {
16 configs: HashMap<String, NamespaceConfig>,
17 store: Box<dyn TupleStore>,
18}
19
20impl Default for ZanzibarService {
21 fn default() -> Self {
22 Self::new()
23 }
24}
25
26impl ZanzibarService {
27 pub fn new() -> Self {
29 ZanzibarService {
30 configs: HashMap::new(),
31 store: Box::new(InMemoryTupleStore::default()),
32 }
33 }
34
35 pub fn add_dsl(&mut self, dsl: &str) -> Result<(), ZanzibarError> {
37 let configs = parser::parse_dsl(dsl)?;
38 for config in configs {
39 self.add_config(config);
40 }
41 Ok(())
42 }
43
44 pub fn add_config(&mut self, config: NamespaceConfig) {
46 self.configs.insert(config.name.clone(), config);
47 }
48
49 pub fn write_tuple(&mut self, tuple: RelationTuple) -> Result<(), ZanzibarError> {
51 self.store
52 .write_tuple(tuple)
53 .map_err(ZanzibarError::StorageError)
54 }
55
56 pub fn delete_tuple(&mut self, tuple: &RelationTuple) -> Result<(), ZanzibarError> {
58 self.store
59 .delete_tuple(tuple)
60 .map_err(ZanzibarError::StorageError)
61 }
62
63 pub fn check(
65 &self,
66 object: &Object,
67 relation: &Relation,
68 user: &User,
69 ) -> Result<bool, ZanzibarError> {
70 let config = self
71 .configs
72 .get(&object.namespace)
73 .ok_or_else(|| ZanzibarError::NamespaceNotFound(object.namespace.clone()))?;
74
75 eval::check(
76 object,
77 relation,
78 user,
79 config,
80 self.store.as_ref(),
81 &mut HashSet::new(),
82 )
83 }
84
85 pub fn expand(
87 &self,
88 object: &Object,
89 relation: &Relation,
90 ) -> Result<model::ExpandedUserset, ZanzibarError> {
91 let config = self
92 .configs
93 .get(&object.namespace)
94 .ok_or_else(|| ZanzibarError::NamespaceNotFound(object.namespace.clone()))?;
95
96 eval::expand(object, relation, config, self.store.as_ref())
97 }
98}
99
100#[cfg(test)]
101mod tests {
102 #[test]
103 fn it_works() {
104 assert_eq!(2 + 2, 4);
105 }
106}