1package photocopy
2
3import (
4 "encoding/json"
5 "fmt"
6 "time"
7)
8
9type PLCEntry struct {
10 Did string `json:"did"`
11 Operation PLCOperationType `json:"operation"`
12 Cid string `json:"cid"`
13 Nullified bool `json:"nullified"`
14 CreatedAt time.Time `json:"createdAt"`
15}
16
17type PLCOperation struct {
18 Sig string `json:"sig" `
19 Prev *string `json:"prev"`
20 Type string `json:"type"`
21 Services map[string]PLCService `json:"services"`
22 AlsoKnownAs []string `json:"alsoKnownAs"`
23 RotationKeys []string `json:"rotationKeys"`
24 VerificationMethods map[string]string `json:"verificationMethods"`
25}
26
27type PLCTombstone struct {
28 Sig string `json:"sig"`
29 Prev string `json:"prev"`
30 Type string `json:"type"`
31}
32
33type PLCService struct {
34 Type string `json:"type"`
35 Endpoint string `json:"endpoint"`
36}
37
38type LegacyPLCOperation struct {
39 Sig string `json:"sig"`
40 Prev string `json:"prev"`
41 Type string `json:"type"`
42 Handle string `json:"handle"`
43 Service string `json:"service"`
44 SigningKey string `json:"signingKey"`
45 RecoveryKey string `json:"recoveryKey"`
46}
47
48type PLCOperationType struct {
49 OperationType string
50 PLCOperation *PLCOperation
51 PLCTombstone *PLCTombstone
52 LegacyPLCOperation *LegacyPLCOperation
53}
54
55type ClickhousePLCEntry struct {
56 Did string `ch:"did"`
57 Cid string `ch:"cid"`
58 Nullified bool `ch:"nullified"`
59 CreatedAt time.Time `ch:"created_at"`
60 PlcOpSig string `ch:"plc_op_sig"`
61 PlcOpPrev string `ch:"plc_op_prev"`
62 PlcOpType string `ch:"plc_op_type"`
63 PlcOpServices []string `ch:"plc_op_services"`
64 PlcOpAlsoKnownAs []string `ch:"plc_op_also_known_as"`
65 PlcOpRotationKeys []string `ch:"plc_op_rotation_keys"`
66 PlcTombSig string `ch:"plc_tomb_sig"`
67 PlcTombPrev string `ch:"plc_tomb_prev"`
68 PlcTombType string `ch:"plc_tomb_type"`
69 LegacyOpSig string `ch:"legacy_op_sig"`
70 LegacyOpPrev string `ch:"legacy_op_prev"`
71 LegacyOpType string `ch:"legacy_op_type"`
72 LegacyOpHandle string `ch:"legacy_op_handle"`
73 LegacyOpService string `ch:"legacy_op_service"`
74 LegacyOpSigningKey string `ch:"legacy_op_signing_key"`
75 LegacyOpRecoveryKey string `ch:"legacy_op_recovery_key"`
76}
77
78func (o *PLCOperationType) UnmarshalJSON(data []byte) error {
79 type Base struct {
80 PLCOperation *PLCOperation
81 PLCTombstone *PLCTombstone
82 LegacyPLCOperation *LegacyPLCOperation
83 Type string `json:"type"`
84 }
85
86 var base Base
87 if err := json.Unmarshal(data, &base); err != nil {
88 return err
89 }
90
91 switch base.Type {
92 case "plc_operation":
93 var op PLCOperation
94 if err := json.Unmarshal(data, &op); err != nil {
95 return err
96 }
97 o.PLCOperation = &op
98 o.OperationType = "plc_operation"
99 case "plc_tombstone":
100 var op PLCTombstone
101 if err := json.Unmarshal(data, &op); err != nil {
102 return err
103 }
104 o.PLCTombstone = &op
105 o.OperationType = "plc_tombstone"
106 case "create":
107 var op LegacyPLCOperation
108 if err := json.Unmarshal(data, &op); err != nil {
109 return err
110 }
111 o.LegacyPLCOperation = &op
112 o.OperationType = "legacy_plc_operation"
113 default:
114 if base.PLCOperation != nil || base.PLCTombstone != nil || base.LegacyPLCOperation != nil {
115 o.PLCOperation = base.PLCOperation
116 o.PLCTombstone = base.PLCTombstone
117 o.LegacyPLCOperation = base.LegacyPLCOperation
118 } else {
119 return fmt.Errorf("invalid operation type %s", base.Type)
120 }
121 }
122
123 return nil
124}
125
126func (e *PLCEntry) prepareForClickhouse() (*ClickhousePLCEntry, error) {
127 che := &ClickhousePLCEntry{
128 Did: e.Did,
129 Cid: e.Cid,
130 Nullified: e.Nullified,
131 CreatedAt: e.CreatedAt,
132 }
133 if e.Operation.PLCOperation != nil {
134 pop := e.Operation.PLCOperation
135 che.PlcOpSig = pop.Sig
136 if pop.Prev != nil {
137 che.PlcOpPrev = *pop.Prev
138 }
139 che.PlcOpType = pop.Type
140 services := []string{}
141 for _, s := range pop.Services {
142 services = append(services, s.Endpoint)
143 }
144 che.PlcOpServices = services
145 che.PlcOpAlsoKnownAs = pop.AlsoKnownAs
146 che.PlcOpRotationKeys = pop.RotationKeys
147 if e.Operation.PLCOperation.Services == nil {
148 for _, s := range e.Operation.PLCOperation.Services {
149 che.PlcOpServices = append(che.PlcOpServices, s.Endpoint)
150 }
151 }
152 return che, nil
153 } else if e.Operation.PLCTombstone != nil {
154 che.PlcTombSig = e.Operation.PLCTombstone.Sig
155 che.PlcTombPrev = e.Operation.PLCTombstone.Prev
156 che.PlcTombType = e.Operation.PLCTombstone.Type
157 return che, nil
158 } else if e.Operation.LegacyPLCOperation != nil {
159 lop := e.Operation.LegacyPLCOperation
160 che.LegacyOpSig = lop.Sig
161 che.LegacyOpPrev = lop.Prev
162 che.LegacyOpType = lop.Type
163 che.LegacyOpService = lop.Service
164 che.LegacyOpHandle = lop.Handle
165 che.LegacyOpSigningKey = lop.SigningKey
166 che.LegacyOpRecoveryKey = lop.RecoveryKey
167 return che, nil
168 }
169
170 return nil, fmt.Errorf("no valid plc operation type")
171}