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  }