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 }