Federation (#327)
* initial commit federation * more federation * more federation * more federation * completes follow, accept, undo * add trail create activity * process trail create activity * more trail create activity * adds missing endpoints * adds update and delete activity * adds comment activities * adds activities back * adds summit logs activities * deletes follow counts table * fixes migrations * fixes migrations * fixes migrations * fixes migrations * adds remote profiles * ctd * ctd * we are getting closer... * adds public summit logs * fixes federated trails in lists * adds remote lists * adds list activites * fixes lists * adds notifications * adds iri redirect * fixes comments and summitlogs * fixes follows and profiles * adds asynchronous send * fixes list search * adds encryption key * bug fixes * fixes activity signing * removes custon activity object types * adds html editor * fixes html editor * fixes display issues on mastodon * adds federated sharing * finishes announcements * fixes small summit log issues * adds trail likes * finalizes likes * fixes images for komoot * add disable federation option * adds private profiles * updates docs * adds federated comments * adds trail and comments actvitiypub routes * adds mentions to editor * adds mentions to trails, comments, summit logs * updates theme * updates theme * update docs * update docs * updates docs * fixes various frontend problems * fixes activitypub follows api * updates docs * updates docs --------- Co-authored-by: Christian Beutel <>
This commit is contained in:
377
db/federation/delete.go
Normal file
377
db/federation/delete.go
Normal file
@@ -0,0 +1,377 @@
|
||||
package federation
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
pub "github.com/go-ap/activitypub"
|
||||
"github.com/meilisearch/meilisearch-go"
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
"github.com/pocketbase/pocketbase/tools/security"
|
||||
)
|
||||
|
||||
func CreateTrailDeleteActivity(app core.App, r *core.Record) error {
|
||||
|
||||
origin := os.Getenv("ORIGIN")
|
||||
if origin == "" {
|
||||
return fmt.Errorf("ORIGIN not set")
|
||||
}
|
||||
|
||||
author, err := app.FindRecordById("activitypub_actors", r.GetString("author"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
collection, err := app.FindCollectionByNameOrId("activitypub_activities")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
recordId := security.RandomStringWithAlphabet(core.DefaultIdLength, core.DefaultIdAlphabet)
|
||||
|
||||
id := fmt.Sprintf("%s/api/v1/activitypub/activity/%s", origin, recordId)
|
||||
to := "https://www.w3.org/ns/activitystreams#Public"
|
||||
cc := author.GetString("iri") + "/followers"
|
||||
object := fmt.Sprintf("%s/api/v1/trail/%s", origin, r.Id)
|
||||
|
||||
record := core.NewRecord(collection)
|
||||
record.Set("id", recordId)
|
||||
record.Set("iri", id)
|
||||
record.Set("type", string(pub.DeleteType))
|
||||
record.Set("to", to)
|
||||
record.Set("cc", cc)
|
||||
record.Set("object", object)
|
||||
record.Set("actor", author.GetString("iri"))
|
||||
record.Set("published", time.Now())
|
||||
|
||||
err = app.Save(record)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
activity := pub.DeleteNew(pub.IRI(id), pub.IRI(object))
|
||||
activity.Actor = pub.IRI(author.GetString("iri"))
|
||||
activity.To = pub.ItemCollection{pub.IRI(to)}
|
||||
activity.CC = pub.ItemCollection{pub.IRI(cc)}
|
||||
activity.Published = time.Now()
|
||||
|
||||
follows, err := app.FindRecordsByFilter("follows", "followee={:followee}&&status='accepted'", "", -1, 0, dbx.Params{"followee": author.Id})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
recipients := []string{}
|
||||
for _, f := range follows {
|
||||
follower, err := app.FindRecordById("activitypub_actors", f.GetString("follower"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
recipients = append(recipients, follower.GetString("inbox"))
|
||||
}
|
||||
|
||||
return PostActivity(app, author, activity, recipients)
|
||||
}
|
||||
|
||||
func CreateCommentDeleteActivity(app core.App, client meilisearch.ServiceManager, r *core.Record) error {
|
||||
|
||||
origin := os.Getenv("ORIGIN")
|
||||
if origin == "" {
|
||||
return fmt.Errorf("ORIGIN not set")
|
||||
}
|
||||
|
||||
author, err := app.FindRecordById("activitypub_actors", r.GetString("author"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !author.GetBool("isLocal") {
|
||||
return nil
|
||||
}
|
||||
|
||||
commentTrail, err := app.FindRecordById("trails", r.GetString("trail"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
commentTrailAuthor, err := app.FindRecordById("activitypub_actors", commentTrail.GetString("author"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if commentTrailAuthor.GetBool("isLocal") {
|
||||
return nil
|
||||
}
|
||||
|
||||
collection, err := app.FindCollectionByNameOrId("activitypub_activities")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
recordId := security.RandomStringWithAlphabet(core.DefaultIdLength, core.DefaultIdAlphabet)
|
||||
|
||||
id := fmt.Sprintf("%s/api/v1/activitypub/activity/%s", origin, recordId)
|
||||
to := commentTrailAuthor.GetString("iri")
|
||||
object := fmt.Sprintf("%s/api/v1/comment/%s", origin, r.Id)
|
||||
|
||||
activity := pub.DeleteNew(pub.IRI(id), pub.IRI(object))
|
||||
activity.Actor = pub.IRI(author.GetString("iri"))
|
||||
activity.To = pub.ItemCollection{pub.IRI(to)}
|
||||
activity.Published = time.Now()
|
||||
|
||||
err = PostActivity(app, author, activity, []string{to + "/inbox"})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
record := core.NewRecord(collection)
|
||||
record.Set("id", recordId)
|
||||
record.Set("iri", id)
|
||||
record.Set("type", string(pub.DeleteType))
|
||||
record.Set("to", to)
|
||||
record.Set("object", object)
|
||||
record.Set("actor", author.GetString("iri"))
|
||||
record.Set("published", time.Now())
|
||||
|
||||
return app.Save(record)
|
||||
}
|
||||
|
||||
func CreateSummitLogDeleteActivity(app core.App, r *core.Record) error {
|
||||
|
||||
origin := os.Getenv("ORIGIN")
|
||||
if origin == "" {
|
||||
return fmt.Errorf("ORIGIN not set")
|
||||
}
|
||||
|
||||
author, err := app.FindRecordById("activitypub_actors", r.GetString("author"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !author.GetBool("isLocal") {
|
||||
return nil
|
||||
}
|
||||
|
||||
summitLogTrail, err := app.FindRecordById("trails", r.GetString("trail"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
summitLogTrailAuthor, err := app.FindRecordById("activitypub_actors", summitLogTrail.GetString("author"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
collection, err := app.FindCollectionByNameOrId("activitypub_activities")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
recordId := security.RandomStringWithAlphabet(core.DefaultIdLength, core.DefaultIdAlphabet)
|
||||
|
||||
id := fmt.Sprintf("%s/api/v1/activitypub/activity/%s", origin, recordId)
|
||||
to := summitLogTrailAuthor.GetString("iri")
|
||||
object := fmt.Sprintf("%s/api/v1/summit-log/%s", origin, r.Id)
|
||||
cc := pub.ItemCollection{pub.IRI(author.GetString("iri") + "/followers")}
|
||||
|
||||
activity := pub.DeleteNew(pub.IRI(id), pub.IRI(object))
|
||||
activity.Actor = pub.IRI(author.GetString("iri"))
|
||||
activity.To = pub.ItemCollection{pub.IRI(to)}
|
||||
activity.CC = cc
|
||||
activity.Published = time.Now()
|
||||
|
||||
follows, err := app.FindRecordsByFilter("follows", "followee={:followee}&&status='accepted'", "", -1, 0, dbx.Params{"followee": author.Id})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
recipients := []string{}
|
||||
|
||||
for _, f := range follows {
|
||||
follower, err := app.FindRecordById("activitypub_actors", f.GetString("follower"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
recipients = append(recipients, follower.GetString("inbox"))
|
||||
}
|
||||
|
||||
if author.Id != summitLogTrailAuthor.Id {
|
||||
recipients = append(recipients, summitLogTrailAuthor.GetString("inbox"))
|
||||
}
|
||||
|
||||
err = PostActivity(app, author, activity, recipients)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
record := core.NewRecord(collection)
|
||||
record.Set("id", recordId)
|
||||
record.Set("iri", id)
|
||||
record.Set("type", string(pub.DeleteType))
|
||||
record.Set("to", to)
|
||||
record.Set("cc", cc)
|
||||
record.Set("object", object)
|
||||
record.Set("actor", author.GetString("iri"))
|
||||
record.Set("published", time.Now())
|
||||
|
||||
return app.Save(record)
|
||||
}
|
||||
|
||||
func CreateListDeleteActivity(app core.App, r *core.Record) error {
|
||||
|
||||
origin := os.Getenv("ORIGIN")
|
||||
if origin == "" {
|
||||
return fmt.Errorf("ORIGIN not set")
|
||||
}
|
||||
|
||||
author, err := app.FindRecordById("activitypub_actors", r.GetString("author"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !author.GetBool("isLocal") {
|
||||
return nil
|
||||
}
|
||||
|
||||
collection, err := app.FindCollectionByNameOrId("activitypub_activities")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
recordId := security.RandomStringWithAlphabet(core.DefaultIdLength, core.DefaultIdAlphabet)
|
||||
|
||||
id := fmt.Sprintf("%s/api/v1/activitypub/activity/%s", origin, recordId)
|
||||
to := "https://www.w3.org/ns/activitystreams#Public"
|
||||
cc := author.GetString("iri") + "/followers"
|
||||
object := fmt.Sprintf("%s/api/v1/list/%s", origin, r.Id)
|
||||
|
||||
activity := pub.DeleteNew(pub.IRI(id), pub.IRI(object))
|
||||
activity.Actor = pub.IRI(author.GetString("iri"))
|
||||
activity.To = pub.ItemCollection{pub.IRI(to)}
|
||||
activity.CC = pub.ItemCollection{pub.IRI(cc)}
|
||||
activity.Published = time.Now()
|
||||
|
||||
follows, err := app.FindRecordsByFilter("follows", "followee={:followee}&&status='accepted'", "", -1, 0, dbx.Params{"followee": author.Id})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
recipients := []string{}
|
||||
for _, f := range follows {
|
||||
follower, err := app.FindRecordById("activitypub_actors", f.GetString("follower"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
recipients = append(recipients, follower.GetString("inbox"))
|
||||
}
|
||||
|
||||
err = PostActivity(app, author, activity, recipients)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
record := core.NewRecord(collection)
|
||||
record.Set("id", recordId)
|
||||
record.Set("iri", id)
|
||||
record.Set("type", string(pub.DeleteType))
|
||||
record.Set("to", to)
|
||||
record.Set("cc", cc)
|
||||
record.Set("object", object)
|
||||
record.Set("actor", author.GetString("iri"))
|
||||
record.Set("published", time.Now())
|
||||
|
||||
return app.Save(record)
|
||||
}
|
||||
|
||||
func ProcessDeleteActivity(app core.App, actor *core.Record, activity pub.Activity) error {
|
||||
// no need to do anything if the actor is local
|
||||
if actor.GetBool("isLocal") {
|
||||
return nil
|
||||
}
|
||||
|
||||
object := activity.Object.GetID().String()
|
||||
|
||||
var err error
|
||||
switch {
|
||||
case strings.Contains(object, "trail"):
|
||||
err = processDeleteTrailActivity(app, activity)
|
||||
case strings.Contains(object, "comment"):
|
||||
err = processDeleteCommentActivity(app, actor, activity)
|
||||
case strings.Contains(object, "summit-log"):
|
||||
err = processDeleteSummitLogActivity(app, actor, activity)
|
||||
case strings.Contains(object, "list"):
|
||||
err = processDeleteListActivity(app, actor, activity)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func processDeleteTrailActivity(app core.App, activity pub.Activity) error {
|
||||
|
||||
trailUrl, err := url.Parse(activity.Object.GetID().String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
recordId := path.Base(trailUrl.Path)
|
||||
|
||||
trail, err := app.FindRecordById("trails", recordId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return app.Delete(trail)
|
||||
}
|
||||
|
||||
func processDeleteCommentActivity(app core.App, actor *core.Record, activity pub.Activity) error {
|
||||
object := activity.Object.GetID().String()
|
||||
|
||||
comment, err := app.FindFirstRecordByData("comments", "iri", object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if comment.GetString("author") != actor.Id {
|
||||
return fmt.Errorf("actor is not comment author")
|
||||
}
|
||||
|
||||
err = app.Delete(comment)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func processDeleteSummitLogActivity(app core.App, actor *core.Record, activity pub.Activity) error {
|
||||
object := activity.Object.GetID().String()
|
||||
|
||||
summitLog, err := app.FindFirstRecordByData("summit_logs", "iri", object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if summitLog.GetString("author") != actor.Id {
|
||||
return fmt.Errorf("actor is not summit log author")
|
||||
}
|
||||
|
||||
return app.Delete(summitLog)
|
||||
}
|
||||
|
||||
func processDeleteListActivity(app core.App, actor *core.Record, activity pub.Activity) error {
|
||||
|
||||
object := activity.Object.GetID().String()
|
||||
list, err := app.FindFirstRecordByData("lists", "iri", object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if list.GetString("author") != actor.Id {
|
||||
return fmt.Errorf("actor is not summit log author")
|
||||
}
|
||||
return app.Delete(list)
|
||||
}
|
||||
Reference in New Issue
Block a user