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

     1  package auth
     2  
     3  import (
     4  	"time"
     5  
     6  	libkb "github.com/keybase/client/go/libkb"
     7  	logger "github.com/keybase/client/go/logger"
     8  	keybase1 "github.com/keybase/client/go/protocol/keybase1"
     9  	context "golang.org/x/net/context"
    10  )
    11  
    12  const (
    13  	pollWait = 5 * time.Second
    14  )
    15  
    16  type pubsubMessageInner struct {
    17  	UID keybase1.UID `json:"uid"`
    18  }
    19  
    20  type pubsubMessageOuter struct {
    21  	SyncStamp int                `json:"sync_stamp"`
    22  	Message   pubsubMessageInner `json:"message"`
    23  }
    24  
    25  type serverState struct {
    26  	InstanceID      string `json:"instance_id"`
    27  	LatestSyncStamp int    `json:"latest_sync_stamp"`
    28  }
    29  
    30  type pubsubResponse struct {
    31  	Status      libkb.AppStatus      `json:"status"`
    32  	ServerState serverState          `json:"server_state"`
    33  	Messages    []pubsubMessageOuter `json:"messages"`
    34  }
    35  
    36  func (p *pubsubResponse) GetAppStatus() *libkb.AppStatus {
    37  	return &p.Status
    38  }
    39  
    40  var _ UserKeyAPIer = (*userKeyAPI)(nil)
    41  
    42  type userKeysResPublicKeys struct {
    43  	Sibkeys []keybase1.KID `json:"sibkeys"`
    44  	Subkeys []keybase1.KID `json:"subkeys"`
    45  }
    46  
    47  type userKeyRes struct {
    48  	Status     libkb.AppStatus       `json:"status"`
    49  	Username   string                `json:"username"`
    50  	PublicKeys userKeysResPublicKeys `json:"public_keys"`
    51  	Deleted    bool                  `json:"deleted"`
    52  }
    53  
    54  func (k *userKeyRes) GetAppStatus() *libkb.AppStatus {
    55  	return &k.Status
    56  }
    57  
    58  type userKeyAPI struct {
    59  	log           logger.Logger
    60  	api           libkb.API
    61  	lastSyncPoint int
    62  	instanceID    string
    63  }
    64  
    65  func (u *userKeyAPI) GetUser(ctx context.Context, uid keybase1.UID) (
    66  	un libkb.NormalizedUsername, sibkeys, subkeys []keybase1.KID, isDeleted bool, err error) {
    67  	u.log.Debug("+ GetUser")
    68  	defer func() {
    69  		u.log.Debug("- GetUser -> %v", err)
    70  	}()
    71  	var ukr userKeyRes
    72  	err = u.api.GetDecodeCtx(ctx, libkb.APIArg{
    73  		Endpoint: "user/keys",
    74  		Args: libkb.HTTPArgs{
    75  			"uid":          libkb.S{Val: uid.String()},
    76  			"load_deleted": libkb.B{Val: true},
    77  		},
    78  	}, &ukr)
    79  	if err != nil {
    80  		return "", nil, nil, false, err
    81  	}
    82  	un = libkb.NewNormalizedUsername(ukr.Username)
    83  	return un, ukr.PublicKeys.Sibkeys, ukr.PublicKeys.Subkeys, ukr.Deleted, nil
    84  }
    85  
    86  func (u *userKeyAPI) PollForChanges(ctx context.Context) (uids []keybase1.UID, err error) {
    87  	defer func() {
    88  		if err != nil {
    89  			u.log.Error("- poll -> %v", err)
    90  		}
    91  	}()
    92  
    93  	var psb pubsubResponse
    94  	args := libkb.HTTPArgs{
    95  		"feed":            libkb.S{Val: "user.key_change"},
    96  		"last_sync_stamp": libkb.I{Val: u.lastSyncPoint},
    97  		"instance_id":     libkb.S{Val: u.instanceID},
    98  		"wait_for_msec":   libkb.I{Val: int(pollWait / time.Millisecond)},
    99  	}
   100  	err = u.api.GetDecodeCtx(ctx, libkb.APIArg{
   101  		Endpoint: "pubsub/poll",
   102  		Args:     args,
   103  	}, &psb)
   104  
   105  	// If there was an error (say if the API server was down), then don't busy
   106  	// loop, wait the pollWait amount of time before exiting.
   107  	if err != nil {
   108  		u.log.Debug("Error in poll; waiting for pollWait=%s time", pollWait)
   109  		select {
   110  		case <-time.After(pollWait):
   111  		case <-ctx.Done():
   112  			u.log.Debug("Wait short-circuited due to context cancellation")
   113  		}
   114  		return uids, err
   115  	}
   116  
   117  	for _, message := range psb.Messages {
   118  		uids = append(uids, message.Message.UID)
   119  	}
   120  	u.lastSyncPoint = psb.ServerState.LatestSyncStamp
   121  	u.instanceID = psb.ServerState.InstanceID
   122  
   123  	return uids, err
   124  }
   125  
   126  // NewUserKeyAPIer returns a UserKeyAPIer implementation.
   127  func NewUserKeyAPIer(log logger.Logger, api libkb.API) UserKeyAPIer {
   128  	return &userKeyAPI{log: log, api: api}
   129  }