fork of indigo with slightly nicer lexgen
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 166 lines 3.8 kB view raw
1package label 2 3import ( 4 "bytes" 5 "fmt" 6 7 comatproto "github.com/bluesky-social/indigo/api/atproto" 8 "github.com/bluesky-social/indigo/atproto/crypto" 9 "github.com/bluesky-social/indigo/atproto/data" 10 "github.com/bluesky-social/indigo/atproto/syntax" 11) 12 13// version of the label data fromat implemented by this package 14const ATPROTO_LABEL_VERSION int64 = 1 15 16type Label struct { 17 CID *string `json:"cid,omitempty" cborgen:"cid,omitempty"` 18 CreatedAt string `json:"cts" cborgen:"cts"` 19 ExpiresAt *string `json:"exp,omitempty" cborgen:"exp,omitempty"` 20 Negated *bool `json:"neg,omitempty" cborgen:"neg,omitempty"` 21 SourceDID string `json:"src" cborgen:"src"` 22 URI string `json:"uri" cborgen:"uri"` 23 Val string `json:"val" cborgen:"val"` 24 Version int64 `json:"ver" cborgen:"ver"` 25 Sig data.Bytes `json:"sig,omitempty" cborgen:"sig,omitempty"` 26} 27 28// converts to map[string]any for printing as JSON 29func (l *Label) Data() map[string]any { 30 d := map[string]any{ 31 "cid": l.CID, 32 "cts": l.CreatedAt, 33 "src": l.SourceDID, 34 "uri": l.URI, 35 "val": l.Val, 36 "ver": l.Version, 37 } 38 if l.CID != nil { 39 d["cid"] = l.CID 40 } 41 if l.ExpiresAt != nil { 42 d["exp"] = l.ExpiresAt 43 } 44 if l.Negated != nil { 45 d["neg"] = l.Negated 46 } 47 if l.Sig != nil { 48 d["sig"] = data.Bytes(l.Sig) 49 } 50 return d 51} 52 53// does basic checks on syntax and structure 54func (l *Label) VerifySyntax() error { 55 if l.Version != ATPROTO_LABEL_VERSION { 56 return fmt.Errorf("unsupported label version: %d", l.Version) 57 } 58 if len(l.Val) == 0 { 59 return fmt.Errorf("empty label value") 60 } 61 if l.CID != nil { 62 _, err := syntax.ParseCID(*l.CID) 63 if err != nil { 64 return fmt.Errorf("invalid label: %w", err) 65 } 66 } 67 _, err := syntax.ParseDatetime(l.CreatedAt) 68 if err != nil { 69 return fmt.Errorf("invalid label: %w", err) 70 } 71 if l.ExpiresAt != nil { 72 _, err := syntax.ParseDatetime(*l.ExpiresAt) 73 if err != nil { 74 return fmt.Errorf("invalid label: %w", err) 75 } 76 } 77 _, err = syntax.ParseDID(l.SourceDID) 78 if err != nil { 79 return fmt.Errorf("invalid label: %w", err) 80 } 81 _, err = syntax.ParseURI(l.URI) 82 if err != nil { 83 return fmt.Errorf("invalid label: %w", err) 84 } 85 return nil 86} 87 88func (l *Label) UnsignedBytes() ([]byte, error) { 89 buf := new(bytes.Buffer) 90 if l.Sig == nil { 91 if err := l.MarshalCBOR(buf); err != nil { 92 return nil, err 93 } 94 return buf.Bytes(), nil 95 } 96 unsigned := Label{ 97 CID: l.CID, 98 CreatedAt: l.CreatedAt, 99 ExpiresAt: l.ExpiresAt, 100 Negated: l.Negated, 101 SourceDID: l.SourceDID, 102 URI: l.URI, 103 Val: l.Val, 104 Version: l.Version, 105 } 106 if err := unsigned.MarshalCBOR(buf); err != nil { 107 return nil, err 108 } 109 return buf.Bytes(), nil 110} 111 112// Signs the commit, storing the signature in the `Sig` field 113func (l *Label) Sign(privkey crypto.PrivateKey) error { 114 b, err := l.UnsignedBytes() 115 if err != nil { 116 return err 117 } 118 sig, err := privkey.HashAndSign(b) 119 if err != nil { 120 return err 121 } 122 l.Sig = sig 123 return nil 124} 125 126// Verifies `Sig` field using the provided key. Returns `nil` if signature is valid. 127func (l *Label) VerifySignature(pubkey crypto.PublicKey) error { 128 if l.Sig == nil { 129 return fmt.Errorf("can not verify unsigned commit") 130 } 131 b, err := l.UnsignedBytes() 132 if err != nil { 133 return err 134 } 135 return pubkey.HashAndVerify(b, l.Sig) 136} 137 138func (l *Label) ToLexicon() comatproto.LabelDefs_Label { 139 return comatproto.LabelDefs_Label{ 140 Cid: l.CID, 141 Cts: l.CreatedAt, 142 Exp: l.ExpiresAt, 143 Sig: []byte(l.Sig), 144 Src: l.SourceDID, 145 Uri: l.URI, 146 Val: l.Val, 147 Ver: &l.Version, 148 } 149} 150 151func FromLexicon(l *comatproto.LabelDefs_Label) Label { 152 var v int64 = 0 153 if l.Ver != nil { 154 v = *l.Ver 155 } 156 return Label{ 157 CID: l.Cid, 158 CreatedAt: l.Cts, 159 ExpiresAt: l.Exp, 160 Sig: []byte(l.Sig), 161 SourceDID: l.Src, 162 URI: l.Uri, 163 Val: l.Val, 164 Version: v, 165 } 166}