summaryrefslogtreecommitdiff
path: root/internal/processing/workers
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/workers
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/workers')
-rw-r--r--internal/processing/workers/fromclientapi.go23
-rw-r--r--internal/processing/workers/fromfediapi.go2
-rw-r--r--internal/processing/workers/surfaceemail.go118
-rw-r--r--internal/processing/workers/surfacenotify.go41
4 files changed, 136 insertions, 48 deletions
diff --git a/internal/processing/workers/fromclientapi.go b/internal/processing/workers/fromclientapi.go
index c7e78fee2..ed513c331 100644
--- a/internal/processing/workers/fromclientapi.go
+++ b/internal/processing/workers/fromclientapi.go
@@ -209,18 +209,23 @@ func (p *Processor) ProcessFromClientAPI(ctx context.Context, cMsg messages.From
}
func (p *clientAPI) CreateAccount(ctx context.Context, cMsg messages.FromClientAPI) error {
- account, ok := cMsg.GTSModel.(*gtsmodel.Account)
+ newUser, ok := cMsg.GTSModel.(*gtsmodel.User)
if !ok {
- return gtserror.Newf("%T not parseable as *gtsmodel.Account", cMsg.GTSModel)
+ return gtserror.Newf("%T not parseable as *gtsmodel.User", cMsg.GTSModel)
+ }
+
+ // Notify mods of the new signup.
+ if err := p.surface.notifySignup(ctx, newUser); err != nil {
+ log.Errorf(ctx, "error notifying mods of new sign-up: %v", err)
}
- // Send a confirmation email to the newly created account.
- user, err := p.state.DB.GetUserByAccountID(ctx, account.ID)
- if err != nil {
- return gtserror.Newf("db error getting user for account id %s: %w", account.ID, err)
+ // Send "new sign up" email to mods.
+ if err := p.surface.emailAdminNewSignup(ctx, newUser); err != nil {
+ log.Errorf(ctx, "error emailing new signup: %v", err)
}
- if err := p.surface.emailPleaseConfirm(ctx, user, account.Username); err != nil {
+ // Send "please confirm your address" email to the new user.
+ if err := p.surface.emailUserPleaseConfirm(ctx, newUser); err != nil {
log.Errorf(ctx, "error emailing confirm: %v", err)
}
@@ -458,7 +463,7 @@ func (p *clientAPI) UpdateReport(ctx context.Context, cMsg messages.FromClientAP
return nil
}
- if err := p.surface.emailReportClosed(ctx, report); err != nil {
+ if err := p.surface.emailUserReportClosed(ctx, report); err != nil {
log.Errorf(ctx, "error emailing report closed: %v", err)
}
@@ -644,7 +649,7 @@ func (p *clientAPI) ReportAccount(ctx context.Context, cMsg messages.FromClientA
}
}
- if err := p.surface.emailReportOpened(ctx, report); err != nil {
+ if err := p.surface.emailAdminReportOpened(ctx, report); err != nil {
log.Errorf(ctx, "error emailing report opened: %v", err)
}
diff --git a/internal/processing/workers/fromfediapi.go b/internal/processing/workers/fromfediapi.go
index 2fc3b4b26..7b0e72490 100644
--- a/internal/processing/workers/fromfediapi.go
+++ b/internal/processing/workers/fromfediapi.go
@@ -473,7 +473,7 @@ func (p *fediAPI) CreateFlag(ctx context.Context, fMsg messages.FromFediAPI) err
// TODO: handle additional side effects of flag creation:
// - notify admins by dm / notification
- if err := p.surface.emailReportOpened(ctx, incomingReport); err != nil {
+ if err := p.surface.emailAdminReportOpened(ctx, incomingReport); err != nil {
log.Errorf(ctx, "error emailing report opened: %v", err)
}
diff --git a/internal/processing/workers/surfaceemail.go b/internal/processing/workers/surfaceemail.go
index a6c97f48f..c00b22c86 100644
--- a/internal/processing/workers/surfaceemail.go
+++ b/internal/processing/workers/surfaceemail.go
@@ -31,41 +31,9 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/uris"
)
-func (s *surface) emailReportOpened(ctx context.Context, report *gtsmodel.Report) error {
- instance, err := s.state.DB.GetInstance(ctx, config.GetHost())
- if err != nil {
- return gtserror.Newf("error getting instance: %w", err)
- }
-
- toAddresses, err := s.state.DB.GetInstanceModeratorAddresses(ctx)
- if err != nil {
- if errors.Is(err, db.ErrNoEntries) {
- // No registered moderator addresses.
- return nil
- }
- return gtserror.Newf("error getting instance moderator addresses: %w", err)
- }
-
- if err := s.state.DB.PopulateReport(ctx, report); err != nil {
- return gtserror.Newf("error populating report: %w", err)
- }
-
- reportData := email.NewReportData{
- InstanceURL: instance.URI,
- InstanceName: instance.Title,
- ReportURL: instance.URI + "/settings/admin/reports/" + report.ID,
- ReportDomain: report.Account.Domain,
- ReportTargetDomain: report.TargetAccount.Domain,
- }
-
- if err := s.emailSender.SendNewReportEmail(toAddresses, reportData); err != nil {
- return gtserror.Newf("error emailing instance moderators: %w", err)
- }
-
- return nil
-}
-
-func (s *surface) emailReportClosed(ctx context.Context, report *gtsmodel.Report) error {
+// emailUserReportClosed emails the user who created the
+// given report, to inform them the report has been closed.
+func (s *surface) emailUserReportClosed(ctx context.Context, report *gtsmodel.Report) error {
user, err := s.state.DB.GetUserByAccountID(ctx, report.Account.ID)
if err != nil {
return gtserror.Newf("db error getting user: %w", err)
@@ -104,7 +72,9 @@ func (s *surface) emailReportClosed(ctx context.Context, report *gtsmodel.Report
return s.emailSender.SendReportClosedEmail(user.Email, reportClosedData)
}
-func (s *surface) emailPleaseConfirm(ctx context.Context, user *gtsmodel.User, username string) error {
+// emailUserPleaseConfirm emails the given user
+// to ask them to confirm their email address.
+func (s *surface) emailUserPleaseConfirm(ctx context.Context, user *gtsmodel.User) error {
if user.UnconfirmedEmail == "" ||
user.UnconfirmedEmail == user.Email {
// User has already confirmed this
@@ -130,7 +100,7 @@ func (s *surface) emailPleaseConfirm(ctx context.Context, user *gtsmodel.User, u
if err := s.emailSender.SendConfirmEmail(
user.UnconfirmedEmail,
email.ConfirmData{
- Username: username,
+ Username: user.Account.Username,
InstanceURL: instance.URI,
InstanceName: instance.Title,
ConfirmLink: confirmLink,
@@ -158,3 +128,77 @@ func (s *surface) emailPleaseConfirm(ctx context.Context, user *gtsmodel.User, u
return nil
}
+
+// emailAdminReportOpened emails all active moderators/admins
+// of this instance that a new report has been created.
+func (s *surface) emailAdminReportOpened(ctx context.Context, report *gtsmodel.Report) error {
+ instance, err := s.state.DB.GetInstance(ctx, config.GetHost())
+ if err != nil {
+ return gtserror.Newf("error getting instance: %w", err)
+ }
+
+ toAddresses, err := s.state.DB.GetInstanceModeratorAddresses(ctx)
+ if err != nil {
+ if errors.Is(err, db.ErrNoEntries) {
+ // No registered moderator addresses.
+ return nil
+ }
+ return gtserror.Newf("error getting instance moderator addresses: %w", err)
+ }
+
+ if err := s.state.DB.PopulateReport(ctx, report); err != nil {
+ return gtserror.Newf("error populating report: %w", err)
+ }
+
+ reportData := email.NewReportData{
+ InstanceURL: instance.URI,
+ InstanceName: instance.Title,
+ ReportURL: instance.URI + "/settings/admin/reports/" + report.ID,
+ ReportDomain: report.Account.Domain,
+ ReportTargetDomain: report.TargetAccount.Domain,
+ }
+
+ if err := s.emailSender.SendNewReportEmail(toAddresses, reportData); err != nil {
+ return gtserror.Newf("error emailing instance moderators: %w", err)
+ }
+
+ return nil
+}
+
+// emailAdminNewSignup emails all active moderators/admins of this
+// instance that a new account sign-up has been submitted to the instance.
+func (s *surface) emailAdminNewSignup(ctx context.Context, newUser *gtsmodel.User) error {
+ instance, err := s.state.DB.GetInstance(ctx, config.GetHost())
+ if err != nil {
+ return gtserror.Newf("error getting instance: %w", err)
+ }
+
+ toAddresses, err := s.state.DB.GetInstanceModeratorAddresses(ctx)
+ if err != nil {
+ if errors.Is(err, db.ErrNoEntries) {
+ // No registered moderator addresses.
+ return nil
+ }
+ return gtserror.Newf("error getting instance moderator addresses: %w", err)
+ }
+
+ // Ensure user populated.
+ if err := s.state.DB.PopulateUser(ctx, newUser); err != nil {
+ return gtserror.Newf("error populating user: %w", err)
+ }
+
+ newSignupData := email.NewSignupData{
+ InstanceURL: instance.URI,
+ InstanceName: instance.Title,
+ SignupEmail: newUser.UnconfirmedEmail,
+ SignupUsername: newUser.Account.Username,
+ SignupReason: newUser.Reason,
+ SignupURL: "TODO",
+ }
+
+ if err := s.emailSender.SendNewSignupEmail(toAddresses, newSignupData); err != nil {
+ return gtserror.Newf("error emailing instance moderators: %w", err)
+ }
+
+ return nil
+}
diff --git a/internal/processing/workers/surfacenotify.go b/internal/processing/workers/surfacenotify.go
index a8c36248c..9c82712f2 100644
--- a/internal/processing/workers/surfacenotify.go
+++ b/internal/processing/workers/surfacenotify.go
@@ -333,6 +333,45 @@ func (s *surface) notifyPollClose(ctx context.Context, status *gtsmodel.Status)
return errs.Combine()
}
+func (s *surface) notifySignup(ctx context.Context, newUser *gtsmodel.User) error {
+ modAccounts, err := s.state.DB.GetInstanceModerators(ctx)
+ if err != nil {
+ if errors.Is(err, db.ErrNoEntries) {
+ // No registered
+ // mod accounts.
+ return nil
+ }
+
+ // Real error.
+ return gtserror.Newf("error getting instance moderator accounts: %w", err)
+ }
+
+ // Ensure user + account populated.
+ if err := s.state.DB.PopulateUser(ctx, newUser); err != nil {
+ return gtserror.Newf("db error populating new user: %w", err)
+ }
+
+ if err := s.state.DB.PopulateAccount(ctx, newUser.Account); err != nil {
+ return gtserror.Newf("db error populating new user's account: %w", err)
+ }
+
+ // Notify each moderator.
+ var errs gtserror.MultiError
+ for _, mod := range modAccounts {
+ if err := s.notify(ctx,
+ gtsmodel.NotificationSignup,
+ mod,
+ newUser.Account,
+ "",
+ ); err != nil {
+ errs.Appendf("error notifying moderator %s: %w", mod.ID, err)
+ continue
+ }
+ }
+
+ return errs.Combine()
+}
+
// notify creates, inserts, and streams a new
// notification to the target account if it
// doesn't yet exist with the given parameters.
@@ -342,7 +381,7 @@ func (s *surface) notifyPollClose(ctx context.Context, status *gtsmodel.Status)
// targets into this function without filtering
// for non-local first.
//
-// targetAccountID and originAccountID must be
+// targetAccount and originAccount must be
// set, but statusID can be an empty string.
func (s *surface) notify(
ctx context.Context,