[chore] reversion: use specific columns for updating user again (#1059)

This commit is contained in:
tobi 2022-11-16 11:27:08 +01:00 committed by GitHub
parent 8598dea98b
commit 940abc279c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 37 additions and 27 deletions

View file

@ -151,8 +151,7 @@
admin := true admin := true
u.Admin = &admin u.Admin = &admin
u.UpdatedAt = time.Now() if err := dbConn.UpdateUser(ctx, u, "admin"); err != nil {
if err := dbConn.UpdateUser(ctx, u); err != nil {
return err return err
} }
@ -186,8 +185,7 @@
admin := false admin := false
u.Admin = &admin u.Admin = &admin
u.UpdatedAt = time.Now() if err := dbConn.UpdateUser(ctx, u, "admin"); err != nil {
if err := dbConn.UpdateUser(ctx, u); err != nil {
return err return err
} }
@ -221,8 +219,7 @@
disabled := true disabled := true
u.Disabled = &disabled u.Disabled = &disabled
u.UpdatedAt = time.Now() if err := dbConn.UpdateUser(ctx, u, "disabled"); err != nil {
if err := dbConn.UpdateUser(ctx, u); err != nil {
return err return err
} }
@ -268,8 +265,7 @@
} }
u.EncryptedPassword = string(pw) u.EncryptedPassword = string(pw)
u.UpdatedAt = time.Now() if err := dbConn.UpdateUser(ctx, u, "encrypted_password"); err != nil {
if err := dbConn.UpdateUser(ctx, u); err != nil {
return err return err
} }

View file

