github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/engine/signup_join.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/hex"
     8  	"fmt"
     9  
    10  	"github.com/keybase/client/go/libkb"
    11  	keybase1 "github.com/keybase/client/go/protocol/keybase1"
    12  )
    13  
    14  type SignupJoinEngine struct {
    15  	uv       keybase1.UserVersion
    16  	session  string
    17  	csrf     string
    18  	username libkb.NormalizedUsername
    19  	ppGen    libkb.PassphraseGeneration
    20  	libkb.Contextified
    21  }
    22  
    23  func NewSignupJoinEngine(g *libkb.GlobalContext) *SignupJoinEngine {
    24  	return &SignupJoinEngine{Contextified: libkb.NewContextified(g)}
    25  }
    26  
    27  func (s *SignupJoinEngine) Init() error {
    28  	return nil
    29  }
    30  
    31  func (s *SignupJoinEngine) CheckRegistered() (err error) {
    32  	s.G().Log.Debug("+ libkb.SignupJoinEngine::CheckRegistered")
    33  	if cr := s.G().Env.GetConfig(); cr == nil {
    34  		err = fmt.Errorf("No configuration file available")
    35  	} else if u := cr.GetUID(); u.Exists() {
    36  		err = libkb.AlreadyRegisteredError{UID: u}
    37  	}
    38  	s.G().Log.Debug("- libkb.SignupJoinEngine::CheckRegistered -> %s", libkb.ErrToOk(err))
    39  	return err
    40  }
    41  
    42  type SignupJoinEngineRunArg struct {
    43  	Username    string
    44  	Email       string
    45  	InviteCode  string
    46  	PWHash      []byte
    47  	PWSalt      []byte
    48  	RandomPW    bool
    49  	PDPKA5KID   keybase1.KID
    50  	SkipMail    bool
    51  	VerifyEmail bool
    52  	BotToken    keybase1.BotToken
    53  }
    54  
    55  func (s *SignupJoinEngine) Post(m libkb.MetaContext, arg SignupJoinEngineRunArg) (err error) {
    56  	var res *libkb.APIRes
    57  	var ppGenTmp int
    58  	postArgs := libkb.HTTPArgs{
    59  		"salt":          libkb.S{Val: hex.EncodeToString(arg.PWSalt)},
    60  		"pwh":           libkb.S{Val: hex.EncodeToString(arg.PWHash)},
    61  		"random_pw":     libkb.B{Val: arg.RandomPW},
    62  		"username":      libkb.S{Val: arg.Username},
    63  		"invitation_id": libkb.S{Val: arg.InviteCode},
    64  		"pwh_version":   libkb.I{Val: int(libkb.ClientTriplesecVersion)},
    65  		"skip_mail":     libkb.B{Val: arg.SkipMail},
    66  		"pdpka5_kid":    libkb.S{Val: arg.PDPKA5KID.String()},
    67  		"platform":      libkb.S{Val: libkb.GetPlatformString()},
    68  		"verify_email":  libkb.B{Val: arg.VerifyEmail},
    69  	}
    70  	if len(arg.Email) > 0 {
    71  		postArgs["email"] = libkb.S{Val: arg.Email}
    72  	} else {
    73  		postArgs["no_email"] = libkb.B{Val: true}
    74  	}
    75  	if arg.BotToken.Exists() {
    76  		postArgs["bot_token"] = libkb.S{Val: arg.BotToken.String()}
    77  	}
    78  	res, err = m.G().API.Post(m, libkb.APIArg{
    79  		Endpoint: "signup",
    80  		Args:     postArgs,
    81  	})
    82  	if err == nil {
    83  		s.username = libkb.NewNormalizedUsername(arg.Username)
    84  		libkb.GetUIDVoid(res.Body.AtKey("uid"), &s.uv.Uid, &err)
    85  		res.Body.AtKey("session").GetStringVoid(&s.session, &err)
    86  		res.Body.AtKey("csrf_token").GetStringVoid(&s.csrf, &err)
    87  		res.Body.AtPath("me.basics.passphrase_generation").GetIntVoid(&ppGenTmp, &err)
    88  	}
    89  	if err == nil {
    90  		err = libkb.CheckUIDAgainstUsername(s.uv.Uid, arg.Username)
    91  		s.ppGen = libkb.PassphraseGeneration(ppGenTmp)
    92  	}
    93  	return err
    94  }
    95  
    96  type SignupJoinEngineRunRes struct {
    97  	PassphraseOk bool
    98  	PostOk       bool
    99  	WriteOk      bool
   100  	UV           keybase1.UserVersion
   101  	User         *libkb.User
   102  	Err          error
   103  	PpGen        libkb.PassphraseGeneration
   104  }
   105  
   106  func (r SignupJoinEngineRunRes) Error() string {
   107  	return r.Err.Error()
   108  }
   109  
   110  func (s *SignupJoinEngine) Run(m libkb.MetaContext, arg SignupJoinEngineRunArg) (res SignupJoinEngineRunRes) {
   111  	res.PassphraseOk = true
   112  
   113  	if res.Err = s.Post(m, arg); res.Err != nil {
   114  		return
   115  	}
   116  	res.PostOk = true
   117  	if res.Err = s.WriteOut(m, arg); res.Err != nil {
   118  		return
   119  	}
   120  	res.WriteOk = true
   121  	res.UV = s.uv
   122  	res.PpGen = s.ppGen
   123  	return
   124  }
   125  
   126  func (s *SignupJoinEngine) WriteOut(m libkb.MetaContext, arg SignupJoinEngineRunArg) error {
   127  	lctx := m.LoginContext()
   128  	if err := lctx.CreateLoginSessionWithSalt(s.username.String(), arg.PWSalt); err != nil {
   129  		return err
   130  	}
   131  	var nilDeviceID keybase1.DeviceID
   132  	if err := lctx.SaveState(s.session, s.csrf, s.username, s.uv, nilDeviceID); err != nil {
   133  		return err
   134  	}
   135  	if arg.BotToken.Exists() {
   136  		m.Debug("SignupJoinEngine#WriteOut: not saving config since in bot mode")
   137  		return nil
   138  	}
   139  	// Switching to a new user is an operation on the GlobalContext, and will atomically
   140  	// update the config file and alter the current ActiveDevice. So farm out to over there.
   141  	return m.SwitchUserNewConfig(s.uv.Uid, s.username, arg.PWSalt, nilDeviceID)
   142  }
   143  
   144  func (s *SignupJoinEngine) PostInviteRequest(m libkb.MetaContext, arg libkb.InviteRequestArg) error {
   145  	return libkb.PostInviteRequest(m, arg)
   146  }