Browse Source

Troubleshoot misskey follows

Store the original follow request object and use it for approvals.
Closes #1690
pull/1819/head
Gabe Kangas 3 years ago
parent
commit
e46f8e2a66
No known key found for this signature in database
GPG Key ID: 9A56337728BC81EA
  1. 2
      activitypub/apmodels/actor.go
  2. 2
      activitypub/inbox/follow.go
  3. 2
      activitypub/inbox/worker_test.go
  4. 1
      activitypub/persistence/followers.go
  5. 25
      activitypub/persistence/persistence.go
  6. 8
      activitypub/requests/acceptFollow.go
  7. 3
      activitypub/resolvers/follow.go
  8. 4
      controllers/admin/followers.go
  9. 4
      core/data/data.go
  10. 12
      core/data/migrations.go
  11. 2
      db/db.go
  12. 21
      db/models.go
  13. 4
      db/query.sql
  14. 23
      db/query.sql.go
  15. 1
      db/schema.sql

2
activitypub/apmodels/actor.go

@ -30,6 +30,8 @@ type ActivityPubActor struct { @@ -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.

2
activitypub/inbox/follow.go

@ -39,7 +39,7 @@ func handleFollowInboxRequest(c context.Context, activity vocab.ActivityStreamsF @@ -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
}

2
activitypub/inbox/worker_test.go

@ -74,10 +74,12 @@ func TestBlockedDomains(t *testing.T) { @@ -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())

1
activitypub/persistence/followers.go

@ -23,6 +23,7 @@ func createFederationFollowersTable() { @@ -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);`

25
activitypub/persistence/persistence.go

@ -36,7 +36,13 @@ func AddFollow(follow apmodels.ActivityPubActor, approved bool) error { @@ -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 { @@ -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 @@ -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)
}

8
activitypub/requests/acceptFollow.go

@ -14,8 +14,8 @@ import ( @@ -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 @@ -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 @@ -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

3
activitypub/resolvers/follow.go

@ -2,11 +2,11 @@ package resolvers @@ -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) @@ -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

4
controllers/admin/followers.go

@ -37,14 +37,14 @@ func ApproveFollower(w http.ResponseWriter, r *http.Request) { @@ -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
}

4
core/data/data.go

@ -17,7 +17,7 @@ import ( @@ -17,7 +17,7 @@ import (
)
const (
schemaVersion = 3
schemaVersion = 4
)
var (
@ -139,6 +139,8 @@ func migrateDatabase(db *sql.DB, from, to int) error { @@ -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")
}

12
core/data/migrations.go

@ -9,6 +9,18 @@ import ( @@ -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.

2
db/db.go

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

21
db/models.go

@ -1,4 +1,6 @@ @@ -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 { @@ -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 {

4
db/query.sql

@ -24,7 +24,7 @@ UPDATE ap_followers SET approved_at = $1, disabled_at = null WHERE iri = $2; @@ -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; @@ -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);

23
db/query.sql.go

@ -1,4 +1,6 @@ @@ -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 ( @@ -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 @@ -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 @@ -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, @@ -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,

1
db/schema.sql

@ -8,6 +8,7 @@ CREATE TABLE IF NOT EXISTS ap_followers ( @@ -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,

Loading…
Cancel
Save