@ -20,7 +20,7 @@ type AuthAuthorizeTestSuite struct {
type authorizeHandlerTestCase struct { type authorizeHandlerTestCase struct {
description string description string
mutateUserAccount func(*gtsmodel.User, *gtsmodel.Account) mutateUserAccount func(*gtsmodel.User, *gtsmodel.Account) []string
expectedStatusCode int expectedStatusCode int
expectedLocationHeader string expectedLocationHeader string
} }
@ -29,40 +29,44 @@ func (suite *AuthAuthorizeTestSuite) TestAccountAuthorizeHandler() {
tests := []authorizeHandlerTestCase{ tests := []authorizeHandlerTestCase{
{ {
description: "user has their email unconfirmed", description: "user has their email unconfirmed",
mutateUserAccount: func(user *gtsmodel.User, account *gtsmodel.Account) { mutateUserAccount: func(user *gtsmodel.User, account *gtsmodel.Account) []string {
// nothing to do, weed_lord420 already has their email unconfirmed user.ConfirmedAt = time.Time{}
return []string{"confirmed_at"}
}, },
expectedStatusCode: http.StatusSeeOther, expectedStatusCode: http.StatusSeeOther,
expectedLocationHeader: auth.CheckYourEmailPath, expectedLocationHeader: auth.CheckYourEmailPath,
}, },
{ {
description: "user has their email confirmed but is not approved", description: "user has their email confirmed but is not approved",
mutateUserAccount: func(user *gtsmodel.User, account *gtsmodel.Account) { mutateUserAccount: func(user *gtsmodel.User, account *gtsmodel.Account) []string {
user.ConfirmedAt = time.Now() user.ConfirmedAt = time.Now()
user.Email = user.UnconfirmedEmail user.Email = user.UnconfirmedEmail
return []string{"confirmed_at", "email"}
}, },
expectedStatusCode: http.StatusSeeOther, expectedStatusCode: http.StatusSeeOther,
expectedLocationHeader: auth.WaitForApprovalPath, expectedLocationHeader: auth.WaitForApprovalPath,
}, },
{ {
description: "user has their email confirmed and is approved, but User entity has been disabled", description: "user has their email confirmed and is approved, but User entity has been disabled",
mutateUserAccount: func(user *gtsmodel.User, account *gtsmodel.Account) { mutateUserAccount: func(user *gtsmodel.User, account *gtsmodel.Account) []string {
user.ConfirmedAt = time.Now() user.ConfirmedAt = time.Now()
user.Email = user.UnconfirmedEmail user.Email = user.UnconfirmedEmail
user.Approved = testrig.TrueBool() user.Approved = testrig.TrueBool()
user.Disabled = testrig.TrueBool() user.Disabled = testrig.TrueBool()
return []string{"confirmed_at", "email", "approved", "disabled"}
}, },
expectedStatusCode: http.StatusSeeOther, expectedStatusCode: http.StatusSeeOther,
expectedLocationHeader: auth.AccountDisabledPath, expectedLocationHeader: auth.AccountDisabledPath,
}, },
{ {
description: "user has their email confirmed and is approved, but Account entity has been suspended", description: "user has their email confirmed and is approved, but Account entity has been suspended",
mutateUserAccount: func(user *gtsmodel.User, account *gtsmodel.Account) { mutateUserAccount: func(user *gtsmodel.User, account *gtsmodel.Account) []string {
user.ConfirmedAt = time.Now() user.ConfirmedAt = time.Now()
user.Email = user.UnconfirmedEmail user.Email = user.UnconfirmedEmail
user.Approved = testrig.TrueBool() user.Approved = testrig.TrueBool()
user.Disabled = testrig.FalseBool() user.Disabled = testrig.FalseBool()
account.SuspendedAt = time.Now() account.SuspendedAt = time.Now()
return []string{"confirmed_at", "email", "approved", "disabled"}
}, },
expectedStatusCode: http.StatusSeeOther, expectedStatusCode: http.StatusSeeOther,
expectedLocationHeader: auth.AccountDisabledPath, expectedLocationHeader: auth.AccountDisabledPath,
@ -77,7 +81,6 @@ func (suite *AuthAuthorizeTestSuite) TestAccountAuthorizeHandler() {
*user = *suite.testUsers["unconfirmed_account"] *user = *suite.testUsers["unconfirmed_account"]
*account = *suite.testAccounts["unconfirmed_account"] *account = *suite.testAccounts["unconfirmed_account"]
user.SignInCount++ // cannot be 0 or fails NULL constraint
testSession := sessions.Default(ctx) testSession := sessions.Default(ctx)
testSession.Set(sessionUserID, user.ID) testSession.Set(sessionUserID, user.ID)
@ -86,11 +89,11 @@ func (suite *AuthAuthorizeTestSuite) TestAccountAuthorizeHandler() {
panic(fmt.Errorf("failed on case %s: %w", testCase.description, err)) panic(fmt.Errorf("failed on case %s: %w", testCase.description, err))
} }
testCase.mutateUserAccount(user, account) columns := testCase.mutateUserAccount(user, account)
testCase.description = fmt.Sprintf("%s, %t, %s", user.Email, *user.Disabled, account.SuspendedAt) testCase.description = fmt.Sprintf("%s, %t, %s", user.Email, *user.Disabled, account.SuspendedAt)
err := suite.db.UpdateUser(context.Background(), user) err := suite.db.UpdateUser(context.Background(), user, columns...)
suite.NoError(err) suite.NoError(err)
err = suite.db.UpdateAccount(context.Background(), account) err = suite.db.UpdateAccount(context.Background(), account)
suite.NoError(err) suite.NoError(err)

View file

@ -133,18 +133,29 @@ func (u *userDB) PutUser(ctx context.Context, user *gtsmodel.User) db.Error {
}) })
} }
func (u *userDB) UpdateUser(ctx context.Context, user *gtsmodel.User) db.Error { func (u *userDB) UpdateUser(ctx context.Context, user *gtsmodel.User, columns ...string) db.Error {
// Update the user's last-updated // Update the user's last-updated
user.UpdatedAt = time.Now() user.UpdatedAt = time.Now()
return u.cache.Store(user, func() error { if len(columns) > 0 {
_, err := u.conn. // If we're updating by column, ensure "updated_at" is included
NewUpdate(). columns = append(columns, "updated_at")
Model(user). }
Where("? = ?", bun.Ident("user.id"), user.ID).
Exec(ctx) // Update the user in DB
_, err := u.conn.
NewUpdate().
Model(user).
Where("? = ?", bun.Ident("user.id"), user.ID).
Column(columns...).
Exec(ctx)
if err != nil {
return u.conn.ProcessError(err) return u.conn.ProcessError(err)
}) }
// Invalidate in cache
u.cache.Invalidate("ID", user.ID)
return nil
} }
func (u *userDB) DeleteUserByID(ctx context.Context, userID string) db.Error { func (u *userDB) DeleteUserByID(ctx context.Context, userID string) db.Error {

View file

@ -36,8 +36,8 @@ type User interface {
GetUserByConfirmationToken(ctx context.Context, confirmationToken string) (*gtsmodel.User, Error) GetUserByConfirmationToken(ctx context.Context, confirmationToken string) (*gtsmodel.User, Error)
// PutUser will attempt to place user in the database // PutUser will attempt to place user in the database
PutUser(ctx context.Context, user *gtsmodel.User) Error PutUser(ctx context.Context, user *gtsmodel.User) Error
// UpdateUser updates one user by its primary key. // UpdateUser updates one user by its primary key, updating either only the specified columns, or all of them.
UpdateUser(ctx context.Context, user *gtsmodel.User) Error UpdateUser(ctx context.Context, user *gtsmodel.User, columns ...string) Error
// DeleteUserByID deletes one user by its ID. // DeleteUserByID deletes one user by its ID.
DeleteUserByID(ctx context.Context, userID string) Error DeleteUserByID(ctx context.Context, userID string) Error
} }