Email confirmation fix (#1231)

* Email confirmation fix

* Added test for incorrect auth user confirming e-mail change
This commit is contained in:
John Murphy 2017-02-16 21:07:20 +08:00 committed by GitHub
parent b22e41d175
commit c8d284fd3c
6 changed files with 29 additions and 11 deletions

View file

@ -21,13 +21,26 @@ func testChangeEmail(t *testing.T, ds kolide.Datastore) {
require.Nil(t, err) require.Nil(t, err)
err = ds.PendingEmailChange(user.ID, "xxxx@yyy.com", "abcd12345") err = ds.PendingEmailChange(user.ID, "xxxx@yyy.com", "abcd12345")
require.Nil(t, err) require.Nil(t, err)
newMail, err := ds.ConfirmPendingEmailChange("abcd12345") newMail, err := ds.ConfirmPendingEmailChange(user.ID, "abcd12345")
require.Nil(t, err) require.Nil(t, err)
assert.Equal(t, "xxxx@yyy.com", newMail) assert.Equal(t, "xxxx@yyy.com", newMail)
user, err = ds.UserByID(user.ID) user, err = ds.UserByID(user.ID)
require.Nil(t, err) require.Nil(t, err)
assert.Equal(t, "xxxx@yyy.com", user.Email) assert.Equal(t, "xxxx@yyy.com", user.Email)
// this should fail because it doesn't exist // this should fail because it doesn't exist
newMail, err = ds.ConfirmPendingEmailChange("abcd12345") newMail, err = ds.ConfirmPendingEmailChange(user.ID, "abcd12345")
assert.NotNil(t, err) assert.NotNil(t, err)
// test that wrong user can't confirm e-mail change
err = ds.PendingEmailChange(user.ID, "other@bob.com", "uniquetoken")
require.Nil(t, err)
otheruser, err := ds.NewUser(&kolide.User{
Username: "fred",
Password: []byte("supersecret"),
Email: "other@bobcom",
})
require.Nil(t, err)
_, err = ds.ConfirmPendingEmailChange(otheruser.ID, "uniquetoken")
assert.NotNil(t, err)
} }

View file

@ -4,6 +4,6 @@ func (ds *Datastore) PendingEmailChange(uid uint, newEmail, token string) error
panic("deprecated") panic("deprecated")
} }
func (ds *Datastore) ConfirmPendingEmailChange(token string) (string, error) { func (ds *Datastore) ConfirmPendingEmailChange(uid uint, token string) (string, error) {
panic("deprecated") panic("deprecated")
} }

View file

@ -25,7 +25,7 @@ func (ds *Datastore) PendingEmailChange(uid uint, newEmail, token string) error
// ConfirmPendingEmailChange finds email change record, updates user with new email, // ConfirmPendingEmailChange finds email change record, updates user with new email,
// then deletes change record if everything succeeds. // then deletes change record if everything succeeds.
func (ds *Datastore) ConfirmPendingEmailChange(token string) (newEmail string, err error) { func (ds *Datastore) ConfirmPendingEmailChange(id uint, token string) (newEmail string, err error) {
var ( var (
tx *sqlx.Tx tx *sqlx.Tx
success bool // indicates all db operations success if true success bool // indicates all db operations success if true
@ -36,7 +36,7 @@ func (ds *Datastore) ConfirmPendingEmailChange(token string) (newEmail string, e
Token string Token string
NewEmail string `db:"new_email"` NewEmail string `db:"new_email"`
}{} }{}
err = ds.db.Get(&changeRecord, "SELECT * FROM email_changes WHERE token = ?", token) err = ds.db.Get(&changeRecord, "SELECT * FROM email_changes WHERE token = ? AND user_id = ?", token, id)
if err != nil { if err != nil {
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
return "", notFound("email change with token") return "", notFound("email change with token")

View file

@ -24,8 +24,9 @@ type UserStore interface {
// with a link that they can use to confirm the change. // with a link that they can use to confirm the change.
PendingEmailChange(userID uint, newEmail, token string) error PendingEmailChange(userID uint, newEmail, token string) error
// ConfirmPendingEmailChange will confirm new email address identified by token is valid. // ConfirmPendingEmailChange will confirm new email address identified by token is valid.
// The new email will be written to user record. // The new email will be written to user record. userID is the ID of the
ConfirmPendingEmailChange(token string) (string, error) // user whose e-mail is being changed.
ConfirmPendingEmailChange(userID uint, token string) (string, error)
} }
// UserService contains methods for managing a Kolide User. // UserService contains methods for managing a Kolide User.

View file

@ -20,7 +20,7 @@ type SaveUserFunc func(user *kolide.User) error
type PendingEmailChangeFunc func(userID uint, newEmail string, token string) error type PendingEmailChangeFunc func(userID uint, newEmail string, token string) error
type ConfirmPendingEmailChangeFunc func(token string) (string, error) type ConfirmPendingEmailChangeFunc func(userID uint, token string) (string, error)
type UserStore struct { type UserStore struct {
NewUserFunc NewUserFunc NewUserFunc NewUserFunc
@ -83,7 +83,7 @@ func (s *UserStore) PendingEmailChange(userID uint, newEmail string, token strin
return s.PendingEmailChangeFunc(userID, newEmail, token) return s.PendingEmailChangeFunc(userID, newEmail, token)
} }
func (s *UserStore) ConfirmPendingEmailChange(token string) (string, error) { func (s *UserStore) ConfirmPendingEmailChange(userID uint, token string) (string, error) {
s.ConfirmPendingEmailChangeFuncInvoked = true s.ConfirmPendingEmailChangeFuncInvoked = true
return s.ConfirmPendingEmailChangeFunc(token) return s.ConfirmPendingEmailChangeFunc(userID, token)
} }

View file

@ -159,7 +159,11 @@ func (svc service) modifyEmailAddress(ctx context.Context, user *kolide.User, em
} }
func (svc service) ChangeUserEmail(ctx context.Context, token string) (string, error) { func (svc service) ChangeUserEmail(ctx context.Context, token string) (string, error) {
return svc.ds.ConfirmPendingEmailChange(token) vc, ok := viewer.FromContext(ctx)
if !ok {
return "", errNoContext
}
return svc.ds.ConfirmPendingEmailChange(vc.UserID(), token)
} }
func (svc service) User(ctx context.Context, id uint) (*kolide.User, error) { func (svc service) User(ctx context.Context, id uint) (*kolide.User, error) {