github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/engine/email_change.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  	"github.com/keybase/client/go/libkb"
     8  	keybase1 "github.com/keybase/client/go/protocol/keybase1"
     9  	jsonw "github.com/keybase/go-jsonw"
    10  )
    11  
    12  // EmailChange is an engine that changes a user's email via signed statement.
    13  type EmailChange struct {
    14  	arg *keybase1.EmailChangeArg
    15  	libkb.Contextified
    16  }
    17  
    18  // NewEmailChange creates a new engine for changing a user's email
    19  // address via signature (and therefore without passphrase required)
    20  func NewEmailChange(g *libkb.GlobalContext, a *keybase1.EmailChangeArg) *EmailChange {
    21  	return &EmailChange{
    22  		arg:          a,
    23  		Contextified: libkb.NewContextified(g),
    24  	}
    25  }
    26  
    27  // Name provides the name of the engine for the engine interface
    28  func (c *EmailChange) Name() string {
    29  	return "EmailChange"
    30  }
    31  
    32  // Prereqs returns engine prereqs
    33  func (c *EmailChange) Prereqs() Prereqs {
    34  	return Prereqs{Device: true}
    35  }
    36  
    37  // RequiredUIs returns the required UIs.
    38  func (c *EmailChange) RequiredUIs() []libkb.UIKind {
    39  	return []libkb.UIKind{
    40  		libkb.SecretUIKind,
    41  	}
    42  }
    43  
    44  // SubConsumers requires the other UI consumers of this engine
    45  func (c *EmailChange) SubConsumers() []libkb.UIConsumer {
    46  	return []libkb.UIConsumer{}
    47  }
    48  
    49  // Run the engine
    50  func (c *EmailChange) Run(m libkb.MetaContext) (err error) {
    51  	defer m.Trace("EmailChange#Run", &err)()
    52  
    53  	if !libkb.CheckEmail.F(c.arg.NewEmail) {
    54  		return libkb.BadEmailError{}
    55  	}
    56  
    57  	var me *libkb.User
    58  	me, err = libkb.LoadMe(libkb.NewLoadUserArgWithMetaContext(m).WithForceReload())
    59  	if err != nil {
    60  		return err
    61  	}
    62  
    63  	// need unlocked signing key
    64  	ska := libkb.SecretKeyArg{
    65  		Me:      me,
    66  		KeyType: libkb.DeviceSigningKeyType,
    67  	}
    68  	arg := m.SecretKeyPromptArg(ska, "tracking signature")
    69  	signingKey, err := m.G().Keyrings.GetSecretKeyWithPrompt(m, arg)
    70  	if err != nil {
    71  		return err
    72  	}
    73  	if signingKey == nil {
    74  		return libkb.NoSecretKeyError{}
    75  	}
    76  	var proof *jsonw.Wrapper
    77  	proof, err = me.UpdateEmailProof(m, signingKey, c.arg.NewEmail)
    78  	if err != nil {
    79  		return err
    80  	}
    81  	var sig string
    82  	sig, _, _, err = libkb.SignJSON(proof, signingKey)
    83  	if err != nil {
    84  		return err
    85  	}
    86  
    87  	_, err = m.G().API.Post(m, libkb.APIArg{
    88  		Endpoint:    "account/email_update_signed",
    89  		SessionType: libkb.APISessionTypeREQUIRED,
    90  		Args: libkb.HTTPArgs{
    91  			"sig":         libkb.S{Val: sig},
    92  			"signing_kid": libkb.S{Val: signingKey.GetKID().String()},
    93  		},
    94  	})
    95  
    96  	if err != nil {
    97  		return err
    98  	}
    99  
   100  	return nil
   101  }