diff options
author | 2022-03-15 16:12:35 +0100 | |
---|---|---|
committer | 2022-03-15 16:12:35 +0100 | |
commit | 532c4cc6978a7fe707373106eebade237c89693a (patch) | |
tree | 937bf0a44ef2a8d8d366786693decf2c65b20db5 /internal/processing/account | |
parent | [performance] Add dereference shortcuts to avoid making http calls to self (#... (diff) | |
download | gotosocial-532c4cc6978a7fe707373106eebade237c89693a.tar.xz |
[feature] Federate local account deletion (#431)
* add account delete to API
* model account delete request
* add AccountDeleteLocal
* federate local account deletes
* add DeleteLocal
* update transport (controller) to allow shortcuts
* delete logic + testing
* update swagger docs
* more tests + fixes
Diffstat (limited to 'internal/processing/account')
-rw-r--r-- | internal/processing/account/account.go | 5 | ||||
-rw-r--r-- | internal/processing/account/delete.go | 53 |
2 files changed, 54 insertions, 4 deletions
diff --git a/internal/processing/account/account.go b/internal/processing/account/account.go index b2321f414..c670ee24a 100644 --- a/internal/processing/account/account.go +++ b/internal/processing/account/account.go @@ -42,7 +42,10 @@ type Processor interface { Create(ctx context.Context, applicationToken oauth2.TokenInfo, application *gtsmodel.Application, form *apimodel.AccountCreateRequest) (*apimodel.Token, error) // Delete deletes an account, and all of that account's statuses, media, follows, notifications, etc etc etc. // The origin passed here should be either the ID of the account doing the delete (can be itself), or the ID of a domain block. - Delete(ctx context.Context, account *gtsmodel.Account, origin string) error + Delete(ctx context.Context, account *gtsmodel.Account, origin string) gtserror.WithCode + // DeleteLocal is like delete, but specifically for deletion of local accounts rather than federated ones. + // Unlike Delete, it will propagate the deletion out across the federating API to other instances. + DeleteLocal(ctx context.Context, account *gtsmodel.Account, form *apimodel.AccountDeleteRequest) gtserror.WithCode // Get processes the given request for account information. Get(ctx context.Context, requestingAccount *gtsmodel.Account, targetAccountID string) (*apimodel.Account, error) // Update processes the update of an account with the given form diff --git a/internal/processing/account/delete.go b/internal/processing/account/delete.go index 44429822e..d15c4858c 100644 --- a/internal/processing/account/delete.go +++ b/internal/processing/account/delete.go @@ -20,13 +20,17 @@ package account import ( "context" + "errors" "time" "github.com/sirupsen/logrus" "github.com/superseriousbusiness/gotosocial/internal/ap" + apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" "github.com/superseriousbusiness/gotosocial/internal/db" + "github.com/superseriousbusiness/gotosocial/internal/gtserror" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" "github.com/superseriousbusiness/gotosocial/internal/messages" + "golang.org/x/crypto/bcrypt" ) // Delete handles the complete deletion of an account. @@ -50,7 +54,7 @@ import ( // 16. Delete account's user // 17. Delete account's timeline // 18. Delete account itself -func (p *processor) Delete(ctx context.Context, account *gtsmodel.Account, origin string) error { +func (p *processor) Delete(ctx context.Context, account *gtsmodel.Account, origin string) gtserror.WithCode { fields := logrus.Fields{ "func": "Delete", "username": account.Username, @@ -256,7 +260,7 @@ selectStatusesLoop: // 16. Delete account's user l.Debug("deleting account user") if err := p.db.DeleteWhere(ctx, []db.Where{{Key: "account_id", Value: account.ID}}, >smodel.User{}); err != nil { - return err + return gtserror.NewErrorInternalError(err) } // 17. Delete account's timeline @@ -282,9 +286,52 @@ selectStatusesLoop: account, err := p.db.UpdateAccount(ctx, account) if err != nil { - return err + return gtserror.NewErrorInternalError(err) } l.Infof("deleted account with username %s from domain %s", account.Username, account.Domain) return nil } + +func (p *processor) DeleteLocal(ctx context.Context, account *gtsmodel.Account, form *apimodel.AccountDeleteRequest) gtserror.WithCode { + fromClientAPIMessage := messages.FromClientAPI{ + APObjectType: ap.ActorPerson, + APActivityType: ap.ActivityDelete, + TargetAccount: account, + } + + if form.DeleteOriginID == account.ID { + // the account owner themself has requested deletion via the API, get their user from the db + user := >smodel.User{} + if err := p.db.GetWhere(ctx, []db.Where{{Key: "account_id", Value: account.ID}}, user); err != nil { + return gtserror.NewErrorInternalError(err) + } + + // now check that the password they supplied is correct + // make sure a password is actually set and bail if not + if user.EncryptedPassword == "" { + return gtserror.NewErrorForbidden(errors.New("user password was not set")) + } + + // compare the provided password with the encrypted one from the db, bail if they don't match + if err := bcrypt.CompareHashAndPassword([]byte(user.EncryptedPassword), []byte(form.Password)); err != nil { + return gtserror.NewErrorForbidden(errors.New("invalid password")) + } + + fromClientAPIMessage.OriginAccount = account + } else { + // the delete has been requested by some other account, grab it; + // if we've reached this point we know it has permission already + requestingAccount, err := p.db.GetAccountByID(ctx, form.DeleteOriginID) + if err != nil { + return gtserror.NewErrorInternalError(err) + } + + fromClientAPIMessage.OriginAccount = requestingAccount + } + + // put the delete in the processor queue to handle the rest of it asynchronously + p.fromClientAPI <- fromClientAPIMessage + + return nil +} |