github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/identify3/service.go (about)

     1  package identify3
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/keybase/client/go/engine"
     7  	"github.com/keybase/client/go/libkb"
     8  	keybase1 "github.com/keybase/client/go/protocol/keybase1"
     9  )
    10  
    11  func Identify3(mctx libkb.MetaContext, ui3 keybase1.Identify3UiInterface, arg keybase1.Identify3Arg) (err error) {
    12  	ui1, err := NewUIAdapterMakeSession(mctx.BackgroundWithLogTags(), ui3, arg.GuiID)
    13  	if err != nil {
    14  		return err
    15  	}
    16  	i2arg := keybase1.Identify2Arg{
    17  		UserAssertion:    string(arg.Assertion),
    18  		ForceRemoteCheck: arg.IgnoreCache,
    19  		ForceDisplay:     true,
    20  		IdentifyBehavior: keybase1.TLFIdentifyBehavior_GUI_PROFILE,
    21  		NoSkipSelf:       true,
    22  	}
    23  	mctx = mctx.WithIdentifyUI(ui1)
    24  	eng := engine.NewResolveThenIdentify2(mctx.G(), &i2arg)
    25  	err = engine.RunEngine2(mctx, eng)
    26  	if err != nil {
    27  		return err
    28  	}
    29  
    30  	return nil
    31  }
    32  
    33  type identify3Action int
    34  
    35  const (
    36  	identify3ActionFollow   identify3Action = 1
    37  	identify3ActionUnfollow identify3Action = 2
    38  	identify3ActionIgnore   identify3Action = 3
    39  )
    40  
    41  func FollowUser(mctx libkb.MetaContext, arg keybase1.Identify3FollowUserArg) (err error) {
    42  	var action identify3Action
    43  	if arg.Follow {
    44  		action = identify3ActionFollow
    45  	} else {
    46  		action = identify3ActionUnfollow
    47  	}
    48  	return doActionAndRemove(mctx, arg.GuiID, action)
    49  }
    50  
    51  func doAction(mctx libkb.MetaContext, guiID keybase1.Identify3GUIID, action identify3Action) error {
    52  	sess, err := mctx.G().Identify3State.Get(guiID)
    53  	if err != nil {
    54  		return err
    55  	}
    56  	if sess == nil {
    57  		return libkb.NewNotFoundError(fmt.Sprintf("session %s wasn't found", guiID))
    58  	}
    59  
    60  	// Lock the session mainly because we want to protect the outcome, which unfortunately
    61  	// is difficult to copy. But be certain never to grab the Identify3State lock while
    62  	// holding the session lock (see comment below in doActionAndRemove).
    63  	sess.Lock()
    64  	defer sess.Unlock()
    65  	outcome := sess.OutcomeLocked()
    66  
    67  	if outcome == nil {
    68  		return libkb.NewNotFoundError(fmt.Sprintf("outcome for session %s wasn't ready; is there a race?", guiID))
    69  	}
    70  
    71  	switch action {
    72  	case identify3ActionFollow, identify3ActionIgnore:
    73  		err = doFollow(mctx, action, outcome)
    74  	case identify3ActionUnfollow:
    75  		err = doUnfollow(mctx, outcome)
    76  	}
    77  
    78  	return err
    79  }
    80  
    81  func doActionAndRemove(mctx libkb.MetaContext, guiID keybase1.Identify3GUIID, action identify3Action) error {
    82  	err := doAction(mctx, guiID, action)
    83  	if err != nil {
    84  		return err
    85  	}
    86  
    87  	// It's important not to hold the session lock when calling this function, since the background expire
    88  	// thread in identify3 grabs the state lock and then the session locks.
    89  	mctx.G().Identify3State.Remove(guiID)
    90  
    91  	return err
    92  }
    93  
    94  func doUnfollow(mctx libkb.MetaContext, outcome *libkb.IdentifyOutcome) (err error) {
    95  	sv := libkb.KeybaseSignatureV2
    96  	uarg := engine.UntrackEngineArg{
    97  		Username:   outcome.Username,
    98  		SigVersion: sv,
    99  	}
   100  	eng := engine.NewUntrackEngine(mctx.G(), &uarg)
   101  	return engine.RunEngine2(mctx, eng)
   102  }
   103  
   104  func doFollow(mctx libkb.MetaContext, action identify3Action, outcome *libkb.IdentifyOutcome) (err error) {
   105  	sv := keybase1.SigVersion(2)
   106  	ttarg := engine.TrackTokenArg{
   107  		Options: keybase1.TrackOptions{
   108  			SigVersion: &sv,
   109  		},
   110  		Outcome: outcome,
   111  	}
   112  	if action == identify3ActionIgnore {
   113  		ttarg.Options.ExpiringLocal = true
   114  	}
   115  	eng := engine.NewTrackToken(mctx.G(), &ttarg)
   116  	return engine.RunEngine2(mctx, eng)
   117  }
   118  
   119  func IgnoreUser(mctx libkb.MetaContext, guiID keybase1.Identify3GUIID) (err error) {
   120  	return doActionAndRemove(mctx, guiID, identify3ActionIgnore)
   121  }