mirror of
https://github.com/superseriousbusiness/gotosocial
synced 2025-06-05 21:59:39 +02:00
Database updates (#144)
* start moving some database stuff around * continue moving db stuff around * more fiddling * more updates * and some more * and yet more * i broke SOMETHING but what, it's a mystery * tidy up * vendor ttlcache * use ttlcache * fix up some tests * rename some stuff * little reminder * some more updates
This commit is contained in:
@@ -1,3 +1,21 @@
|
||||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package federation
|
||||
|
||||
import (
|
||||
|
@@ -29,7 +29,6 @@ import (
|
||||
"github.com/go-fed/activity/streams/vocab"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/ap"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/id"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/transport"
|
||||
@@ -65,8 +64,8 @@ func (d *deref) GetRemoteAccount(username string, remoteAccountID *url.URL, refr
|
||||
new := true
|
||||
|
||||
// check if we already have the account in our db
|
||||
maybeAccount := >smodel.Account{}
|
||||
if err := d.db.GetWhere([]db.Where{{Key: "uri", Value: remoteAccountID.String()}}, maybeAccount); err == nil {
|
||||
maybeAccount, err := d.db.GetAccountByURI(remoteAccountID.String())
|
||||
if err == nil {
|
||||
// we've seen this account before so it's not new
|
||||
new = false
|
||||
if !refresh {
|
||||
|
@@ -27,14 +27,14 @@ import (
|
||||
)
|
||||
|
||||
func (d *deref) DereferenceAnnounce(announce *gtsmodel.Status, requestingUsername string) error {
|
||||
if announce.GTSBoostedStatus == nil || announce.GTSBoostedStatus.URI == "" {
|
||||
if announce.BoostOf == nil || announce.BoostOf.URI == "" {
|
||||
// we can't do anything unfortunately
|
||||
return errors.New("DereferenceAnnounce: no URI to dereference")
|
||||
}
|
||||
|
||||
boostedStatusURI, err := url.Parse(announce.GTSBoostedStatus.URI)
|
||||
boostedStatusURI, err := url.Parse(announce.BoostOf.URI)
|
||||
if err != nil {
|
||||
return fmt.Errorf("DereferenceAnnounce: couldn't parse boosted status URI %s: %s", announce.GTSBoostedStatus.URI, err)
|
||||
return fmt.Errorf("DereferenceAnnounce: couldn't parse boosted status URI %s: %s", announce.BoostOf.URI, err)
|
||||
}
|
||||
if blocked, err := d.blockedDomain(boostedStatusURI.Host); blocked || err != nil {
|
||||
return fmt.Errorf("DereferenceAnnounce: domain %s is blocked", boostedStatusURI.Host)
|
||||
@@ -47,7 +47,7 @@ func (d *deref) DereferenceAnnounce(announce *gtsmodel.Status, requestingUsernam
|
||||
|
||||
boostedStatus, _, _, err := d.GetRemoteStatus(requestingUsername, boostedStatusURI, false)
|
||||
if err != nil {
|
||||
return fmt.Errorf("DereferenceAnnounce: error dereferencing remote status with id %s: %s", announce.GTSBoostedStatus.URI, err)
|
||||
return fmt.Errorf("DereferenceAnnounce: error dereferencing remote status with id %s: %s", announce.BoostOf.URI, err)
|
||||
}
|
||||
|
||||
announce.Content = boostedStatus.Content
|
||||
@@ -60,6 +60,6 @@ func (d *deref) DereferenceAnnounce(announce *gtsmodel.Status, requestingUsernam
|
||||
announce.BoostOfAccountID = boostedStatus.AccountID
|
||||
announce.Visibility = boostedStatus.Visibility
|
||||
announce.VisibilityAdvanced = boostedStatus.VisibilityAdvanced
|
||||
announce.GTSBoostedStatus = boostedStatus
|
||||
announce.BoostOf = boostedStatus
|
||||
return nil
|
||||
}
|
||||
|
@@ -31,7 +31,7 @@ func (d *deref) blockedDomain(host string) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
if err == db.ErrNoEntries {
|
||||
// there are no entries so there's no block
|
||||
return false, nil
|
||||
}
|
||||
|
@@ -66,8 +66,8 @@ func (d *deref) GetRemoteStatus(username string, remoteStatusID *url.URL, refres
|
||||
new := true
|
||||
|
||||
// check if we already have the status in our db
|
||||
maybeStatus := >smodel.Status{}
|
||||
if err := d.db.GetWhere([]db.Where{{Key: "uri", Value: remoteStatusID.String()}}, maybeStatus); err == nil {
|
||||
maybeStatus, err := d.db.GetStatusByURI(remoteStatusID.String())
|
||||
if err == nil {
|
||||
// we've seen this status before so it's not new
|
||||
new = false
|
||||
|
||||
@@ -109,7 +109,7 @@ func (d *deref) GetRemoteStatus(username string, remoteStatusID *url.URL, refres
|
||||
return nil, statusable, new, fmt.Errorf("GetRemoteStatus: error populating status fields: %s", err)
|
||||
}
|
||||
|
||||
if err := d.db.Put(gtsStatus); err != nil {
|
||||
if err := d.db.PutStatus(gtsStatus); err != nil {
|
||||
return nil, statusable, new, fmt.Errorf("GetRemoteStatus: error putting new status: %s", err)
|
||||
}
|
||||
} else {
|
||||
@@ -276,7 +276,7 @@ func (d *deref) populateStatusFields(status *gtsmodel.Status, requestingUsername
|
||||
// * the remote URL (a.RemoteURL)
|
||||
// This should be enough to pass along to the media processor.
|
||||
attachmentIDs := []string{}
|
||||
for _, a := range status.GTSMediaAttachments {
|
||||
for _, a := range status.Attachments {
|
||||
l.Tracef("dereferencing attachment: %+v", a)
|
||||
|
||||
// it might have been processed elsewhere so check first if it's already in the database or not
|
||||
@@ -288,7 +288,7 @@ func (d *deref) populateStatusFields(status *gtsmodel.Status, requestingUsername
|
||||
attachmentIDs = append(attachmentIDs, maybeAttachment.ID)
|
||||
continue
|
||||
}
|
||||
if _, ok := err.(db.ErrNoEntries); !ok {
|
||||
if err != db.ErrNoEntries {
|
||||
// we have a real error
|
||||
return fmt.Errorf("error checking db for existence of attachment with remote url %s: %s", a.RemoteURL, err)
|
||||
}
|
||||
@@ -307,7 +307,7 @@ func (d *deref) populateStatusFields(status *gtsmodel.Status, requestingUsername
|
||||
}
|
||||
attachmentIDs = append(attachmentIDs, deferencedAttachment.ID)
|
||||
}
|
||||
status.Attachments = attachmentIDs
|
||||
status.AttachmentIDs = attachmentIDs
|
||||
|
||||
// 2. Hashtags
|
||||
|
||||
@@ -317,53 +317,84 @@ func (d *deref) populateStatusFields(status *gtsmodel.Status, requestingUsername
|
||||
// At this point, mentions should have the namestring and mentionedAccountURI set on them.
|
||||
//
|
||||
// We should dereference any accounts mentioned here which we don't have in our db yet, by their URI.
|
||||
mentions := []string{}
|
||||
for _, m := range status.GTSMentions {
|
||||
|
||||
mentionIDs := []string{}
|
||||
for _, m := range status.Mentions {
|
||||
if m.ID != "" {
|
||||
continue
|
||||
// we've already populated this mention, since it has an ID
|
||||
l.Debug("mention already populated")
|
||||
continue
|
||||
}
|
||||
|
||||
if m.TargetAccountURI == "" {
|
||||
// can't do anything with this mention
|
||||
l.Debug("target URI not set on mention")
|
||||
continue
|
||||
}
|
||||
|
||||
targetAccountURI, err := url.Parse(m.TargetAccountURI)
|
||||
if err != nil {
|
||||
l.Debugf("error parsing mentioned account uri %s: %s", m.TargetAccountURI, err)
|
||||
continue
|
||||
}
|
||||
|
||||
var targetAccount *gtsmodel.Account
|
||||
if a, err := d.db.GetAccountByURL(targetAccountURI.String()); err == nil {
|
||||
targetAccount = a
|
||||
} else if a, _, err := d.GetRemoteAccount(requestingUsername, targetAccountURI, false); err == nil {
|
||||
targetAccount = a
|
||||
} else {
|
||||
// we can't find the target account so bail
|
||||
l.Debug("can't retrieve account targeted by mention")
|
||||
continue
|
||||
}
|
||||
|
||||
mID, err := id.NewRandomULID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.ID = mID
|
||||
|
||||
uri, err := url.Parse(m.MentionedAccountURI)
|
||||
if err != nil {
|
||||
l.Debugf("error parsing mentioned account uri %s: %s", m.MentionedAccountURI, err)
|
||||
continue
|
||||
m = >smodel.Mention{
|
||||
ID: mID,
|
||||
StatusID: status.ID,
|
||||
Status: m.Status,
|
||||
CreatedAt: status.CreatedAt,
|
||||
UpdatedAt: status.UpdatedAt,
|
||||
OriginAccountID: status.Account.ID,
|
||||
OriginAccountURI: status.AccountURI,
|
||||
OriginAccount: status.Account,
|
||||
TargetAccountID: targetAccount.ID,
|
||||
TargetAccount: targetAccount,
|
||||
NameString: m.NameString,
|
||||
TargetAccountURI: targetAccount.URI,
|
||||
TargetAccountURL: targetAccount.URL,
|
||||
}
|
||||
|
||||
m.StatusID = status.ID
|
||||
m.OriginAccountID = status.GTSAuthorAccount.ID
|
||||
m.OriginAccountURI = status.GTSAuthorAccount.URI
|
||||
|
||||
targetAccount, _, err := d.GetRemoteAccount(requestingUsername, uri, false)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// by this point, we know the targetAccount exists in our database with an ID :)
|
||||
m.TargetAccountID = targetAccount.ID
|
||||
if err := d.db.Put(m); err != nil {
|
||||
return fmt.Errorf("error creating mention: %s", err)
|
||||
}
|
||||
mentions = append(mentions, m.ID)
|
||||
mentionIDs = append(mentionIDs, m.ID)
|
||||
}
|
||||
status.Mentions = mentions
|
||||
status.MentionIDs = mentionIDs
|
||||
|
||||
// status has replyToURI but we don't have an ID yet for the status it replies to
|
||||
if status.InReplyToURI != "" && status.InReplyToID == "" {
|
||||
replyToStatus := >smodel.Status{}
|
||||
if err := d.db.GetWhere([]db.Where{{Key: "uri", Value: status.InReplyToURI}}, replyToStatus); err == nil {
|
||||
statusURI, err := url.Parse(status.InReplyToURI)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if replyToStatus, err := d.db.GetStatusByURI(status.InReplyToURI); err == nil {
|
||||
// we have the status
|
||||
status.InReplyToID = replyToStatus.ID
|
||||
status.InReplyTo = replyToStatus
|
||||
status.InReplyToAccountID = replyToStatus.AccountID
|
||||
status.InReplyToAccount = replyToStatus.Account
|
||||
} else if replyToStatus, _, _, err := d.GetRemoteStatus(requestingUsername, statusURI, false); err == nil {
|
||||
// we got the status
|
||||
status.InReplyToID = replyToStatus.ID
|
||||
status.InReplyTo = replyToStatus
|
||||
status.InReplyToAccountID = replyToStatus.AccountID
|
||||
status.InReplyToAccount = replyToStatus.Account
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@@ -1,3 +1,21 @@
|
||||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package federatingdb
|
||||
|
||||
import (
|
||||
|
@@ -1,3 +1,21 @@
|
||||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package federatingdb
|
||||
|
||||
import (
|
||||
|
@@ -112,8 +112,8 @@ func (f *federatingDB) Create(ctx context.Context, asType vocab.Type) error {
|
||||
}
|
||||
status.ID = statusID
|
||||
|
||||
if err := f.db.Put(status); err != nil {
|
||||
if _, ok := err.(db.ErrAlreadyExists); ok {
|
||||
if err := f.db.PutStatus(status); err != nil {
|
||||
if err == db.ErrAlreadyExists {
|
||||
// the status already exists in the database, which means we've already handled everything else,
|
||||
// so we can just return nil here and be done with it.
|
||||
return nil
|
||||
|
@@ -1,3 +1,21 @@
|
||||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package federatingdb
|
||||
|
||||
import (
|
||||
@@ -6,7 +24,6 @@ import (
|
||||
"net/url"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
||||
)
|
||||
@@ -52,10 +69,8 @@ func (f *federatingDB) Delete(ctx context.Context, id *url.URL) error {
|
||||
|
||||
// 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 {
|
||||
s, err := f.db.GetStatusByURI(id.String())
|
||||
if 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 {
|
||||
@@ -69,8 +84,8 @@ func (f *federatingDB) Delete(ctx context.Context, id *url.URL) error {
|
||||
}
|
||||
}
|
||||
|
||||
a := >smodel.Account{}
|
||||
if err := f.db.GetWhere(where, a); err == nil {
|
||||
a, err := f.db.GetAccountByURI(id.String())
|
||||
if 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 {
|
||||
|
@@ -1,3 +1,21 @@
|
||||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package federatingdb
|
||||
|
||||
import (
|
||||
|
@@ -31,7 +31,8 @@ func (f *federatingDB) Followers(c context.Context, actorIRI *url.URL) (follower
|
||||
acct := >smodel.Account{}
|
||||
|
||||
if util.IsUserPath(actorIRI) {
|
||||
if err := f.db.GetWhere([]db.Where{{Key: "uri", Value: actorIRI.String()}}, acct); err != nil {
|
||||
acct, err = f.db.GetAccountByURI(actorIRI.String())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("FOLLOWERS: db error getting account with uri %s: %s", actorIRI.String(), err)
|
||||
}
|
||||
} else if util.IsFollowersPath(actorIRI) {
|
||||
@@ -42,8 +43,8 @@ func (f *federatingDB) Followers(c context.Context, actorIRI *url.URL) (follower
|
||||
return nil, fmt.Errorf("FOLLOWERS: could not parse actor IRI %s as users or followers path", actorIRI.String())
|
||||
}
|
||||
|
||||
acctFollowers := []gtsmodel.Follow{}
|
||||
if err := f.db.GetFollowersByAccountID(acct.ID, &acctFollowers, false); err != nil {
|
||||
acctFollowers, err := f.db.GetAccountFollowedBy(acct.ID, false)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("FOLLOWERS: db error getting followers for account id %s: %s", acct.ID, err)
|
||||
}
|
||||
|
||||
|
@@ -8,7 +8,6 @@ import (
|
||||
"github.com/go-fed/activity/streams"
|
||||
"github.com/go-fed/activity/streams/vocab"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
||||
)
|
||||
@@ -28,21 +27,37 @@ func (f *federatingDB) Following(c context.Context, actorIRI *url.URL) (followin
|
||||
)
|
||||
l.Debugf("entering FOLLOWING function with actorIRI %s", actorIRI.String())
|
||||
|
||||
acct := >smodel.Account{}
|
||||
var acct *gtsmodel.Account
|
||||
if util.IsUserPath(actorIRI) {
|
||||
if err := f.db.GetWhere([]db.Where{{Key: "uri", Value: actorIRI.String()}}, acct); err != nil {
|
||||
username, err := util.ParseUserPath(actorIRI)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("FOLLOWING: error parsing user path: %s", err)
|
||||
}
|
||||
|
||||
a, err := f.db.GetLocalAccountByUsername(username)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("FOLLOWING: db error getting account with uri %s: %s", actorIRI.String(), err)
|
||||
}
|
||||
|
||||
acct = a
|
||||
} else if util.IsFollowingPath(actorIRI) {
|
||||
if err := f.db.GetWhere([]db.Where{{Key: "following_uri", Value: actorIRI.String()}}, acct); err != nil {
|
||||
username, err := util.ParseFollowingPath(actorIRI)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("FOLLOWING: error parsing following path: %s", err)
|
||||
}
|
||||
|
||||
a, err := f.db.GetLocalAccountByUsername(username)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("FOLLOWING: db error getting account with following uri %s: %s", actorIRI.String(), err)
|
||||
}
|
||||
|
||||
acct = a
|
||||
} else {
|
||||
return nil, fmt.Errorf("FOLLOWING: could not parse actor IRI %s as users or following path", actorIRI.String())
|
||||
}
|
||||
|
||||
acctFollowing := []gtsmodel.Follow{}
|
||||
if err := f.db.GetFollowingByAccountID(acct.ID, &acctFollowing); err != nil {
|
||||
acctFollowing, err := f.db.GetAccountFollows(acct.ID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("FOLLOWING: db error getting following for account id %s: %s", acct.ID, err)
|
||||
}
|
||||
|
||||
|
@@ -43,8 +43,8 @@ func (f *federatingDB) Get(c context.Context, id *url.URL) (value vocab.Type, er
|
||||
l.Debug("entering GET function")
|
||||
|
||||
if util.IsUserPath(id) {
|
||||
acct := >smodel.Account{}
|
||||
if err := f.db.GetWhere([]db.Where{{Key: "uri", Value: id.String()}}, acct); err != nil {
|
||||
acct, err := f.db.GetAccountByURI(id.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
l.Debug("is user path! returning account")
|
||||
|
@@ -1,3 +1,21 @@
|
||||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package federatingdb
|
||||
|
||||
import (
|
||||
|
@@ -1,3 +1,21 @@
|
||||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package federatingdb
|
||||
|
||||
import (
|
||||
|
@@ -1,3 +1,21 @@
|
||||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package federatingdb
|
||||
|
||||
import (
|
||||
@@ -62,7 +80,7 @@ func (f *federatingDB) OutboxForInbox(c context.Context, inboxIRI *url.URL) (out
|
||||
}
|
||||
acct := >smodel.Account{}
|
||||
if err := f.db.GetWhere([]db.Where{{Key: "inbox_uri", Value: inboxIRI.String()}}, acct); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
if err == db.ErrNoEntries {
|
||||
return nil, fmt.Errorf("no actor found that corresponds to inbox %s", inboxIRI.String())
|
||||
}
|
||||
return nil, fmt.Errorf("db error searching for actor with inbox %s", inboxIRI.String())
|
||||
|
@@ -54,16 +54,16 @@ func (f *federatingDB) Owns(c context.Context, id *url.URL) (bool, error) {
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("error parsing statuses path for url %s: %s", id.String(), err)
|
||||
}
|
||||
if err := f.db.GetWhere([]db.Where{{Key: "uri", Value: uid}}, >smodel.Status{}); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
status, err := f.db.GetStatusByURI(uid)
|
||||
if err != nil {
|
||||
if err == db.ErrNoEntries {
|
||||
// there are no entries for this status
|
||||
return false, nil
|
||||
}
|
||||
// an actual error happened
|
||||
return false, fmt.Errorf("database error fetching status with id %s: %s", uid, err)
|
||||
}
|
||||
l.Debugf("we own url %s", id.String())
|
||||
return true, nil
|
||||
return status.Local, nil
|
||||
}
|
||||
|
||||
if util.IsUserPath(id) {
|
||||
@@ -71,8 +71,8 @@ func (f *federatingDB) Owns(c context.Context, id *url.URL) (bool, error) {
|
||||
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 {
|
||||
if _, err := f.db.GetLocalAccountByUsername(username); err != nil {
|
||||
if err == db.ErrNoEntries {
|
||||
// there are no entries for this username
|
||||
return false, nil
|
||||
}
|
||||
@@ -88,8 +88,8 @@ func (f *federatingDB) Owns(c context.Context, id *url.URL) (bool, error) {
|
||||
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 {
|
||||
if _, err := f.db.GetLocalAccountByUsername(username); err != nil {
|
||||
if err == db.ErrNoEntries {
|
||||
// there are no entries for this username
|
||||
return false, nil
|
||||
}
|
||||
@@ -105,8 +105,8 @@ func (f *federatingDB) Owns(c context.Context, id *url.URL) (bool, error) {
|
||||
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 {
|
||||
if _, err := f.db.GetLocalAccountByUsername(username); err != nil {
|
||||
if err == db.ErrNoEntries {
|
||||
// there are no entries for this username
|
||||
return false, nil
|
||||
}
|
||||
@@ -122,8 +122,8 @@ func (f *federatingDB) Owns(c context.Context, id *url.URL) (bool, error) {
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("error parsing like path for url %s: %s", id.String(), err)
|
||||
}
|
||||
if err := f.db.GetLocalAccountByUsername(username, >smodel.Account{}); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
if _, err := f.db.GetLocalAccountByUsername(username); err != nil {
|
||||
if err == db.ErrNoEntries {
|
||||
// there are no entries for this username
|
||||
return false, nil
|
||||
}
|
||||
@@ -131,7 +131,7 @@ func (f *federatingDB) Owns(c context.Context, id *url.URL) (bool, error) {
|
||||
return false, fmt.Errorf("database error fetching account with username %s: %s", username, err)
|
||||
}
|
||||
if err := f.db.GetByID(likeID, >smodel.StatusFave{}); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
if err == db.ErrNoEntries {
|
||||
// there are no entries
|
||||
return false, nil
|
||||
}
|
||||
@@ -147,8 +147,8 @@ func (f *federatingDB) Owns(c context.Context, id *url.URL) (bool, error) {
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("error parsing block path for url %s: %s", id.String(), err)
|
||||
}
|
||||
if err := f.db.GetLocalAccountByUsername(username, >smodel.Account{}); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
if _, err := f.db.GetLocalAccountByUsername(username); err != nil {
|
||||
if err == db.ErrNoEntries {
|
||||
// there are no entries for this username
|
||||
return false, nil
|
||||
}
|
||||
@@ -156,7 +156,7 @@ func (f *federatingDB) Owns(c context.Context, id *url.URL) (bool, error) {
|
||||
return false, fmt.Errorf("database error fetching account with username %s: %s", username, err)
|
||||
}
|
||||
if err := f.db.GetByID(blockID, >smodel.Block{}); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
if err == db.ErrNoEntries {
|
||||
// there are no entries
|
||||
return false, nil
|
||||
}
|
||||
|
@@ -1,3 +1,21 @@
|
||||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package federatingdb
|
||||
|
||||
import (
|
||||
|
@@ -1,3 +1,21 @@
|
||||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package federatingdb
|
||||
|
||||
import (
|
||||
|
@@ -97,8 +97,8 @@ func (f *federatingDB) NewID(c context.Context, t vocab.Type) (idURL *url.URL, e
|
||||
for iter := actorProp.Begin(); iter != actorProp.End(); iter = iter.Next() {
|
||||
// take the IRI of the first actor we can find (there should only be one)
|
||||
if iter.IsIRI() {
|
||||
actorAccount := >smodel.Account{}
|
||||
if err := f.db.GetWhere([]db.Where{{Key: "uri", Value: iter.GetIRI().String()}}, actorAccount); err == nil { // if there's an error here, just use the fallback behavior -- we don't need to return an error here
|
||||
// if there's an error here, just use the fallback behavior -- we don't need to return an error here
|
||||
if actorAccount, err := f.db.GetAccountByURI(iter.GetIRI().String()); err == nil {
|
||||
newID, err := id.NewRandomULID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -213,7 +213,7 @@ func (f *federatingDB) ActorForOutbox(c context.Context, outboxIRI *url.URL) (ac
|
||||
}
|
||||
acct := >smodel.Account{}
|
||||
if err := f.db.GetWhere([]db.Where{{Key: "outbox_uri", Value: outboxIRI.String()}}, acct); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
if err == db.ErrNoEntries {
|
||||
return nil, fmt.Errorf("no actor found that corresponds to outbox %s", outboxIRI.String())
|
||||
}
|
||||
return nil, fmt.Errorf("db error searching for actor with outbox %s", outboxIRI.String())
|
||||
@@ -238,7 +238,7 @@ func (f *federatingDB) ActorForInbox(c context.Context, inboxIRI *url.URL) (acto
|
||||
}
|
||||
acct := >smodel.Account{}
|
||||
if err := f.db.GetWhere([]db.Where{{Key: "inbox_uri", Value: inboxIRI.String()}}, acct); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
if err == db.ErrNoEntries {
|
||||
return nil, fmt.Errorf("no actor found that corresponds to inbox %s", inboxIRI.String())
|
||||
}
|
||||
return nil, fmt.Errorf("db error searching for actor with inbox %s", inboxIRI.String())
|
||||
|
@@ -113,8 +113,8 @@ func (f *federator) AuthenticatePostInbox(ctx context.Context, w http.ResponseWr
|
||||
return nil, false, errors.New("username was empty")
|
||||
}
|
||||
|
||||
requestedAccount := >smodel.Account{}
|
||||
if err := f.db.GetLocalAccountByUsername(username, requestedAccount); err != nil {
|
||||
requestedAccount, err := f.db.GetLocalAccountByUsername(username)
|
||||
if err != nil {
|
||||
return nil, false, fmt.Errorf("could not fetch requested account with username %s: %s", username, err)
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ func (f *federator) AuthenticatePostInbox(ctx context.Context, w http.ResponseWr
|
||||
// authentication has passed, so add an instance entry for this instance if it hasn't been done already
|
||||
i := >smodel.Instance{}
|
||||
if err := f.db.GetWhere([]db.Where{{Key: "domain", Value: publicKeyOwnerURI.Host, CaseInsensitive: true}}, i); err != nil {
|
||||
if _, ok := err.(db.ErrNoEntries); !ok {
|
||||
if err != db.ErrNoEntries {
|
||||
// there's been an actual error
|
||||
return ctx, false, fmt.Errorf("error getting requesting account with public key id %s: %s", publicKeyOwnerURI.String(), err)
|
||||
}
|
||||
@@ -176,8 +176,6 @@ func (f *federator) AuthenticatePostInbox(ctx context.Context, w http.ResponseWr
|
||||
// Finally, if the authentication and authorization succeeds, then
|
||||
// blocked must be false and error nil. The request will continue
|
||||
// to be processed.
|
||||
//
|
||||
// TODO: implement domain block checking here as well
|
||||
func (f *federator) Blocked(ctx context.Context, actorIRIs []*url.URL) (bool, error) {
|
||||
l := f.log.WithFields(logrus.Fields{
|
||||
"func": "Blocked",
|
||||
@@ -191,19 +189,18 @@ func (f *federator) Blocked(ctx context.Context, actorIRIs []*url.URL) (bool, er
|
||||
return false, errors.New("requested account not set on request context, so couldn't determine blocks")
|
||||
}
|
||||
|
||||
for _, uri := range actorIRIs {
|
||||
blockedDomain, err := f.blockedDomain(uri.Host)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("error checking domain block: %s", err)
|
||||
}
|
||||
if blockedDomain {
|
||||
return true, nil
|
||||
}
|
||||
blocked, err := f.db.AreURIsBlocked(actorIRIs)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("error checking domain blocks: %s", err)
|
||||
}
|
||||
if blocked {
|
||||
return blocked, nil
|
||||
}
|
||||
|
||||
requestingAccount := >smodel.Account{}
|
||||
if err := f.db.GetWhere([]db.Where{{Key: "uri", Value: uri.String()}}, requestingAccount); err != nil {
|
||||
_, ok := err.(db.ErrNoEntries)
|
||||
if ok {
|
||||
for _, uri := range actorIRIs {
|
||||
requestingAccount, err := f.db.GetAccountByURI(uri.String())
|
||||
if err != nil {
|
||||
if err == db.ErrNoEntries {
|
||||
// we don't have an entry for this account so it's not blocked
|
||||
// TODO: allow a different default to be set for this behavior
|
||||
continue
|
||||
@@ -211,12 +208,11 @@ func (f *federator) Blocked(ctx context.Context, actorIRIs []*url.URL) (bool, er
|
||||
return false, fmt.Errorf("error getting account with uri %s: %s", uri.String(), err)
|
||||
}
|
||||
|
||||
// check if requested account blocks requesting account
|
||||
if err := f.db.GetWhere([]db.Where{
|
||||
{Key: "account_id", Value: requestedAccount.ID},
|
||||
{Key: "target_account_id", Value: requestingAccount.ID},
|
||||
}, >smodel.Block{}); err == nil {
|
||||
// a block exists
|
||||
blocked, err = f.db.IsBlocked(requestedAccount.ID, requestingAccount.ID, true)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("error checking account block: %s", err)
|
||||
}
|
||||
if blocked {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
@@ -30,7 +30,7 @@ import (
|
||||
)
|
||||
|
||||
func (f *federator) FingerRemoteAccount(requestingUsername string, targetUsername string, targetDomain string) (*url.URL, error) {
|
||||
if blocked, err := f.blockedDomain(targetDomain); blocked || err != nil {
|
||||
if blocked, err := f.db.IsDomainBlocked(targetDomain); blocked || err != nil {
|
||||
return nil, fmt.Errorf("FingerRemoteAccount: domain %s is blocked", targetDomain)
|
||||
}
|
||||
|
||||
|
@@ -1,3 +1,21 @@
|
||||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package federation
|
||||
|
||||
import "net/url"
|
||||
|
@@ -1,3 +1,21 @@
|
||||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package federation
|
||||
|
||||
import (
|
||||
|
@@ -1,23 +0,0 @@
|
||||
package federation
|
||||
|
||||
import (
|
||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
)
|
||||
|
||||
func (f *federator) blockedDomain(host string) (bool, error) {
|
||||
b := >smodel.DomainBlock{}
|
||||
err := f.db.GetWhere([]db.Where{{Key: "domain", Value: host, CaseInsensitive: true}}, b)
|
||||
if err == nil {
|
||||
// block exists
|
||||
return true, nil
|
||||
}
|
||||
|
||||
if _, ok := err.(db.ErrNoEntries); ok {
|
||||
// there are no entries so there's no block
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// there's an actual error
|
||||
return false, err
|
||||
}
|
Reference in New Issue
Block a user