daemon/identity.bend
cswap-bend-cli@0.1.0.0 · 121 lines · 23 definitions
1import Base
2import cswap-bend-cli@0.1.0.0/json.bend as Json
3import cswap-bend-cli@0.1.0.0/act.bend as Act
4import cswap-bend-cli@0.1.0.0/fs.bend as Fs
5import cswap-bend-cli@0.1.0.0/lock.bend as Lock
6import cswap-bend-cli@0.1.0.0/store/base.bend as SBase
7import cswap-bend-cli@0.1.0.0/store/seq.bend as SSeq
8import cswap-bend-cli@0.1.0.0/store/io.bend as SIo
9
10
11
12
13
14
15
16def ActM(-A: Type) -> Type:
17 Act.of(A)
18
19def ActM.pure(-A: Type, x: A) -> Act.of(A):
20 Act.pure(A, x)
21
22def ActM.bind(-A: Type, -B: Type, m: Act.of(A), f: A -> Act.of(B)) -> Act.of(B):
23 Act.bind(A, B, m, f)
24
25def str_of(+j: Json.Json, +k: String) -> String:
26 String.trim(SSeq.field_str(j, k))
27
28def rec_of(+m: Maybe<&2, Json.Json>, +slot: String) -> Json.Json:
29 match m:
30 case None{}:
31 Json.JObj{Json.JNil{}}
32 case Some{seq}:
33 Maybe.default(&2, Json.Json, SSeq.slot_record(seq, slot), Json.JObj{Json.JNil{}})
34
35def fill2(+empty: Bool, +seq: Json.Json, +slot: String, +uuid: String, +ts: String) -> Json.Json:
36 match empty:
37 case False{}:
38 seq
39 case True{}:
40 SSeq.stamp(Json.set("accounts", Json.set(slot, Json.set("uuid", Json.JStr{uuid}, Maybe.default(&2, Json.Json, SSeq.slot_record(seq, slot), Json.JObj{Json.JNil{}})), SSeq.accounts_of(seq)), seq), ts)
41
42
43def fill(+seq: Json.Json, +slot: String, +uuid: String, +ts: String) -> Json.Json:
44 fill2(String.is_empty(str_of(Maybe.default(&2, Json.Json, SSeq.slot_record(seq, slot), Json.JObj{Json.JNil{}}), "uuid")), seq, slot, uuid, ts)
45
46def fill_with(+m: Maybe<&2, Json.Json>, +root: String, +slot: String, +uuid: String, +ts: String) -> Act.of(Unit):
47 match m:
48 case None{}:
49 Act.pure(Unit, Unit{})
50 case Some{seq}:
51 SIo.write_seq(root, fill(seq, slot, uuid, ts))
52
53def backfill_locked(+root: String, +slot: String, +uuid: String) -> Act.of(Unit):
54 do ActM<Unit>:
55 ts : String <- SIo.now_iso()
56 m : Maybe<&2, Json.Json> <- SIo.read_seq(root)
57 fill_with(m, root, slot, uuid, ts)
58
59def backfill(+root: String, +slot: String, +uuid: String) -> Act.of(Unit):
60 Lock.with_lock(Unit, SBase.lock_path(root), 10000, backfill_locked(root, slot, uuid))
61
62def org_differs(+ta_org: String, +slot_org: String) -> Bool:
63 Bool.not(String.is_empty(ta_org)) && Bool.not(String.is_empty(slot_org)) && Bool.not(String.eq(ta_org, slot_org))
64
65def verdict(+conflict: Bool) -> String:
66 match conflict:
67 case True{}:
68 "identity-conflict"
69 case False{}:
70 "ok"
71
72def swallow(r: Fs.Res(Unit)) -> Act.of(Unit):
73 Act.pure(Unit, Unit{})
74
75def best_effort(m: Act.of(Unit)) -> Act.of(Unit):
76 IO.bind(Fs.Res(Unit), Fs.Res(Unit), m, r => swallow(r))
77
78def learned(+root: String, +slot: String, +ta_uuid: String) -> Act.of(String):
79 do ActM<String>:
80 best_effort(backfill(root, slot, ta_uuid))
81 return "ok"
82
83def learn2(+empty: Bool, +slot_uuid: String, +root: String, +slot: String, +ta_uuid: String) -> Act.of(String):
84 match empty:
85 case True{}:
86 learned(root, slot, ta_uuid)
87 case False{}:
88 Act.pure(String, verdict(Bool.not(String.eq(slot_uuid, ta_uuid))))
89
90def learn(+slot_uuid: String, +root: String, +slot: String, +ta_uuid: String) -> Act.of(String):
91 learn2(String.is_empty(slot_uuid), slot_uuid, root, slot, ta_uuid)
92
93def judged2(+conflict: Bool, +root: String, +slot: String, +ta_uuid: String, +rec: Json.Json) -> Act.of(String):
94 match conflict:
95 case True{}:
96 Act.pure(String, "identity-conflict")
97 case False{}:
98 learn(str_of(rec, "uuid"), root, slot, ta_uuid)
99
100def judged(+root: String, +slot: String, +ta_uuid: String, +ta_org: String, +rec: Json.Json) -> Act.of(String):
101 judged2(org_differs(ta_org, str_of(rec, "organizationUuid")), root, slot, ta_uuid, rec)
102
103def judged_in(+root: String, +slot: String, +ta_uuid: String, +ta_org: String, +m: Maybe<&2, Json.Json>) -> Act.of(String):
104 judged(root, slot, ta_uuid, ta_org, rec_of(m, slot))
105
106def known(+root: String, +slot: String, +ta_uuid: String, +ta_org: String) -> Act.of(String):
107 do ActM<String>:
108 m : Maybe<&2, Json.Json> <- SIo.read_seq(root)
109 judged_in(root, slot, ta_uuid, ta_org, m)
110
111def with_uuid(+empty: Bool, +root: String, +slot: String, +ta_uuid: String, +ta_org: String) -> Act.of(String):
112 match empty:
113 case True{}:
114 Act.pure(String, "ok")
115 case False{}:
116 known(root, slot, ta_uuid, ta_org)
117
118
119
120def check(+root: String, +slot: String, +acct: Json.Json) -> Act.of(String):
121 with_uuid(String.is_empty(str_of(acct, "uuid")), root, slot, str_of(acct, "uuid"), str_of(acct, "organizationUuid"))