···7979end
80808181module Did = struct
8282- open struct
8383- type string_or_strings = [`String of string | `Strings of string list]
8484-8585- let string_or_strings_to_yojson = function
8686- | `String c ->
8787- `String c
8888- | `Strings cs ->
8989- `List (List.map (fun c -> `String c) cs)
9090-9191- let string_or_strings_of_yojson = function
9292- | `String c ->
9393- Ok (`Strings [c])
9494- | `List cs ->
9595- Ok (`Strings (Yojson.Safe.Util.filter_string cs))
9696- | _ ->
9797- Error "invalid field value"
9898-9999- type string_or_string_map =
100100- [`String of string | `StringMap of (string * string) list]
101101-102102- let string_or_string_map_to_yojson = function
103103- | `String c ->
104104- `String c
105105- | `StringMap m ->
106106- `Assoc (List.map (fun (k, v) -> (k, `String v)) m)
107107-108108- let string_or_string_map_of_yojson = function
109109- | `String c ->
110110- Ok (`StringMap [(c, "")])
111111- | `Assoc m ->
112112- Ok
113113- (`StringMap
114114- (List.map (fun (k, v) -> (k, Yojson.Safe.Util.to_string v)) m) )
115115- | _ ->
116116- Error "invalid field value"
117117-118118- type string_or_string_map_or_either_list =
119119- [ `String of string
120120- | `StringMap of (string * string) list
121121- | `List of string_or_string_map list ]
122122-123123- let string_or_string_map_or_either_list_to_yojson = function
124124- | `String c ->
125125- `String c
126126- | `StringMap m ->
127127- `Assoc (List.map (fun (k, v) -> (k, `String v)) m)
128128- | `List l ->
129129- `List (List.map string_or_string_map_to_yojson l)
130130-131131- let string_or_string_map_or_either_list_of_yojson = function
132132- | `String c ->
133133- Ok (`StringMap [(c, "")])
134134- | `Assoc m ->
135135- Ok
136136- (`StringMap
137137- (List.map (fun (k, v) -> (k, Yojson.Safe.Util.to_string v)) m) )
138138- | `List l ->
139139- Ok
140140- (`List
141141- ( List.map string_or_string_map_of_yojson l
142142- |> List.filter_map (function Ok x -> Some x | Error _ -> None) )
143143- )
144144- | _ ->
145145- Error "invalid field value"
146146- end
8282+ open Util.Did_doc_types
1478314884 module Document = struct
14985 type service =
+68-8
pegasus/lib/plc.ml
···11+open Cohttp
22+open Cohttp_lwt
33+open Cohttp_lwt_unix
44+open Util.Did_doc_types
55+66+let default_endpoint = "https://plc.directory"
77+18type t = {did: string; rotation_key: Kleidos.key; endpoint: string}
29310type service = {type': string [@key "type"]; endpoint: string}
44-[@@deriving yojson]
1111+[@@deriving yojson {strict= false}]
512613type unsigned_operation =
714 | Operation of
···1320 ; services: (string * service) list
1421 ; prev: string option }
1522 | Tombstone of {type': string [@key "type"]; prev: string}
1616-[@@deriving yojson]
2323+[@@deriving yojson {strict= false}]
17241825let unsigned_operation_to_yojson = function
1926 | Operation
···95102 ; signature: string [@key "sig"] }
96103 | Tombstone of
97104 {type': string [@key "type"]; prev: string; signature: string [@key "sig"]}
9898-[@@deriving yojson]
105105+[@@deriving yojson {strict= false}]
99106100107let signed_operation_to_yojson = function
101108 | Operation
···127134 | _ ->
128135 failwith "unexpected json structure" )
129136137137+type audit_log_operation =
138138+ { signature: string [@key "sig"]
139139+ ; prev: string option
140140+ ; type': string [@key "type"]
141141+ ; services: (string * service) list
142142+ [@to_yojson
143143+ fun l -> `Assoc (List.map (fun (k, v) -> (k, service_to_yojson v)) l)]
144144+ [@of_yojson
145145+ function
146146+ | `Assoc fields ->
147147+ Ok
148148+ (List.filter_map
149149+ (fun (k, v) ->
150150+ match service_of_yojson v with
151151+ | Ok service ->
152152+ Some (k, service)
153153+ | _ ->
154154+ None )
155155+ fields )
156156+ | _ ->
157157+ Error "Expected object for services"]
158158+ ; also_known_as: string list [@key "alsoKnownAs"]
159159+ ; rotation_keys: string list [@key "rotationKeys"]
160160+ ; verification_methods: string_map [@key "verificationMethods"] }
161161+[@@deriving yojson {strict= false}]
162162+163163+type audit_log_entry =
164164+ { did: string
165165+ ; operation: audit_log_operation
166166+ ; cid: string
167167+ ; nullified: bool
168168+ ; created_at: string [@key "createdAt"] }
169169+[@@deriving yojson {strict= false}]
170170+171171+type audit_log = audit_log_entry list [@@deriving yojson {strict= false}]
172172+130173let sign_operation (key : Kleidos.key) operation : signed_operation =
131174 let sig_privkey, (module Sig_curve) = key in
132175 let cbor = unsigned_operation_to_yojson operation |> Dag_cbor.encode_yojson in
···149192 | Tombstone {type'; prev} ->
150193 Tombstone {type'; prev; signature= sig_str}
151194152152-let submit_operation ?(endpoint = "https://plc.directory") did operation :
195195+let submit_operation ?(endpoint = default_endpoint) did operation :
153196 (unit, int * string) Lwt_result.t =
154154- let open Cohttp in
155155- let open Cohttp_lwt_unix in
156197 let endpoint = Uri.(with_path (of_string endpoint) did) in
157198 let headers = Header.of_list [("Content-Type", "application/json")] in
158199 let body =
159200 operation |> signed_operation_to_yojson |> Yojson.Safe.to_string
160160- |> Cohttp_lwt.Body.of_string
201201+ |> Body.of_string
161202 in
162203 let%lwt res, body = Client.post ~headers ~body endpoint in
163204 match res.status with
164205 | `OK ->
165206 Lwt.return_ok ()
166207 | _ ->
167167- let%lwt body_str = Cohttp_lwt.Body.to_string body in
208208+ let%lwt body_str = Body.to_string body in
168209 Lwt.return_error (Http.Status.to_int res.status, body_str)
169210170211let did_of_operation operation : string =
···213254 | Error (status, error) ->
214255 Lwt.return_error
215256 @@ Format.sprintf "error %d while submitting operation; %s" status error
257257+258258+let get_audit_log ?endpoint did : (audit_log, string) Lwt_result.t =
259259+ let uri =
260260+ Uri.of_string
261261+ @@ Format.sprintf "%s/%s/log/audit"
262262+ (Option.value endpoint ~default:"https://plc.directory")
263263+ did
264264+ in
265265+ let headers = Http.Header.init_with "Accept" "application/json" in
266266+ let%lwt res, body = Client.get ~headers uri in
267267+ match res.status with
268268+ | `OK ->
269269+ let%lwt body = Body.to_string body in
270270+ Lwt.return @@ audit_log_of_yojson @@ Yojson.Safe.from_string body
271271+ | s ->
272272+ let%lwt body_str = Body.to_string body in
273273+ Lwt.return_error
274274+ @@ Format.sprintf "error %d while fetching audit log; %s"
275275+ (Http.Status.to_int s) body_str
+84
pegasus/lib/util.ml
···7171 end
7272end
73737474+module Did_doc_types = struct
7575+ type string_or_strings = [`String of string | `Strings of string list]
7676+7777+ let string_or_strings_to_yojson = function
7878+ | `String c ->
7979+ `String c
8080+ | `Strings cs ->
8181+ `List (List.map (fun c -> `String c) cs)
8282+8383+ let string_or_strings_of_yojson = function
8484+ | `String c ->
8585+ Ok (`Strings [c])
8686+ | `List cs ->
8787+ Ok (`Strings (Yojson.Safe.Util.filter_string cs))
8888+ | _ ->
8989+ Error "invalid field value"
9090+9191+ type string_map = (string * string) list
9292+9393+ let string_map_to_yojson = function
9494+ | [] ->
9595+ `Assoc []
9696+ | m ->
9797+ `Assoc (List.map (fun (k, v) -> (k, `String v)) m)
9898+9999+ let string_map_of_yojson = function
100100+ | `Null ->
101101+ Ok []
102102+ | `Assoc m ->
103103+ Ok
104104+ (List.filter_map
105105+ (fun (k, v) ->
106106+ match (k, v) with _, `String s -> Some (k, s) | _, _ -> None )
107107+ m )
108108+ | _ ->
109109+ Error "invalid field value"
110110+111111+ type string_or_string_map = [`String of string | `StringMap of string_map]
112112+113113+ let string_or_string_map_to_yojson = function
114114+ | `String c ->
115115+ `String c
116116+ | `StringMap m ->
117117+ `Assoc (List.map (fun (k, v) -> (k, `String v)) m)
118118+119119+ let string_or_string_map_of_yojson = function
120120+ | `String c ->
121121+ Ok (`StringMap [(c, "")])
122122+ | `Assoc m ->
123123+ Ok
124124+ (`StringMap
125125+ (List.map (fun (k, v) -> (k, Yojson.Safe.Util.to_string v)) m) )
126126+ | _ ->
127127+ Error "invalid field value"
128128+129129+ type string_or_string_map_or_either_list =
130130+ [ `String of string
131131+ | `StringMap of string_map
132132+ | `List of string_or_string_map list ]
133133+134134+ let string_or_string_map_or_either_list_to_yojson = function
135135+ | `String c ->
136136+ `String c
137137+ | `StringMap m ->
138138+ `Assoc (List.map (fun (k, v) -> (k, `String v)) m)
139139+ | `List l ->
140140+ `List (List.map string_or_string_map_to_yojson l)
141141+142142+ let string_or_string_map_or_either_list_of_yojson = function
143143+ | `String c ->
144144+ Ok (`StringMap [(c, "")])
145145+ | `Assoc m ->
146146+ Ok
147147+ (`StringMap
148148+ (List.map (fun (k, v) -> (k, Yojson.Safe.Util.to_string v)) m) )
149149+ | `List l ->
150150+ Ok
151151+ (`List
152152+ ( List.map string_or_string_map_of_yojson l
153153+ |> List.filter_map (function Ok x -> Some x | Error _ -> None) ) )
154154+ | _ ->
155155+ Error "invalid field value"
156156+end
157157+74158(* turns a caqti error into an exception *)
75159let caqti_result_exn = function
76160 | Ok x ->
+7-1
pegasus/lib/xrpc.ml
···1313 match%lwt auth init with
1414 | Ok creds -> (
1515 try%lwt hdlr {req= init.req; db= init.db; auth= creds}
1616- with e -> log_exn e ; exn_to_response e )
1616+ with e ->
1717+ ( match is_xrpc_error e with
1818+ | true ->
1919+ ()
2020+ | false ->
2121+ log_exn ~req:init.req e ) ;
2222+ exn_to_response e )
1723 | Error e ->
1824 exn_to_response e
1925