diff --git a/internal/api/identity.go b/internal/api/identity.go index b6301c751..44604d961 100644 --- a/internal/api/identity.go +++ b/internal/api/identity.go @@ -73,6 +73,11 @@ func (a *API) DeleteIdentity(w http.ResponseWriter, r *http.Request) error { if terr := tx.UpdateOnly(user, "phone_confirmed_at"); terr != nil { return apierrors.NewInternalServerError("Database error updating user phone").WithInternalError(terr) } + if terr := user.UpdateUserMetaData(tx, map[string]interface{}{ + "phone_verified": false, + }); terr != nil { + return apierrors.NewInternalServerError("Database error updating user phone metadata").WithInternalError(terr) + } default: if terr := user.UpdateUserEmailFromIdentities(tx); terr != nil { if models.IsUniqueConstraintViolatedError(terr) { diff --git a/internal/api/identity_test.go b/internal/api/identity_test.go index 92151a58c..597079daa 100644 --- a/internal/api/identity_test.go +++ b/internal/api/identity_test.go @@ -208,6 +208,7 @@ func (ts *IdentityTestSuite) TestUnlinkIdentity() { case "phone": require.Equal(ts.T(), "", u.GetPhone()) require.Nil(ts.T(), u.PhoneConfirmedAt) + require.Equal(ts.T(), false, u.UserMetaData["phone_verified"]) case "email": require.Equal(ts.T(), "", u.GetEmail()) require.Nil(ts.T(), u.EmailConfirmedAt) diff --git a/internal/models/user.go b/internal/models/user.go index f88a9729b..e96bb96c9 100644 --- a/internal/models/user.go +++ b/internal/models/user.go @@ -551,6 +551,24 @@ func (u *User) ConfirmPhone(tx *storage.Connection) error { return err } + if err := u.UpdateUserMetaData(tx, map[string]any{ + "phone_verified": true, + }); err != nil { + return err + } + + identity, err := FindIdentityByIdAndProvider(tx, u.ID.String(), "phone") + if err != nil { + if !IsNotFoundError(err) { + return err + } + } else if err := identity.UpdateIdentityData(tx, map[string]interface{}{ + "phone": u.GetPhone(), + "phone_verified": true, + }); err != nil { + return err + } + return ClearAllOneTimeTokensForUser(tx, u.ID) } @@ -633,6 +651,12 @@ func (u *User) ConfirmPhoneChange(tx *storage.Connection) error { return err } + if err := u.UpdateUserMetaData(tx, map[string]interface{}{ + "phone_verified": true, + }); err != nil { + return err + } + identity, err := FindIdentityByIdAndProvider(tx, u.ID.String(), "phone") if err != nil { if IsNotFoundError(err) { diff --git a/internal/models/user_test.go b/internal/models/user_test.go index 502392605..f51f2827b 100644 --- a/internal/models/user_test.go +++ b/internal/models/user_test.go @@ -463,6 +463,32 @@ func (ts *UserTestSuite) TestConfirmPhoneChange() { require.NotNil(ts.T(), identity.IdentityData) require.Equal(ts.T(), identity.IdentityData["phone"], "987654321") + require.Equal(ts.T(), true, user.UserMetaData["phone_verified"]) +} + +func (ts *UserTestSuite) TestConfirmPhone() { + user, err := NewUser("123456789", "", "", "authenticated", map[string]interface{}{ + "phone_verified": false, + }) + require.NoError(ts.T(), err) + require.NoError(ts.T(), ts.db.Create(user)) + + identity, err := NewIdentity(user, "phone", map[string]interface{}{ + "sub": user.ID.String(), + "phone_verified": false, + }) + require.NoError(ts.T(), err) + require.NoError(ts.T(), ts.db.Create(identity)) + + require.NoError(ts.T(), user.ConfirmPhone(ts.db)) + + require.NotNil(ts.T(), user.PhoneConfirmedAt) + require.Equal(ts.T(), true, user.UserMetaData["phone_verified"]) + + identity, err = FindIdentityByIdAndProvider(ts.db, user.ID.String(), "phone") + require.NoError(ts.T(), err) + require.Equal(ts.T(), true, identity.IdentityData["phone_verified"]) + require.Equal(ts.T(), "123456789", identity.IdentityData["phone"]) } func (ts *UserTestSuite) TestUpdateUserEmailSuccess() {