mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-11-23 22:33:31 -06:00
[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
This commit is contained in:
parent
e63b653199
commit
532c4cc697
15 changed files with 541 additions and 16 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue