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  }