summaryrefslogtreecommitdiff
path: root/internal/processing/user
diff options
context:
space:
mode:
authorLibravatar tobi <31960611+tsmethurst@users.noreply.github.com>2024-04-11 11:45:53 +0200
committerLibravatar GitHub <noreply@github.com>2024-04-11 11:45:53 +0200
commit9fb8a78f91adffd5f4d28df1270e407c25a7a16e (patch)
treed68200744e28d07e75a52bb0c9f6593c86a38a91 /internal/processing/user
parent[performance] massively improved ActivityPub delivery worker efficiency (#2812) (diff)
downloadgotosocial-9fb8a78f91adffd5f4d28df1270e407c25a7a16e.tar.xz
[feature] New user sign-up via web page (#2796)
* [feature] User sign-up form and admin notifs * add chosen + filtered languages to migration * remove stray comment * chosen languages schmosen schmanguages * proper error on local account missing
Diffstat (limited to 'internal/processing/user')
-rw-r--r--internal/processing/user/email.go65
-rw-r--r--internal/processing/user/email_test.go2
2 files changed, 46 insertions, 21 deletions
diff --git a/internal/processing/user/email.go b/internal/processing/user/email.go
index dd2a96ae3..2b27c6c92 100644
--- a/internal/processing/user/email.go
+++ b/internal/processing/user/email.go
@@ -28,53 +28,78 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
)
-var oneWeek = 168 * time.Hour
-
-// EmailConfirm processes an email confirmation request, usually initiated as a result of clicking on a link
-// in a 'confirm your email address' type email.
-func (p *Processor) EmailConfirm(ctx context.Context, token string) (*gtsmodel.User, gtserror.WithCode) {
+// EmailGetUserForConfirmToken retrieves the user (with account) from
+// the database for the given "confirm your email" token string.
+func (p *Processor) EmailGetUserForConfirmToken(ctx context.Context, token string) (*gtsmodel.User, gtserror.WithCode) {
if token == "" {
- return nil, gtserror.NewErrorNotFound(errors.New("no token provided"))
+ err := errors.New("no token provided")
+ return nil, gtserror.NewErrorNotFound(err)
}
user, err := p.state.DB.GetUserByConfirmationToken(ctx, token)
if err != nil {
- if err == db.ErrNoEntries {
- return nil, gtserror.NewErrorNotFound(err)
+ if !errors.Is(err, db.ErrNoEntries) {
+ // Real error.
+ return nil, gtserror.NewErrorInternalError(err)
}
- return nil, gtserror.NewErrorInternalError(err)
+
+ // No user found for this token.
+ return nil, gtserror.NewErrorNotFound(err)
}
if user.Account == nil {
- a, err := p.state.DB.GetAccountByID(ctx, user.AccountID)
+ user.Account, err = p.state.DB.GetAccountByID(ctx, user.AccountID)
if err != nil {
- return nil, gtserror.NewErrorNotFound(err)
+ // We need the account for a local user.
+ return nil, gtserror.NewErrorInternalError(err)
}
- user.Account = a
}
if !user.Account.SuspendedAt.IsZero() {
- return nil, gtserror.NewErrorForbidden(fmt.Errorf("ConfirmEmail: account %s is suspended", user.AccountID))
+ err := fmt.Errorf("account %s is suspended", user.AccountID)
+ return nil, gtserror.NewErrorForbidden(err, err.Error())
+ }
+
+ return user, nil
+}
+
+// EmailConfirm processes an email confirmation request,
+// usually initiated as a result of clicking on a link
+// in a 'confirm your email address' type email.
+func (p *Processor) EmailConfirm(ctx context.Context, token string) (*gtsmodel.User, gtserror.WithCode) {
+ user, errWithCode := p.EmailGetUserForConfirmToken(ctx, token)
+ if errWithCode != nil {
+ return nil, errWithCode
}
- if user.UnconfirmedEmail == "" || user.UnconfirmedEmail == user.Email {
- // no pending email confirmations so just return OK
+ if user.UnconfirmedEmail == "" ||
+ user.UnconfirmedEmail == user.Email {
+ // Confirmed already, just return.
return user, nil
}
+ // Ensure token not expired.
+ const oneWeek = 168 * time.Hour
if user.ConfirmationSentAt.Before(time.Now().Add(-oneWeek)) {
- return nil, gtserror.NewErrorForbidden(errors.New("ConfirmEmail: confirmation token expired"))
+ err := errors.New("confirmation token expired (older than one week)")
+ return nil, gtserror.NewErrorForbidden(err, err.Error())
}
- // mark the user's email address as confirmed + remove the unconfirmed address and the token
- updatingColumns := []string{"email", "unconfirmed_email", "confirmed_at", "confirmation_token", "updated_at"}
+ // Mark the user's email address as confirmed,
+ // and remove the unconfirmed address and the token.
user.Email = user.UnconfirmedEmail
user.UnconfirmedEmail = ""
user.ConfirmedAt = time.Now()
user.ConfirmationToken = ""
- user.UpdatedAt = time.Now()
- if err := p.state.DB.UpdateByID(ctx, user, user.ID, updatingColumns...); err != nil {
+ if err := p.state.DB.UpdateUser(
+ ctx,
+ user,
+ "email",
+ "unconfirmed_email",
+ "confirmed_at",
+ "confirmation_token",
+ ); err != nil {
return nil, gtserror.NewErrorInternalError(err)
}
diff --git a/internal/processing/user/email_test.go b/internal/processing/user/email_test.go
index b42446991..23d448a84 100644
--- a/internal/processing/user/email_test.go
+++ b/internal/processing/user/email_test.go
@@ -76,7 +76,7 @@ func (suite *EmailConfirmTestSuite) TestConfirmEmailOldToken() {
// confirm with the token set above
updatedUser, errWithCode := suite.user.EmailConfirm(ctx, "1d1aa44b-afa4-49c8-ac4b-eceb61715cc6")
suite.Nil(updatedUser)
- suite.EqualError(errWithCode, "ConfirmEmail: confirmation token expired")
+ suite.EqualError(errWithCode, "confirmation token expired (older than one week)")
}
func TestEmailConfirmTestSuite(t *testing.T) {