diff options
Diffstat (limited to 'internal/federation/federating_db.go')
-rw-r--r-- | internal/federation/federating_db.go | 205 |
1 files changed, 165 insertions, 40 deletions
diff --git a/internal/federation/federating_db.go b/internal/federation/federating_db.go index 8f203e132..af685904a 100644 --- a/internal/federation/federating_db.go +++ b/internal/federation/federating_db.go @@ -241,6 +241,40 @@ func (f *federatingDB) Owns(c context.Context, id *url.URL) (bool, error) { return true, nil } + if util.IsFollowersPath(id) { + username, err := util.ParseFollowersPath(id) + if err != nil { + return false, fmt.Errorf("error parsing statuses path for url %s: %s", id.String(), err) + } + if err := f.db.GetLocalAccountByUsername(username, >smodel.Account{}); err != nil { + if _, ok := err.(db.ErrNoEntries); ok { + // there are no entries for this username + return false, nil + } + // an actual error happened + return false, fmt.Errorf("database error fetching account with username %s: %s", username, err) + } + l.Debug("we DO own this") + return true, nil + } + + if util.IsFollowingPath(id) { + username, err := util.ParseFollowingPath(id) + if err != nil { + return false, fmt.Errorf("error parsing statuses path for url %s: %s", id.String(), err) + } + if err := f.db.GetLocalAccountByUsername(username, >smodel.Account{}); err != nil { + if _, ok := err.(db.ErrNoEntries); ok { + // there are no entries for this username + return false, nil + } + // an actual error happened + return false, fmt.Errorf("database error fetching account with username %s: %s", username, err) + } + l.Debug("we DO own this") + return true, nil + } + return false, fmt.Errorf("could not match activityID: %s", id.String()) } @@ -502,6 +536,15 @@ func (f *federatingDB) Update(ctx context.Context, asType vocab.Type) error { l.Error("receiving account was set on context but couldn't be parsed") } + requestingAcctI := ctx.Value(util.APRequestingAccount) + if receivingAcctI == nil { + l.Error("requesting account wasn't set on context") + } + requestingAcct, ok := requestingAcctI.(*gtsmodel.Account) + if !ok { + l.Error("requesting account was set on context but couldn't be parsed") + } + fromFederatorChanI := ctx.Value(util.APFromFederatorChanKey) if fromFederatorChanI == nil { l.Error("from federator channel wasn't set on context") @@ -511,51 +554,76 @@ func (f *federatingDB) Update(ctx context.Context, asType vocab.Type) error { l.Error("from federator channel was set on context but couldn't be parsed") } - switch asType.GetTypeName() { - case gtsmodel.ActivityStreamsUpdate: - update, ok := asType.(vocab.ActivityStreamsCreate) - if !ok { - return errors.New("could not convert type to create") + typeName := asType.GetTypeName() + if typeName == gtsmodel.ActivityStreamsApplication || + typeName == gtsmodel.ActivityStreamsGroup || + typeName == gtsmodel.ActivityStreamsOrganization || + typeName == gtsmodel.ActivityStreamsPerson || + typeName == gtsmodel.ActivityStreamsService { + // it's an UPDATE to some kind of account + var accountable typeutils.Accountable + + switch asType.GetTypeName() { + case gtsmodel.ActivityStreamsApplication: + l.Debug("got update for APPLICATION") + i, ok := asType.(vocab.ActivityStreamsApplication) + if !ok { + return errors.New("could not convert type to application") + } + accountable = i + case gtsmodel.ActivityStreamsGroup: + l.Debug("got update for GROUP") + i, ok := asType.(vocab.ActivityStreamsGroup) + if !ok { + return errors.New("could not convert type to group") + } + accountable = i + case gtsmodel.ActivityStreamsOrganization: + l.Debug("got update for ORGANIZATION") + i, ok := asType.(vocab.ActivityStreamsOrganization) + if !ok { + return errors.New("could not convert type to organization") + } + accountable = i + case gtsmodel.ActivityStreamsPerson: + l.Debug("got update for PERSON") + i, ok := asType.(vocab.ActivityStreamsPerson) + if !ok { + return errors.New("could not convert type to person") + } + accountable = i + case gtsmodel.ActivityStreamsService: + l.Debug("got update for SERVICE") + i, ok := asType.(vocab.ActivityStreamsService) + if !ok { + return errors.New("could not convert type to service") + } + accountable = i } - object := update.GetActivityStreamsObject() - for objectIter := object.Begin(); objectIter != object.End(); objectIter = objectIter.Next() { - switch objectIter.GetType().GetTypeName() { - case string(gtsmodel.ActivityStreamsPerson): - person := objectIter.GetActivityStreamsPerson() - updatedAcct, err := f.typeConverter.ASRepresentationToAccount(person) - if err != nil { - return fmt.Errorf("error converting person to account: %s", err) - } - if err := f.db.Put(updatedAcct); err != nil { - return fmt.Errorf("database error inserting updated account: %s", err) - } - fromFederatorChan <- gtsmodel.FromFederator{ - APObjectType: gtsmodel.ActivityStreamsProfile, - APActivityType: gtsmodel.ActivityStreamsUpdate, - GTSModel: updatedAcct, - ReceivingAccount: receivingAcct, - } + updatedAcct, err := f.typeConverter.ASRepresentationToAccount(accountable, true) + if err != nil { + return fmt.Errorf("error converting to account: %s", err) + } - case string(gtsmodel.ActivityStreamsApplication): - application := objectIter.GetActivityStreamsApplication() - updatedAcct, err := f.typeConverter.ASRepresentationToAccount(application) - if err != nil { - return fmt.Errorf("error converting person to account: %s", err) - } - if err := f.db.Put(updatedAcct); err != nil { - return fmt.Errorf("database error inserting updated account: %s", err) - } + if requestingAcct.URI != updatedAcct.URI { + return fmt.Errorf("update for account %s was requested by account %s, this is not valid", updatedAcct.URI, requestingAcct.URI) + } - fromFederatorChan <- gtsmodel.FromFederator{ - APObjectType: gtsmodel.ActivityStreamsProfile, - APActivityType: gtsmodel.ActivityStreamsUpdate, - GTSModel: updatedAcct, - ReceivingAccount: receivingAcct, - } - } + updatedAcct.ID = requestingAcct.ID // set this here so the db will update properly instead of trying to PUT this and getting constraint issues + if err := f.db.UpdateByID(requestingAcct.ID, updatedAcct); err != nil { + return fmt.Errorf("database error inserting updated account: %s", err) + } + + fromFederatorChan <- gtsmodel.FromFederator{ + APObjectType: gtsmodel.ActivityStreamsProfile, + APActivityType: gtsmodel.ActivityStreamsUpdate, + GTSModel: updatedAcct, + ReceivingAccount: receivingAcct, } + } + return nil } @@ -565,7 +633,7 @@ func (f *federatingDB) Update(ctx context.Context, asType vocab.Type) error { // Protocol instead call Update to create a Tombstone. // // The library makes this call only after acquiring a lock first. -func (f *federatingDB) Delete(c context.Context, id *url.URL) error { +func (f *federatingDB) Delete(ctx context.Context, id *url.URL) error { l := f.log.WithFields( logrus.Fields{ "func": "Delete", @@ -573,6 +641,63 @@ func (f *federatingDB) Delete(c context.Context, id *url.URL) error { }, ) l.Debugf("received DELETE id %s", id.String()) + + inboxAcctI := ctx.Value(util.APAccount) + if inboxAcctI == nil { + l.Error("inbox account wasn't set on context") + return nil + } + inboxAcct, ok := inboxAcctI.(*gtsmodel.Account) + if !ok { + l.Error("inbox account was set on context but couldn't be parsed") + return nil + } + + fromFederatorChanI := ctx.Value(util.APFromFederatorChanKey) + if fromFederatorChanI == nil { + l.Error("from federator channel wasn't set on context") + return nil + } + fromFederatorChan, ok := fromFederatorChanI.(chan gtsmodel.FromFederator) + if !ok { + l.Error("from federator channel was set on context but couldn't be parsed") + return nil + } + + // in a delete we only get the URI, we can't know if we have a status or a profile or something else, + // so we have to try a few different things... + where := []db.Where{{Key: "uri", Value: id.String()}} + + s := >smodel.Status{} + if err := f.db.GetWhere(where, s); err == nil { + // it's a status + l.Debugf("uri is for status with id: %s", s.ID) + if err := f.db.DeleteByID(s.ID, >smodel.Status{}); err != nil { + return fmt.Errorf("Delete: err deleting status: %s", err) + } + fromFederatorChan <- gtsmodel.FromFederator{ + APObjectType: gtsmodel.ActivityStreamsNote, + APActivityType: gtsmodel.ActivityStreamsDelete, + GTSModel: s, + ReceivingAccount: inboxAcct, + } + } + + a := >smodel.Account{} + if err := f.db.GetWhere(where, a); err == nil { + // it's an account + l.Debugf("uri is for an account with id: %s", s.ID) + if err := f.db.DeleteByID(a.ID, >smodel.Account{}); err != nil { + return fmt.Errorf("Delete: err deleting account: %s", err) + } + fromFederatorChan <- gtsmodel.FromFederator{ + APObjectType: gtsmodel.ActivityStreamsProfile, + APActivityType: gtsmodel.ActivityStreamsDelete, + GTSModel: a, + ReceivingAccount: inboxAcct, + } + } + return nil } |