Troubleshoot misskey follows

Store the original follow request object and use it for approvals.
Closes #1690
This commit is contained in:
Gabe Kangas 2022-04-07 16:14:47 -07:00
parent f8181fd036
commit e46f8e2a66
No known key found for this signature in database
GPG key ID: 9A56337728BC81EA
15 changed files with 76 additions and 38 deletions

View file

@ -30,6 +30,8 @@ type ActivityPubActor struct {
FullUsername string
// Image is the avatar image of the Actor.
Image *url.URL
// RequestObject is the actual follow request object.
RequestObject vocab.ActivityStreamsFollow
// W3IDSecurityV1PublicKey is the public key of the actor.
W3IDSecurityV1PublicKey vocab.W3IDSecurityV1PublicKeyProperty
// DisabledAt is the time, if any, this follower was blocked/removed.

View file

@ -39,7 +39,7 @@ func handleFollowInboxRequest(c context.Context, activity vocab.ActivityStreamsF
localAccountName := data.GetDefaultFederationUsername()
if approved {
if err := requests.SendFollowAccept(follow.Inbox, follow.FollowRequestIri, localAccountName); err != nil {
if err := requests.SendFollowAccept(follow.Inbox, activity, localAccountName); err != nil {
log.Errorln("unable to send follow accept", err)
return err
}

View file

@ -74,10 +74,12 @@ func TestBlockedDomains(t *testing.T) {
func TestBlockedActors(t *testing.T) {
person := makeFakePerson()
fakeRequest := streams.NewActivityStreamsFollow()
persistence.AddFollow(apmodels.ActivityPubActor{
ActorIri: person.GetJSONLDId().GetIRI(),
Inbox: person.GetJSONLDId().GetIRI(),
FollowRequestIri: person.GetJSONLDId().GetIRI(),
RequestObject: fakeRequest,
}, false)
persistence.BlockOrRejectFollower(person.GetJSONLDId().GetIRI().String())

View file

@ -23,6 +23,7 @@ func createFederationFollowersTable() {
"created_at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
"approved_at" TIMESTAMP,
"disabled_at" TIMESTAMP,
"request_object" BLOB,
PRIMARY KEY (iri));
CREATE INDEX iri_index ON ap_followers (iri);
CREATE INDEX approved_at_index ON ap_followers (approved_at);`

View file

@ -36,7 +36,13 @@ func AddFollow(follow apmodels.ActivityPubActor, approved bool) error {
if follow.Image != nil {
image = follow.Image.String()
}
return createFollow(follow.ActorIri.String(), follow.Inbox.String(), follow.FollowRequestIri.String(), follow.Name, follow.Username, image, approved)
followRequestObject, err := apmodels.Serialize(follow.RequestObject)
if err != nil {
return errors.Wrap(err, "error serializing follow request object")
}
return createFollow(follow.ActorIri.String(), follow.Inbox.String(), follow.FollowRequestIri.String(), follow.Name, follow.Username, image, followRequestObject, approved)
}
// RemoveFollow will remove a follow from the datastore.
@ -109,7 +115,7 @@ func BlockOrRejectFollower(iri string) error {
})
}
func createFollow(actor string, inbox string, request string, name string, username string, image string, approved bool) error {
func createFollow(actor, inbox, request, name, username, image string, requestObject []byte, approved bool) error {
tx, err := _datastore.DB.Begin()
if err != nil {
log.Debugln(err)
@ -127,13 +133,14 @@ func createFollow(actor string, inbox string, request string, name string, usern
}
if err = _datastore.GetQueries().WithTx(tx).AddFollower(context.Background(), db.AddFollowerParams{
Iri: actor,
Inbox: inbox,
Name: sql.NullString{String: name, Valid: true},
Username: username,
Image: sql.NullString{String: image, Valid: true},
ApprovedAt: approvedAt,
Request: request,
Iri: actor,
Inbox: inbox,
Name: sql.NullString{String: name, Valid: true},
Username: username,
Image: sql.NullString{String: image, Valid: true},
ApprovedAt: approvedAt,
Request: request,
RequestObject: requestObject,
}); err != nil {
log.Errorln("error creating new federation follow: ", err)
}

View file

@ -14,8 +14,8 @@ import (
)
// SendFollowAccept will send an accept activity to a follow request from a specified local user.
func SendFollowAccept(inbox *url.URL, followRequestIRI *url.URL, fromLocalAccountName string) error {
followAccept := makeAcceptFollow(followRequestIRI, fromLocalAccountName)
func SendFollowAccept(inbox *url.URL, originalFollowActivity vocab.ActivityStreamsFollow, fromLocalAccountName string) error {
followAccept := makeAcceptFollow(originalFollowActivity, fromLocalAccountName)
localAccountIRI := apmodels.MakeLocalIRIForAccount(fromLocalAccountName)
var jsonmap map[string]interface{}
@ -31,7 +31,7 @@ func SendFollowAccept(inbox *url.URL, followRequestIRI *url.URL, fromLocalAccoun
return nil
}
func makeAcceptFollow(followRequestIri *url.URL, fromAccountName string) vocab.ActivityStreamsAccept {
func makeAcceptFollow(originalFollowActivity vocab.ActivityStreamsFollow, fromAccountName string) vocab.ActivityStreamsAccept {
acceptIDString := shortid.MustGenerate()
acceptID := apmodels.MakeLocalIRIForResource(acceptIDString)
actorID := apmodels.MakeLocalIRIForAccount(fromAccountName)
@ -45,7 +45,7 @@ func makeAcceptFollow(followRequestIri *url.URL, fromAccountName string) vocab.A
accept.SetActivityStreamsActor(actor)
object := streams.NewActivityStreamsObjectProperty()
object.AppendIRI(followRequestIri)
object.AppendActivityStreamsFollow(originalFollowActivity)
accept.SetActivityStreamsObject(object)
return accept

View file

@ -2,11 +2,11 @@ package resolvers
import (
"context"
"errors"
"fmt"
"github.com/go-fed/activity/streams/vocab"
"github.com/owncast/owncast/activitypub/apmodels"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
)
@ -32,6 +32,7 @@ func MakeFollowRequest(c context.Context, activity vocab.ActivityStreamsFollow)
Name: person.Name,
Username: fullUsername,
Image: person.Image,
RequestObject: activity,
}
return &followRequest, nil

View file

@ -37,14 +37,14 @@ func ApproveFollower(w http.ResponseWriter, r *http.Request) {
localAccountName := data.GetDefaultFederationUsername()
follower, err := persistence.GetFollower(approval.ActorIRI)
followRequest, err := persistence.GetFollower(approval.ActorIRI)
if err != nil {
controllers.WriteSimpleResponse(w, false, err.Error())
return
}
// Send the approval to the follow requestor.
if err := requests.SendFollowAccept(follower.Inbox, follower.FollowRequestIri, localAccountName); err != nil {
if err := requests.SendFollowAccept(followRequest.Inbox, followRequest.RequestObject, localAccountName); err != nil {
controllers.WriteSimpleResponse(w, false, err.Error())
return
}

View file

@ -17,7 +17,7 @@ import (
)
const (
schemaVersion = 3
schemaVersion = 4
)
var (
@ -139,6 +139,8 @@ func migrateDatabase(db *sql.DB, from, to int) error {
migrateToSchema2(db)
case 2:
migrateToSchema3(db)
case 3:
migrateToSchema4(db)
default:
log.Fatalln("missing database migration step")
}

View file

@ -9,6 +9,18 @@ import (
"github.com/teris-io/shortid"
)
func migrateToSchema4(db *sql.DB) {
stmt, err := db.Prepare("ALTER TABLE ap_followers ADD COLUMN request_object BLOB")
if err != nil {
log.Fatal(err)
}
defer stmt.Close()
_, err = stmt.Exec()
if err != nil {
log.Warnln(err)
}
}
func migrateToSchema3(db *sql.DB) {
// Since it's just a backlog of chat messages let's wipe the old messages
// and recreate the table.

View file

@ -1,4 +1,6 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.13.0
package db

View file

@ -1,4 +1,6 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.13.0
package db
@ -16,15 +18,16 @@ type ApAcceptedActivity struct {
}
type ApFollower struct {
Iri string
Inbox string
Name sql.NullString
Username string
Image sql.NullString
Request string
CreatedAt sql.NullTime
ApprovedAt sql.NullTime
DisabledAt sql.NullTime
Iri string
Inbox string
Name sql.NullString
Username string
Image sql.NullString
Request string
RequestObject []byte
CreatedAt sql.NullTime
ApprovedAt sql.NullTime
DisabledAt sql.NullTime
}
type ApOutbox struct {

View file

@ -24,7 +24,7 @@ UPDATE ap_followers SET approved_at = $1, disabled_at = null WHERE iri = $2;
UPDATE ap_followers SET approved_at = null, disabled_at = $1 WHERE iri = $2;
-- name: GetFollowerByIRI :one
SELECT iri, inbox, name, username, image, request, created_at, approved_at, disabled_at FROM ap_followers WHERE iri = $1;
SELECT iri, inbox, name, username, image, request, request_object, created_at, approved_at, disabled_at FROM ap_followers WHERE iri = $1;
-- name: GetOutboxWithOffset :many
SELECT value FROM ap_outbox LIMIT $1 OFFSET $2;
@ -39,7 +39,7 @@ SELECT value, live_notification, created_at FROM ap_outbox WHERE iri = $1;
DELETE FROM ap_followers WHERE iri = $1;
-- name: AddFollower :exec
INSERT INTO ap_followers(iri, inbox, request, name, username, image, approved_at) values($1, $2, $3, $4, $5, $6, $7);
INSERT INTO ap_followers(iri, inbox, request, request_object, name, username, image, approved_at) values($1, $2, $3, $4, $5, $6, $7, $8);
-- name: AddToOutbox :exec
INSERT INTO ap_outbox(iri, value, type, live_notification) values($1, $2, $3, $4);

View file

@ -1,4 +1,6 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.13.0
// source: query.sql
package db
@ -10,17 +12,18 @@ import (
)
const addFollower = `-- name: AddFollower :exec
INSERT INTO ap_followers(iri, inbox, request, name, username, image, approved_at) values($1, $2, $3, $4, $5, $6, $7)
INSERT INTO ap_followers(iri, inbox, request, request_object, name, username, image, approved_at) values($1, $2, $3, $4, $5, $6, $7, $8)
`
type AddFollowerParams struct {
Iri string
Inbox string
Request string
Name sql.NullString
Username string
Image sql.NullString
ApprovedAt sql.NullTime
Iri string
Inbox string
Request string
RequestObject []byte
Name sql.NullString
Username string
Image sql.NullString
ApprovedAt sql.NullTime
}
func (q *Queries) AddFollower(ctx context.Context, arg AddFollowerParams) error {
@ -28,6 +31,7 @@ func (q *Queries) AddFollower(ctx context.Context, arg AddFollowerParams) error
arg.Iri,
arg.Inbox,
arg.Request,
arg.RequestObject,
arg.Name,
arg.Username,
arg.Image,
@ -229,7 +233,7 @@ func (q *Queries) GetFederationFollowersWithOffset(ctx context.Context, arg GetF
}
const getFollowerByIRI = `-- name: GetFollowerByIRI :one
SELECT iri, inbox, name, username, image, request, created_at, approved_at, disabled_at FROM ap_followers WHERE iri = $1
SELECT iri, inbox, name, username, image, request, request_object, created_at, approved_at, disabled_at FROM ap_followers WHERE iri = $1
`
func (q *Queries) GetFollowerByIRI(ctx context.Context, iri string) (ApFollower, error) {
@ -242,6 +246,7 @@ func (q *Queries) GetFollowerByIRI(ctx context.Context, iri string) (ApFollower,
&i.Username,
&i.Image,
&i.Request,
&i.RequestObject,
&i.CreatedAt,
&i.ApprovedAt,
&i.DisabledAt,

View file

@ -8,6 +8,7 @@ CREATE TABLE IF NOT EXISTS ap_followers (
"username" TEXT NOT NULL,
"image" TEXT,
"request" TEXT NOT NULL,
"request_object" BLOB,
"created_at" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
"approved_at" TIMESTAMP,
"disabled_at" TIMESTAMP,