github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/engine/sigslist.go (about) 1 // Copyright 2015 Keybase, Inc. All rights reserved. Use of 2 // this source code is governed by the included BSD license. 3 4 package engine 5 6 import ( 7 "encoding/json" 8 "regexp" 9 10 "github.com/keybase/client/go/libkb" 11 keybase1 "github.com/keybase/client/go/protocol/keybase1" 12 ) 13 14 // SigsList is an engine for the sigs-list command. 15 type SigsList struct { 16 SigsListArgs 17 18 user *libkb.User 19 sigs []libkb.TypedChainLink 20 libkb.Contextified 21 } 22 23 type SigsListArgs struct { 24 Username string 25 Types map[string]bool 26 Filterx string 27 Verbose bool 28 Revoked bool 29 } 30 31 // NewSigsList creates a SigsList engine. 32 func NewSigsList(g *libkb.GlobalContext, args SigsListArgs) *SigsList { 33 return &SigsList{ 34 SigsListArgs: args, 35 Contextified: libkb.NewContextified(g), 36 } 37 } 38 39 // Name is the unique engine name. 40 func (e *SigsList) Name() string { 41 return "SigsList" 42 } 43 44 // GetPrereqs returns the engine prereqs. 45 func (e *SigsList) Prereqs() Prereqs { 46 return Prereqs{} 47 } 48 49 // RequiredUIs returns the required UIs. 50 func (e *SigsList) RequiredUIs() []libkb.UIKind { 51 return []libkb.UIKind{} 52 } 53 54 // SubConsumers returns the other UI consumers for this engine. 55 func (e *SigsList) SubConsumers() []libkb.UIConsumer { 56 return nil 57 } 58 59 // Run starts the engine. 60 func (e *SigsList) Run(m libkb.MetaContext) error { 61 arg := libkb.NewLoadUserArgWithMetaContext(m) 62 if len(e.Username) > 0 { 63 arg = arg.WithName(e.Username) 64 } else { 65 arg = arg.WithSelf(true) 66 } 67 68 var err error 69 e.user, err = libkb.LoadUser(arg) 70 if err != nil { 71 return err 72 } 73 74 e.sigs = e.user.IDTable().Order 75 return e.processSigs() 76 } 77 78 // Sigs returns the sig list, after processing. 79 func (e *SigsList) Sigs() []keybase1.Sig { 80 res := make([]keybase1.Sig, len(e.sigs)) 81 for i, s := range e.sigs { 82 var key string 83 fp := s.GetPGPFingerprint() 84 if fp != nil { 85 key = fp.ToDisplayString(e.Verbose) 86 } 87 res[i] = keybase1.Sig{ 88 Seqno: s.GetSeqno(), 89 SigIDDisplay: s.GetSigID().ToDisplayString(e.Verbose), 90 Type: s.Type(), 91 CTime: keybase1.ToTime(s.GetCTime()), 92 Revoked: s.IsRevoked(), 93 Active: e.isActiveKey(s), 94 Key: key, 95 Body: s.ToDisplayString(), 96 } 97 } 98 return res 99 } 100 101 // ugh 102 type sigexp struct { 103 Seqno keybase1.Seqno `json:"seqno"` 104 SigID string `json:"sig_id"` 105 Type string `json:"type"` 106 CTime int64 `json:"ctime"` 107 Revoked bool `json:"revoked"` 108 Active bool `json:"active"` 109 Key string `json:"key_fingerprint,omitempty"` 110 Body string `json:"statement"` 111 } 112 113 func (e *SigsList) JSON() (string, error) { 114 exp := make([]sigexp, len(e.sigs)) 115 for i, s := range e.sigs { 116 var key string 117 fp := s.GetPGPFingerprint() 118 if fp != nil { 119 key = fp.ToDisplayString(true /* verbose */) 120 } 121 exp[i] = sigexp{ 122 Seqno: s.GetSeqno(), 123 SigID: s.GetSigID().ToDisplayString(true /* verbose */), 124 Type: s.Type(), 125 CTime: s.GetCTime().Unix(), 126 Revoked: s.IsRevoked(), 127 Active: e.isActiveKey(s), 128 Key: key, 129 Body: s.ToDisplayString(), 130 } 131 } 132 j, err := json.MarshalIndent(exp, "", "\t") 133 if err != nil { 134 return "", err 135 } 136 return string(j), nil 137 138 } 139 140 func (e *SigsList) processSigs() error { 141 if err := e.skipSigs(); err != nil { 142 return err 143 } 144 if err := e.selectSigs(); err != nil { 145 return err 146 } 147 return e.filterRxx() 148 } 149 150 func (e *SigsList) skipSigs() error { 151 e.filterSigs(func(l libkb.TypedChainLink) bool { 152 return !e.skipLink(l) 153 }) 154 return nil 155 } 156 157 func (e *SigsList) selectSigs() error { 158 if e.Types != nil { 159 e.filterSigs(func(l libkb.TypedChainLink) bool { 160 ok, found := e.Types[l.Type()] 161 return ok && found 162 }) 163 } 164 return nil 165 } 166 167 func (e *SigsList) filterRxx() error { 168 if len(e.Filterx) == 0 { 169 return nil 170 } 171 rxx, err := regexp.Compile(e.Filterx) 172 if err != nil { 173 return err 174 } 175 e.filterSigs(func(l libkb.TypedChainLink) bool { 176 return rxx.MatchString(l.ToDisplayString()) 177 }) 178 return nil 179 } 180 181 func (e *SigsList) filterSigs(f func(libkb.TypedChainLink) bool) { 182 var sigs []libkb.TypedChainLink 183 for _, link := range e.sigs { 184 if f(link) { 185 sigs = append(sigs, link) 186 } 187 } 188 e.sigs = sigs 189 } 190 191 func (e *SigsList) isActiveKey(link libkb.TypedChainLink) bool { 192 return link.IsInCurrentFamily(e.user) 193 } 194 195 func (e *SigsList) skipLink(link libkb.TypedChainLink) bool { 196 return (!e.Revoked && (link.IsRevoked() || link.IsRevocationIsh())) 197 }