github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/service/phone_numbers.go (about) 1 package service 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "strings" 7 8 "github.com/keybase/client/go/gregor" 9 "github.com/keybase/client/go/libkb" 10 "github.com/keybase/client/go/phonenumbers" 11 gregor1 "github.com/keybase/client/go/protocol/gregor1" 12 keybase1 "github.com/keybase/client/go/protocol/keybase1" 13 "github.com/keybase/go-framed-msgpack-rpc/rpc" 14 15 "golang.org/x/net/context" 16 ) 17 18 type PhoneNumbersHandler struct { 19 libkb.Contextified 20 *BaseHandler 21 } 22 23 func NewPhoneNumbersHandler(xp rpc.Transporter, g *libkb.GlobalContext) *PhoneNumbersHandler { 24 handler := &PhoneNumbersHandler{ 25 Contextified: libkb.NewContextified(g), 26 BaseHandler: NewBaseHandler(g, xp), 27 } 28 return handler 29 } 30 31 var _ keybase1.PhoneNumbersInterface = (*PhoneNumbersHandler)(nil) 32 33 func (h *PhoneNumbersHandler) AddPhoneNumber(ctx context.Context, arg keybase1.AddPhoneNumberArg) (err error) { 34 mctx := libkb.NewMetaContext(ctx, h.G()) 35 defer mctx.Trace("PhoneNumbersHandler#AddPhoneNumber", &err)() 36 if err = libkb.IsPossiblePhoneNumber(arg.PhoneNumber); err != nil { 37 return err 38 } 39 return phonenumbers.AddPhoneNumber(mctx, arg.PhoneNumber, arg.Visibility) 40 } 41 42 func (h *PhoneNumbersHandler) EditPhoneNumber(ctx context.Context, arg keybase1.EditPhoneNumberArg) (err error) { 43 mctx := libkb.NewMetaContext(ctx, h.G()) 44 defer mctx.Trace("PhoneNumbersHandler#AddPhoneNumber", &err)() 45 if err = libkb.IsPossiblePhoneNumber(arg.OldPhoneNumber); err != nil { 46 return err 47 } 48 if err = libkb.IsPossiblePhoneNumber(arg.PhoneNumber); err != nil { 49 return err 50 } 51 52 if err = phonenumbers.DeletePhoneNumber(mctx, arg.OldPhoneNumber); err != nil { 53 return err 54 } 55 return phonenumbers.AddPhoneNumber(mctx, arg.PhoneNumber, arg.Visibility) 56 } 57 58 func (h *PhoneNumbersHandler) VerifyPhoneNumber(ctx context.Context, arg keybase1.VerifyPhoneNumberArg) (err error) { 59 mctx := libkb.NewMetaContext(ctx, h.G()) 60 defer mctx.Trace("PhoneNumbersHandler#VerifyPhoneNumber", &err)() 61 if err = libkb.IsPossiblePhoneNumber(arg.PhoneNumber); err != nil { 62 return err 63 } 64 65 return phonenumbers.VerifyPhoneNumber(mctx, arg.PhoneNumber, arg.Code) 66 } 67 68 func (h *PhoneNumbersHandler) ResendVerificationForPhoneNumber(ctx context.Context, arg keybase1.ResendVerificationForPhoneNumberArg) (err error) { 69 mctx := libkb.NewMetaContext(ctx, h.G()) 70 defer mctx.Trace("PhoneNumbersHandler#ResendVerificationForPhoneNumber", &err)() 71 if err = libkb.IsPossiblePhoneNumber(arg.PhoneNumber); err != nil { 72 return err 73 } 74 75 numbers, err := phonenumbers.GetPhoneNumbers(mctx) 76 if err != nil { 77 return err 78 } 79 80 // We are going to "re-add" phone number with the same visibility setting. 81 var readdVisibility keybase1.IdentityVisibility 82 var found bool 83 for _, v := range numbers { 84 if v.Superseded { 85 continue 86 } 87 88 if v.PhoneNumber == arg.PhoneNumber { 89 if v.Verified { 90 return fmt.Errorf("Number %s is already verified", v.PhoneNumber) 91 } 92 readdVisibility = v.Visibility 93 found = true 94 break 95 } 96 } 97 98 if !found { 99 return fmt.Errorf("Number %s was not found, it has to be added first before resending verification code", 100 arg.PhoneNumber) 101 } 102 103 return phonenumbers.AddPhoneNumber(mctx, arg.PhoneNumber, readdVisibility) 104 } 105 106 func (h *PhoneNumbersHandler) GetPhoneNumbers(ctx context.Context, sessionID int) (ret []keybase1.UserPhoneNumber, err error) { 107 mctx := libkb.NewMetaContext(ctx, h.G()) 108 defer mctx.Trace("PhoneNumbersHandler#GetPhoneNumbers", &err)() 109 return phonenumbers.GetPhoneNumbers(mctx) 110 } 111 112 func (h *PhoneNumbersHandler) DeletePhoneNumber(ctx context.Context, arg keybase1.DeletePhoneNumberArg) (err error) { 113 mctx := libkb.NewMetaContext(ctx, h.G()) 114 defer mctx.Trace("PhoneNumbersHandler#DeletePhoneNumber", &err)() 115 if err = libkb.IsPossiblePhoneNumber(arg.PhoneNumber); err != nil { 116 return err 117 } 118 119 return phonenumbers.DeletePhoneNumber(mctx, arg.PhoneNumber) 120 } 121 122 func (h *PhoneNumbersHandler) SetVisibilityPhoneNumber(ctx context.Context, arg keybase1.SetVisibilityPhoneNumberArg) (err error) { 123 mctx := libkb.NewMetaContext(ctx, h.G()) 124 defer mctx.Trace("PhoneNumbersHandler#SetVisibilityPhoneNumber", &err)() 125 if err = libkb.IsPossiblePhoneNumber(arg.PhoneNumber); err != nil { 126 return err 127 } 128 129 return phonenumbers.SetVisibilityPhoneNumber(mctx, arg.PhoneNumber, arg.Visibility) 130 } 131 132 func (h *PhoneNumbersHandler) SetVisibilityAllPhoneNumber(ctx context.Context, arg keybase1.SetVisibilityAllPhoneNumberArg) (err error) { 133 mctx := libkb.NewMetaContext(ctx, h.G()) 134 defer mctx.Trace("PhoneNumbersHandler#SetVisibilityAllPhoneNumber", &err)() 135 return phonenumbers.SetVisibilityAllPhoneNumber(mctx, arg.Visibility) 136 } 137 138 const phoneNumbersGregorHandlerName = "phoneHandler" 139 140 type phoneNumbersGregorHandler struct { 141 libkb.Contextified 142 } 143 144 var _ libkb.GregorInBandMessageHandler = (*phoneNumbersGregorHandler)(nil) 145 146 func newPhoneNumbersGregorHandler(g *libkb.GlobalContext) *phoneNumbersGregorHandler { 147 return &phoneNumbersGregorHandler{ 148 Contextified: libkb.NewContextified(g), 149 } 150 } 151 152 func (r *phoneNumbersGregorHandler) Create(ctx context.Context, cli gregor1.IncomingInterface, category string, item gregor.Item) (bool, error) { 153 switch category { 154 case "phone.added", "phone.verified", "phone.superseded", 155 "phone.visibility_changed", "phone.deleted": 156 return true, r.handlePhoneMsg(ctx, cli, category, item) 157 case "phone.unverified_count": 158 // handled in badgestate 159 return true, nil 160 default: 161 if strings.HasPrefix(category, "phone.") { 162 return false, fmt.Errorf("unknown phoneNumbersGregorHandler category: %q", category) 163 } 164 return false, nil 165 } 166 } 167 168 func (r *phoneNumbersGregorHandler) Dismiss(ctx context.Context, cli gregor1.IncomingInterface, category string, item gregor.Item) (bool, error) { 169 return false, nil 170 } 171 172 func (r *phoneNumbersGregorHandler) IsAlive() bool { 173 return true 174 } 175 176 func (r *phoneNumbersGregorHandler) Name() string { 177 return phoneNumbersGregorHandlerName 178 } 179 180 func (r *phoneNumbersGregorHandler) handlePhoneMsg(ctx context.Context, cli gregor1.IncomingInterface, category string, item gregor.Item) error { 181 mctx := libkb.NewMetaContext(ctx, r.G()) 182 mctx.Debug("phoneNumbersGregorHandler: %s received", category) 183 var msg keybase1.PhoneNumberChangedMsg 184 if err := json.Unmarshal(item.Body().Bytes(), &msg); err != nil { 185 mctx.Debug("error unmarshaling %s item: %s", category, err) 186 return err 187 } 188 mctx.Debug("%s unmarshaled: %+v", category, msg) 189 190 phoneNumbers, err := phonenumbers.GetPhoneNumbers(mctx) 191 if err != nil { 192 mctx.Error("Could not get current phone number list during handlePhoneMsg: %s", err) 193 } else { 194 r.G().NotifyRouter.HandlePhoneNumbersChanged(ctx, phoneNumbers, category, msg.PhoneNumber) 195 } 196 // Do not dismiss these notifications so other devices can see it and 197 // update their state as well. 198 return nil 199 }