mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-12-18 22:53:00 -06:00
progress on delete account
This commit is contained in:
parent
5bf7b46cf4
commit
c2db321861
3 changed files with 170 additions and 49 deletions
|
|
@ -18,28 +18,104 @@
|
||||||
|
|
||||||
package account
|
package account
|
||||||
|
|
||||||
import "github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
import (
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||||
|
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||||
|
"github.com/superseriousbusiness/gotosocial/internal/oauth"
|
||||||
|
)
|
||||||
|
|
||||||
func (p *processor) Delete(account *gtsmodel.Account) error {
|
func (p *processor) Delete(account *gtsmodel.Account) error {
|
||||||
|
l := p.log.WithFields(logrus.Fields{
|
||||||
|
"func": "Delete",
|
||||||
|
"username": account.Username,
|
||||||
|
})
|
||||||
|
|
||||||
|
l.Debug("beginning account delete process")
|
||||||
|
|
||||||
// TODO in this function:
|
// TODO in this function:
|
||||||
// 1. Delete account's application(s), clients, and oauth tokens
|
// 1. Delete account's application(s), clients, and oauth tokens
|
||||||
// 2. Delete account's blocks
|
// 2. Delete account's blocks
|
||||||
// 3. Delete account's emoji
|
// 3. Delete account's emoji
|
||||||
// 4. Delete account's follow requests
|
// 4. Delete account's follow requests
|
||||||
// 5. Delete account's follows
|
// 5. Delete account's follows
|
||||||
// 6. Delete account's follow requests
|
// 6. Delete account's media attachments
|
||||||
// 7. Delete account's media attachments
|
// 7. Delete account's mentions
|
||||||
// 8. Delete account's mentions
|
// 8. Delete account's notifications
|
||||||
// 9. Delete account's notifications
|
// 9. Delete account's polls
|
||||||
// 10. Delete account's polls
|
// 10. Delete account's statuses
|
||||||
// 11. Delete account's statuses
|
// 11. Delete account's bookmarks
|
||||||
// 12. Delete account's bookmarks
|
// 12. Delete account's faves
|
||||||
// 13. Delete account's faves
|
// 13. Delete account's mutes
|
||||||
// 14. Delete account's mutes
|
// 14. Delete account's streams
|
||||||
// 15. Delete account's streams
|
// 15. Delete account's tags
|
||||||
// 16. Delete account's tags
|
// 16. Delete account's user
|
||||||
// 17. Delete account's user
|
// 17. Delete account's timeline
|
||||||
// 18. Delete account's timeline
|
// 18. Delete account itself
|
||||||
|
|
||||||
|
// 1. Delete account's application(s), clients, and oauth tokens
|
||||||
|
// we only need to do this step for local account since remote ones won't have any tokens or applications on our server
|
||||||
|
if account.Domain == "" {
|
||||||
|
// see if we can get a user for this account
|
||||||
|
u := >smodel.User{}
|
||||||
|
if err := p.db.GetWhere([]db.Where{{Key: "account_id", Value: account.ID}}, u); err == nil {
|
||||||
|
// we got one! select all tokens with the user's ID
|
||||||
|
tokens := []*oauth.Token{}
|
||||||
|
if err := p.db.GetWhere([]db.Where{{Key: "user_id", Value: u.ID}}, &tokens); err == nil {
|
||||||
|
// we have some tokens to delete
|
||||||
|
for _, t := range tokens {
|
||||||
|
// delete client(s) associated with this token
|
||||||
|
if err := p.db.DeleteByID(t.ClientID, &oauth.Client{}); err != nil {
|
||||||
|
l.Errorf("error deleting oauth client: %s", err)
|
||||||
|
}
|
||||||
|
// delete application(s) associated with this token
|
||||||
|
if err := p.db.DeleteWhere([]db.Where{{Key: "client_id", Value: t.ClientID}}, >smodel.Application{}); err != nil {
|
||||||
|
l.Errorf("error deleting application: %s", err)
|
||||||
|
}
|
||||||
|
// delete the token itself
|
||||||
|
if err := p.db.DeleteByID(t.ID, t); err != nil {
|
||||||
|
l.Errorf("error deleting oauth token: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Delete account's blocks
|
||||||
|
// first delete any blocks that this account created
|
||||||
|
if err := p.db.DeleteWhere([]db.Where{{Key: "account_id", Value: account.ID}}, &[]*gtsmodel.Block{}); err != nil {
|
||||||
|
l.Errorf("error deleting blocks created by account: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// now delete any blocks that target this account
|
||||||
|
if err := p.db.DeleteWhere([]db.Where{{Key: "target_account_id", Value: account.ID}}, &[]*gtsmodel.Block{}); err != nil {
|
||||||
|
l.Errorf("error deleting blocks targeting account: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Delete account's emoji
|
||||||
|
// nothing to do here
|
||||||
|
|
||||||
|
// 4. Delete account's follow requests
|
||||||
|
// first delete any follow requests that this account created
|
||||||
|
if err := p.db.DeleteWhere([]db.Where{{Key: "account_id", Value: account.ID}}, &[]*gtsmodel.FollowRequest{}); err != nil {
|
||||||
|
l.Errorf("error deleting follow requests created by account: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// now delete any follow requests that target this account
|
||||||
|
if err := p.db.DeleteWhere([]db.Where{{Key: "target_account_id", Value: account.ID}}, &[]*gtsmodel.FollowRequest{}); err != nil {
|
||||||
|
l.Errorf("error deleting follow requests targeting account: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. Delete account's follows
|
||||||
|
// first delete any follows that this account created
|
||||||
|
if err := p.db.DeleteWhere([]db.Where{{Key: "account_id", Value: account.ID}}, &[]*gtsmodel.Follow{}); err != nil {
|
||||||
|
l.Errorf("error deleting follows created by account: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// now delete any follows that target this account
|
||||||
|
if err := p.db.DeleteWhere([]db.Where{{Key: "target_account_id", Value: account.ID}}, &[]*gtsmodel.Follow{}); err != nil {
|
||||||
|
l.Errorf("error deleting follows targeting account: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ func (f *filter) StatusVisible(targetStatus *gtsmodel.Status, requestingAccount
|
||||||
return false, fmt.Errorf("error pulling relevant accounts for status %s: %s", targetStatus.ID, err)
|
return false, fmt.Errorf("error pulling relevant accounts for status %s: %s", targetStatus.ID, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
domainBlocked, err := f.blockedRelevant(relevantAccounts)
|
domainBlocked, err := f.domainBlockedRelevant(relevantAccounts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Debugf("error checking domain block: %s", err)
|
l.Debugf("error checking domain block: %s", err)
|
||||||
return false, fmt.Errorf("error checking domain block: %s", err)
|
return false, fmt.Errorf("error checking domain block: %s", err)
|
||||||
|
|
@ -134,8 +134,8 @@ func (f *filter) StatusVisible(targetStatus *gtsmodel.Status, requestingAccount
|
||||||
}
|
}
|
||||||
|
|
||||||
// status boosts accounts id
|
// status boosts accounts id
|
||||||
if relevantAccounts.BoostedAccount != nil {
|
if relevantAccounts.BoostedStatusAuthor != nil {
|
||||||
if blocked, err := f.db.Blocked(relevantAccounts.BoostedAccount.ID, requestingAccount.ID); err != nil {
|
if blocked, err := f.db.Blocked(relevantAccounts.BoostedStatusAuthor.ID, requestingAccount.ID); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
} else if blocked {
|
} else if blocked {
|
||||||
l.Trace("a block exists between requesting account and boosted account")
|
l.Trace("a block exists between requesting account and boosted account")
|
||||||
|
|
@ -163,6 +163,16 @@ func (f *filter) StatusVisible(targetStatus *gtsmodel.Status, requestingAccount
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// boost mentions accounts
|
||||||
|
for _, a := range relevantAccounts.BoostedMentionedAccounts {
|
||||||
|
if blocked, err := f.db.Blocked(a.ID, requestingAccount.ID); err != nil {
|
||||||
|
return false, err
|
||||||
|
} else if blocked {
|
||||||
|
l.Trace("a block exists between requesting account and a boosted mentioned account")
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// if the requesting account is mentioned in the status it should always be visible
|
// if the requesting account is mentioned in the status it should always be visible
|
||||||
for _, acct := range relevantAccounts.MentionedAccounts {
|
for _, acct := range relevantAccounts.MentionedAccounts {
|
||||||
if acct.ID == requestingAccount.ID {
|
if acct.ID == requestingAccount.ID {
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import (
|
||||||
func (f *filter) pullRelevantAccountsFromStatus(targetStatus *gtsmodel.Status) (*relevantAccounts, error) {
|
func (f *filter) pullRelevantAccountsFromStatus(targetStatus *gtsmodel.Status) (*relevantAccounts, error) {
|
||||||
accounts := &relevantAccounts{
|
accounts := &relevantAccounts{
|
||||||
MentionedAccounts: []*gtsmodel.Account{},
|
MentionedAccounts: []*gtsmodel.Account{},
|
||||||
|
BoostedMentionedAccounts: []*gtsmodel.Account{},
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the author account
|
// get the author account
|
||||||
|
|
@ -31,29 +32,6 @@ func (f *filter) pullRelevantAccountsFromStatus(targetStatus *gtsmodel.Status) (
|
||||||
accounts.ReplyToAccount = repliedToAccount
|
accounts.ReplyToAccount = repliedToAccount
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the boosted account from the status and add it to the pile
|
|
||||||
if targetStatus.BoostOfID != "" {
|
|
||||||
// retrieve the boosted status first
|
|
||||||
boostedStatus := >smodel.Status{}
|
|
||||||
if err := f.db.GetByID(targetStatus.BoostOfID, boostedStatus); err != nil {
|
|
||||||
return accounts, fmt.Errorf("PullRelevantAccountsFromStatus: error getting boostedStatus with id %s: %s", targetStatus.BoostOfID, err)
|
|
||||||
}
|
|
||||||
boostedAccount := >smodel.Account{}
|
|
||||||
if err := f.db.GetByID(boostedStatus.AccountID, boostedAccount); err != nil {
|
|
||||||
return accounts, fmt.Errorf("PullRelevantAccountsFromStatus: error getting boostedAccount with id %s: %s", boostedStatus.AccountID, err)
|
|
||||||
}
|
|
||||||
accounts.BoostedAccount = boostedAccount
|
|
||||||
|
|
||||||
// the boosted status might be a reply to another account so we should get that too
|
|
||||||
if boostedStatus.InReplyToAccountID != "" {
|
|
||||||
boostedStatusRepliedToAccount := >smodel.Account{}
|
|
||||||
if err := f.db.GetByID(boostedStatus.InReplyToAccountID, boostedStatusRepliedToAccount); err != nil {
|
|
||||||
return accounts, fmt.Errorf("PullRelevantAccountsFromStatus: error getting boostedStatusRepliedToAccount with id %s: %s", boostedStatus.InReplyToAccountID, err)
|
|
||||||
}
|
|
||||||
accounts.BoostedReplyToAccount = boostedStatusRepliedToAccount
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// now get all accounts with IDs that are mentioned in the status
|
// now get all accounts with IDs that are mentioned in the status
|
||||||
for _, mentionID := range targetStatus.Mentions {
|
for _, mentionID := range targetStatus.Mentions {
|
||||||
|
|
||||||
|
|
@ -69,16 +47,60 @@ func (f *filter) pullRelevantAccountsFromStatus(targetStatus *gtsmodel.Status) (
|
||||||
accounts.MentionedAccounts = append(accounts.MentionedAccounts, mentionedAccount)
|
accounts.MentionedAccounts = append(accounts.MentionedAccounts, mentionedAccount)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get the boosted account from the status and add it to the pile
|
||||||
|
if targetStatus.BoostOfID != "" {
|
||||||
|
// retrieve the boosted status first
|
||||||
|
boostedStatus := >smodel.Status{}
|
||||||
|
if err := f.db.GetByID(targetStatus.BoostOfID, boostedStatus); err != nil {
|
||||||
|
return accounts, fmt.Errorf("PullRelevantAccountsFromStatus: error getting boostedStatus with id %s: %s", targetStatus.BoostOfID, err)
|
||||||
|
}
|
||||||
|
boostedAccount := >smodel.Account{}
|
||||||
|
if err := f.db.GetByID(boostedStatus.AccountID, boostedAccount); err != nil {
|
||||||
|
return accounts, fmt.Errorf("PullRelevantAccountsFromStatus: error getting boostedAccount with id %s: %s", boostedStatus.AccountID, err)
|
||||||
|
}
|
||||||
|
accounts.BoostedStatusAuthor = boostedAccount
|
||||||
|
|
||||||
|
// the boosted status might be a reply to another account so we should get that too
|
||||||
|
if boostedStatus.InReplyToAccountID != "" {
|
||||||
|
boostedStatusRepliedToAccount := >smodel.Account{}
|
||||||
|
if err := f.db.GetByID(boostedStatus.InReplyToAccountID, boostedStatusRepliedToAccount); err != nil {
|
||||||
|
return accounts, fmt.Errorf("PullRelevantAccountsFromStatus: error getting boostedStatusRepliedToAccount with id %s: %s", boostedStatus.InReplyToAccountID, err)
|
||||||
|
}
|
||||||
|
accounts.BoostedReplyToAccount = boostedStatusRepliedToAccount
|
||||||
|
}
|
||||||
|
|
||||||
|
// now get all accounts with IDs that are mentioned in the status
|
||||||
|
for _, mentionID := range boostedStatus.Mentions {
|
||||||
|
mention := >smodel.Mention{}
|
||||||
|
if err := f.db.GetByID(mentionID, mention); err != nil {
|
||||||
|
return accounts, fmt.Errorf("PullRelevantAccountsFromStatus: error getting boosted mention with id %s: %s", mentionID, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
mentionedAccount := >smodel.Account{}
|
||||||
|
if err := f.db.GetByID(mention.TargetAccountID, mentionedAccount); err != nil {
|
||||||
|
return accounts, fmt.Errorf("PullRelevantAccountsFromStatus: error getting boosted mentioned account: %s", err)
|
||||||
|
}
|
||||||
|
accounts.BoostedMentionedAccounts = append(accounts.BoostedMentionedAccounts, mentionedAccount)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return accounts, nil
|
return accounts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// relevantAccounts denotes accounts that are replied to, boosted by, or mentioned in a status.
|
// relevantAccounts denotes accounts that are replied to, boosted by, or mentioned in a status.
|
||||||
type relevantAccounts struct {
|
type relevantAccounts struct {
|
||||||
|
// Who wrote the status
|
||||||
StatusAuthor *gtsmodel.Account
|
StatusAuthor *gtsmodel.Account
|
||||||
|
// Who is the status replying to
|
||||||
ReplyToAccount *gtsmodel.Account
|
ReplyToAccount *gtsmodel.Account
|
||||||
BoostedAccount *gtsmodel.Account
|
// Which accounts are mentioned (tagged) in the status
|
||||||
BoostedReplyToAccount *gtsmodel.Account
|
|
||||||
MentionedAccounts []*gtsmodel.Account
|
MentionedAccounts []*gtsmodel.Account
|
||||||
|
// Who authed the boosted status
|
||||||
|
BoostedStatusAuthor *gtsmodel.Account
|
||||||
|
// If the boosted status replies to another account, who does it reply to?
|
||||||
|
BoostedReplyToAccount *gtsmodel.Account
|
||||||
|
// Who is mentioned (tagged) in the boosted status
|
||||||
|
BoostedMentionedAccounts []*gtsmodel.Account
|
||||||
}
|
}
|
||||||
|
|
||||||
// blockedDomain checks whether the given domain is blocked by us or not
|
// blockedDomain checks whether the given domain is blocked by us or not
|
||||||
|
|
@ -99,9 +121,12 @@ func (f *filter) blockedDomain(host string) (bool, error) {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// blockedRelevant checks through all relevant accounts attached to a status
|
// domainBlockedRelevant checks through all relevant accounts attached to a status
|
||||||
// to make sure none of them are domain blocked by this instance.
|
// to make sure none of them are domain blocked by this instance.
|
||||||
func (f *filter) blockedRelevant(r *relevantAccounts) (bool, error) {
|
//
|
||||||
|
// Will return true+nil if there's a block, false+nil if there's no block, or
|
||||||
|
// an error if something goes wrong.
|
||||||
|
func (f *filter) domainBlockedRelevant(r *relevantAccounts) (bool, error) {
|
||||||
if r.StatusAuthor != nil {
|
if r.StatusAuthor != nil {
|
||||||
b, err := f.blockedDomain(r.StatusAuthor.Domain)
|
b, err := f.blockedDomain(r.StatusAuthor.Domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -122,8 +147,18 @@ func (f *filter) blockedRelevant(r *relevantAccounts) (bool, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.BoostedAccount != nil {
|
for _, a := range r.MentionedAccounts {
|
||||||
b, err := f.blockedDomain(r.BoostedAccount.Domain)
|
b, err := f.blockedDomain(a.Domain)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if b {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.BoostedStatusAuthor != nil {
|
||||||
|
b, err := f.blockedDomain(r.BoostedStatusAuthor.Domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
@ -142,7 +177,7 @@ func (f *filter) blockedRelevant(r *relevantAccounts) (bool, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, a := range r.MentionedAccounts {
|
for _, a := range r.BoostedMentionedAccounts {
|
||||||
b, err := f.blockedDomain(a.Domain)
|
b, err := f.blockedDomain(a.Domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue