github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/service/signup.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 service
     5  
     6  import (
     7  	"github.com/keybase/client/go/engine"
     8  	"github.com/keybase/client/go/libkb"
     9  	keybase1 "github.com/keybase/client/go/protocol/keybase1"
    10  	"github.com/keybase/go-framed-msgpack-rpc/rpc"
    11  	"golang.org/x/net/context"
    12  )
    13  
    14  type SignupHandler struct {
    15  	*BaseHandler
    16  	libkb.Contextified
    17  }
    18  
    19  func NewSignupHandler(xp rpc.Transporter, g *libkb.GlobalContext) *SignupHandler {
    20  	return &SignupHandler{
    21  		BaseHandler:  NewBaseHandler(g, xp),
    22  		Contextified: libkb.NewContextified(g),
    23  	}
    24  }
    25  
    26  type usernameAvailableRes struct {
    27  	libkb.AppStatusEmbed
    28  	Available bool   `json:"available"`
    29  	Reason    string `json:"reason"`
    30  }
    31  
    32  func (h *SignupHandler) CheckUsernameAvailable(ctx context.Context, arg keybase1.CheckUsernameAvailableArg) error {
    33  	mctx := libkb.NewMetaContext(ctx, h.G())
    34  	var apiRes usernameAvailableRes
    35  	err := mctx.G().API.GetDecode(mctx, libkb.APIArg{
    36  		Endpoint:    "user/username_available",
    37  		SessionType: libkb.APISessionTypeNONE,
    38  		Args: libkb.HTTPArgs{
    39  			"username": libkb.S{Val: arg.Username},
    40  		},
    41  	}, &apiRes)
    42  	if err != nil {
    43  		return err
    44  	}
    45  	if apiRes.Available {
    46  		return nil
    47  	}
    48  	switch apiRes.Reason {
    49  	case "invalid":
    50  		return libkb.AppStatusError{
    51  			Code: libkb.SCBadUsername,
    52  			Name: "BAD_USERNAME",
    53  			Desc: "Usernames must be 2-16 characters long, and can use letters, numbers, and underscores.",
    54  		}
    55  	case "user":
    56  		// User found, so the name is taken.
    57  		return libkb.AppStatusError{
    58  			Code: libkb.SCBadSignupUsernameTaken,
    59  			Name: "BAD_SIGNUP_USERNAME_TAKEN",
    60  			Desc: "This username is already taken! Please pick another one.",
    61  		}
    62  	case "reserved":
    63  		return libkb.AppStatusError{
    64  			Code: libkb.SCBadSignupUsernameReserved,
    65  			Name: "BAD_SIGNUP_USERNAME_RESERVED",
    66  			Desc: "This username is reserved by the Keybase team, possibly for your organization. Contact reservations@keybase.io to claim it.",
    67  		}
    68  	case "user_deleted":
    69  		return libkb.AppStatusError{
    70  			Code: libkb.SCBadSignupUsernameDeleted,
    71  			Name: "BAD_SIGNUP_USERNAME_DELETED",
    72  			Desc: "This username has been deleted! Please pick another one.",
    73  		}
    74  	case "team":
    75  		return libkb.AppStatusError{
    76  			Code: libkb.SCBadSignupTeamName,
    77  			Name: "BAD_SIGNUP_TEAM_NAME",
    78  			Desc: "This username is already taken. Please pick another one.",
    79  		}
    80  	default:
    81  		return libkb.AppStatusError{
    82  			Code: libkb.SCGenericAPIError,
    83  			Name: "GENERIC",
    84  			Desc: "This username is not available.",
    85  		}
    86  	}
    87  }
    88  
    89  func (h *SignupHandler) Signup(ctx context.Context, arg keybase1.SignupArg) (res keybase1.SignupRes, err error) {
    90  	uis := libkb.UIs{
    91  		LogUI:     h.getLogUI(arg.SessionID),
    92  		GPGUI:     h.getGPGUI(arg.SessionID),
    93  		SecretUI:  h.getSecretUI(arg.SessionID, h.G()),
    94  		LoginUI:   h.getLoginUI(arg.SessionID),
    95  		SessionID: arg.SessionID,
    96  	}
    97  	runarg := engine.SignupEngineRunArg{
    98  		Username:                 arg.Username,
    99  		Email:                    arg.Email,
   100  		InviteCode:               arg.InviteCode,
   101  		Passphrase:               arg.Passphrase,
   102  		GenerateRandomPassphrase: arg.RandomPw,
   103  		StoreSecret:              arg.StoreSecret,
   104  		DeviceName:               arg.DeviceName,
   105  		DeviceType:               arg.DeviceType,
   106  		SkipMail:                 arg.SkipMail,
   107  		GenPGPBatch:              arg.GenPGPBatch,
   108  		SkipPaper:                !arg.GenPaper,
   109  		VerifyEmail:              arg.VerifyEmail,
   110  		BotToken:                 arg.BotToken,
   111  		SkipGPG:                  arg.SkipGPG,
   112  	}
   113  	m := libkb.NewMetaContext(ctx, h.G()).WithUIs(uis)
   114  	eng := engine.NewSignupEngine(h.G(), &runarg)
   115  	err = engine.RunEngine2(m, eng)
   116  
   117  	if err == nil {
   118  		// everything succeeded
   119  
   120  		// these don't really matter as they aren't checked with nil err,
   121  		// but just to make sure:
   122  		res.PassphraseOk = true
   123  		res.PostOk = true
   124  		res.WriteOk = true
   125  		if pk := eng.PaperKey(); pk != nil && arg.BotToken.Exists() {
   126  			res.PaperKey = pk.String()
   127  		}
   128  		return res, nil
   129  	}
   130  
   131  	// check to see if the error is a join engine run result:
   132  	if e, ok := err.(engine.SignupJoinEngineRunRes); ok {
   133  		res.PassphraseOk = e.PassphraseOk
   134  		res.PostOk = e.PostOk
   135  		res.WriteOk = e.WriteOk
   136  		err = e.Err
   137  		return res, err
   138  	}
   139  
   140  	// not a join engine error:
   141  	return res, err
   142  }
   143  
   144  func (h *SignupHandler) InviteRequest(ctx context.Context, arg keybase1.InviteRequestArg) (err error) {
   145  	m := libkb.NewMetaContext(ctx, h.G())
   146  	return libkb.PostInviteRequest(m, libkb.InviteRequestArg{
   147  		Email:    arg.Email,
   148  		Fullname: arg.Fullname,
   149  		Notes:    arg.Notes,
   150  	})
   151  }
   152  
   153  func (h *SignupHandler) CheckInvitationCode(ctx context.Context, arg keybase1.CheckInvitationCodeArg) (err error) {
   154  	return libkb.CheckInvitationCode(libkb.NewMetaContext(ctx, h.G()), arg.InvitationCode)
   155  }
   156  
   157  func (h *SignupHandler) GetInvitationCode(c context.Context, sessionID int) (code string, err error) {
   158  	return libkb.GetInvitationCode(libkb.NewMetaContext(c, h.G()))
   159  }