1 import Base 2 import ./type.bend as G 3 4 def same_identity(+a: String, +b: String) -> Bool: 5 String.eq(String.to_lower(a), String.to_lower(b)) 6 7 def in_domain(+identity: String, +domain: String) -> Bool: 8 String.ends_with(String.to_lower(identity), "@" ++ String.to_lower(domain)) 9 10 def keep_if(c: Bool, x: String, rest: List<&2, String>) -> List<&2, String>: 11 match c: 12 case True{}: 13 x <> rest 14 case False{}: 15 rest 16 17 # ---- the people: identities in the organization's directory domain ---- 18 def outside.go(xs: List<&2, G.Person>, +domain: String) -> List<&2, String>: 19 match xs: 20 case []: 21 [] 22 case G.Person{_, +identity} <> rest: 23 keep_if(Bool.not(in_domain(identity, domain)), identity, outside.go(rest, domain)) 24 25 # The people's identities that are not in the organization's directory domain. 26 def outside_domain(a: G.Agreement) -> List<&2, String>: 27 match a: 28 case G.Agreement{+domain, people, _, _}: 29 outside.go(people, domain) 30 31 # Every person's identity is in the organization's directory domain. 32 def people_in_domain(a: G.Agreement) -> Bool: 33 List.is_empty(&2, String, outside_domain(a)) 34 35 # The key of the person with this identity (case insensitive), or "" when none has it. 36 def person_of.go(xs: List<&2, G.Person>, +identity: String) -> String: 37 match xs: 38 case []: 39 "" 40 case G.Person{key, +id} <> rest: 41 Bool.pick(String, same_identity(identity, id), key, person_of.go(rest, identity)) 42 43 def person_of(a: G.Agreement, +identity: String) -> String: 44 match a: 45 case G.Agreement{_, people, _, _}: 46 person_of.go(people, identity) 47 48 # ---- the identities in use ---- 49 def unknown.go(ids: List<&2, String>, +xs: List<&2, G.Person>) -> List<&2, String>: 50 match ids: 51 case []: 52 [] 53 case +id <> rest: 54 keep_if(String.is_empty(person_of.go(xs, id)), id, unknown.go(rest, xs)) 55 56 # The identities in use that are none of the agreement's people. 57 def unknown_identities(ids: List<&2, String>, a: G.Agreement) -> List<&2, String>: 58 match a: 59 case G.Agreement{_, +people, _, _}: 60 unknown.go(ids, people) 61 62 # Every identity actually in use is one of the agreement's people. 63 def identities_known(ids: List<&2, String>, a: G.Agreement) -> Bool: 64 List.is_empty(&2, String, unknown_identities(ids, a)) 65 66 # ---- grants ---- 67 def granted.go(xs: List<&2, G.Grant>, +person: String, +scope: String) -> List<&2, String>: 68 match xs: 69 case []: 70 [] 71 case G.Grant{+p, +sc, acts} <> rest: 72 Bool.pick(List<&2, String>, String.eq(person, p) && String.eq(scope, sc), acts, granted.go(rest, person, scope)) 73 74 # What `person` is granted on `scope`; [] when nothing is granted there. 75 def granted(a: G.Agreement, +person: String, +scope: String) -> List<&2, String>: 76 match a: 77 case G.Agreement{_, _, grants, _}: 78 granted.go(grants, person, scope)