Merge remote-tracking branch 'origin/main' into brian/trail-card-tags

This commit is contained in:
Christian Beutel
2025-06-26 13:03:28 +02:00
368 changed files with 59133 additions and 35785 deletions

View File

@@ -86,7 +86,7 @@ jobs:
# docker buildx build db/ --no-cache -t flomp/wanderer-db:$VERSION -t flomp/wanderer-db:latest --platform=linux/amd64,linux/arm64 --push
# Build web image
export PUBLIC_VALHALLA_URL=https://valhalla1.openstreetmap.de
export PUBLIC_VALHALLA_URL=https://valhalla.openstreetmap.de
cd web
npm ci && npm run build
cd ..

5
.gitignore vendored
View File

@@ -3,11 +3,12 @@
db/pocketbase*
search/meilisearch
search/meilisearch*
search/data.ms*
search/dumps
run.sh
build*.sh
start.*
data/
data*/

View File

@@ -1,3 +1,25 @@
# v0.17.0
> [!CAUTION]
This release contains breaking changes. They are marked with a ⚠️.
**Please update to version v0.16.5 first before updating to v0.17.0.**
## Configuration
Check the reopsitory's [`docker-compose.yml`](https://github.com/Flomp/wanderer/blob/main/docker-compose.yml) for a valid configuration.
- ⚠️ The PocketBase environment variable `POCKETBASE_ENCRYPTION_KEY` is now required. It requires a valid 32 character AES key as its value. To generate a key, run `openssl rand -hex 16`.
- ⚠️ The PocketBase environment variable `ORIGIN`is now required. It must be set to the public IP or hostname (including the port) of your wanderer frontend and must equal the value set for the frontend's `ORIGIN` environment variable.
## Features
- Adds federation
- Adds rich text editor for descriptions and comments
## Docs
- Adds documentation for federation
- Restructures the documentation in three distinct parts (for users, admins & developers) for better separation of concerns
## Translation
- New language: Russian (thanks @jeffscrum)
# v0.16.5
## Features
@@ -251,7 +273,7 @@ This release contains breaking changes. Most migrations will happen automaticall
- Fixes issue with GPX export when using Google Chrome (thanks [@tofublock](https://github.com/tofublock))
## Miscellaneous
As the number of contributors to this project continues to grow (which Im very happy about), Ive set up a [Discord channel](https://discord.gg/MdpybUHc) for more direct communication. If youre interested in helping with Wanderer, feel free to join!
As the number of contributors to this project continues to grow (which Im very happy about), Ive set up a [Discord channel](https://discord.gg/MdpybUHc) for more direct communication. If youre interested in helping with wanderer, feel free to join!
# v0.11.0
## Features

View File

@@ -44,7 +44,7 @@ The first startup can take up to 90 seconds after which you can access the front
> ⚠️ if you are using wanderer in a production environment make sure to change the MEILI_MASTER_KEY variable.
You can also run wanderer on bare-metal. Check out the [documentation](https://wanderer.to/getting-started/installation/#from-source) for a detailed how-to guide.
You can also run wanderer on bare-metal. Check out the [documentation](https://wanderer.to/run/installation/#installation-from-source) for a detailed how-to guide.
## Support wanderer

View File

@@ -3,6 +3,7 @@ FROM alpine:3.16
WORKDIR /
COPY migrations ./migrations
COPY templates ./templates
ARG TARGETARCH
RUN echo ${TARGETARCH}

222
db/federation/activity.go Normal file
View File

@@ -0,0 +1,222 @@
package federation
import (
"bytes"
"context"
"crypto/x509"
"database/sql"
"encoding/pem"
"fmt"
"io"
"net/http"
"net/url"
"os"
"slices"
"strings"
"time"
pub "github.com/go-ap/activitypub"
"sync"
"github.com/go-ap/jsonld"
"github.com/go-fed/httpsig"
"github.com/pocketbase/pocketbase/core"
"github.com/pocketbase/pocketbase/tools/security"
"golang.org/x/sync/semaphore"
)
func PostActivity(app core.App, actor *core.Record, activity *pub.Activity, recipients []string) error {
encryptionKey := os.Getenv("POCKETBASE_ENCRYPTION_KEY")
if len(encryptionKey) == 0 {
return fmt.Errorf("POCKETBASE_ENCRYPTION_KEY not set")
}
origin := os.Getenv("ORIGIN")
if origin == "" {
return fmt.Errorf("ORIGIN not set")
}
algs := []httpsig.Algorithm{httpsig.RSA_SHA256}
postHeaders := []string{"(request-target)", "Date", "Digest", "Content-Type", "Host"}
expiresIn := 60
body, err := jsonld.WithContext(
jsonld.IRI(pub.ActivityBaseURI),
jsonld.IRI(pub.SecurityContextURI),
).Marshal(activity)
if err != nil {
return err
}
decryptedPrivateKey, err := security.Decrypt(actor.GetString("private_key"), encryptionKey)
if err != nil {
return err
}
privateKey, err := x509.ParsePKCS1PrivateKey(decryptedPrivateKey)
if err != nil {
return err
}
pubID := actor.GetString("iri") + "#main-key"
client := &http.Client{}
var wg sync.WaitGroup
sem := semaphore.NewWeighted(5) // Limit to 5 concurrent sends
slices.Sort(recipients)
uniqueRecipients := slices.Compact(recipients)
for _, v := range uniqueRecipients {
wg.Add(1)
go func(inbox string) {
defer wg.Done()
signer, _, err := httpsig.NewSigner(algs, httpsig.DigestSha256, postHeaders, httpsig.Signature, int64(expiresIn))
if err != nil {
return
}
if err := sem.Acquire(context.Background(), 1); err != nil {
app.Logger().Error(fmt.Sprintf("Semaphore acquire failed: %s", err))
return
}
defer sem.Release(1)
buf := bytes.NewBuffer(body)
req, err := http.NewRequest(http.MethodPost, inbox, buf)
if err != nil {
app.Logger().Error(fmt.Sprintf("Request creation failed: %s", err))
return
}
req.Header.Add("Content-Type", "application/activity+json")
req.Header.Add("Date", strings.ReplaceAll(time.Now().UTC().Format(time.RFC1123), "UTC", "GMT"))
req.Header.Add("Host", req.Host)
if err := signer.SignRequest(privateKey, pubID, req, body); err != nil {
app.Logger().Error(fmt.Sprintf("Signing request failed: %s", err))
return
}
resp, err := client.Do(req)
if err != nil {
app.Logger().Error(fmt.Sprintf("Error sending request to inbox %s: %s", inbox, err))
return
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusAccepted {
body, _ := io.ReadAll(resp.Body)
app.Logger().Error(fmt.Sprintf("Inbox %s responded with %d: %s", inbox, resp.StatusCode, body))
} else {
app.Logger().Info(fmt.Sprintf("Sent %s to %s", activity.Type, inbox), "activity", activity)
}
}(v)
}
wg.Wait()
return nil
}
func ProcessActivity(e *core.RequestEvent) error {
origin := os.Getenv("ORIGIN")
if origin == "" {
return fmt.Errorf("ORIGIN not set")
}
body, err := io.ReadAll(e.Request.Body)
if err != nil {
return err
}
var activity pub.Activity
activity.UnmarshalJSON(body)
inbox := fmt.Sprintf("%s%s", origin, e.Request.Header.Get("X-Forwarded-Path"))
userActor, err := e.App.FindFirstRecordByData("activitypub_actors", "inbox", inbox)
if err != nil {
return err
}
actor, err := e.App.FindFirstRecordByData("activitypub_actors", "iri", activity.Actor.GetID().String())
if err != nil {
if err == sql.ErrNoRows {
actor, err = GetActorByIRI(e.App, userActor, activity.Actor.GetID().String(), false)
if err != nil {
return err
}
} else {
return err
}
}
verified, err := verifySignature(e.App, e.Request, actor.GetString("public_key"))
if err != nil || !verified {
e.App.Logger().Error(err.Error())
return e.UnauthorizedError("Invalid http signature", err)
}
switch activity.Type {
case pub.FollowType:
ProcessFollowActivity(e.App, actor, activity)
case pub.AcceptType:
ProcessAcceptActivity(e.App, actor, activity)
case pub.UndoType:
ProcessUndoActivity(e.App, actor, activity)
case pub.UpdateType:
fallthrough
case pub.CreateType:
ProcessCreateOrUpdateActivity(e.App, actor, activity)
case pub.DeleteType:
ProcessDeleteActivity(e.App, actor, activity)
case pub.AnnounceType:
ProcessAnnounceActivity(e.App, actor, activity)
case pub.LikeType:
ProcessLikeActivity(e.App, actor, activity)
}
return e.JSON(http.StatusOK, nil)
}
func verifySignature(app core.App, req *http.Request, publicKeyPem string) (bool, error) {
origin := os.Getenv("ORIGIN")
if origin == "" {
return false, fmt.Errorf("ORIGIN not set")
}
block, _ := pem.Decode([]byte(publicKeyPem))
if block == nil || block.Type != "PUBLIC KEY" {
return false, fmt.Errorf("could not decode publicKeyPem to PUBLIC KEY pem block type")
}
req.URL = &url.URL{
Path: req.Header.Get("X-Forwarded-Path"),
}
url, err := url.Parse(origin)
if err != nil {
return false, err
}
req.Header.Set("Host", url.Host)
req.Host = url.Host
app.Logger().Info(req.Header.Get("signature"))
publicKey, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return false, err
}
v, err := httpsig.NewVerifier(req)
if err != nil {
return false, err
}
err = v.Verify(publicKey, httpsig.RSA_SHA256)
if err != nil {
return false, err
}
return true, nil
}

368
db/federation/actor.go Normal file
View File

@@ -0,0 +1,368 @@
package federation
import (
"crypto/x509"
"database/sql"
"encoding/json"
"fmt"
"net/http"
"net/url"
"os"
"strings"
"time"
pub "github.com/go-ap/activitypub"
"github.com/go-fed/httpsig"
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/core"
"github.com/pocketbase/pocketbase/tools/security"
)
type WebfingerResponse struct {
Subject string `json:"subject"`
Links []struct {
Rel string `json:"rel"`
Href string `json:"href"`
} `json:"links"`
}
func SplitHandle(handle string) (string, string) {
cleaned := strings.TrimPrefix(handle, "@")
cleaned = strings.TrimSpace(cleaned)
if !strings.Contains(cleaned, "@") {
return cleaned, ""
}
parts := strings.SplitN(cleaned, "@", 2)
user := parts[0]
domain := parts[1]
return user, domain
}
func GetActorByHandle(app core.App, actor *core.Record, handle string, includeFollows bool) (*core.Record, error) {
username, domain := SplitHandle(handle)
filter := "preferred_username={:username}&&"
if domain != "" {
filter += "domain={:domain}"
} else {
filter += "isLocal=true"
}
var dbActor *core.Record
dbActor, err := app.FindFirstRecordByFilter("activitypub_actors", filter, dbx.Params{"username": username, "domain": domain})
if err != nil && err == sql.ErrNoRows {
collection, err := app.FindCollectionByNameOrId("activitypub_actors")
if err != nil {
return nil, err
}
dbActor = core.NewRecord(collection)
dbActor.Set("isLocal", false)
iri, err := iriFromHandle(domain, username)
if err != nil {
return nil, err
}
dbActor.Set("iri", iri)
} else if err != nil {
return nil, err
}
return assembleActor(actor, dbActor, app, includeFollows)
}
func GetActorByIRI(app core.App, actor *core.Record, iri string, includeFollows bool) (*core.Record, error) {
var dbActor *core.Record
dbActor, err := app.FindFirstRecordByFilter("activitypub_actors", "iri={:iri}", dbx.Params{"iri": iri})
if err != nil && err == sql.ErrNoRows {
collection, err := app.FindCollectionByNameOrId("activitypub_actors")
if err != nil {
return nil, err
}
dbActor = core.NewRecord(collection)
dbActor.Set("isLocal", false)
dbActor.Set("iri", iri)
} else if err != nil {
return nil, err
}
return assembleActor(actor, dbActor, app, includeFollows)
}
func iriFromHandle(domain string, username string) (string, error) {
client := &http.Client{}
webfingerURL := fmt.Sprintf("http://%s/.well-known/webfinger?resource=acct:%s@%s", domain, username, domain)
resp, err := client.Get(webfingerURL)
if err != nil || resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("webfinger request failed: %v", err)
}
defer resp.Body.Close()
var wf WebfingerResponse
if err := json.NewDecoder(resp.Body).Decode(&wf); err != nil {
return "", err
}
for _, link := range wf.Links {
if link.Rel == "self" {
return link.Href, nil
}
}
return "", fmt.Errorf("no iri in response")
}
func assembleActor(actor *core.Record, dbActor *core.Record, app core.App, includeFollows bool) (*core.Record, error) {
origin := os.Getenv("ORIGIN")
if origin == "" {
return nil, fmt.Errorf("ORIGIN environment variable not set")
}
private := false
if dbActor.GetBool("isLocal") {
user, err := app.FindRecordById("users", dbActor.GetString("user"))
if err != nil {
return nil, err
}
settings, err := app.FindFirstRecordByData("settings", "user", user.Id)
if err != nil {
return nil, err
}
if user.GetString("avatar") != "" {
dbActor.Set("icon", fmt.Sprintf("%s/api/v1/files/users/%s/%s", origin, user.Id, user.GetString("avatar")))
}
dbActor.Set("summary", settings.GetString("bio"))
followerCount, err := app.CountRecords("follows", dbx.NewExp("followee={:user}", dbx.Params{"user": dbActor.Id}))
if err != nil {
return nil, err
}
dbActor.Set("followerCount", followerCount)
followingCount, err := app.CountRecords("follows", dbx.NewExp("follower={:user}", dbx.Params{"user": dbActor.Id}))
if err != nil {
return nil, err
}
dbActor.Set("followingCount", followingCount)
dbActor.Set("last_fetched", time.Now())
privacy := settings.GetString("privacy")
result := make(map[string]interface{})
json.Unmarshal([]byte(privacy), &result)
private = result["account"] == "private"
} else {
// check if value is still cached
twoHoursAgo := time.Now().Add(-2 * time.Hour)
if !includeFollows && dbActor.GetDateTime("last_fetched").Time().After(twoHoursAgo) {
return dbActor, nil
}
pubActor, followers, following, err := fetchRemoteActor(actor, dbActor.GetString("iri"), includeFollows)
if err != nil {
if dbActor.Id != "" {
return dbActor, err
}
return nil, err
}
icon := ""
if pub.IsObject(pubActor.Icon) {
iconObject, err := pub.ToObject(pubActor.Icon)
if err == nil && iconObject.URL != nil {
icon = iconObject.URL.GetID().String()
}
}
parsedUrl, err := url.Parse(dbActor.GetString("iri"))
if err != nil {
return nil, err
}
domain := strings.TrimPrefix(parsedUrl.Hostname(), "www.")
dbActor.Set("domain", domain)
dbActor.Set("followers", pubActor.Followers.GetID().String())
dbActor.Set("inbox", pubActor.Inbox.GetID().String())
dbActor.Set("iri", pubActor.GetID().String())
dbActor.Set("username", pubActor.Name.String())
dbActor.Set("preferred_username", pubActor.PreferredUsername.String())
dbActor.Set("following", pubActor.Following.GetID().String())
dbActor.Set("summary", pubActor.Summary.String())
dbActor.Set("outbox", pubActor.Outbox.GetID().String())
dbActor.Set("icon", icon)
dbActor.Set("published", pubActor.Published.String())
dbActor.Set("public_key", pubActor.PublicKey.PublicKeyPem)
dbActor.Set("last_fetched", time.Now())
if includeFollows {
dbActor.Set("followerCount", int(followers.TotalItems))
dbActor.Set("followingCount", int(following.TotalItems))
}
}
err := app.Save(dbActor)
if err != nil && err.Error() == "iri: Value must be unique." {
dbActor, err = app.FindFirstRecordByData("activitypub_actors", "iri", dbActor.GetString("iri"))
if err != nil {
return nil, err
}
return dbActor, nil
} else if err != nil {
return nil, err
}
if private {
return dbActor, fmt.Errorf("profile is private")
}
return dbActor, nil
}
// Fetches an AP actor and optionally followers/following collections
func fetchRemoteActor(actor *core.Record, iri string, includeFollows bool) (*pub.Actor, *pub.OrderedCollection, *pub.OrderedCollection, error) {
encryptionKey := os.Getenv("POCKETBASE_ENCRYPTION_KEY")
if len(encryptionKey) == 0 {
return nil, nil, nil, fmt.Errorf("POCKETBASE_ENCRYPTION_KEY not set")
}
client := &http.Client{}
req, _ := http.NewRequest("GET", iri, nil)
headers := map[string]string{
"Accept": "application/ld+json",
"Content-Type": "application/activity+json",
"Date": strings.ReplaceAll(time.Now().UTC().Format(time.RFC1123), "UTC", "GMT"),
"Host": req.Host,
}
for k, v := range headers {
req.Header.Add(k, v)
}
dbPrivateKey := actor.GetString("private_key")
if dbPrivateKey != "" {
algs := []httpsig.Algorithm{httpsig.RSA_SHA256}
postHeaders := []string{"(request-target)", "Date", "Digest", "Content-Type", "Host"}
expiresIn := 60
signer, _, err := httpsig.NewSigner(algs, httpsig.DigestSha256, postHeaders, httpsig.Signature, int64(expiresIn))
if err != nil {
return nil, nil, nil, err
}
decryptedPrivateKey, err := security.Decrypt(dbPrivateKey, encryptionKey)
if err != nil {
return nil, nil, nil, err
}
privateKey, err := x509.ParsePKCS1PrivateKey(decryptedPrivateKey)
if err != nil {
return nil, nil, nil, err
}
pubID := actor.GetString("iri") + "#main-key"
if err := signer.SignRequest(privateKey, pubID, req, []byte{}); err != nil {
return nil, nil, nil, err
}
}
resp, err := client.Do(req)
if err != nil {
return nil, nil, nil, fmt.Errorf("actor fetch failed: %v", err)
} else if resp.StatusCode != http.StatusOK {
return nil, nil, nil, fmt.Errorf("actor fetch failed: status %v", resp.StatusCode)
}
defer resp.Body.Close()
var pubActor pub.Actor
if err := json.NewDecoder(resp.Body).Decode(&pubActor); err != nil {
return nil, nil, nil, err
}
var followers, following pub.OrderedCollection
if includeFollows {
// Fetch followers
if data, err := FetchCollection(actor, pubActor.Followers.GetID().String()); err == nil {
followers = *data
}
// Fetch following
if data, err := FetchCollection(actor, pubActor.Following.GetID().String()); err == nil {
following = *data
}
}
return &pubActor, &followers, &following, nil
}
func FetchCollection(actor *core.Record, url string) (*pub.OrderedCollection, error) {
encryptionKey := os.Getenv("POCKETBASE_ENCRYPTION_KEY")
if len(encryptionKey) == 0 {
return nil, fmt.Errorf("POCKETBASE_ENCRYPTION_KEY not set")
}
req, _ := http.NewRequest("GET", url, nil)
headers := map[string]string{
"Accept": "application/ld+json",
"Content-Type": "application/activity+json",
"Date": strings.ReplaceAll(time.Now().UTC().Format(time.RFC1123), "UTC", "GMT"),
"Host": req.Host,
}
for k, v := range headers {
req.Header.Add(k, v)
}
dbPrivateKey := actor.GetString("private_key")
if dbPrivateKey != "" {
algs := []httpsig.Algorithm{httpsig.RSA_SHA256}
postHeaders := []string{"(request-target)", "Date", "Digest", "Content-Type", "Host"}
expiresIn := 60
signer, _, err := httpsig.NewSigner(algs, httpsig.DigestSha256, postHeaders, httpsig.Signature, int64(expiresIn))
if err != nil {
return nil, err
}
decryptedPrivateKey, err := security.Decrypt(dbPrivateKey, encryptionKey)
if err != nil {
return nil, err
}
privateKey, err := x509.ParsePKCS1PrivateKey(decryptedPrivateKey)
if err != nil {
return nil, err
}
pubID := actor.GetString("iri") + "#main-key"
if err := signer.SignRequest(privateKey, pubID, req, []byte{}); err != nil {
return nil, err
}
}
resp, err := http.DefaultClient.Do(req)
if err != nil || resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("collection fetch failed for %s: %v", url, err)
}
defer resp.Body.Close()
var collection pub.OrderedCollection
if err := json.NewDecoder(resp.Body).Decode(&collection); err != nil {
return nil, err
}
return &collection, nil
}

276
db/federation/announce.go Normal file
View File

@@ -0,0 +1,276 @@
package federation
import (
"database/sql"
"fmt"
"net/url"
"os"
"path"
"pocketbase/util"
"strings"
"time"
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/core"
"github.com/pocketbase/pocketbase/tools/security"
pub "github.com/go-ap/activitypub"
)
type AnnounceType string
const (
TrailAnnounceType AnnounceType = "trail"
ListAnnounceType AnnounceType = "list"
)
func CreateAnnounceActivity(app core.App, record *core.Record, typ AnnounceType) error {
origin := os.Getenv("ORIGIN")
if origin == "" {
return fmt.Errorf("ORIGIN not set")
}
var subject *core.Record
var object pub.Item
var err error
if typ == TrailAnnounceType {
subject, err = app.FindRecordById("trails", record.GetString("trail"))
if err != nil {
return err
}
object, err = util.ObjectFromTrail(app, subject, nil)
if err != nil {
return err
}
} else if typ == ListAnnounceType {
subject, err = app.FindRecordById("lists", record.GetString("list"))
if err != nil {
return err
}
object, err = util.ObjectFromList(app, subject)
if err != nil {
return err
}
} else {
return fmt.Errorf("unknown announce type")
}
subjectActor, err := app.FindRecordById("activitypub_actors", subject.GetString("author"))
if err != nil {
return err
}
objectActor, err := app.FindRecordById("activitypub_actors", record.GetString("actor"))
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 := objectActor.GetString("iri")
actor := subjectActor.GetString("iri")
activity := pub.AnnounceNew(pub.IRI(id), object)
activity.To = pub.ItemCollection{pub.IRI(to)}
activity.Actor = pub.IRI(actor)
activity.Tag = pub.ItemCollection{
pub.Object{
Type: pub.NoteType,
Name: pub.NaturalLanguageValuesNew(pub.LangRefValueNew(pub.NilLangRef, "permission")),
Content: pub.NaturalLanguageValuesNew(pub.LangRefValueNew(pub.NilLangRef, record.GetString("permission"))),
},
}
err = PostActivity(app, subjectActor, activity, []string{objectActor.GetString("inbox")})
if err != nil {
return err
}
activityRecord := core.NewRecord(collection)
activityRecord.Set("id", recordId)
activityRecord.Set("iri", id)
activityRecord.Set("to", []string{to})
activityRecord.Set("type", string(pub.AnnounceType))
activityRecord.Set("object", object)
activityRecord.Set("actor", actor)
activityRecord.Set("published", time.Now())
return app.Save(activityRecord)
}
// process incoming announce activity
func ProcessAnnounceActivity(app core.App, actor *core.Record, activity pub.Activity) error {
origin := os.Getenv("ORIGIN")
if origin == "" {
return fmt.Errorf("ORIGIN not set")
}
object := activity.Object.GetID().String()
if strings.Contains(object, "/api/v1/trail") {
processTrailAnnounceActivity(app, actor, activity)
} else if strings.Contains(object, "/api/v1/list") {
processListAnnounceActivity(app, actor, activity)
} else {
return fmt.Errorf("unknown announce type")
}
return nil
}
func processTrailAnnounceActivity(app core.App, actor *core.Record, activity pub.Activity) error {
objectActor, err := app.FindFirstRecordByData("activitypub_actors", "iri", activity.To[0].GetID().String())
if err != nil {
return err
}
var trail *core.Record
if !actor.GetBool("isLocal") {
trail, err = util.TrailFromActivity(activity, app, actor)
if err != nil {
return err
}
permission := "view"
// tags, err := pub.ToItemCollection(activity.Tag)
// if err != nil {
// return err
// }
// for _, tag := range tags.Collection() {
// tagObj, err := pub.ToObject(tag)
// if err != nil {
// continue
// }
// name := tagObj.Name.First().Value.String()
// content := tagObj.Content.First().Value.String()
// if name == "permission" {
// permission = content
// }
// }
record, err := app.FindFirstRecordByFilter("trail_share", "trail={:trailId}&&actor={:actorId}", dbx.Params{"trailId": trail.Id, "actorId": objectActor.Id})
if err != nil {
if err == sql.ErrNoRows {
collection, err := app.FindCollectionByNameOrId("trail_share")
if err != nil {
return err
}
record = core.NewRecord(collection)
record.Set("trail", trail.Id)
record.Set("actor", objectActor.Id)
} else {
return err
}
}
record.Set("permission", permission)
err = app.Save(record)
if err != nil {
return err
}
} else {
trailUrl, err := url.Parse(activity.Object.GetID().String())
if err != nil {
return err
}
trailId := path.Base(trailUrl.Path)
trail, err = app.FindRecordById("trails", trailId)
if err != nil {
return err
}
}
notification := util.Notification{
Type: util.TrailShare,
Metadata: map[string]string{
"id": trail.Id,
"trail": trail.GetString("name"),
"author": fmt.Sprintf("@%s@%s", actor.GetString("preferred_username"), actor.GetString("domain")),
},
Seen: false,
Author: actor.Id,
}
err = util.SendNotification(app, notification, objectActor)
if err != nil {
return err
}
return nil
}
func processListAnnounceActivity(app core.App, actor *core.Record, activity pub.Activity) error {
objectActor, err := app.FindFirstRecordByData("activitypub_actors", "iri", activity.To[0].GetID().String())
if err != nil {
return err
}
var list *core.Record
if !actor.GetBool("isLocal") {
list, err = util.ListFromActivity(activity, app, actor)
if err != nil {
return err
}
record, err := app.FindFirstRecordByFilter("list_share", "list={:listId}&&actor={:actorId}", dbx.Params{"listId": list.Id, "actorId": objectActor.Id})
if err != nil {
if err == sql.ErrNoRows {
collection, err := app.FindCollectionByNameOrId("list_share")
if err != nil {
return err
}
record = core.NewRecord(collection)
record.Set("list", list.Id)
record.Set("actor", objectActor.Id)
record.Set("permission", "view")
} else {
return err
}
}
err = app.Save(record)
if err != nil {
return err
}
} else {
listUrl, err := url.Parse(activity.Object.GetID().String())
if err != nil {
return err
}
listId := path.Base(listUrl.Path)
list, err = app.FindRecordById("trails", listId)
if err != nil {
return err
}
}
notification := util.Notification{
Type: util.ListShare,
Metadata: map[string]string{
"id": list.Id,
"list": list.GetString("name"),
"author": fmt.Sprintf("@%s@%s", actor.GetString("preferred_username"), actor.GetString("domain")),
},
Seen: false,
Author: actor.Id,
}
err = util.SendNotification(app, notification, objectActor)
if err != nil {
return err
}
return nil
}

849
db/federation/create.go Normal file
View File

@@ -0,0 +1,849 @@
package federation
import (
"context"
"database/sql"
"fmt"
"net/url"
"os"
"path"
"strconv"
"strings"
"time"
"pocketbase/util"
pub "github.com/go-ap/activitypub"
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/core"
"github.com/pocketbase/pocketbase/tools/filesystem"
"github.com/pocketbase/pocketbase/tools/security"
"golang.org/x/net/html"
)
func CreateTrailActivity(app core.App, actor *core.Record, trail *core.Record, typ pub.ActivityVocabularyType) error {
if !trail.GetBool("public") {
// only broadcast the trail if it is public
return nil
}
origin := os.Getenv("ORIGIN")
if origin == "" {
return fmt.Errorf("ORIGIN not set")
}
trailAuthor, err := app.FindRecordById("activitypub_actors", trail.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"
mentionedActors, handles, err := ActorsFromMentions(app, actor, trail.GetString("description"))
if err != nil {
return err
}
mentions := []string{}
cc := pub.ItemCollection{pub.IRI(trailAuthor.GetString("followers"))}
tags := pub.ItemCollection{}
for i, m := range mentionedActors {
inbox := m.GetString("inbox")
mention := pub.MentionNew(pub.IRI(m.GetString("iri")))
mention.Href = pub.IRI(m.GetString("iri"))
mention.Name = pub.NaturalLanguageValuesNew(pub.LangRefValueNew(pub.NilLangRef, handles[i]))
tags.Append(mention)
mentions = append(mentions, inbox)
cc.Append(pub.IRI(inbox))
}
trailObject, err := util.ObjectFromTrail(app, trail, &tags)
if err != nil {
return err
}
activity := pub.ActivityNew(pub.IRI(id), typ, trailObject)
activity.Actor = pub.IRI(trailAuthor.GetString("iri"))
activity.To = pub.ItemCollection{pub.IRI(to)}
activity.CC = cc
activity.Published = time.Now()
record := core.NewRecord(collection)
record.Set("id", recordId)
record.Set("iri", id)
record.Set("to", []string{to})
record.Set("cc", cc)
record.Set("type", string(typ))
record.Set("object", trailObject)
record.Set("actor", trailAuthor.GetString("iri"))
record.Set("published", time.Now())
err = app.Save(record)
if err != nil {
return err
}
follows, err := app.FindRecordsByFilter("follows", "followee={:followee}&&status='accepted'", "", -1, 0, dbx.Params{"followee": trailAuthor.Id})
if err != nil {
return err
}
recipients := mentions
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, trailAuthor, activity, recipients)
}
func CreateCommentActivity(app core.App, actor *core.Record, comment *core.Record, typ pub.ActivityVocabularyType) error {
origin := os.Getenv("ORIGIN")
if origin == "" {
return fmt.Errorf("ORIGIN not set")
}
// author of the comment
commentAuthor, err := app.FindRecordById("activitypub_actors", comment.GetString("author"))
if err != nil {
return err
}
commentTrail, err := app.FindRecordById("trails", comment.GetString("trail"))
if err != nil {
return err
}
commentTrailAuthor, err := app.FindRecordById("activitypub_actors", commentTrail.GetString("author"))
if err != nil {
return err
}
activityRecordId := security.RandomStringWithAlphabet(core.DefaultIdLength, core.DefaultIdAlphabet)
id := fmt.Sprintf("%s/api/v1/activitypub/activity/%s", origin, activityRecordId)
to := "https://www.w3.org/ns/activitystreams#Public"
mentionedActors, handles, err := ActorsFromMentions(app, actor, comment.GetString("text"))
if err != nil {
return err
}
recipients := []string{}
tags := pub.ItemCollection{}
for i, m := range mentionedActors {
mention := pub.MentionNew(pub.IRI(m.GetString("iri")))
mention.Href = pub.IRI(m.GetString("iri"))
mention.Name = pub.NaturalLanguageValuesNew(pub.LangRefValueNew(pub.NilLangRef, handles[i]))
tags.Append(mention)
recipients = append(recipients, m.GetString("inbox"))
}
recipients = append(recipients, commentTrailAuthor.GetString("inbox"))
cc := pub.ItemCollection{}
for _, r := range recipients {
cc.Append(pub.IRI(r))
}
author := commentAuthor.GetString("iri")
commentObject, err := util.ObjectFromComment(app, comment, &tags)
if err != nil {
return err
}
activity := pub.ActivityNew(pub.IRI(id), typ, commentObject)
activity.Actor = pub.IRI(author)
activity.To = pub.ItemCollection{pub.IRI(to)}
activity.CC = cc
activity.Published = time.Now()
activity.Object = commentObject
collection, err := app.FindCollectionByNameOrId("activitypub_activities")
if err != nil {
return err
}
record := core.NewRecord(collection)
record.Set("id", activityRecordId)
record.Set("iri", id)
record.Set("to", []string{to})
record.Set("cc", recipients)
record.Set("type", string(typ))
record.Set("object", commentObject)
record.Set("actor", author)
record.Set("published", time.Now())
err = app.Save(record)
if err != nil {
return err
}
return PostActivity(app, commentAuthor, activity, recipients)
}
func CreateSummitLogActivity(app core.App, actor *core.Record, summitLog *core.Record, typ pub.ActivityVocabularyType) error {
origin := os.Getenv("ORIGIN")
if origin == "" {
return fmt.Errorf("ORIGIN not set")
}
summitLogAuthor, err := app.FindRecordById("activitypub_actors", summitLog.GetString("author"))
if err != nil {
return err
}
var summitLogAuthorId string
// first check if we find the trail locally
summitLogTrail, err := app.FindRecordById("trails", summitLog.GetString("trail"))
if err != nil {
return err
}
if !summitLogTrail.GetBool("public") {
// only broadcast the log if the trail it belongs to is public
return nil
}
summitLogAuthorId = summitLogTrail.GetString("author")
summitLogTrailAuthor, err := app.FindRecordById("activitypub_actors", summitLogAuthorId)
if err != nil {
return err
}
collection, err := app.FindCollectionByNameOrId("activitypub_activities")
if err != nil {
return err
}
var trailIRI pub.IRI
if summitLogTrailAuthor.GetBool("isLocal") {
trailId := summitLog.GetString("trail")
trailIRI = pub.IRI(fmt.Sprintf("%s/api/v1/trail/%s", origin, trailId))
} else {
trailIRI = pub.IRI(summitLogTrail.GetString("iri"))
}
recordId := security.RandomStringWithAlphabet(core.DefaultIdLength, core.DefaultIdAlphabet)
id := fmt.Sprintf("%s/api/v1/activitypub/activity/%s", origin, recordId)
to := pub.ItemCollection{pub.IRI("https://www.w3.org/ns/activitystreams#Public")}
// someone else created the summit log on the trail -> inform the trail's author
if summitLogAuthor.Id != summitLogTrailAuthor.Id {
to.Append(pub.IRI(summitLogTrailAuthor.GetString("iri")))
}
mentionedActors, handles, err := ActorsFromMentions(app, actor, summitLog.GetString("text"))
if err != nil {
return err
}
mentions := []string{}
cc := pub.ItemCollection{pub.IRI(summitLogAuthor.GetString("followers"))}
mentionTags := pub.ItemCollection{}
for i, m := range mentionedActors {
inbox := m.GetString("inbox")
mention := pub.MentionNew(pub.IRI(m.GetString("iri")))
mention.Href = pub.IRI(m.GetString("iri"))
mention.Name = pub.NaturalLanguageValuesNew(pub.LangRefValueNew(pub.NilLangRef, handles[i]))
mentionTags.Append(mention)
mentions = append(mentions, inbox)
cc.Append(pub.IRI(inbox))
}
photos := summitLog.GetStringSlice("photos")
gpx := ""
if summitLog.GetString("gpx") != "" {
gpx = fmt.Sprintf("%s/api/v1/files/summit_logs/%s/%s", origin, summitLog.Id, summitLog.GetString("gpx"))
}
attachments := make(pub.ItemCollection, max(len(photos), 2))
for i := range len(photos) {
iri := fmt.Sprintf("%s/api/v1/files/summit_logs/%s/%s", origin, summitLog.Id, photos[i])
attachments[i] = pub.Document{
Type: pub.ImageType,
MediaType: "image/jpeg",
URL: pub.IRI(iri),
}
}
if gpx != "" {
attachments.Append(pub.Document{
Type: pub.DocumentType,
MediaType: "application/xml+gpx",
URL: pub.IRI(gpx),
})
}
tags := pub.ItemCollection{
pub.Object{
Type: pub.NoteType,
Name: pub.NaturalLanguageValuesNew(pub.LangRefValueNew(pub.NilLangRef, "elevation_gain")),
Content: pub.NaturalLanguageValuesNew(pub.LangRefValueNew(pub.NilLangRef, fmt.Sprintf("%fm", summitLog.GetFloat("elevation_gain")))),
},
pub.Object{
Type: pub.NoteType,
Name: pub.NaturalLanguageValuesNew(pub.LangRefValueNew(pub.NilLangRef, "elevation_loss")),
Content: pub.NaturalLanguageValuesNew(pub.LangRefValueNew(pub.NilLangRef, fmt.Sprintf("%fm", summitLog.GetFloat("elevation_loss")))),
},
pub.Object{
Type: pub.NoteType,
Name: pub.NaturalLanguageValuesNew(pub.LangRefValueNew(pub.NilLangRef, "distance")),
Content: pub.NaturalLanguageValuesNew(pub.LangRefValueNew(pub.NilLangRef, fmt.Sprintf("%fm", summitLog.GetFloat("distance")))),
},
pub.Object{
Type: pub.NoteType,
Name: pub.NaturalLanguageValuesNew(pub.LangRefValueNew(pub.NilLangRef, "duration")),
Content: pub.NaturalLanguageValuesNew(pub.LangRefValueNew(pub.NilLangRef, fmt.Sprintf("%fm", summitLog.GetFloat("duration")))),
},
}
for _, m := range mentionTags {
tags.Append(m)
}
logObject := pub.ObjectNew(pub.NoteType)
logObject.Content = pub.NaturalLanguageValuesNew(pub.LangRefValueNew(pub.NilLangRef, summitLog.GetString("text")))
logObject.AttributedTo = pub.IRI(summitLogAuthor.GetString("iri"))
logObject.Published = summitLog.GetDateTime("created").Time()
logObject.ID = pub.IRI(fmt.Sprintf("%s/api/v1/summit-log/%s", origin, summitLog.Id))
logObject.URL = pub.IRI(fmt.Sprintf("%s/trail/view/@%s/%s", origin, summitLogTrailAuthor.GetString("preferred_username"), summitLog.GetString("trail")))
logObject.InReplyTo = trailIRI
logObject.Tag = tags
logObject.StartTime = summitLog.GetDateTime("date").Time()
logObject.Attachment = attachments
activity := pub.ActivityNew(pub.IRI(id), typ, logObject)
activity.Actor = pub.IRI(summitLogAuthor.GetString("iri"))
activity.To = to
activity.CC = cc
activity.Published = time.Now()
follows, err := app.FindRecordsByFilter("follows", "followee={:followee}&&status='accepted'", "", -1, 0, dbx.Params{"followee": summitLogAuthor.Id})
if err != nil {
return err
}
recipients := mentions
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 summitLogAuthor.Id != summitLogTrailAuthor.Id {
recipients = append(recipients, summitLogTrailAuthor.GetString("inbox"))
}
err = PostActivity(app, summitLogAuthor, activity, recipients)
if err != nil {
return err
}
record := core.NewRecord(collection)
record.Set("id", recordId)
record.Set("iri", id)
record.Set("to", to)
record.Set("cc", cc)
record.Set("type", string(typ))
record.Set("object", logObject)
record.Set("actor", summitLogAuthor.GetString("iri"))
record.Set("published", time.Now())
return app.Save(record)
}
func CreateListActivity(app core.App, list *core.Record, typ pub.ActivityVocabularyType) error {
if !list.GetBool("public") {
// only broadcast the list if it is public
return nil
}
origin := os.Getenv("ORIGIN")
if origin == "" {
return fmt.Errorf("ORIGIN not set")
}
// author of the list
listAuthor, err := app.FindRecordById("activitypub_actors", list.GetString("author"))
if err != nil {
return err
}
activityRecordId := security.RandomStringWithAlphabet(core.DefaultIdLength, core.DefaultIdAlphabet)
id := fmt.Sprintf("%s/api/v1/activitypub/activity/%s", origin, activityRecordId)
to := "https://www.w3.org/ns/activitystreams#Public"
cc := listAuthor.GetString("followers")
author := listAuthor.GetString("iri")
listObject, err := util.ObjectFromList(app, list)
if err != nil {
return err
}
activity := pub.ActivityNew(pub.IRI(id), typ, listObject)
activity.Actor = pub.IRI(author)
activity.To = pub.ItemCollection{pub.IRI(to)}
activity.CC = pub.ItemCollection{pub.IRI(cc)}
activity.Published = time.Now()
activity.Object = listObject
collection, err := app.FindCollectionByNameOrId("activitypub_activities")
if err != nil {
return err
}
follows, err := app.FindRecordsByFilter("follows", "followee={:followee}&&status='accepted'", "", -1, 0, dbx.Params{"followee": listAuthor.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, listAuthor, activity, recipients)
if err != nil {
return err
}
record := core.NewRecord(collection)
record.Set("id", activityRecordId)
record.Set("iri", id)
record.Set("to", []string{to})
record.Set("cc", []string{cc})
record.Set("type", string(typ))
record.Set("object", listObject)
record.Set("actor", author)
record.Set("published", time.Now())
return app.Save(record)
}
func ProcessCreateOrUpdateActivity(app core.App, actor *core.Record, activity pub.Activity) error {
var err error
if strings.Contains(activity.Object.GetID().String(), "/api/v1/trail") {
err = processCreateOrUpdateTrailActivity(activity, app, actor)
} else if strings.Contains(activity.Object.GetID().String(), "/api/v1/summit-log") {
err = processCreateOrUpdateSummitLogActivity(activity, app, actor)
} else if strings.Contains(activity.Object.GetID().String(), "/api/v1/list") {
err = processCreateOrUpdateListActivity(activity, app, actor)
} else {
err = processCreateOrUpdateCommentActivity(activity, app, actor)
}
if err != nil {
return err
}
return nil
}
func processCreateOrUpdateTrailActivity(activity pub.Activity, app core.App, actor *core.Record) error {
// no need to do anything if the actor is local
if actor.GetBool("isLocal") {
return nil
}
trail, err := util.TrailFromActivity(activity, app, actor)
trailObject, _ := pub.ToObject(activity.Object)
for _, t := range trailObject.Tag {
if t.GetType() == pub.MentionType {
mention := t.(*pub.Mention)
mentionedActor, err := app.FindFirstRecordByData("activitypub_actors", "iri", mention.Href.GetID().String())
if err != nil {
continue
}
notification := util.Notification{
Type: util.TrailMention,
Metadata: map[string]string{
"id": trail.Id,
"author": fmt.Sprintf("@%s@%s", actor.GetString("preferred_username"), actor.GetString("domain")),
},
Seen: false,
Author: actor.Id,
}
return util.SendNotification(app, notification, mentionedActor)
}
}
return err
}
func processCreateOrUpdateCommentActivity(activity pub.Activity, app core.App, actor *core.Record) error {
commentObject, err := pub.ToObject(activity.Object)
if err != nil {
return err
}
if commentObject.InReplyTo == nil {
return fmt.Errorf("error processing comment: InReplyTo empty")
}
trailUrl, err := url.Parse(commentObject.InReplyTo.GetLink().String())
if err != nil {
return err
}
trailId := path.Base(trailUrl.Path)
var trail *core.Record
trail, err = app.FindFirstRecordByFilter("trails", "iri={:iri} || id={:id}", dbx.Params{"id": trailId, "iri": commentObject.InReplyTo.GetID().String()})
// if the trail is not present on this instance fetch it
if err != nil {
if err == sql.ErrNoRows {
trailObject, err := util.TrailObjectFromIRI(commentObject.InReplyTo.GetLink().String())
if err != nil {
return err
}
activity := pub.ActivityNew(pub.IRI("new"), pub.CreateType, trailObject)
trail, err = util.TrailFromActivity(*activity, app, actor)
if err != nil {
return err
}
} else {
return err
}
}
trailAuthor, err := app.FindRecordById("activitypub_actors", trail.GetString("author"))
if err != nil {
return err
}
// no need to do anything else if the actor is local
if actor.GetBool("isLocal") {
return nil
}
record, err := app.FindFirstRecordByData("comments", "iri", commentObject.ID.String())
if err != nil {
if err == sql.ErrNoRows {
collection, err := app.FindCollectionByNameOrId("comments")
if err != nil {
return err
}
record = core.NewRecord(collection)
} else {
return err
}
}
record.Set("iri", commentObject.ID.String())
record.Set("text", commentObject.Content.First().Value)
record.Set("author", actor.Id)
record.Set("trail", trail.Id)
err = app.Save(record)
if err != nil {
return err
}
// send notifications to all mentioned actors
for _, t := range commentObject.Tag {
if t.GetType() == pub.MentionType {
mention := t.(*pub.Mention)
mentionedActor, err := app.FindFirstRecordByData("activitypub_actors", "iri", mention.Href.GetID().String())
if err != nil {
continue
}
notification := util.Notification{
Type: util.CommentMention,
Metadata: map[string]string{
"comment": commentObject.Content.First().Value.String(),
"trail_id": trail.Id,
"trail_name": trail.GetString("name"),
"trail_author": fmt.Sprintf("@%s@%s", trailAuthor.GetString("preferred_username"), trailAuthor.GetString("domain")),
},
Seen: false,
Author: actor.Id,
}
return util.SendNotification(app, notification, mentionedActor)
}
}
if activity.Type == pub.CreateType {
// send a notification to the trail author
notification := util.Notification{
Type: util.TrailComment,
Metadata: map[string]string{
"comment": commentObject.Content.First().Value.String(),
"trail_id": trail.Id,
"trail_name": trail.GetString("name"),
"trail_author": fmt.Sprintf("@%s@%s", trailAuthor.GetString("preferred_username"), trailAuthor.GetString("domain")),
},
Seen: false,
Author: actor.Id,
}
return util.SendNotification(app, notification, trailAuthor)
}
return nil
}
func processCreateOrUpdateSummitLogActivity(activity pub.Activity, app core.App, actor *core.Record) error {
logObject, err := pub.ToObject(activity.Object)
if err != nil {
return err
}
trailIRI, err := url.Parse(logObject.InReplyTo.GetID().String())
if err != nil {
return err
}
trailId := path.Base(trailIRI.Path)
trail, err := app.FindFirstRecordByFilter("trails", "iri={:iri} || id={:id}", dbx.Params{"id": trailId, "iri": logObject.InReplyTo.GetID().String()})
// if the trail is not present on this instance fetch it
if err != nil {
if err == sql.ErrNoRows {
trailObject, err := util.TrailObjectFromIRI(logObject.InReplyTo.GetLink().String())
if err != nil {
return err
}
activity := pub.ActivityNew(pub.IRI("new"), pub.CreateType, trailObject)
trail, err = util.TrailFromActivity(*activity, app, actor)
if err != nil {
return err
}
} else {
return err
}
}
trailAuthor, err := app.FindRecordById("activitypub_actors", trail.GetString("author"))
if err != nil {
return err
}
newSummitLog := false
record, err := app.FindFirstRecordByData("summit_logs", "iri", logObject.ID.String())
if err != nil {
if err == sql.ErrNoRows {
collection, err := app.FindCollectionByNameOrId("summit_logs")
if err != nil {
return err
}
record = core.NewRecord(collection)
newSummitLog = true
} else {
return err
}
}
// no need to do anything else if the actor is local
if actor.GetBool("isLocal") {
return nil
}
var distance, duration, elevation_gain, elevation_loss float64
tags, err := pub.ToItemCollection(logObject.Tag)
if err != nil {
return err
}
for _, tag := range tags.Collection() {
tagObj, err := pub.ToObject(tag)
if err != nil {
continue
}
content := tagObj.Content.First().Value.String()
switch tagObj.Name.First().Value.String() {
case "elevation_gain":
elevation_gain, err = strconv.ParseFloat(content[:len(content)-1], 64)
case "elevation_loss":
elevation_loss, err = strconv.ParseFloat(content[:len(content)-1], 64)
case "duration":
duration, err = strconv.ParseFloat(content[:len(content)-1], 64)
case "distance":
distance, err = strconv.ParseFloat(content[:len(content)-1], 64)
}
if err != nil {
continue
}
}
record.Set("date", logObject.StartTime)
record.Set("text", logObject.Content.First().Value)
record.Set("distance", distance)
record.Set("duration", duration)
record.Set("elevation_gain", elevation_gain)
record.Set("elevation_loss", elevation_loss)
record.Set("author", actor.Id)
record.Set("trail", trail.Id)
record.Set("iri", logObject.ID.String())
if logObject.Attachment != nil {
attachments, err := pub.ToItemCollection(logObject.Attachment)
if err != nil {
return err
}
photoURLs := []string{}
gpxURL := ""
for _, a := range attachments.Collection() {
attachment, err := pub.ToObject(a)
if err != nil {
continue
}
if attachment.Type == pub.DocumentType && attachment.MediaType == "application/xml+gpx" {
gpxURL = attachment.URL.GetLink().String()
} else if attachment.Type == pub.ImageType {
photoURLs = append(photoURLs, attachment.URL.GetLink().String())
}
}
if len(photoURLs) > 0 {
photos := make([]*filesystem.File, len(photoURLs))
for i, purl := range photoURLs {
photo, err := filesystem.NewFileFromURL(context.Background(), purl)
if err != nil {
continue
}
photos[i] = photo
}
record.Set("photos", photos)
}
if gpxURL != "" {
gpx, err := filesystem.NewFileFromURL(context.Background(), gpxURL)
if err != nil {
return err
}
record.Set("gpx", gpx)
}
}
err = app.Save(record)
if err != nil {
return err
}
// send notifications to all mentioned actors
for _, t := range logObject.Tag {
if t.GetType() == pub.MentionType {
mention := t.(*pub.Mention)
mentionedActor, err := app.FindFirstRecordByData("activitypub_actors", "iri", mention.Href.GetID().String())
if err != nil {
continue
}
notification := util.Notification{
Type: util.SummitLogMention,
Metadata: map[string]string{
"trail_id": trail.Id,
"trail_name": trail.GetString("name"),
"trail_author": fmt.Sprintf("@%s@%s", trailAuthor.GetString("preferred_username"), trailAuthor.GetString("domain")),
},
Seen: false,
Author: actor.Id,
}
return util.SendNotification(app, notification, mentionedActor)
}
}
if newSummitLog {
// send a notification to the trail author
notification := util.Notification{
Type: util.SummitLogCreate,
Metadata: map[string]string{
"trail_id": trail.Id,
"trail_name": trail.GetString("name"),
"trail_author": fmt.Sprintf("@%s@%s", trailAuthor.GetString("preferred_username"), trailAuthor.GetString("domain")),
},
Seen: false,
Author: actor.Id,
}
return util.SendNotification(app, notification, trailAuthor)
}
return nil
}
func processCreateOrUpdateListActivity(activity pub.Activity, app core.App, actor *core.Record) error {
// no need to do anything if the actor is local
if actor.GetBool("isLocal") {
return nil
}
_, err := util.ListFromActivity(activity, app, actor)
return err
}
func ActorsFromMentions(app core.App, actor *core.Record, htmlStr string) ([]*core.Record, []string, error) {
doc, err := html.Parse(strings.NewReader(htmlStr))
if err != nil {
return nil, nil, err
}
var handles []string
var actors []*core.Record
var f func(*html.Node)
f = func(n *html.Node) {
if n.Type == html.ElementNode && n.Data == "a" {
var isMention bool
for _, attr := range n.Attr {
if attr.Key == "class" && strings.Contains(attr.Val, "mention") {
isMention = true
break
}
}
if isMention && n.FirstChild != nil && n.FirstChild.Type == html.TextNode {
handle := strings.TrimSpace(n.FirstChild.Data)
if strings.HasPrefix(handle, "@") {
handles = append(handles, handle)
}
}
}
for c := n.FirstChild; c != nil; c = c.NextSibling {
f(c)
}
}
f(doc)
for _, h := range handles {
actor, err := GetActorByHandle(app, actor, h, false)
if err != nil {
continue
}
actors = append(actors, actor)
}
return actors, handles, nil
}

377
db/federation/delete.go Normal file
View 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)
}

160
db/federation/follow.go Normal file
View File

@@ -0,0 +1,160 @@
package federation
import (
"fmt"
"os"
"pocketbase/util"
"time"
pub "github.com/go-ap/activitypub"
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/core"
"github.com/pocketbase/pocketbase/tools/security"
)
// create outgoing follow activity
func CreateFollowActivity(app core.App, follow *core.Record) error {
origin := os.Getenv("ORIGIN")
if origin == "" {
return fmt.Errorf("ORIGIN not set")
}
follower := follow.GetString("follower")
followee := follow.GetString("followee")
followerActor, err := app.FindRecordById("activitypub_actors", follower)
if err != nil {
return err
}
followeeActor, err := app.FindRecordById("activitypub_actors", followee)
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)
activity := pub.FollowNew(pub.IRI(id), pub.IRI(followeeActor.GetString("iri")))
activity.Actor = pub.IRI(followerActor.GetString("iri"))
err = PostActivity(app, followerActor, activity, []string{followeeActor.GetString("inbox")})
if err != nil {
return err
}
record := core.NewRecord(collection)
record.Set("id", recordId)
record.Set("iri", id)
record.Set("type", string(pub.FollowType))
record.Set("object", followeeActor.GetString("iri"))
record.Set("actor", followerActor.GetString("iri"))
record.Set("published", time.Now())
return app.Save(record)
}
// process incoming follow activity
func ProcessFollowActivity(app core.App, actor *core.Record, activity pub.Activity) error {
origin := os.Getenv("ORIGIN")
if origin == "" {
return fmt.Errorf("ORIGIN not set")
}
// find the followee in our db
object, err := app.FindFirstRecordByData("activitypub_actors", "iri", activity.Object)
if err != nil {
return err
}
// a remote actor has requested the follow
// this means we have not yet created a follow entry in our db
// we accept it immediately
if !actor.GetBool("isLocal") {
followCollection, err := app.FindCollectionByNameOrId("follows")
if err != nil {
return err
}
followRecord := core.NewRecord(followCollection)
followRecord.Set("follower", actor.Id)
followRecord.Set("followee", object.Id)
followRecord.Set("status", "accepted")
err = app.Save(followRecord)
if err != nil {
return err
}
}
recordId := security.RandomStringWithAlphabet(core.DefaultIdLength, core.DefaultIdAlphabet)
id := fmt.Sprintf("%s/api/v1/activitypub/activity/%s", origin, recordId)
// send the accept activity back to the actor's inbox
acceptActivity := pub.AcceptNew(pub.IRI(id), activity)
acceptActivity.Actor = activity.Object
err = PostActivity(app, object, acceptActivity, []string{actor.GetString("inbox")})
if err != nil {
return err
}
// create record of the accept activity in our db
collection, err := app.FindCollectionByNameOrId("activitypub_activities")
if err != nil {
return err
}
record := core.NewRecord(collection)
record.Set("id", recordId)
record.Set("iri", id)
record.Set("type", string(pub.AcceptType))
record.Set("object", activity)
record.Set("actor", object.GetString("iri"))
record.Set("published", time.Now())
err = app.Save(record)
if err != nil {
return err
}
// send a notification to the followee
notification := util.Notification{
Type: util.NewFollower,
Metadata: map[string]string{
"follower": fmt.Sprintf("@%s@%s", actor.GetString("preferred_username"), actor.GetString("domain")),
},
Seen: false,
Author: actor.Id,
}
return util.SendNotification(app, notification, object)
}
func ProcessAcceptActivity(app core.App, actor *core.Record, activity pub.Activity) error {
followActivity := activity.Object.(*pub.Activity)
follower, err := app.FindFirstRecordByData("activitypub_actors", "iri", followActivity.Actor)
if err != nil {
return err
}
follow, err := app.FindFirstRecordByFilter("follows", "follower={:follower} && followee={:followee}", dbx.Params{"follower": follower.Id, "followee": actor.Id})
if err != nil {
return err
}
follow.Set("status", "accepted")
err = app.Save(follow)
if err != nil {
return err
}
// err = util.SyncOutbox(app, actor)
// if err != nil {
// return err
// }
return nil
}

118
db/federation/like.go Normal file
View File

@@ -0,0 +1,118 @@
package federation
import (
"fmt"
"os"
"path"
"pocketbase/util"
"time"
pub "github.com/go-ap/activitypub"
"github.com/pocketbase/pocketbase/core"
"github.com/pocketbase/pocketbase/tools/security"
)
// create outgoing follow activity
func CreateLikeActivity(app core.App, like *core.Record) error {
origin := os.Getenv("ORIGIN")
if origin == "" {
return fmt.Errorf("ORIGIN not set")
}
actor, err := app.FindRecordById("activitypub_actors", like.GetString("actor"))
if err != nil {
return err
}
trail, err := app.FindRecordById("trails", like.GetString("trail"))
if err != nil {
return err
}
trailAuthor, err := app.FindRecordById("activitypub_actors", trail.GetString("author"))
if err != nil {
return err
}
object := trail.GetString("iri")
if object == "" {
// trail is local
object = fmt.Sprintf("%s/api/v1/trail/%s", origin, trail.Id)
}
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)
activity := pub.LikeNew(pub.IRI(id), pub.IRI(object))
activity.Actor = pub.IRI(actor.GetString("iri"))
err = PostActivity(app, actor, activity, []string{trailAuthor.GetString("inbox")})
if err != nil {
return err
}
record := core.NewRecord(collection)
record.Set("id", recordId)
record.Set("iri", id)
record.Set("type", string(pub.LikeType))
record.Set("object", object)
record.Set("actor", actor.GetString("iri"))
record.Set("published", time.Now())
return app.Save(record)
}
// process incoming like activity
func ProcessLikeActivity(app core.App, actor *core.Record, activity pub.Activity) error {
origin := os.Getenv("ORIGIN")
if origin == "" {
return fmt.Errorf("ORIGIN not set")
}
trailId := path.Base(activity.Object.GetID().String())
trail, err := app.FindRecordById("trails", trailId)
if err != nil {
return err
}
trailAuthor, err := app.FindRecordById("activitypub_actors", trail.GetString("author"))
if err != nil {
return err
}
if !actor.GetBool("isLocal") {
trailLikeCollection, err := app.FindCollectionByNameOrId("trail_like")
if err != nil {
return err
}
likeRecord := core.NewRecord(trailLikeCollection)
likeRecord.Set("trail", trail.Id)
likeRecord.Set("actor", actor.Id)
err = app.Save(likeRecord)
if err != nil {
return err
}
}
// send a notification to the trail author
notification := util.Notification{
Type: util.TrailLike,
Metadata: map[string]string{
"trail_id": trail.Id,
"trail_name": trail.GetString("name"),
"trail_author": fmt.Sprintf("@%s", trailAuthor.GetString("preferred_username")),
"liker": fmt.Sprintf("@%s@%s", actor.GetString("preferred_username"), actor.GetString("domain")),
},
Seen: false,
Author: actor.Id,
}
return util.SendNotification(app, notification, trailAuthor)
}

194
db/federation/undo.go Normal file
View File

@@ -0,0 +1,194 @@
package federation
import (
"fmt"
"os"
"path"
"time"
pub "github.com/go-ap/activitypub"
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/core"
"github.com/pocketbase/pocketbase/tools/security"
)
// create outgoing follow activity
func CreateUnfollowActivity(app core.App, follow *core.Record) error {
origin := os.Getenv("ORIGIN")
if origin == "" {
return fmt.Errorf("ORIGIN not set")
}
follower := follow.GetString("follower")
followee := follow.GetString("followee")
followerActor, err := app.FindRecordById("activitypub_actors", follower)
if err != nil {
return err
}
followeeActor, err := app.FindRecordById("activitypub_actors", followee)
if err != nil {
return err
}
// find the original follow activity
followActivityRecord, err := app.FindFirstRecordByFilter("activitypub_activities", "actor={:actor}&&object={:object}&&type={:type}", dbx.Params{"actor": followerActor.GetString("iri"), "object": followeeActor.GetString("iri"), "type": string(pub.FollowType)})
if err != nil {
return err
}
followActivity := pub.FollowNew(pub.IRI(followActivityRecord.GetString("iri")), pub.IRI(followeeActor.GetString("iri")))
followActivity.Actor = pub.IRI(followActivityRecord.GetString("actor"))
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)
record := core.NewRecord(collection)
record.Set("id", recordId)
record.Set("iri", id)
record.Set("type", string(pub.UndoType))
record.Set("object", followActivity)
record.Set("actor", followerActor.GetString("iri"))
record.Set("published", time.Now())
err = app.Save(record)
if err != nil {
return err
}
activity := pub.UndoNew(pub.IRI(id), followActivity)
activity.Actor = pub.IRI(followerActor.GetString("iri"))
return PostActivity(app, followerActor, activity, []string{followeeActor.GetString("inbox")})
}
// create outgoing unlike activity
func CreateUnlikeActivity(app core.App, like *core.Record) error {
origin := os.Getenv("ORIGIN")
if origin == "" {
return fmt.Errorf("ORIGIN not set")
}
actor, err := app.FindRecordById("activitypub_actors", like.GetString("actor"))
if err != nil {
return err
}
trail, err := app.FindRecordById("trails", like.GetString("trail"))
if err != nil {
return err
}
trailAuthor, err := app.FindRecordById("activitypub_actors", trail.GetString("author"))
if err != nil {
return err
}
object := trail.GetString("iri")
if object == "" {
// trail is local
object = fmt.Sprintf("%s/api/v1/trail/%s", origin, trail.Id)
}
// find the original follow activity
likeActivityRecord, err := app.FindFirstRecordByFilter("activitypub_activities", "actor={:actor}&&object={:object}&&type={:type}", dbx.Params{"actor": actor.GetString("iri"), "object": object, "type": string(pub.LikeType)})
if err != nil {
return err
}
likeActivity := pub.LikeNew(pub.IRI(likeActivityRecord.GetString("iri")), pub.IRI(object))
likeActivity.Actor = pub.IRI(likeActivityRecord.GetString("actor"))
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)
record := core.NewRecord(collection)
record.Set("id", recordId)
record.Set("iri", id)
record.Set("type", string(pub.UndoType))
record.Set("object", likeActivity)
record.Set("actor", actor.GetString("iri"))
record.Set("published", time.Now())
err = app.Save(record)
if err != nil {
return err
}
activity := pub.UndoNew(pub.IRI(id), likeActivity)
activity.Actor = pub.IRI(actor.GetString("iri"))
return PostActivity(app, actor, activity, []string{trailAuthor.GetString("inbox")})
}
func ProcessUndoActivity(app core.App, actor *core.Record, activity pub.Activity) error {
if activity.Object.GetType() == pub.FollowType {
return processUnfollowActivity(app, actor, activity)
} else if activity.Object.GetType() == pub.LikeType {
return processUnlikeActivity(app, actor, activity)
} else {
return fmt.Errorf("unknown undo activity object type")
}
}
func processUnfollowActivity(app core.App, actor *core.Record, activity pub.Activity) error {
// this was a local follow
if actor.GetBool("isLocal") {
return nil
}
followActivity := activity.Object.(*pub.Activity)
followee, err := app.FindFirstRecordByData("activitypub_actors", "iri", followActivity.Object)
if err != nil {
return err
}
follow, err := app.FindFirstRecordByFilter("follows", "follower={:follower} && followee={:followee}", dbx.Params{"follower": actor.Id, "followee": followee.Id})
if err != nil {
return err
}
err = app.Delete(follow)
if err != nil {
return err
}
return nil
}
func processUnlikeActivity(app core.App, actor *core.Record, activity pub.Activity) error {
if actor.GetBool("isLocal") {
return nil
}
likeActivity := activity.Object.(*pub.Activity)
trailId := path.Base(likeActivity.Object.GetID().String())
trail, err := app.FindRecordById("trails", trailId)
if err != nil {
return err
}
like, err := app.FindFirstRecordByFilter("trail_like", "actor={:actor} && trail={:trail}", dbx.Params{"actor": actor.Id, "trail": trail.Id})
if err != nil {
return err
}
err = app.Delete(like)
if err != nil {
return err
}
return nil
}

View File

@@ -11,9 +11,15 @@ require (
)
require (
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 // indirect
github.com/aymerick/douceur v0.2.0 // indirect
github.com/go-ap/errors v0.0.0-20250409143711-5686c11ae650 // indirect
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73 // indirect
github.com/go-sql-driver/mysql v1.8.1 // indirect
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
github.com/gorilla/css v1.0.1 // indirect
github.com/twpayne/go-geom v1.6.1 // indirect
github.com/valyala/fastjson v1.6.4 // indirect
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect
)
@@ -26,6 +32,8 @@ require (
github.com/fatih/color v1.18.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
github.com/ganigeorgiev/fexpr v0.4.1 // indirect
github.com/go-ap/activitypub v0.0.0-20250409143848-7113328b1f3d
github.com/go-fed/httpsig v1.1.0
github.com/go-ozzo/ozzo-validation/v4 v4.3.0 // indirect
github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
github.com/google/uuid v1.6.0 // indirect
@@ -34,6 +42,7 @@ require (
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/microcosm-cc/bluemonday v1.0.27
github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/spf13/cast v1.7.1

View File

@@ -1,5 +1,7 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 h1:cliQ4HHsCo6xi2oWZYKWW4bly/Ory9FuTpFPRxj/mAg=
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078/go.mod h1:g/V2Hjas6Z1UHUp4yIx6bATpNzJ7DYtD0FG3+xARWxs=
github.com/alecthomas/assert/v2 v2.10.0 h1:jjRCHsj6hBJhkmhznrCzoNpbA3zqy0fYiUcYZP/GkPY=
github.com/alecthomas/assert/v2 v2.10.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
@@ -9,6 +11,8 @@ github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer5
github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@@ -28,6 +32,14 @@ github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3G
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
github.com/ganigeorgiev/fexpr v0.4.1 h1:hpUgbUEEWIZhSDBtf4M9aUNfQQ0BZkGRaMePy7Gcx5k=
github.com/ganigeorgiev/fexpr v0.4.1/go.mod h1:RyGiGqmeXhEQ6+mlGdnUleLHgtzzu/VGO2WtJkF5drE=
github.com/go-ap/activitypub v0.0.0-20250409143848-7113328b1f3d h1:IWrWGnmKzpHqginJ18ljKkty/X8glxM8Mg3pk6bkb8g=
github.com/go-ap/activitypub v0.0.0-20250409143848-7113328b1f3d/go.mod h1:EUtZuXtHo4yKkTJmcbAZYW+X1G2poeT8icmBh24eq7o=
github.com/go-ap/errors v0.0.0-20250409143711-5686c11ae650 h1:tlwla5IQUea0CuktkBd2FLDwVzts4OeTWPPkhQPSK5Q=
github.com/go-ap/errors v0.0.0-20250409143711-5686c11ae650/go.mod h1:Vkh+Z3f24K8nMsJKXo1FHn5ebPsXvB/WDH5JRtYqdNo=
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73 h1:GMKIYXyXPGIp+hYiWOhfqK4A023HdgisDT4YGgf99mw=
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73/go.mod h1:jyveZeGw5LaADntW+UEsMjl3IlIwk+DxlYNsbofQkGA=
github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI=
github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM=
github.com/go-ozzo/ozzo-validation/v4 v4.3.0 h1:byhDUpfEwjsVQb1vBunvIjh2BHQ9ead57VkAEY4V+Es=
github.com/go-ozzo/ozzo-validation/v4 v4.3.0/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRiTzuqKbvfrL2RxCj6Ew=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
@@ -45,6 +57,8 @@ github.com/google/pprof v0.0.0-20250315033105-103756e64e1d h1:tx51Lf+wdE+aavqH8T
github.com/google/pprof v0.0.0-20250315033105-103756e64e1d/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
@@ -63,6 +77,8 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/meilisearch/meilisearch-go v0.29.0 h1:HZ9NEKN59USINQ/DXJge/aaXq8IrsKbXGTdAoBaaDz4=
github.com/meilisearch/meilisearch-go v0.29.0/go.mod h1:2cRCAn4ddySUsFfNDLVPod/plRibQsJkXF/4gLhxbOk=
github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -99,7 +115,10 @@ github.com/twpayne/go-gpx v1.5.0 h1:HvFSJ+0r0sbhOQ8mTvd0/n0FhcgjTFsKQGG6o7PV6G4=
github.com/twpayne/go-gpx v1.5.0/go.mod h1:vjvu/125399qj6k+px2v2v8dm08DM4I4dFBJmHHt2TE=
github.com/twpayne/go-polyline v1.1.1 h1:/tSF1BR7rN4HWj4XKqvRUNrCiYVMCvywxTFVofvDV0w=
github.com/twpayne/go-polyline v1.1.1/go.mod h1:ybd9IWWivW/rlXPXuuckeKUyF3yrIim+iqA7kSl4NFY=
github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw=
@@ -109,6 +128,7 @@ golang.org/x/image v0.25.0 h1:Y6uW6rH1y5y/LK1J8BPWZtr6yZ7hrsy6hFrXjgsc2fQ=
golang.org/x/image v0.25.0/go.mod h1:tCAmOEGthTtkalusGp1g3xa2gke8J6c2N565dTyl9Rs=
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
@@ -117,6 +137,7 @@ golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=

View File

@@ -33,6 +33,15 @@ func SyncKomoot(app core.App) error {
}
userId := i.GetString("user")
actor, err := app.FindFirstRecordByData("activitypub_actors", "user", userId)
if err != nil {
warning := fmt.Sprintf("no actor found for user: %s\n", userId)
fmt.Print(warning)
app.Logger().Warn(warning)
continue
}
actorId := actor.Id
komootString := i.GetString("komoot")
komootIntegration := KomootIntegration{
Planned: true,
@@ -71,7 +80,7 @@ func SyncKomoot(app core.App) error {
continue
}
hasNewTours, err = syncTrailWithTours(app, k, komootIntegration, userId, tours)
hasNewTours, err = syncTrailWithTours(app, k, komootIntegration, userId, actorId, tours)
if err != nil {
warning := fmt.Sprintf("error syncing komoot tours with trails: %v\n", err)
fmt.Print(warning)
@@ -165,7 +174,7 @@ func (k *KomootApi) fetchTours(page int) ([]KomootTour, error) {
}
func (k *KomootApi) fetchDetailedTour(tour KomootTour) (*DetailedKomootTour, error) {
url := fmt.Sprintf("https://api.komoot.de/v007/tours/%d?_embedded=coordinates,way_types,surfaces,directions,participants,timeline,cover_images&directions=v2&fields=timeline&format=coordinate_array&timeline_highlights_fields=tips,recommenders", tour.ID)
url := fmt.Sprintf("https://api.komoot.de/v007/tours/%d?_embedded=coordinates,way_types,surfaces,directions,participants,timeline,cover_images&directions=v2&fields=timeline&format=coordinate_array&timeline_highlights_fields=tips,recommenders&page=2", tour.ID)
body, err := sendRequest(url, k.buildHeader())
if err != nil {
return nil, err
@@ -176,7 +185,7 @@ func (k *KomootApi) fetchDetailedTour(tour KomootTour) (*DetailedKomootTour, err
return data, nil
}
func syncTrailWithTours(app core.App, k *KomootApi, i KomootIntegration, user string, tours []KomootTour) (bool, error) {
func syncTrailWithTours(app core.App, k *KomootApi, i KomootIntegration, user string, actor string, tours []KomootTour) (bool, error) {
hasNewTours := false
for _, tour := range tours {
trails, err := app.FindRecordsByFilter("trails", "external_id = {:id}", "", 1, 0, dbx.Params{"id": strconv.Itoa(int(tour.ID))})
@@ -202,7 +211,7 @@ func syncTrailWithTours(app core.App, k *KomootApi, i KomootIntegration, user st
app.Logger().Warn(fmt.Sprintf("Unable to create waypoints for tour '%s': %v", tour.Name, err))
continue
}
err = createTrailFromTour(app, detailedTour, gpx, user, wpIds)
err = createTrailFromTour(app, k, detailedTour, gpx, actor, wpIds)
if err != nil {
app.Logger().Warn(fmt.Sprintf("Unable to create trail for tour '%s': %v", tour.Name, err))
continue
@@ -212,27 +221,9 @@ func syncTrailWithTours(app core.App, k *KomootApi, i KomootIntegration, user st
return hasNewTours, nil
}
func createTrailFromTour(app core.App, detailedTour *DetailedKomootTour, gpx *filesystem.File, user string, wpIds []string) error {
var summitLogRecord *core.Record
if detailedTour.Type == "tour_recorded" {
collection, err := app.FindCollectionByNameOrId("summit_logs")
if err != nil {
return err
}
func createTrailFromTour(app core.App, k *KomootApi, detailedTour *DetailedKomootTour, gpx *filesystem.File, actor string, wpIds []string) error {
trailid := security.RandomStringWithAlphabet(core.DefaultIdLength, core.DefaultIdAlphabet)
summitLogRecord = core.NewRecord(collection)
summitLogRecord.Load(map[string]any{
"distance": detailedTour.Distance,
"elevation_gain": detailedTour.ElevationUp,
"elevation_loss": detailedTour.ElevationDown,
"duration": detailedTour.Duration,
"date": detailedTour.Date,
"author": user,
})
if err := app.Save(summitLogRecord); err != nil {
return err
}
}
collection, err := app.FindCollectionByNameOrId("trails")
if err != nil {
return err
@@ -259,7 +250,7 @@ func createTrailFromTour(app core.App, detailedTour *DetailedKomootTour, gpx *fi
var photos []*filesystem.File
if len(detailedTour.Embedded.CoverImages.Embedded.Items) > 0 {
photos, err = fetchRoutePhotos(detailedTour)
photos, err = fetchRoutePhotos(k, detailedTour)
if err != nil {
return err
}
@@ -277,12 +268,13 @@ func createTrailFromTour(app core.App, detailedTour *DetailedKomootTour, gpx *fi
}
record.Load(map[string]any{
"id": trailid,
"name": detailedTour.Name,
"public": detailedTour.Status == "public",
"distance": detailedTour.Distance,
"elevation_gain": detailedTour.ElevationUp,
"elevation_loss": detailedTour.ElevationDown,
"duration": detailedTour.Duration / 60,
"duration": detailedTour.Duration,
"date": detailedTour.Date,
"external_provider": "komoot",
"external_id": strconv.Itoa(detailedTour.ID),
@@ -291,12 +283,9 @@ func createTrailFromTour(app core.App, detailedTour *DetailedKomootTour, gpx *fi
"difficulty": diffculty,
"category": categoryId,
"waypoints": wpIds,
"author": user,
"author": actor,
})
if summitLogRecord != nil {
record.Set("summit_logs", summitLogRecord.Id)
}
if photos != nil {
record.Set("photos", photos)
}
@@ -308,6 +297,27 @@ func createTrailFromTour(app core.App, detailedTour *DetailedKomootTour, gpx *fi
return err
}
if detailedTour.Type == "tour_recorded" {
collection, err := app.FindCollectionByNameOrId("summit_logs")
if err != nil {
return err
}
summitLogRecord := core.NewRecord(collection)
summitLogRecord.Load(map[string]any{
"distance": detailedTour.Distance,
"elevation_gain": detailedTour.ElevationUp,
"elevation_loss": detailedTour.ElevationDown,
"duration": detailedTour.Duration,
"date": detailedTour.Date,
"author": actor,
"trail": trailid,
})
if err := app.Save(summitLogRecord); err != nil {
return err
}
}
return nil
}
@@ -365,11 +375,22 @@ func createWaypointsFromTour(app core.App, tour *DetailedKomootTour, user string
return wpIds, nil
}
func fetchRoutePhotos(tour *DetailedKomootTour) ([]*filesystem.File, error) {
func fetchRoutePhotos(k *KomootApi, tour *DetailedKomootTour) ([]*filesystem.File, error) {
url := fmt.Sprintf("https://api.komoot.de/v007/tours/%d/cover_images/", tour.ID)
body, err := sendRequest(url, k.buildHeader())
if err != nil {
return nil, err
}
photos := make([]*filesystem.File, len(tour.Embedded.CoverImages.Embedded.Items))
var data *CoverImages
err = json.Unmarshal(body, &data)
if err != nil {
return nil, err
}
for i, img := range tour.Embedded.CoverImages.Embedded.Items {
photos := make([]*filesystem.File, data.Page.TotalElements)
for i, img := range data.Embedded.Items {
photo, err := fetchPhoto(img.Src, "", "")
if err != nil {
return nil, err

View File

@@ -36,9 +36,18 @@ func SyncStrava(app core.App) error {
}
userId := i.GetString("user")
actor, err := app.FindFirstRecordByData("activitypub_actors", "user", userId)
if err != nil {
warning := fmt.Sprintf("no actor found for user: %s\n", userId)
fmt.Print(warning)
app.Logger().Warn(warning)
continue
}
actorId := actor.Id
stravaString := i.GetString("strava")
var stravaIntegration StravaIntegration
err := json.Unmarshal([]byte(stravaString), &stravaIntegration)
err = json.Unmarshal([]byte(stravaString), &stravaIntegration)
if err != nil {
return err
}
@@ -103,7 +112,7 @@ func SyncStrava(app core.App) error {
app.Logger().Warn(warning)
break
}
hasNewRoutes, err = syncTrailsWithRoutes(app, r.AccessToken, userId, routes)
hasNewRoutes, err = syncTrailsWithRoutes(app, r.AccessToken, userId, actorId, routes)
if err != nil {
warning := fmt.Sprintf("error syncing strava routes with trails: %v\n", err)
fmt.Print(warning)
@@ -124,7 +133,7 @@ func SyncStrava(app core.App) error {
app.Logger().Warn(warning)
break
}
hasNewActivities, err = syncTrailsWithActivities(app, r.AccessToken, userId, activities)
hasNewActivities, err = syncTrailsWithActivities(app, r.AccessToken, userId, actorId, activities)
if err != nil {
warning := fmt.Sprintf("error syncing strava activities with trails: %v", err)
fmt.Print(warning)
@@ -226,7 +235,7 @@ func fetchStravaActivities(accessToken string, page int) ([]StravaActivity, erro
return activities, nil
}
func syncTrailsWithRoutes(app core.App, accessToken string, user string, routes []StravaRoute) (bool, error) {
func syncTrailsWithRoutes(app core.App, accessToken string, user string, actor string, routes []StravaRoute) (bool, error) {
hasNewRoutes := false
for _, route := range routes {
trails, err := app.FindRecordsByFilter("trails", "external_id = {:id}", "", 1, 0, dbx.Params{"id": route.IDStr})
@@ -247,7 +256,7 @@ func syncTrailsWithRoutes(app core.App, accessToken string, user string, routes
app.Logger().Warn(fmt.Sprintf("Unable to create waypoints for route '%s': %v", route.Name, err))
continue
}
err = createTrailFromRoute(app, route, gpx, user, wpIds)
err = createTrailFromRoute(app, route, gpx, actor, wpIds)
if err != nil {
app.Logger().Warn(fmt.Sprintf("Unable to create trail for route '%s': %v", route.Name, err))
continue
@@ -296,7 +305,7 @@ func fetchRouteGPX(route StravaRoute, accessToken string) (*filesystem.File, err
return gpxFile, nil
}
func createTrailFromRoute(app core.App, route StravaRoute, gpx *filesystem.File, user string, wpIds []string) error {
func createTrailFromRoute(app core.App, route StravaRoute, gpx *filesystem.File, actor string, wpIds []string) error {
collection, err := app.FindCollectionByNameOrId("trails")
if err != nil {
return err
@@ -333,7 +342,7 @@ func createTrailFromRoute(app core.App, route StravaRoute, gpx *filesystem.File,
"public": !route.Private,
"distance": route.Distance,
"elevation_gain": route.ElevationGain,
"duration": route.EstimatedMovingTime / 60,
"duration": route.EstimatedMovingTime,
"date": time.Unix(int64(route.Timestamp), 0),
"external_provider": "strava",
"external_id": route.IDStr,
@@ -342,7 +351,7 @@ func createTrailFromRoute(app core.App, route StravaRoute, gpx *filesystem.File,
"waypoints": wpIds,
"difficulty": "easy",
"category": category,
"author": user,
"author": actor,
})
if gpx != nil {
@@ -383,7 +392,7 @@ func createWaypointsFromRoute(app core.App, route StravaRoute, user string) ([]s
return wpIds, nil
}
func syncTrailsWithActivities(app core.App, accessToken string, user string, activities []StravaActivity) (bool, error) {
func syncTrailsWithActivities(app core.App, accessToken string, user string, actor string, activities []StravaActivity) (bool, error) {
hasNewActivites := false
for _, activity := range activities {
trails, err := app.FindRecordsByFilter("trails", "external_id = {:id}", "", 1, 0, dbx.Params{"id": strconv.Itoa(int(activity.ID))})
@@ -404,7 +413,7 @@ func syncTrailsWithActivities(app core.App, accessToken string, user string, act
app.Logger().Warn(fmt.Sprintf("Unable to fetch GPX for activity '%s': %v", activity.Name, err))
continue
}
err = createTrailFromActivity(app, detailedActivity, gpx, user)
err = createTrailFromActivity(app, detailedActivity, gpx, actor)
if err != nil {
app.Logger().Warn(fmt.Sprintf("Unable to create trail from activity '%s': %v", activity.Name, err))
continue
@@ -514,7 +523,7 @@ func createTrailFromActivity(app core.App, activity *DetailedStravaActivity, gpx
"public": !activity.Private,
"distance": activity.Distance,
"elevation_gain": activity.TotalElevationGain,
"duration": activity.ElapsedTime / 60,
"duration": activity.ElapsedTime,
"date": activity.StartDate,
"external_provider": "strava",
"external_id": activity.ID,

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,102 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("j6w72f0kb5ivd7x")
if err != nil {
return nil
}
return app.Delete(collection)
}, func(app core.App) error {
jsonData := `{
"createRule": null,
"deleteRule": null,
"fields": [
{
"autogeneratePattern": "",
"hidden": false,
"id": "text3208210256",
"max": 0,
"min": 0,
"name": "id",
"pattern": "^[a-z0-9]+$",
"presentable": false,
"primaryKey": true,
"required": true,
"system": true,
"type": "text"
},
{
"cascadeDelete": false,
"collectionId": "pbc_1295301207",
"hidden": false,
"id": "relation1148540665",
"maxSelect": 1,
"minSelect": 0,
"name": "actor",
"presentable": false,
"required": false,
"system": false,
"type": "relation"
},
{
"cascadeDelete": true,
"collectionId": "_pb_users_auth_",
"hidden": false,
"id": "_clone_kce8",
"maxSelect": 1,
"minSelect": 0,
"name": "user",
"presentable": false,
"required": false,
"system": false,
"type": "relation"
},
{
"hidden": false,
"id": "json2215181735",
"maxSize": 1,
"name": "followers",
"presentable": false,
"required": false,
"system": false,
"type": "json"
},
{
"hidden": false,
"id": "json1908379107",
"maxSize": 1,
"name": "following",
"presentable": false,
"required": false,
"system": false,
"type": "json"
}
],
"id": "j6w72f0kb5ivd7x",
"indexes": [],
"listRule": "@request.auth.id = user || (@collection.users_anonymous.id ?= user && @collection.users_anonymous.private ?= false)",
"name": "follow_counts",
"system": false,
"type": "view",
"updateRule": null,
"viewQuery": "SELECT \n (ROW_NUMBER() OVER()) as id,\n activitypub_actors.id as actor,\n activitypub_actors.user as user,\n COALESCE(followers.count, 0) AS followers,\n COALESCE(following.count, 0) AS following\nFROM activitypub_actors\nLEFT JOIN (\n SELECT followee AS actor_id, COUNT(*) AS count\n FROM follows\n GROUP BY followee\n) AS followers ON activitypub_actors.id = followers.actor_id\nLEFT JOIN (\n SELECT follower AS actor_id, COUNT(*) AS count\n FROM follows\n GROUP BY follower\n) AS following ON activitypub_actors.id = following.actor_id",
"viewRule": "@request.auth.id = user || (@collection.users_anonymous.id ?= user && @collection.users_anonymous.private ?= false)"
}`
collection := &core.Collection{}
if err := json.Unmarshal([]byte(jsonData), &collection); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,186 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("t9lphichi5xwyeu")
if err != nil {
return nil
}
return app.Delete(collection)
}, func(app core.App) error {
jsonData := `{
"createRule": null,
"deleteRule": null,
"fields": [
{
"autogeneratePattern": "",
"hidden": false,
"id": "text3208210256",
"max": 0,
"min": 0,
"name": "id",
"pattern": "^[a-z0-9]+$",
"presentable": false,
"primaryKey": true,
"required": true,
"system": true,
"type": "text"
},
{
"hidden": false,
"id": "json2310347867",
"maxSize": 1,
"name": "trail_id",
"presentable": false,
"required": false,
"system": false,
"type": "json"
},
{
"hidden": false,
"id": "json2862495610",
"maxSize": 1,
"name": "date",
"presentable": false,
"required": false,
"system": false,
"type": "json"
},
{
"hidden": false,
"id": "json1579384326",
"maxSize": 1,
"name": "name",
"presentable": false,
"required": false,
"system": false,
"type": "json"
},
{
"hidden": false,
"id": "json1843675174",
"maxSize": 1,
"name": "description",
"presentable": false,
"required": false,
"system": false,
"type": "json"
},
{
"hidden": false,
"id": "json3275261007",
"maxSize": 1,
"name": "gpx",
"presentable": false,
"required": false,
"system": false,
"type": "json"
},
{
"hidden": false,
"id": "json3182418120",
"maxSize": 1,
"name": "author",
"presentable": false,
"required": false,
"system": false,
"type": "json"
},
{
"hidden": false,
"id": "json142008537",
"maxSize": 1,
"name": "photos",
"presentable": false,
"required": false,
"system": false,
"type": "json"
},
{
"hidden": false,
"id": "json479369857",
"maxSize": 1,
"name": "distance",
"presentable": false,
"required": false,
"system": false,
"type": "json"
},
{
"hidden": false,
"id": "json2254405824",
"maxSize": 1,
"name": "duration",
"presentable": false,
"required": false,
"system": false,
"type": "json"
},
{
"hidden": false,
"id": "json3015100073",
"maxSize": 1,
"name": "elevation_gain",
"presentable": false,
"required": false,
"system": false,
"type": "json"
},
{
"hidden": false,
"id": "json3171089056",
"maxSize": 1,
"name": "elevation_loss",
"presentable": false,
"required": false,
"system": false,
"type": "json"
},
{
"hidden": false,
"id": "json2990389176",
"maxSize": 1,
"name": "created",
"presentable": false,
"required": false,
"system": false,
"type": "json"
},
{
"hidden": false,
"id": "json2363381545",
"maxSize": 1,
"name": "type",
"presentable": false,
"required": false,
"system": false,
"type": "json"
}
],
"id": "t9lphichi5xwyeu",
"indexes": [],
"listRule": "(@collection.users_anonymous.id ?= author && @collection.users_anonymous.private ?= false\n&&\n@collection.trails.id ?= trail_id && \n (\n @collection.trails.author ?= @request.auth.id ||\n @collection.trails.public ?= true || \n (@request.auth.id != \"\" && @collection.trails.trail_share_via_trail.user ?= @request.auth.id)\n )) && @request.auth.id = author",
"name": "activities",
"system": false,
"type": "view",
"updateRule": null,
"viewQuery": "SELECT id,trail_id,date,name,description,gpx,author,photos,distance,duration,elevation_gain,elevation_loss,created,type \nFROM (\n SELECT summit_logs.id,trails.id as trail_id,summit_logs.date,trails.name,text as description,summit_logs.gpx,summit_logs.author,summit_logs.photos,summit_logs.distance,summit_logs.duration,summit_logs.elevation_gain,summit_logs.elevation_loss,summit_logs.created,\"summit_log\" as type \n FROM summit_logs\n JOIN trails ON summit_logs.id IN (\n SELECT value\n FROM json_each(trails.summit_logs)\n )\n UNION\n SELECT id,id as trail_id,date,name,description,gpx,author,photos,distance,duration,elevation_gain,elevation_loss,created,\"trail\" as type \n FROM trails\n)\nORDER BY created DESC",
"viewRule": "(@collection.users_anonymous.id ?= author && @collection.users_anonymous.private ?= false\n&&\n@collection.trails.id ?= trail_id && \n (\n @collection.trails.author ?= @request.auth.id ||\n @collection.trails.public ?= true || \n (@request.auth.id != \"\" && @collection.trails.trail_share_via_trail.user ?= @request.auth.id)\n )) && @request.auth.id = author"
}`
collection := &core.Collection{}
if err := json.Unmarshal([]byte(jsonData), &collection); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,285 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
jsonData := `[
{
"id": "pbc_1295301207",
"listRule": "",
"viewRule": "",
"createRule": null,
"updateRule": null,
"deleteRule": null,
"name": "activitypub_actors",
"type": "base",
"fields": [
{
"autogeneratePattern": "[a-z0-9]{15}",
"hidden": false,
"id": "text3208210256",
"max": 15,
"min": 15,
"name": "id",
"pattern": "^[a-z0-9]+$",
"presentable": false,
"primaryKey": true,
"required": true,
"system": true,
"type": "text"
},
{
"autogeneratePattern": "",
"hidden": false,
"id": "text4166911607",
"max": 0,
"min": 0,
"name": "username",
"pattern": "",
"presentable": false,
"primaryKey": false,
"required": true,
"system": false,
"type": "text"
},
{
"autogeneratePattern": "",
"hidden": false,
"id": "text4002953752",
"max": 0,
"min": 0,
"name": "preferred_username",
"pattern": "",
"presentable": false,
"primaryKey": false,
"required": false,
"system": false,
"type": "text"
},
{
"autogeneratePattern": "",
"hidden": false,
"id": "text2812878347",
"max": 0,
"min": 0,
"name": "domain",
"pattern": "",
"presentable": false,
"primaryKey": false,
"required": false,
"system": false,
"type": "text"
},
{
"autogeneratePattern": "",
"hidden": false,
"id": "text3458754147",
"max": 0,
"min": 0,
"name": "summary",
"pattern": "",
"presentable": false,
"primaryKey": false,
"required": false,
"system": false,
"type": "text"
},
{
"hidden": false,
"id": "number1386272118",
"max": null,
"min": null,
"name": "followerCount",
"onlyInt": true,
"presentable": false,
"required": false,
"system": false,
"type": "number"
},
{
"hidden": false,
"id": "number3430500629",
"max": null,
"min": null,
"name": "followingCount",
"onlyInt": true,
"presentable": false,
"required": false,
"system": false,
"type": "number"
},
{
"hidden": false,
"id": "date1748787223",
"max": "",
"min": "",
"name": "published",
"presentable": false,
"required": false,
"system": false,
"type": "date"
},
{
"exceptDomains": null,
"hidden": false,
"id": "url126331327",
"name": "iri",
"onlyDomains": null,
"presentable": false,
"required": true,
"system": false,
"type": "url"
},
{
"exceptDomains": null,
"hidden": false,
"id": "url2115105593",
"name": "inbox",
"onlyDomains": null,
"presentable": false,
"required": true,
"system": false,
"type": "url"
},
{
"exceptDomains": null,
"hidden": false,
"id": "url1793578352",
"name": "outbox",
"onlyDomains": null,
"presentable": false,
"required": false,
"system": false,
"type": "url"
},
{
"exceptDomains": null,
"hidden": false,
"id": "url1704208859",
"name": "icon",
"onlyDomains": null,
"presentable": false,
"required": false,
"system": false,
"type": "url"
},
{
"exceptDomains": null,
"hidden": false,
"id": "url2215181735",
"name": "followers",
"onlyDomains": null,
"presentable": false,
"required": false,
"system": false,
"type": "url"
},
{
"exceptDomains": null,
"hidden": false,
"id": "url1908379107",
"name": "following",
"onlyDomains": null,
"presentable": false,
"required": false,
"system": false,
"type": "url"
},
{
"hidden": false,
"id": "bool2193750486",
"name": "isLocal",
"presentable": false,
"required": false,
"system": false,
"type": "bool"
},
{
"autogeneratePattern": "",
"hidden": false,
"id": "text1727648867",
"max": 0,
"min": 0,
"name": "public_key",
"pattern": "",
"presentable": false,
"primaryKey": false,
"required": true,
"system": false,
"type": "text"
},
{
"autogeneratePattern": "",
"hidden": true,
"id": "text4160324774",
"max": 0,
"min": 0,
"name": "private_key",
"pattern": "",
"presentable": false,
"primaryKey": false,
"required": false,
"system": false,
"type": "text"
},
{
"cascadeDelete": true,
"collectionId": "_pb_users_auth_",
"hidden": false,
"id": "relation2375276105",
"maxSelect": 1,
"minSelect": 0,
"name": "user",
"presentable": false,
"required": false,
"system": false,
"type": "relation"
},
{
"hidden": false,
"id": "date2062531289",
"max": "",
"min": "",
"name": "last_fetched",
"presentable": false,
"required": false,
"system": false,
"type": "date"
},
{
"hidden": false,
"id": "autodate2990389176",
"name": "created",
"onCreate": true,
"onUpdate": false,
"presentable": false,
"system": false,
"type": "autodate"
},
{
"hidden": false,
"id": "autodate3332085495",
"name": "updated",
"onCreate": true,
"onUpdate": true,
"presentable": false,
"system": false,
"type": "autodate"
}
],
"indexes": [
"CREATE UNIQUE INDEX ` + "`idx_rpT7QJwWTm` ON `activitypub_actors` (`iri`)" + `"
],
"system": false
}
]`
return app.ImportCollectionsByMarshaledJSON([]byte(jsonData), false)
}, func(app core.App) error {
return nil
})
}

View File

@@ -0,0 +1,156 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
jsonData := `[
{
"id": "pbc_3752774184",
"listRule": "",
"viewRule": "",
"createRule": null,
"updateRule": null,
"deleteRule": null,
"name": "activitypub_activities",
"type": "base",
"fields": [
{
"autogeneratePattern": "[a-z0-9]{15}",
"hidden": false,
"id": "text3208210256",
"max": 15,
"min": 15,
"name": "id",
"pattern": "^[a-z0-9]+$",
"presentable": false,
"primaryKey": true,
"required": true,
"system": true,
"type": "text"
},
{
"exceptDomains": [],
"hidden": false,
"id": "url2434853685",
"name": "iri",
"onlyDomains": [],
"presentable": false,
"required": true,
"system": false,
"type": "url"
},
{
"autogeneratePattern": "",
"hidden": false,
"id": "text2363381545",
"max": 0,
"min": 0,
"name": "type",
"pattern": "",
"presentable": false,
"primaryKey": false,
"required": true,
"system": false,
"type": "text"
},
{
"hidden": false,
"id": "json3616002756",
"maxSize": 0,
"name": "to",
"presentable": false,
"required": false,
"system": false,
"type": "json"
},
{
"hidden": false,
"id": "json3685882489",
"maxSize": 0,
"name": "cc",
"presentable": false,
"required": false,
"system": false,
"type": "json"
},
{
"hidden": false,
"id": "json2893285722",
"maxSize": 0,
"name": "object",
"presentable": false,
"required": true,
"system": false,
"type": "json"
},
{
"exceptDomains": [],
"hidden": false,
"id": "url1148540665",
"name": "actor",
"onlyDomains": [],
"presentable": false,
"required": true,
"system": false,
"type": "url"
},
{
"hidden": false,
"id": "date1748787223",
"max": "",
"min": "",
"name": "published",
"presentable": false,
"required": true,
"system": false,
"type": "date"
},
{
"autogeneratePattern": "",
"hidden": false,
"id": "text1653163849",
"max": 15,
"min": 15,
"name": "relation",
"pattern": "^[a-z0-9]+$",
"presentable": false,
"primaryKey": false,
"required": false,
"system": false,
"type": "text"
},
{
"hidden": false,
"id": "autodate2990389176",
"name": "created",
"onCreate": true,
"onUpdate": false,
"presentable": false,
"system": false,
"type": "autodate"
},
{
"hidden": false,
"id": "autodate3332085495",
"name": "updated",
"onCreate": true,
"onUpdate": true,
"presentable": false,
"system": false,
"type": "autodate"
}
],
"indexes": [],
"system": false
}
]`
return app.ImportCollectionsByMarshaledJSON([]byte(jsonData), false)
}, func(app core.App) error {
return nil
})
}

View File

@@ -0,0 +1,30 @@
package migrations
import (
"pocketbase/util"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
users, err := app.FindAllRecords("users")
if err != nil {
return err
}
for _, u := range users {
_, err = util.ActorFromUser(app, u)
if err != nil {
return err
}
}
return nil
}, func(app core.App) error {
// add down queries...
return nil
})
}

View File

@@ -0,0 +1,78 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("e864strfxo14pm4")
if err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(15, []byte(`{
"cascadeDelete": true,
"collectionId": "pbc_1295301207",
"hidden": false,
"id": "relation3182418120",
"maxSelect": 1,
"minSelect": 0,
"name": "author",
"presentable": false,
"required": true,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
// update field
if err := collection.Fields.AddMarshaledJSONAt(16, []byte(`{
"cascadeDelete": true,
"collectionId": "_pb_users_auth_",
"hidden": false,
"id": "1utgul91",
"maxSelect": 1,
"minSelect": 0,
"name": "user",
"presentable": false,
"required": false,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("e864strfxo14pm4")
if err != nil {
return err
}
// remove field
collection.Fields.RemoveById("relation3182418120")
// update field
if err := collection.Fields.AddMarshaledJSONAt(15, []byte(`{
"cascadeDelete": true,
"collectionId": "_pb_users_auth_",
"hidden": false,
"id": "1utgul91",
"maxSelect": 1,
"minSelect": 0,
"name": "author",
"presentable": false,
"required": true,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,33 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
trails, err := app.FindAllRecords("trails")
if err != nil {
return err
}
for _, t := range trails {
actor, err := app.FindFirstRecordByData("activitypub_actors", "user", t.GetString("user"))
if err != nil {
return err
}
t.Set("author", actor.Id)
err = app.UnsafeWithoutHooks().Save(t)
if err != nil {
return err
}
}
return nil
}, func(app core.App) error {
// add down queries...
return nil
})
}

View File

@@ -0,0 +1,78 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("comments")
if err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(3, []byte(`{
"cascadeDelete": false,
"collectionId": "pbc_1295301207",
"hidden": false,
"id": "relation3182418120",
"maxSelect": 1,
"minSelect": 0,
"name": "author",
"presentable": false,
"required": true,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
// update field
if err := collection.Fields.AddMarshaledJSONAt(16, []byte(`{
"cascadeDelete": true,
"collectionId": "_pb_users_auth_",
"hidden": false,
"id": "7lwo1mxx",
"maxSelect": 1,
"minSelect": 0,
"name": "user",
"presentable": false,
"required": false,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("comments")
if err != nil {
return err
}
// remove field
collection.Fields.RemoveById("relation3182418120")
// update field
if err := collection.Fields.AddMarshaledJSONAt(15, []byte(`{
"cascadeDelete": true,
"collectionId": "_pb_users_auth_",
"hidden": false,
"id": "7lwo1mxx",
"maxSelect": 1,
"minSelect": 0,
"name": "author",
"presentable": false,
"required": true,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,33 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
comments, err := app.FindAllRecords("comments")
if err != nil {
return err
}
for _, c := range comments {
actor, err := app.FindFirstRecordByData("activitypub_actors", "user", c.GetString("user"))
if err != nil {
continue
}
c.Set("author", actor.Id)
err = app.UnsafeWithoutHooks().Save(c)
if err != nil {
continue
}
}
return nil
}, func(app core.App) error {
// add down queries...
return nil
})
}

View File

@@ -0,0 +1,78 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("summit_logs")
if err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(9, []byte(`{
"cascadeDelete": true,
"collectionId": "pbc_1295301207",
"hidden": false,
"id": "relation3182418120",
"maxSelect": 1,
"minSelect": 0,
"name": "author",
"presentable": false,
"required": true,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
// update field
if err := collection.Fields.AddMarshaledJSONAt(16, []byte(`{
"cascadeDelete": true,
"collectionId": "_pb_users_auth_",
"hidden": false,
"id": "r0mj3tkr",
"maxSelect": 1,
"minSelect": 0,
"name": "user",
"presentable": false,
"required": true,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("summit_logs")
if err != nil {
return err
}
// remove field
collection.Fields.RemoveById("relation3182418120")
// update field
if err := collection.Fields.AddMarshaledJSONAt(15, []byte(`{
"cascadeDelete": true,
"collectionId": "_pb_users_auth_",
"hidden": false,
"id": "r0mj3tkr",
"maxSelect": 1,
"minSelect": 0,
"name": "author",
"presentable": false,
"required": true,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,46 @@
package migrations
import (
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
logs, err := app.FindAllRecords("summit_logs")
if err != nil {
return err
}
for _, l := range logs {
if l.GetString("user") == "" {
trail, err := app.FindFirstRecordByFilter("trails", "summit_logs ?~ {:id}", dbx.Params{"id": l.Id})
if err != nil {
// orphaned
err = app.UnsafeWithoutHooks().Delete(l)
if err != nil {
return err
}
continue
}
l.Set("user", trail.GetString("user"))
}
actor, err := app.FindFirstRecordByData("activitypub_actors", "user", l.GetString("user"))
if err != nil {
return err
}
l.Set("author", actor.Id)
err = app.UnsafeWithoutHooks().Save(l)
if err != nil {
return err
}
}
return nil
}, func(app core.App) error {
// add down queries...
return nil
})
}

View File

@@ -0,0 +1,55 @@
package migrations
import (
"os"
"pocketbase/util"
"github.com/meilisearch/meilisearch-go"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
client := meilisearch.New(os.Getenv("MEILI_URL"), meilisearch.WithAPIKey(os.Getenv("MEILI_MASTER_KEY")))
m.Register(func(app core.App) error {
users, err := app.FindAllRecords("users")
if err != nil {
return err
}
for _, u := range users {
userId := u.Id
actor, err := app.FindFirstRecordByData("activitypub_actors", "user", userId)
if err != nil {
return err
}
searchRules := map[string]interface{}{
"lists": map[string]string{
"filter": "public = true OR author = " + actor.Id + " OR shares = " + userId,
},
"trails": map[string]string{
"filter": "public = true OR author = " + actor.Id + " OR shares = " + userId,
},
}
token, err := util.GenerateMeilisearchToken(searchRules, client)
if err != nil {
return err
}
u.Set("token", token)
if err := app.Save(u); err != nil {
return err
}
}
return nil
}, func(app core.App) error {
// add down queries...
return nil
})
}

View File

@@ -0,0 +1,44 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("dd2l9a4vxpy2ni8")
if err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(10, []byte(`{
"cascadeDelete": true,
"collectionId": "e864strfxo14pm4",
"hidden": false,
"id": "relation2993194383",
"maxSelect": 1,
"minSelect": 0,
"name": "trail",
"presentable": false,
"required": false,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("dd2l9a4vxpy2ni8")
if err != nil {
return err
}
// remove field
collection.Fields.RemoveById("relation2993194383")
return app.Save(collection)
})
}

View File

@@ -0,0 +1,34 @@
package migrations
import (
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
logs, err := app.FindAllRecords("summit_logs")
if err != nil {
return err
}
for _, l := range logs {
trail, err := app.FindFirstRecordByFilter("trails", "summit_logs ?~ {:id}", dbx.Params{"id": l.Id})
if err != nil {
continue
}
l.Set("trail", trail.Id)
err = app.UnsafeWithoutHooks().Save(l)
if err != nil {
return err
}
}
return nil
}, func(app core.App) error {
// add down queries...
return nil
})
}

View File

@@ -0,0 +1,44 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("e864strfxo14pm4")
if err != nil {
return err
}
// remove field
collection.Fields.RemoveById("e1lwowvd")
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("e864strfxo14pm4")
if err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(17, []byte(`{
"cascadeDelete": false,
"collectionId": "dd2l9a4vxpy2ni8",
"hidden": false,
"id": "e1lwowvd",
"maxSelect": 2147483647,
"minSelect": 0,
"name": "summit_logs",
"presentable": false,
"required": false,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,150 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("8obn1ukumze565i")
if err != nil {
return err
}
// update field
if err := collection.Fields.AddMarshaledJSONAt(1, []byte(`{
"cascadeDelete": true,
"collectionId": "_pb_users_auth_",
"hidden": false,
"id": "in1traur",
"maxSelect": 1,
"minSelect": 0,
"name": "old_follower",
"presentable": false,
"required": false,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
// update field
if err := collection.Fields.AddMarshaledJSONAt(2, []byte(`{
"cascadeDelete": true,
"collectionId": "_pb_users_auth_",
"hidden": false,
"id": "wxwomfd5",
"maxSelect": 1,
"minSelect": 0,
"name": "old_followee",
"presentable": false,
"required": false,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(3, []byte(`{
"hidden": false,
"id": "select2063623452",
"maxSelect": 1,
"name": "status",
"presentable": false,
"required": true,
"system": false,
"type": "select",
"values": [
"pending",
"accepted"
]
}`)); err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(1, []byte(`{
"cascadeDelete": true,
"collectionId": "pbc_1295301207",
"hidden": false,
"id": "relation3117812038",
"maxSelect": 1,
"minSelect": 0,
"name": "follower",
"presentable": false,
"required": true,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(2, []byte(`{
"cascadeDelete": true,
"collectionId": "pbc_1295301207",
"hidden": false,
"id": "relation973442177",
"maxSelect": 1,
"minSelect": 0,
"name": "followee",
"presentable": false,
"required": true,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("8obn1ukumze565i")
if err != nil {
return err
}
// update field
if err := collection.Fields.AddMarshaledJSONAt(1, []byte(`{
"cascadeDelete": true,
"collectionId": "_pb_users_auth_",
"hidden": false,
"id": "in1traur",
"maxSelect": 1,
"minSelect": 0,
"name": "follower",
"presentable": false,
"required": false,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
// update field
if err := collection.Fields.AddMarshaledJSONAt(2, []byte(`{
"cascadeDelete": true,
"collectionId": "_pb_users_auth_",
"hidden": false,
"id": "wxwomfd5",
"maxSelect": 1,
"minSelect": 0,
"name": "followee",
"presentable": false,
"required": false,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
// remove field
collection.Fields.RemoveById("relation3117812038")
// remove field
collection.Fields.RemoveById("relation973442177")
return app.Save(collection)
})
}

View File

@@ -0,0 +1,60 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
follows, err := app.FindAllRecords("follows")
if err != nil {
return err
}
seen := map[string]string{}
for _, f := range follows {
oldFollower := f.GetString("old_follower")
oldFollowee := f.GetString("old_followee")
if oldFollowee == "" || oldFollower == "" {
continue
}
seenFollowee, ok := seen[oldFollower]
if ok && seenFollowee == oldFollowee {
err = app.Delete(f)
if err != nil {
return err
}
continue
}
seen[oldFollower] = oldFollowee
followerActor, err := app.FindFirstRecordByData("activitypub_actors", "user", oldFollower)
if err != nil {
return err
}
followeeActor, err := app.FindFirstRecordByData("activitypub_actors", "user", oldFollowee)
if err != nil {
return err
}
f.Set("follower", followerActor.Id)
f.Set("followee", followeeActor.Id)
f.Set("status", "accepted")
err = app.UnsafeWithoutHooks().Save(f)
if err != nil {
return err
}
}
return nil
}, func(app core.App) error {
// add down queries...
return nil
})
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,44 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("lf06qip3f4d11yk")
if err != nil {
return err
}
// remove field
collection.Fields.RemoveById("7lwo1mxx")
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("lf06qip3f4d11yk")
if err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(6, []byte(`{
"cascadeDelete": true,
"collectionId": "_pb_users_auth_",
"hidden": false,
"id": "7lwo1mxx",
"maxSelect": 1,
"minSelect": 0,
"name": "user",
"presentable": false,
"required": false,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,44 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("dd2l9a4vxpy2ni8")
if err != nil {
return err
}
// remove field
collection.Fields.RemoveById("r0mj3tkr")
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("dd2l9a4vxpy2ni8")
if err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(13, []byte(`{
"cascadeDelete": true,
"collectionId": "_pb_users_auth_",
"hidden": false,
"id": "r0mj3tkr",
"maxSelect": 1,
"minSelect": 0,
"name": "user",
"presentable": false,
"required": true,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,44 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("e864strfxo14pm4")
if err != nil {
return err
}
// remove field
collection.Fields.RemoveById("1utgul91")
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("e864strfxo14pm4")
if err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(24, []byte(`{
"cascadeDelete": true,
"collectionId": "_pb_users_auth_",
"hidden": false,
"id": "1utgul91",
"maxSelect": 1,
"minSelect": 0,
"name": "user",
"presentable": false,
"required": false,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,26 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("8obn1ukumze565i")
if err != nil {
return err
}
// // remove field
collection.Fields.RemoveById("in1traur")
// // remove field
collection.Fields.RemoveById("wxwomfd5")
return app.Save(collection)
}, func(app core.App) error {
return nil
})
}

View File

@@ -0,0 +1,186 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
jsonData := `{
"createRule": null,
"deleteRule": null,
"fields": [
{
"autogeneratePattern": "",
"hidden": false,
"id": "text3208210256",
"max": 0,
"min": 0,
"name": "id",
"pattern": "^[a-z0-9]+$",
"presentable": false,
"primaryKey": true,
"required": true,
"system": true,
"type": "text"
},
{
"hidden": false,
"id": "json2310347867",
"maxSize": 1,
"name": "trail_id",
"presentable": false,
"required": false,
"system": false,
"type": "json"
},
{
"hidden": false,
"id": "json2862495610",
"maxSize": 1,
"name": "date",
"presentable": false,
"required": false,
"system": false,
"type": "json"
},
{
"hidden": false,
"id": "json1579384326",
"maxSize": 1,
"name": "name",
"presentable": false,
"required": false,
"system": false,
"type": "json"
},
{
"hidden": false,
"id": "json1843675174",
"maxSize": 1,
"name": "description",
"presentable": false,
"required": false,
"system": false,
"type": "json"
},
{
"hidden": false,
"id": "json3275261007",
"maxSize": 1,
"name": "gpx",
"presentable": false,
"required": false,
"system": false,
"type": "json"
},
{
"hidden": false,
"id": "json3182418120",
"maxSize": 1,
"name": "author",
"presentable": false,
"required": false,
"system": false,
"type": "json"
},
{
"hidden": false,
"id": "json142008537",
"maxSize": 1,
"name": "photos",
"presentable": false,
"required": false,
"system": false,
"type": "json"
},
{
"hidden": false,
"id": "json479369857",
"maxSize": 1,
"name": "distance",
"presentable": false,
"required": false,
"system": false,
"type": "json"
},
{
"hidden": false,
"id": "json2254405824",
"maxSize": 1,
"name": "duration",
"presentable": false,
"required": false,
"system": false,
"type": "json"
},
{
"hidden": false,
"id": "json3015100073",
"maxSize": 1,
"name": "elevation_gain",
"presentable": false,
"required": false,
"system": false,
"type": "json"
},
{
"hidden": false,
"id": "json3171089056",
"maxSize": 1,
"name": "elevation_loss",
"presentable": false,
"required": false,
"system": false,
"type": "json"
},
{
"hidden": false,
"id": "json2990389176",
"maxSize": 1,
"name": "created",
"presentable": false,
"required": false,
"system": false,
"type": "json"
},
{
"hidden": false,
"id": "json2363381545",
"maxSize": 1,
"name": "type",
"presentable": false,
"required": false,
"system": false,
"type": "json"
}
],
"id": "pbc_468398817",
"indexes": [],
"listRule": "@collection.trails.id ?= trail_id && @collection.trails.public ?= true",
"name": "timeline",
"system": false,
"type": "view",
"updateRule": null,
"viewQuery": "-- database: /Users/christianbeutel/Documents/svelte/wanderer/db/pb_data/data.db\nSELECT\n (ROW_NUMBER() OVER ()) as id,\n trail_id,\n date,\n name,\n description,\n gpx,\n author,\n photos,\n distance,\n duration,\n elevation_gain,\n elevation_loss,\n created,\n type\nFROM\n (\n SELECT\n summit_logs.trail as trail_id,\n summit_logs.date,\n trails.name,\n text as description,\n summit_logs.gpx,\n activitypub_actors.iri as author,\n summit_logs.photos,\n summit_logs.distance,\n summit_logs.duration,\n summit_logs.elevation_gain,\n summit_logs.elevation_loss,\n summit_logs.created,\n \"summit_log\" as type\n FROM\n summit_logs\n JOIN trails ON summit_logs.trail = trails.id\n JOIN activitypub_actors ON activitypub_actors.id = summit_logs.author\n UNION\n SELECT\n trails.id as trail_id,\n date,\n trails.name,\n description,\n gpx,\n activitypub_actors.iri as author,\n photos,\n distance,\n duration,\n elevation_gain,\n elevation_loss,\n trails.created,\n \"trail\" as type\n FROM\n trails\n JOIN activitypub_actors ON activitypub_actors.id = trails.author\n )\nORDER BY\n created DESC;\n",
"viewRule": "@collection.trails.id ?= trail_id && @collection.trails.public ?= true"
}`
collection := &core.Collection{}
if err := json.Unmarshal([]byte(jsonData), &collection); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("pbc_468398817")
if err != nil {
return err
}
return app.Delete(collection)
})
}

View File

@@ -0,0 +1,40 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("pbc_468398817")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"viewQuery": "SELECT\n (ROW_NUMBER() OVER ()) as id,\n trail_id,\n date,\n name,\n description,\n gpx,\n author,\n photos,\n distance,\n duration,\n elevation_gain,\n elevation_loss,\n created,\n type\nFROM\n (\n SELECT\n summit_logs.trail as trail_id,\n summit_logs.date,\n trails.name,\n text as description,\n summit_logs.gpx,\n activitypub_actors.iri as author,\n summit_logs.photos,\n summit_logs.distance,\n summit_logs.duration,\n summit_logs.elevation_gain,\n summit_logs.elevation_loss,\n summit_logs.created,\n \"summit_log\" as type\n FROM\n summit_logs\n JOIN trails ON summit_logs.trail = trails.id\n JOIN activitypub_actors ON activitypub_actors.id = summit_logs.author\n UNION\n SELECT\n trails.id as trail_id,\n date,\n trails.name,\n description,\n gpx,\n activitypub_actors.iri as author,\n photos,\n distance,\n duration,\n elevation_gain,\n elevation_loss,\n trails.created,\n \"trail\" as type\n FROM\n trails\n JOIN activitypub_actors ON activitypub_actors.id = trails.author\n )\nORDER BY\n created DESC;\n"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("pbc_468398817")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"viewQuery": "-- database: /Users/christianbeutel/Documents/svelte/wanderer/db/pb_data/data.db\nSELECT\n (ROW_NUMBER() OVER ()) as id,\n trail_id,\n date,\n name,\n description,\n gpx,\n author,\n photos,\n distance,\n duration,\n elevation_gain,\n elevation_loss,\n created,\n type\nFROM\n (\n SELECT\n summit_logs.trail as trail_id,\n summit_logs.date,\n trails.name,\n text as description,\n summit_logs.gpx,\n activitypub_actors.iri as author,\n summit_logs.photos,\n summit_logs.distance,\n summit_logs.duration,\n summit_logs.elevation_gain,\n summit_logs.elevation_loss,\n summit_logs.created,\n \"summit_log\" as type\n FROM\n summit_logs\n JOIN trails ON summit_logs.trail = trails.id\n JOIN activitypub_actors ON activitypub_actors.id = summit_logs.author\n UNION\n SELECT\n trails.id as trail_id,\n date,\n trails.name,\n description,\n gpx,\n activitypub_actors.iri as author,\n photos,\n distance,\n duration,\n elevation_gain,\n elevation_loss,\n trails.created,\n \"trail\" as type\n FROM\n trails\n JOIN activitypub_actors ON activitypub_actors.id = trails.author\n )\nORDER BY\n created DESC;\n"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,40 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("pbc_468398817")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"viewQuery": "SELECT\n id,\n trail_id,\n date,\n name,\n description,\n gpx,\n author,\n photos,\n distance,\n duration,\n elevation_gain,\n elevation_loss,\n created,\n type\nFROM\n (\n SELECT\n summit_logs.id,\n summit_logs.trail as trail_id,\n summit_logs.date,\n trails.name,\n text as description,\n summit_logs.gpx,\n activitypub_actors.iri as author,\n summit_logs.photos,\n summit_logs.distance,\n summit_logs.duration,\n summit_logs.elevation_gain,\n summit_logs.elevation_loss,\n summit_logs.created,\n \"summit_log\" as type\n FROM\n summit_logs\n JOIN trails ON summit_logs.trail = trails.id\n JOIN activitypub_actors ON activitypub_actors.id = summit_logs.author\n UNION\n SELECT\n trails.id,\n trails.id as trail_id,\n date,\n trails.name,\n description,\n gpx,\n activitypub_actors.iri as author,\n photos,\n distance,\n duration,\n elevation_gain,\n elevation_loss,\n trails.created,\n \"trail\" as type\n FROM\n trails\n JOIN activitypub_actors ON activitypub_actors.id = trails.author\n )\nORDER BY\n created DESC;\n"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("pbc_468398817")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"viewQuery": "SELECT\n (ROW_NUMBER() OVER ()) as id,\n trail_id,\n date,\n name,\n description,\n gpx,\n author,\n photos,\n distance,\n duration,\n elevation_gain,\n elevation_loss,\n created,\n type\nFROM\n (\n SELECT\n summit_logs.trail as trail_id,\n summit_logs.date,\n trails.name,\n text as description,\n summit_logs.gpx,\n activitypub_actors.iri as author,\n summit_logs.photos,\n summit_logs.distance,\n summit_logs.duration,\n summit_logs.elevation_gain,\n summit_logs.elevation_loss,\n summit_logs.created,\n \"summit_log\" as type\n FROM\n summit_logs\n JOIN trails ON summit_logs.trail = trails.id\n JOIN activitypub_actors ON activitypub_actors.id = summit_logs.author\n UNION\n SELECT\n trails.id as trail_id,\n date,\n trails.name,\n description,\n gpx,\n activitypub_actors.iri as author,\n photos,\n distance,\n duration,\n elevation_gain,\n elevation_loss,\n trails.created,\n \"trail\" as type\n FROM\n trails\n JOIN activitypub_actors ON activitypub_actors.id = trails.author\n )\nORDER BY\n created DESC;\n"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,43 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("lf06qip3f4d11yk")
if err != nil {
return err
}
// remove field
collection.Fields.RemoveById("fhgxdiam")
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("lf06qip3f4d11yk")
if err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(6, []byte(`{
"hidden": false,
"id": "fhgxdiam",
"max": null,
"min": null,
"name": "rating",
"onlyInt": false,
"presentable": false,
"required": false,
"system": false,
"type": "number"
}`)); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,42 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("e864strfxo14pm4")
if err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(22, []byte(`{
"exceptDomains": [],
"hidden": false,
"id": "url1760183548",
"name": "iri",
"onlyDomains": [],
"presentable": false,
"required": false,
"system": false,
"type": "url"
}`)); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("e864strfxo14pm4")
if err != nil {
return err
}
// remove field
collection.Fields.RemoveById("url1760183548")
return app.Save(collection)
})
}

View File

@@ -0,0 +1,40 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("e864strfxo14pm4")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"createRule": "@request.auth.id != \"\" && (@request.body.author.user = @request.auth.id || author.isLocal = false)"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("e864strfxo14pm4")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"createRule": "@request.auth.id != \"\" && (@request.body.author.user = @request.auth.id)"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,40 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("e864strfxo14pm4")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"updateRule": "author.user = @request.auth.id || (@request.auth.id != \"\" && trail_share_via_trail.trail = id && trail_share_via_trail.user ?= @request.auth.id && trail_share_via_trail.permission = \"edit\") || (@request.auth.id != \"\" && author.isLocal = false)"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("e864strfxo14pm4")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"updateRule": "author.user = @request.auth.id || (@request.auth.id != \"\" && trail_share_via_trail.trail = id && trail_share_via_trail.user ?= @request.auth.id && trail_share_via_trail.permission = \"edit\")"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,42 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("lf06qip3f4d11yk")
if err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(4, []byte(`{
"exceptDomains": null,
"hidden": false,
"id": "url2434853685",
"name": "iri",
"onlyDomains": null,
"presentable": false,
"required": false,
"system": false,
"type": "url"
}`)); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("lf06qip3f4d11yk")
if err != nil {
return err
}
// remove field
collection.Fields.RemoveById("url2434853685")
return app.Save(collection)
})
}

View File

@@ -0,0 +1,42 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("dd2l9a4vxpy2ni8")
if err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(11, []byte(`{
"exceptDomains": null,
"hidden": false,
"id": "url2434853685",
"name": "iri",
"onlyDomains": null,
"presentable": false,
"required": false,
"system": false,
"type": "url"
}`)); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("dd2l9a4vxpy2ni8")
if err != nil {
return err
}
// remove field
collection.Fields.RemoveById("url2434853685")
return app.Save(collection)
})
}

View File

@@ -0,0 +1,40 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("dd2l9a4vxpy2ni8")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"createRule": "@request.auth.id != \"\" && (trail.author.user = @request.auth.id || trail.public = true)"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("dd2l9a4vxpy2ni8")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"createRule": "@request.auth.id != \"\""
}`), &collection); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,78 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("r6gu2ajyidy1x69")
if err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(5, []byte(`{
"cascadeDelete": true,
"collectionId": "pbc_1295301207",
"hidden": false,
"id": "relation3182418120",
"maxSelect": 1,
"minSelect": 0,
"name": "author",
"presentable": false,
"required": true,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
// update field
if err := collection.Fields.AddMarshaledJSONAt(6, []byte(`{
"cascadeDelete": true,
"collectionId": "_pb_users_auth_",
"hidden": false,
"id": "kwm6zdet",
"maxSelect": 1,
"minSelect": 0,
"name": "user",
"presentable": false,
"required": true,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("r6gu2ajyidy1x69")
if err != nil {
return err
}
// remove field
collection.Fields.RemoveById("relation3182418120")
// update field
if err := collection.Fields.AddMarshaledJSONAt(5, []byte(`{
"cascadeDelete": true,
"collectionId": "_pb_users_auth_",
"hidden": false,
"id": "kwm6zdet",
"maxSelect": 1,
"minSelect": 0,
"name": "author",
"presentable": false,
"required": true,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,33 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
lists, err := app.FindAllRecords("lists")
if err != nil {
return err
}
for _, l := range lists {
actor, err := app.FindFirstRecordByData("activitypub_actors", "user", l.GetString("user"))
if err != nil {
continue
}
l.Set("author", actor.Id)
err = app.UnsafeWithoutHooks().Save(l)
if err != nil {
continue
}
}
return nil
}, func(app core.App) error {
// add down queries...
return nil
})
}

View File

@@ -0,0 +1,44 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("r6gu2ajyidy1x69")
if err != nil {
return err
}
// remove field
collection.Fields.RemoveById("kwm6zdet")
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("r6gu2ajyidy1x69")
if err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(6, []byte(`{
"cascadeDelete": true,
"collectionId": "_pb_users_auth_",
"hidden": false,
"id": "kwm6zdet",
"maxSelect": 1,
"minSelect": 0,
"name": "user",
"presentable": false,
"required": true,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,48 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("r6gu2ajyidy1x69")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"createRule": "@request.auth.id != \"\" && (@request.body.author.user = @request.auth.id)",
"deleteRule": "author.user = @request.auth.id ",
"listRule": "author.user = @request.auth.id || public = true || (@request.auth.id != \"\" && list_share_via_list.user ?= @request.auth.id)",
"updateRule": "author.user = @request.auth.id || (@request.auth.id != \"\" && list_share_via_list.list = id && list_share_via_list.user ?= @request.auth.id && list_share_via_list.permission = \"edit\")",
"viewRule": "author.user = @request.auth.id || public = true || (@request.auth.id != \"\" && list_share_via_list.user ?= @request.auth.id)"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("r6gu2ajyidy1x69")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"createRule": "@request.auth.id != \"\" && (@request.body.author = @request.auth.id)",
"deleteRule": "author = @request.auth.id ",
"listRule": "author = @request.auth.id || public = true || (@request.auth.id != \"\" && list_share_via_list.user ?= @request.auth.id)",
"updateRule": "author = @request.auth.id || (@request.auth.id != \"\" && list_share_via_list.list = id && list_share_via_list.user ?= @request.auth.id && list_share_via_list.permission = \"edit\")",
"viewRule": "author = @request.auth.id || public = true || (@request.auth.id != \"\" && list_share_via_list.user ?= @request.auth.id)"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,42 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("r6gu2ajyidy1x69")
if err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(7, []byte(`{
"exceptDomains": null,
"hidden": false,
"id": "url2434853685",
"name": "iri",
"onlyDomains": null,
"presentable": false,
"required": false,
"system": false,
"type": "url"
}`)); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("r6gu2ajyidy1x69")
if err != nil {
return err
}
// remove field
collection.Fields.RemoveById("url2434853685")
return app.Save(collection)
})
}

View File

@@ -0,0 +1,40 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("r6gu2ajyidy1x69")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"createRule": "@request.auth.id != \"\" && (@request.body.author.user = @request.auth.id || author.isLocal = false)"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("r6gu2ajyidy1x69")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"createRule": "@request.auth.id != \"\" && (@request.body.author.user = @request.auth.id)"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,40 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("r6gu2ajyidy1x69")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"updateRule": "author.user = @request.auth.id || (@request.auth.id != \"\" && list_share_via_list.list = id && list_share_via_list.user ?= @request.auth.id && list_share_via_list.permission = \"edit\") || (@request.auth.id != \"\" && author.isLocal = false)"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("r6gu2ajyidy1x69")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"updateRule": "author.user = @request.auth.id || (@request.auth.id != \"\" && list_share_via_list.list = id && list_share_via_list.user ?= @request.auth.id && list_share_via_list.permission = \"edit\")"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,57 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("pbc_468398817")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"viewQuery": "SELECT\n id,\n trail_id,\n iri,\n date,\n name,\n description,\n gpx,\n author,\n photos,\n distance,\n duration,\n elevation_gain,\n elevation_loss,\n created,\n type\nFROM\n (\n SELECT\n summit_logs.id,\n summit_logs.trail as trail_id,\n trails.iri,\n summit_logs.date,\n trails.name,\n text as description,\n summit_logs.gpx,\n activitypub_actors.iri as author,\n summit_logs.photos,\n summit_logs.distance,\n summit_logs.duration,\n summit_logs.elevation_gain,\n summit_logs.elevation_loss,\n summit_logs.created,\n \"summit_log\" as type\n FROM\n summit_logs\n JOIN trails ON summit_logs.trail = trails.id\n JOIN activitypub_actors ON activitypub_actors.id = summit_logs.author\n UNION\n SELECT\n trails.id,\n trails.id as trail_id,\n trails.iri,\n date,\n trails.name,\n description,\n gpx,\n activitypub_actors.iri as author,\n photos,\n distance,\n duration,\n elevation_gain,\n elevation_loss,\n trails.created,\n \"trail\" as type\n FROM\n trails\n JOIN activitypub_actors ON activitypub_actors.id = trails.author\n )\nORDER BY\n created DESC;\n"
}`), &collection); err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(2, []byte(`{
"hidden": false,
"id": "json2434853685",
"maxSize": 1,
"name": "iri",
"presentable": false,
"required": false,
"system": false,
"type": "json"
}`)); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("pbc_468398817")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"viewQuery": "SELECT\n id,\n trail_id,\n date,\n name,\n description,\n gpx,\n author,\n photos,\n distance,\n duration,\n elevation_gain,\n elevation_loss,\n created,\n type\nFROM\n (\n SELECT\n summit_logs.id,\n summit_logs.trail as trail_id,\n summit_logs.date,\n trails.name,\n text as description,\n summit_logs.gpx,\n activitypub_actors.iri as author,\n summit_logs.photos,\n summit_logs.distance,\n summit_logs.duration,\n summit_logs.elevation_gain,\n summit_logs.elevation_loss,\n summit_logs.created,\n \"summit_log\" as type\n FROM\n summit_logs\n JOIN trails ON summit_logs.trail = trails.id\n JOIN activitypub_actors ON activitypub_actors.id = summit_logs.author\n UNION\n SELECT\n trails.id,\n trails.id as trail_id,\n date,\n trails.name,\n description,\n gpx,\n activitypub_actors.iri as author,\n photos,\n distance,\n duration,\n elevation_gain,\n elevation_loss,\n trails.created,\n \"trail\" as type\n FROM\n trails\n JOIN activitypub_actors ON activitypub_actors.id = trails.author\n )\nORDER BY\n created DESC;\n"
}`), &collection); err != nil {
return err
}
// remove field
collection.Fields.RemoveById("json2434853685")
return app.Save(collection)
})
}

View File

@@ -0,0 +1,42 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("e864strfxo14pm4")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"indexes": [
"CREATE INDEX ` + "`" + `idx_6tD5RqfVk2` + "`" + ` ON ` + "`" + `trails` + "`" + ` (` + "`" + `iri` + "`" + `)"
]
}`), &collection); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("e864strfxo14pm4")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"indexes": []
}`), &collection); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,42 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("r6gu2ajyidy1x69")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"indexes": [
"CREATE INDEX ` + "`" + `idx_hLtEU5XGWL` + "`" + ` ON ` + "`" + `lists` + "`" + ` (` + "`" + `iri` + "`" + `)"
]
}`), &collection); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("r6gu2ajyidy1x69")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"indexes": []
}`), &collection); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,108 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("pbc_468398817")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"viewQuery": "SELECT\n id,\n trail_id,\n trail_author_username,\n trail_author_domain,\n trail_iri,\n date,\n name,\n description,\n gpx,\n author,\n photos,\n distance,\n duration,\n elevation_gain,\n elevation_loss,\n created,\n type\nFROM\n (\n SELECT\n summit_logs.id,\n summit_logs.trail as trail_id,\n tapa.username as trail_author_username,\n tapa.domain as trail_author_domain,\n trails.iri as trail_iri,\n summit_logs.date,\n trails.name,\n text as description,\n summit_logs.gpx,\n sapa.iri as author,\n summit_logs.photos,\n summit_logs.distance,\n summit_logs.duration,\n summit_logs.elevation_gain,\n summit_logs.elevation_loss,\n summit_logs.created,\n \"summit_log\" as type\n FROM\n summit_logs\n JOIN trails ON summit_logs.trail = trails.id\n JOIN activitypub_actors sapa ON sapa.id = summit_logs.author\n JOIN activitypub_actors tapa ON tapa.id = trails.author\n UNION\n SELECT\n trails.id,\n trails.id as trail_id,\n activitypub_actors.username as trail_author_username,\n activitypub_actors.domain as trail_author_domain,\n trails.iri as trail_iri,\n date,\n trails.name,\n description,\n gpx,\n activitypub_actors.iri as author,\n photos,\n distance,\n duration,\n elevation_gain,\n elevation_loss,\n trails.created,\n \"trail\" as type\n FROM\n trails\n JOIN activitypub_actors ON activitypub_actors.id = trails.author\n )\nORDER BY\n created DESC;\n"
}`), &collection); err != nil {
return err
}
// remove field
collection.Fields.RemoveById("json2434853685")
// add field
if err := collection.Fields.AddMarshaledJSONAt(2, []byte(`{
"hidden": false,
"id": "json3184124860",
"maxSize": 1,
"name": "trail_author_username",
"presentable": false,
"required": false,
"system": false,
"type": "json"
}`)); err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(3, []byte(`{
"hidden": false,
"id": "json2887874732",
"maxSize": 1,
"name": "trail_author_domain",
"presentable": false,
"required": false,
"system": false,
"type": "json"
}`)); err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(4, []byte(`{
"hidden": false,
"id": "json113557190",
"maxSize": 1,
"name": "trail_iri",
"presentable": false,
"required": false,
"system": false,
"type": "json"
}`)); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("pbc_468398817")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"viewQuery": "SELECT\n id,\n trail_id,\n iri,\n date,\n name,\n description,\n gpx,\n author,\n photos,\n distance,\n duration,\n elevation_gain,\n elevation_loss,\n created,\n type\nFROM\n (\n SELECT\n summit_logs.id,\n summit_logs.trail as trail_id,\n trails.iri,\n summit_logs.date,\n trails.name,\n text as description,\n summit_logs.gpx,\n activitypub_actors.iri as author,\n summit_logs.photos,\n summit_logs.distance,\n summit_logs.duration,\n summit_logs.elevation_gain,\n summit_logs.elevation_loss,\n summit_logs.created,\n \"summit_log\" as type\n FROM\n summit_logs\n JOIN trails ON summit_logs.trail = trails.id\n JOIN activitypub_actors ON activitypub_actors.id = summit_logs.author\n UNION\n SELECT\n trails.id,\n trails.id as trail_id,\n trails.iri,\n date,\n trails.name,\n description,\n gpx,\n activitypub_actors.iri as author,\n photos,\n distance,\n duration,\n elevation_gain,\n elevation_loss,\n trails.created,\n \"trail\" as type\n FROM\n trails\n JOIN activitypub_actors ON activitypub_actors.id = trails.author\n )\nORDER BY\n created DESC;\n"
}`), &collection); err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(2, []byte(`{
"hidden": false,
"id": "json2434853685",
"maxSize": 1,
"name": "iri",
"presentable": false,
"required": false,
"system": false,
"type": "json"
}`)); err != nil {
return err
}
// remove field
collection.Fields.RemoveById("json3184124860")
// remove field
collection.Fields.RemoveById("json2887874732")
// remove field
collection.Fields.RemoveById("json113557190")
return app.Save(collection)
})
}

View File

@@ -0,0 +1,104 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("khrcci2uqknny8h")
if err != nil {
return err
}
// remove field
collection.Fields.RemoveById("tmghd4vo")
// remove field
collection.Fields.RemoveById("exqo1whj")
// add field
if err := collection.Fields.AddMarshaledJSONAt(4, []byte(`{
"cascadeDelete": true,
"collectionId": "pbc_1295301207",
"hidden": false,
"id": "relation1745156937",
"maxSelect": 1,
"minSelect": 0,
"name": "recipient",
"presentable": false,
"required": true,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(5, []byte(`{
"cascadeDelete": true,
"collectionId": "pbc_1295301207",
"hidden": false,
"id": "relation3182418120",
"maxSelect": 1,
"minSelect": 0,
"name": "author",
"presentable": false,
"required": true,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("khrcci2uqknny8h")
if err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(4, []byte(`{
"cascadeDelete": true,
"collectionId": "_pb_users_auth_",
"hidden": false,
"id": "tmghd4vo",
"maxSelect": 1,
"minSelect": 0,
"name": "recipient",
"presentable": false,
"required": true,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(5, []byte(`{
"cascadeDelete": true,
"collectionId": "_pb_users_auth_",
"hidden": false,
"id": "exqo1whj",
"maxSelect": 1,
"minSelect": 0,
"name": "author",
"presentable": false,
"required": true,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
// remove field
collection.Fields.RemoveById("relation1745156937")
// remove field
collection.Fields.RemoveById("relation3182418120")
return app.Save(collection)
})
}

View File

@@ -0,0 +1,44 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("khrcci2uqknny8h")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"listRule": "@request.auth.id = recipient.user",
"updateRule": "@request.auth.id = recipient.user && (@request.body.type = null||@request.body.type = type) && (@request.body.metadata = null||@request.body.metadata = metadata) && (@request.body.recipient = null||@request.body.recipient = recipient) && (@request.body.author = null||@request.body.author = author) && @request.body.seen = true",
"viewRule": "@request.auth.id = recipient.user"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("khrcci2uqknny8h")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"listRule": "@request.auth.id = recipient",
"updateRule": "@request.auth.id = recipient && (@request.body.type = null||@request.body.type = type) && (@request.body.metadata = null||@request.body.metadata = metadata) && (@request.body.recipient = null||@request.body.recipient = recipient) && (@request.body.author = null||@request.body.author = author) && @request.body.seen = true",
"viewRule": "@request.auth.id = recipient"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,67 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("khrcci2uqknny8h")
if err != nil {
return err
}
// update field
if err := collection.Fields.AddMarshaledJSONAt(1, []byte(`{
"hidden": false,
"id": "b57prsbu",
"maxSelect": 1,
"name": "type",
"presentable": false,
"required": true,
"system": false,
"type": "select",
"values": [
"new_follower",
"trail_comment",
"trail_share",
"list_share",
"summit_log_create"
]
}`)); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("khrcci2uqknny8h")
if err != nil {
return err
}
// update field
if err := collection.Fields.AddMarshaledJSONAt(1, []byte(`{
"hidden": false,
"id": "b57prsbu",
"maxSelect": 1,
"name": "type",
"presentable": false,
"required": true,
"system": false,
"type": "select",
"values": [
"trail_create",
"list_create",
"new_follower",
"trail_comment",
"trail_share",
"list_share"
]
}`)); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,42 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("8obn1ukumze565i")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"indexes": [
"CREATE UNIQUE INDEX `+"`"+`idx_oM5KTHL3Lf`+"`"+` ON `+"`"+`follows`+"`"+` (\n `+"`"+`follower`+"`"+`,\n `+"`"+`followee`+"`"+`\n)"
]
}`), &collection); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("8obn1ukumze565i")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"indexes": []
}`), &collection); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,42 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("dd2l9a4vxpy2ni8")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"listRule": "(@request.auth.id != \"\" && (author.user = @request.auth.id || trail.author.user = @request.auth.id)) || trail.public = true || (@collection.trail_share.trail ?= trail && @collection.trail_share.trail ?= @request.auth.id)",
"viewRule": "(@request.auth.id != \"\" && (author.user = @request.auth.id || trail.author.user = @request.auth.id)) || trail.public = true || (@collection.trail_share.trail ?= trail && @collection.trail_share.trail ?= @request.auth.id)"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("dd2l9a4vxpy2ni8")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"listRule": "(@request.auth.id != \"\" && (author.user = @request.auth.id || trail.author.user = @request.auth.id)) || trail.public = true || \ntrail.trail_share_via_trail.user = @request.auth.id",
"viewRule": "(@request.auth.id != \"\" && (author.user = @request.auth.id || trail.author.user = @request.auth.id)) || trail.public = true || \ntrail.trail_share_via_trail.user = @request.auth.id"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,42 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("8obn1ukumze565i")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"listRule": "",
"viewRule": ""
}`), &collection); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("8obn1ukumze565i")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"listRule": "@request.auth.id = follower.user.id || @request.auth.id = followee.user.id",
"viewRule": "@request.auth.id = follower.user.id || @request.auth.id = followee.user.id"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,44 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("1mns8mlal6uf9ku")
if err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(2, []byte(`{
"cascadeDelete": true,
"collectionId": "pbc_1295301207",
"hidden": false,
"id": "relation2375276105",
"maxSelect": 1,
"minSelect": 0,
"name": "actor",
"presentable": false,
"required": true,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("1mns8mlal6uf9ku")
if err != nil {
return err
}
// remove field
collection.Fields.RemoveById("relation2375276105")
return app.UnsafeWithoutHooks().Save(collection)
})
}

View File

@@ -0,0 +1,31 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
shares, err := app.FindAllRecords("trail_share")
if err != nil {
return err
}
for _, s := range shares {
actor, err := app.FindFirstRecordByData("activitypub_actors", "user", s.GetString("user"))
if err != nil {
continue
}
s.Set("actor", actor.Id)
err = app.Save(s)
if err != nil {
return err
}
}
return nil
}, func(app core.App) error {
return nil
})
}

View File

@@ -0,0 +1,80 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("4wbv9tz5zjdrjh1")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"viewQuery": "SELECT activitypub_actors.id, activitypub_actors.user, COALESCE(printf(\"%.2f\", MAX(trails.distance)), 0) AS max_distance,\n COALESCE(printf(\"%.2f\", MAX(trails.elevation_gain)), 0) AS max_elevation_gain, \n COALESCE(printf(\"%.2f\", MAX(trails.elevation_loss)), 0) AS max_elevation_loss, \n COALESCE(printf(\"%.2f\", MAX(trails.duration)), 0) AS max_duration, \n COALESCE(printf(\"%.2f\", MIN(trails.distance)), 0) AS min_distance, \n COALESCE(printf(\"%.2f\", MIN(trails.elevation_gain)), 0) AS min_elevation_gain, \n COALESCE(printf(\"%.2f\", MIN(trails.elevation_loss)), 0) AS min_elevation_loss, \n COALESCE(printf(\"%.2f\", MIN(trails.duration)), 0) AS min_duration \nFROM activitypub_actors \n LEFT JOIN trails ON \n activitypub_actors.id = trails.author OR \n trails.public = 1 OR \n EXISTS (\n SELECT 1 \n FROM trail_share \n WHERE trail_share.trail = trails.id \n AND trail_share.actor = activitypub_actors.id\n ) GROUP BY activitypub_actors.id;"
}`), &collection); err != nil {
return err
}
// remove field
collection.Fields.RemoveById("_clone_U0cX")
// add field
if err := collection.Fields.AddMarshaledJSONAt(1, []byte(`{
"cascadeDelete": true,
"collectionId": "_pb_users_auth_",
"hidden": false,
"id": "_clone_rnMQ",
"maxSelect": 1,
"minSelect": 0,
"name": "user",
"presentable": false,
"required": false,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("4wbv9tz5zjdrjh1")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"viewQuery": "SELECT activitypub_actors.id, activitypub_actors.user, COALESCE(printf(\"%.2f\", MAX(trails.distance)), 0) AS max_distance,\n COALESCE(printf(\"%.2f\", MAX(trails.elevation_gain)), 0) AS max_elevation_gain, \n COALESCE(printf(\"%.2f\", MAX(trails.elevation_loss)), 0) AS max_elevation_loss, \n COALESCE(printf(\"%.2f\", MAX(trails.duration)), 0) AS max_duration, \n COALESCE(printf(\"%.2f\", MIN(trails.distance)), 0) AS min_distance, \n COALESCE(printf(\"%.2f\", MIN(trails.elevation_gain)), 0) AS min_elevation_gain, \n COALESCE(printf(\"%.2f\", MIN(trails.elevation_loss)), 0) AS min_elevation_loss, \n COALESCE(printf(\"%.2f\", MIN(trails.duration)), 0) AS min_duration \nFROM activitypub_actors \n LEFT JOIN trails ON \n activitypub_actors.id = trails.author OR \n trails.public = 1 OR \n EXISTS (\n SELECT 1 \n FROM trail_share \n WHERE trail_share.trail = trails.id \n AND trail_share.user = activitypub_actors.user\n ) GROUP BY activitypub_actors.id;"
}`), &collection); err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(1, []byte(`{
"cascadeDelete": true,
"collectionId": "_pb_users_auth_",
"hidden": false,
"id": "_clone_U0cX",
"maxSelect": 1,
"minSelect": 0,
"name": "user",
"presentable": false,
"required": false,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
// remove field
collection.Fields.RemoveById("_clone_rnMQ")
return app.Save(collection)
})
}

View File

@@ -0,0 +1,80 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("urytyc428mwlbqq")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"viewQuery": "SELECT \n activitypub_actors.id, activitypub_actors.user, \n COALESCE(MAX(trails.lat), 0) AS max_lat, \n COALESCE(MAX(trails.lon), 0) AS max_lon, \n COALESCE(MIN(trails.lat), 0) AS min_lat, \n COALESCE(MIN(trails.lon), 0) AS min_lon \nFROM activitypub_actors \nLEFT JOIN trails \n ON activitypub_actors.id = trails.author \n OR trails.public = TRUE \n OR EXISTS (\n SELECT 1 \n FROM trail_share \n WHERE trail_share.trail = trails.id \n AND trail_share.actor = activitypub_actors.id\n ) \nGROUP BY activitypub_actors.id;"
}`), &collection); err != nil {
return err
}
// remove field
collection.Fields.RemoveById("_clone_2GUq")
// add field
if err := collection.Fields.AddMarshaledJSONAt(1, []byte(`{
"cascadeDelete": true,
"collectionId": "_pb_users_auth_",
"hidden": false,
"id": "_clone_4wMO",
"maxSelect": 1,
"minSelect": 0,
"name": "user",
"presentable": false,
"required": false,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("urytyc428mwlbqq")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"viewQuery": "SELECT \n activitypub_actors.id, activitypub_actors.user, \n COALESCE(MAX(trails.lat), 0) AS max_lat, \n COALESCE(MAX(trails.lon), 0) AS max_lon, \n COALESCE(MIN(trails.lat), 0) AS min_lat, \n COALESCE(MIN(trails.lon), 0) AS min_lon \nFROM activitypub_actors \nLEFT JOIN trails \n ON activitypub_actors.id = trails.author \n OR trails.public = TRUE \n OR EXISTS (\n SELECT 1 \n FROM trail_share \n WHERE trail_share.trail = trails.id \n AND trail_share.user = activitypub_actors.id\n ) \nGROUP BY activitypub_actors.id;"
}`), &collection); err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(1, []byte(`{
"cascadeDelete": true,
"collectionId": "_pb_users_auth_",
"hidden": false,
"id": "_clone_2GUq",
"maxSelect": 1,
"minSelect": 0,
"name": "user",
"presentable": false,
"required": false,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
// remove field
collection.Fields.RemoveById("_clone_4wMO")
return app.Save(collection)
})
}

View File

@@ -0,0 +1,42 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("goeo2ubp103rzp9")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"listRule": "author = @request.auth.id || trails_via_waypoints.author.user ?= @request.auth.id || trails_via_waypoints.public ?= true || \n(@collection.trail_share.trail.id ?= trails_via_waypoints.id && @collection.trail_share.actor.user ?= @request.auth.id)",
"viewRule": "author = @request.auth.id || trails_via_waypoints.author.user ?= @request.auth.id || trails_via_waypoints.public ?= true || \n(@collection.trail_share.trail.id ?= trails_via_waypoints.id && @collection.trail_share.actor.user ?= @request.auth.id)"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("goeo2ubp103rzp9")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"listRule": "author = @request.auth.id || trails_via_waypoints.author.user ?= @request.auth.id || trails_via_waypoints.public ?= true || \n(@collection.trail_share.trail.id ?= trails_via_waypoints.id && @collection.trail_share.user ?= @request.auth.id)",
"viewRule": "author = @request.auth.id || trails_via_waypoints.author.user ?= @request.auth.id || trails_via_waypoints.public ?= true || \n(@collection.trail_share.trail.id ?= trails_via_waypoints.id && @collection.trail_share.user ?= @request.auth.id)"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,44 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("e864strfxo14pm4")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"listRule": "author.user = @request.auth.id || public = true || (@request.auth.id != \"\" && trail_share_via_trail.actor.user ?= @request.auth.id)",
"updateRule": "author.user = @request.auth.id || (@request.auth.id != \"\" && trail_share_via_trail.trail = id && trail_share_via_trail.actor.user ?= @request.auth.id && trail_share_via_trail.permission = \"edit\") || (@request.auth.id != \"\" && author.isLocal = false)",
"viewRule": "author.user = @request.auth.id || public = true || (@request.auth.id != \"\" && trail_share_via_trail.actor.user ?= @request.auth.id)"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("e864strfxo14pm4")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"listRule": "author.user = @request.auth.id || public = true || (@request.auth.id != \"\" && trail_share_via_trail.user ?= @request.auth.id)",
"updateRule": "author.user = @request.auth.id || (@request.auth.id != \"\" && trail_share_via_trail.trail = id && trail_share_via_trail.user ?= @request.auth.id && trail_share_via_trail.permission = \"edit\") || (@request.auth.id != \"\" && author.isLocal = false)",
"viewRule": "author.user = @request.auth.id || public = true || (@request.auth.id != \"\" && trail_share_via_trail.user ?= @request.auth.id)"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,42 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("dd2l9a4vxpy2ni8")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"listRule": "(@request.auth.id != \"\" && (author.user = @request.auth.id || trail.author.user = @request.auth.id)) || trail.public = true || (@collection.trail_share.trail ?= trail && @collection.trail_share.actor.user ?= @request.auth.id)",
"viewRule": "(@request.auth.id != \"\" && (author.user = @request.auth.id || trail.author.user = @request.auth.id)) || trail.public = true || (@collection.trail_share.trail ?= trail && @collection.trail_share.actor.user ?= @request.auth.id)"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("dd2l9a4vxpy2ni8")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"listRule": "(@request.auth.id != \"\" && (author.user = @request.auth.id || trail.author.user = @request.auth.id)) || trail.public = true || (@collection.trail_share.trail ?= trail && @collection.trail_share.trail ?= @request.auth.id)",
"viewRule": "(@request.auth.id != \"\" && (author.user = @request.auth.id || trail.author.user = @request.auth.id)) || trail.public = true || (@collection.trail_share.trail ?= trail && @collection.trail_share.trail ?= @request.auth.id)"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,44 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("lf06qip3f4d11yk")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"createRule": "@request.auth.id != \"\" && (trail.author.user = @request.auth.id || trail.public = true || trail.trail_share_via_trail.actor.user ?= @request.auth.id)",
"listRule": "((@request.auth.id != \"\" && trail.author.user = @request.auth.id) || trail.public = true) || author = @request.auth.id || trail.trail_share_via_trail.actor.user ?= @request.auth.id",
"viewRule": "((@request.auth.id != \"\" && trail.author.user = @request.auth.id) || trail.public = true) || author = @request.auth.id || trail.trail_share_via_trail.actor.user ?= @request.auth.id"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("lf06qip3f4d11yk")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"createRule": "@request.auth.id != \"\" && (trail.author.user = @request.auth.id || trail.public = true || trail.trail_share_via_trail.user ?= @request.auth.id)",
"listRule": "((@request.auth.id != \"\" && trail.author.user = @request.auth.id) || trail.public = true) || author = @request.auth.id || trail.trail_share_via_trail.user ?= @request.auth.id",
"viewRule": "((@request.auth.id != \"\" && trail.author.user = @request.auth.id) || trail.public = true) || author = @request.auth.id || trail.trail_share_via_trail.user ?= @request.auth.id"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,62 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("1mns8mlal6uf9ku")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"listRule": "trail.author.user = @request.auth.id || actor.user = @request.auth.id",
"viewRule": "trail.author.user = @request.auth.id || actor.user = @request.auth.id"
}`), &collection); err != nil {
return err
}
// remove field
collection.Fields.RemoveById("yyzimwee")
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("1mns8mlal6uf9ku")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"listRule": "trail.author.user = @request.auth.id || user = @request.auth.id",
"viewRule": "trail.author.user = @request.auth.id || user = @request.auth.id"
}`), &collection); err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(3, []byte(`{
"cascadeDelete": true,
"collectionId": "_pb_users_auth_",
"hidden": false,
"id": "yyzimwee",
"maxSelect": 1,
"minSelect": 0,
"name": "user",
"presentable": false,
"required": true,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,55 @@
package migrations
import (
"os"
"pocketbase/util"
"github.com/meilisearch/meilisearch-go"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
client := meilisearch.New(os.Getenv("MEILI_URL"), meilisearch.WithAPIKey(os.Getenv("MEILI_MASTER_KEY")))
m.Register(func(app core.App) error {
users, err := app.FindAllRecords("users")
if err != nil {
return err
}
for _, u := range users {
userId := u.Id
actor, err := app.FindFirstRecordByData("activitypub_actors", "user", userId)
if err != nil {
return err
}
searchRules := map[string]interface{}{
"lists": map[string]string{
"filter": "public = true OR author = " + actor.Id + " OR shares = " + actor.Id,
},
"trails": map[string]string{
"filter": "public = true OR author = " + actor.Id + " OR shares = " + actor.Id,
},
}
token, err := util.GenerateMeilisearchToken(searchRules, client)
if err != nil {
return err
}
u.Set("token", token)
if err := app.Save(u); err != nil {
return err
}
}
return nil
}, func(app core.App) error {
// add down queries...
return nil
})
}

View File

@@ -0,0 +1,62 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("1kot7t9na3hi0gl")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"listRule": "list.author = @request.auth.id || actor.user = @request.auth.id",
"viewRule": "list.author = @request.auth.id || actor.user = @request.auth.id"
}`), &collection); err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(3, []byte(`{
"cascadeDelete": true,
"collectionId": "pbc_1295301207",
"hidden": false,
"id": "relation1148540665",
"maxSelect": 1,
"minSelect": 0,
"name": "actor",
"presentable": false,
"required": true,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("1kot7t9na3hi0gl")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"listRule": "list.author = @request.auth.id || user = @request.auth.id",
"viewRule": "list.author = @request.auth.id || user = @request.auth.id"
}`), &collection); err != nil {
return err
}
// remove field
collection.Fields.RemoveById("relation1148540665")
return app.Save(collection)
})
}

View File

@@ -0,0 +1,31 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
shares, err := app.FindAllRecords("list_share")
if err != nil {
return err
}
for _, s := range shares {
actor, err := app.FindFirstRecordByData("activitypub_actors", "user", s.GetString("user"))
if err != nil {
continue
}
s.Set("actor", actor.Id)
err = app.Save(s)
if err != nil {
return err
}
}
return nil
}, func(app core.App) error {
return nil
})
}

View File

@@ -0,0 +1,44 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("r6gu2ajyidy1x69")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"listRule": "author.user = @request.auth.id || public = true || (@request.auth.id != \"\" && list_share_via_list.actor.user ?= @request.auth.id)",
"updateRule": "author.user = @request.auth.id || (@request.auth.id != \"\" && list_share_via_list.list = id && list_share_via_list.actor.user ?= @request.auth.id && list_share_via_list.permission = \"edit\") || (@request.auth.id != \"\" && author.isLocal = false)",
"viewRule": "author.user = @request.auth.id || public = true || (@request.auth.id != \"\" && list_share_via_list.actor.user ?= @request.auth.id)"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("r6gu2ajyidy1x69")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"listRule": "author.user = @request.auth.id || public = true || (@request.auth.id != \"\" && list_share_via_list.user ?= @request.auth.id)",
"updateRule": "author.user = @request.auth.id || (@request.auth.id != \"\" && list_share_via_list.list = id && list_share_via_list.user ?= @request.auth.id && list_share_via_list.permission = \"edit\") || (@request.auth.id != \"\" && author.isLocal = false)",
"viewRule": "author.user = @request.auth.id || public = true || (@request.auth.id != \"\" && list_share_via_list.user ?= @request.auth.id)"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,44 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("1kot7t9na3hi0gl")
if err != nil {
return err
}
// remove field
collection.Fields.RemoveById("mix12kkh")
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("1kot7t9na3hi0gl")
if err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(2, []byte(`{
"cascadeDelete": true,
"collectionId": "_pb_users_auth_",
"hidden": false,
"id": "mix12kkh",
"maxSelect": 1,
"minSelect": 0,
"name": "user",
"presentable": false,
"required": true,
"system": false,
"type": "relation"
}`)); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,48 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("1kot7t9na3hi0gl")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"createRule": "list.author.user = @request.auth.id",
"deleteRule": "list.author.user = @request.auth.id",
"listRule": "list.author.user = @request.auth.id || actor.user = @request.auth.id",
"updateRule": "list.author.user = @request.auth.id",
"viewRule": "list.author.user = @request.auth.id || actor.user = @request.auth.id"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("1kot7t9na3hi0gl")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"createRule": "list.author = @request.auth.id",
"deleteRule": "list.author = @request.auth.id",
"listRule": "list.author = @request.auth.id || actor.user = @request.auth.id",
"updateRule": "list.author = @request.auth.id",
"viewRule": "list.author = @request.auth.id || actor.user = @request.auth.id"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,40 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("dd2l9a4vxpy2ni8")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"createRule": "@request.auth.id != \"\" && (trail.author.user = @request.auth.id || trail.public = true || trail.trail_share_via_trail.actor.user ?= @request.auth.id)"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("dd2l9a4vxpy2ni8")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"createRule": "@request.auth.id != \"\" && (trail.author.user = @request.auth.id || trail.public = true)"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,42 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("dd2l9a4vxpy2ni8")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"listRule": "(@request.auth.id != \"\" && (author.user = @request.auth.id || trail.author.user = @request.auth.id)) || trail.public = true || trail.trail_share_via_trail.actor.user ?= @request.auth.id",
"viewRule": "(@request.auth.id != \"\" && (author.user = @request.auth.id || trail.author.user = @request.auth.id)) || trail.public = true || trail.trail_share_via_trail.actor.user ?= @request.auth.id"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("dd2l9a4vxpy2ni8")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"listRule": "(@request.auth.id != \"\" && (author.user = @request.auth.id || trail.author.user = @request.auth.id)) || trail.public = true || (@collection.trail_share.trail ?= trail && @collection.trail_share.actor.user ?= @request.auth.id)",
"viewRule": "(@request.auth.id != \"\" && (author.user = @request.auth.id || trail.author.user = @request.auth.id)) || trail.public = true || (@collection.trail_share.trail ?= trail && @collection.trail_share.actor.user ?= @request.auth.id)"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,103 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
jsonData := `{
"createRule": null,
"deleteRule": null,
"fields": [
{
"autogeneratePattern": "[a-z0-9]{15}",
"hidden": false,
"id": "text3208210256",
"max": 15,
"min": 15,
"name": "id",
"pattern": "^[a-z0-9]+$",
"presentable": false,
"primaryKey": true,
"required": true,
"system": true,
"type": "text"
},
{
"cascadeDelete": true,
"collectionId": "e864strfxo14pm4",
"hidden": false,
"id": "relation2993194383",
"maxSelect": 1,
"minSelect": 0,
"name": "trail",
"presentable": false,
"required": true,
"system": false,
"type": "relation"
},
{
"cascadeDelete": true,
"collectionId": "pbc_1295301207",
"hidden": false,
"id": "relation1148540665",
"maxSelect": 1,
"minSelect": 0,
"name": "actor",
"presentable": false,
"required": true,
"system": false,
"type": "relation"
},
{
"hidden": false,
"id": "autodate2990389176",
"name": "created",
"onCreate": true,
"onUpdate": false,
"presentable": false,
"system": false,
"type": "autodate"
},
{
"hidden": false,
"id": "autodate3332085495",
"name": "updated",
"onCreate": true,
"onUpdate": true,
"presentable": false,
"system": false,
"type": "autodate"
}
],
"id": "pbc_1995454416",
"indexes": [
"CREATE UNIQUE INDEX ` + "`" + `idx_ywIkmeaSFo` + "`" + ` ON ` + "`" + `trail_like` + "`" + ` (\n ` + "`" + `trail` + "`" + `,\n ` + "`" + `actor` + "`" + `\n)"
],
"listRule": null,
"name": "trail_like",
"system": false,
"type": "base",
"updateRule": null,
"viewRule": null
}`
collection := &core.Collection{}
if err := json.Unmarshal([]byte(jsonData), &collection); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("pbc_1995454416")
if err != nil {
return err
}
return app.Delete(collection)
})
}

View File

@@ -0,0 +1,46 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("pbc_1995454416")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"createRule": "trail.author.user = @request.auth.id || trail.public = true || trail.trail_share_via_trail.actor.user ?= @request.auth.id || actor.user = @request.auth.id",
"deleteRule": "actor.user = @request.auth.id",
"listRule": "trail.author.user = @request.auth.id || trail.public = true || trail.trail_share_via_trail.actor.user ?= @request.auth.id || actor.user = @request.auth.id",
"viewRule": "trail.author.user = @request.auth.id || trail.public = true || trail.trail_share_via_trail.actor.user ?= @request.auth.id || actor.user = @request.auth.id"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("pbc_1995454416")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"createRule": null,
"deleteRule": null,
"listRule": null,
"viewRule": null
}`), &collection); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,42 @@
package migrations
import (
"os"
"github.com/meilisearch/meilisearch-go"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
client := meilisearch.New(os.Getenv("MEILI_URL"), meilisearch.WithAPIKey(os.Getenv("MEILI_MASTER_KEY")))
m.Register(func(app core.App) error {
_, err := client.Index("trails").UpdateSortableAttributes(&[]string{
"created", "date", "difficulty", "distance", "elevation_gain", "elevation_loss", "name", "duration", "author", "like_count",
})
if err != nil {
return err
}
_, err = client.Index("trails").UpdateFilterableAttributes(&[]string{
"_geo", "author", "category", "completed", "date", "difficulty", "distance", "elevation_gain", "elevation_loss", "public", "shares", "tags", "likes",
})
return err
}, func(app core.App) error {
_, err := client.Index("trails").UpdateSortableAttributes(&[]string{
"created", "date", "difficulty", "distance", "elevation_gain", "elevation_loss", "name", "duration", "author",
})
if err != nil {
return err
}
_, err = client.Index("trails").UpdateFilterableAttributes(&[]string{
"_geo", "author", "category", "completed", "date", "difficulty", "distance", "elevation_gain", "elevation_loss", "public", "shares", "tags",
})
return err
})
}

View File

@@ -0,0 +1,67 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("khrcci2uqknny8h")
if err != nil {
return err
}
// update field
if err := collection.Fields.AddMarshaledJSONAt(1, []byte(`{
"hidden": false,
"id": "b57prsbu",
"maxSelect": 1,
"name": "type",
"presentable": false,
"required": true,
"system": false,
"type": "select",
"values": [
"new_follower",
"trail_comment",
"trail_share",
"list_share",
"summit_log_create",
"trail_like"
]
}`)); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("khrcci2uqknny8h")
if err != nil {
return err
}
// update field
if err := collection.Fields.AddMarshaledJSONAt(1, []byte(`{
"hidden": false,
"id": "b57prsbu",
"maxSelect": 1,
"name": "type",
"presentable": false,
"required": true,
"system": false,
"type": "select",
"values": [
"new_follower",
"trail_comment",
"trail_share",
"list_share",
"summit_log_create"
]
}`)); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,43 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("e864strfxo14pm4")
if err != nil {
return err
}
// add field
if err := collection.Fields.AddMarshaledJSONAt(23, []byte(`{
"hidden": false,
"id": "number851275141",
"max": null,
"min": 0,
"name": "like_count",
"onlyInt": true,
"presentable": false,
"required": false,
"system": false,
"type": "number"
}`)); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("e864strfxo14pm4")
if err != nil {
return err
}
// remove field
collection.Fields.RemoveById("number851275141")
return app.Save(collection)
})
}

View File

@@ -0,0 +1,40 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("pbc_1995454416")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"viewRule": "actor.user = @request.auth.id"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("pbc_1995454416")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"viewRule": "trail.author.user = @request.auth.id || trail.public = true || trail.trail_share_via_trail.actor.user ?= @request.auth.id || actor.user = @request.auth.id"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,82 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("e864strfxo14pm4")
if err != nil {
return err
}
// update field
if err := collection.Fields.AddMarshaledJSONAt(11, []byte(`{
"hidden": false,
"id": "aqbpyawe",
"maxSelect": 99,
"maxSize": 20971520,
"mimeTypes": [
"image/jpeg",
"image/vnd.mozilla.apng",
"image/png",
"image/webp",
"image/svg+xml",
"image/heic",
"video/mp4",
"video/webm",
"video/ogg"
],
"name": "photos",
"presentable": false,
"protected": false,
"required": false,
"system": false,
"thumbs": [
"600x0"
],
"type": "file"
}`)); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("e864strfxo14pm4")
if err != nil {
return err
}
// update field
if err := collection.Fields.AddMarshaledJSONAt(11, []byte(`{
"hidden": false,
"id": "aqbpyawe",
"maxSelect": 99,
"maxSize": 20971520,
"mimeTypes": [
"image/jpeg",
"image/vnd.mozilla.apng",
"image/png",
"image/webp",
"image/svg+xml",
"image/heic",
"video/mp4",
"video/webm",
"video/ogg"
],
"name": "photos",
"presentable": false,
"protected": false,
"required": false,
"system": false,
"thumbs": [],
"type": "file"
}`)); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,42 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("pbc_1295301207")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"listRule": "user.settings_via_user.privacy.account != 'private' || user = @request.auth.id",
"viewRule": "user.settings_via_user.privacy.account != 'private' || user = @request.auth.id"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("pbc_1295301207")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"listRule": "",
"viewRule": ""
}`), &collection); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,42 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("lf06qip3f4d11yk")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"indexes": [
"CREATE UNIQUE INDEX ` + "`" + `idx_4T3m08OsP1` + "`" + ` ON ` + "`" + `comments` + "`" + ` (` + "`" + `iri` + "`" + `) WHERE iri IS NOT NULL AND iri != \"\";"
]
}`), &collection); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("lf06qip3f4d11yk")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"indexes": []
}`), &collection); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,44 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("r6gu2ajyidy1x69")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"indexes": [
"CREATE UNIQUE INDEX ` + "`" + `idx_hLtEU5XGWL` + "`" + ` ON ` + "`" + `lists` + "`" + ` (` + "`" + `iri` + "`" + `) WHERE iri IS NOT NULL AND iri != \"\";"
]
}`), &collection); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("r6gu2ajyidy1x69")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"indexes": [
"CREATE INDEX ` + "`" + `idx_hLtEU5XGWL` + "`" + ` ON ` + "`" + `lists` + "`" + ` (` + "`" + `iri` + "`" + `)"
]
}`), &collection); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,42 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("dd2l9a4vxpy2ni8")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"indexes": [
"CREATE UNIQUE INDEX ` + "`" + `idx_iSbmEqYXbV` + "`" + ` ON ` + "`" + `summit_logs` + "`" + ` (` + "`" + `iri` + "`" + `) WHERE iri IS NOT NULL AND iri != \"\";"
]
}`), &collection); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("dd2l9a4vxpy2ni8")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"indexes": []
}`), &collection); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,44 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("e864strfxo14pm4")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"indexes": [
"CREATE UNIQUE INDEX ` + "`" + `idx_6tD5RqfVk2` + "`" + ` ON ` + "`" + `trails` + "`" + ` (` + "`" + `iri` + "`" + `) WHERE iri IS NOT NULL AND iri != \"\";"
]
}`), &collection); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("e864strfxo14pm4")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"indexes": [
"CREATE INDEX ` + "`" + `idx_6tD5RqfVk2` + "`" + ` ON ` + "`" + `trails` + "`" + ` (` + "`" + `iri` + "`" + `)"
]
}`), &collection); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,70 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("khrcci2uqknny8h")
if err != nil {
return err
}
// update field
if err := collection.Fields.AddMarshaledJSONAt(1, []byte(`{
"hidden": false,
"id": "b57prsbu",
"maxSelect": 1,
"name": "type",
"presentable": false,
"required": true,
"system": false,
"type": "select",
"values": [
"new_follower",
"trail_comment",
"trail_share",
"list_share",
"summit_log_create",
"trail_like",
"comment_mention",
"trail_mention"
]
}`)); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("khrcci2uqknny8h")
if err != nil {
return err
}
// update field
if err := collection.Fields.AddMarshaledJSONAt(1, []byte(`{
"hidden": false,
"id": "b57prsbu",
"maxSelect": 1,
"name": "type",
"presentable": false,
"required": true,
"system": false,
"type": "select",
"values": [
"new_follower",
"trail_comment",
"trail_share",
"list_share",
"summit_log_create",
"trail_like"
]
}`)); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,73 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("khrcci2uqknny8h")
if err != nil {
return err
}
// update field
if err := collection.Fields.AddMarshaledJSONAt(1, []byte(`{
"hidden": false,
"id": "b57prsbu",
"maxSelect": 1,
"name": "type",
"presentable": false,
"required": true,
"system": false,
"type": "select",
"values": [
"new_follower",
"trail_comment",
"trail_share",
"list_share",
"summit_log_create",
"trail_like",
"comment_mention",
"trail_mention",
"summit_log_mention"
]
}`)); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("khrcci2uqknny8h")
if err != nil {
return err
}
// update field
if err := collection.Fields.AddMarshaledJSONAt(1, []byte(`{
"hidden": false,
"id": "b57prsbu",
"maxSelect": 1,
"name": "type",
"presentable": false,
"required": true,
"system": false,
"type": "select",
"values": [
"new_follower",
"trail_comment",
"trail_share",
"list_share",
"summit_log_create",
"trail_like",
"comment_mention",
"trail_mention"
]
}`)); err != nil {
return err
}
return app.Save(collection)
})
}

View File

@@ -0,0 +1,58 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
actors, err := app.FindAllRecords("activitypub_actors")
if err != nil {
return err
}
for _, a := range actors {
if !a.GetBool("isLocal") {
continue
}
username := a.GetString("username")
preferredUsername := a.GetString("preferred_username")
a.Set("username", preferredUsername)
a.Set("preferred_username", username)
err = app.Save(a)
if err != nil {
return err
}
}
return nil
}, func(app core.App) error {
actors, err := app.FindAllRecords("activitypub_actors")
if err != nil {
return err
}
for _, a := range actors {
if !a.GetBool("isLocal") {
continue
}
username := a.GetString("username")
preferredUsername := a.GetString("preferred_username")
a.Set("username", preferredUsername)
a.Set("preferred_username", username)
err = app.Save(a)
if err != nil {
return err
}
}
return nil
})
}

View File

@@ -0,0 +1,40 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("pbc_468398817")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"viewQuery": "SELECT\n id,\n trail_id,\n trail_author_username,\n trail_author_domain,\n trail_iri,\n date,\n name,\n description,\n gpx,\n author,\n photos,\n distance,\n duration,\n elevation_gain,\n elevation_loss,\n created,\n type\nFROM\n (\n SELECT\n summit_logs.id,\n summit_logs.trail as trail_id,\n tapa.preferred_username as trail_author_username,\n tapa.domain as trail_author_domain,\n trails.iri as trail_iri,\n summit_logs.date,\n trails.name,\n text as description,\n summit_logs.gpx,\n sapa.iri as author,\n summit_logs.photos,\n summit_logs.distance,\n summit_logs.duration,\n summit_logs.elevation_gain,\n summit_logs.elevation_loss,\n summit_logs.created,\n \"summit_log\" as type\n FROM\n summit_logs\n JOIN trails ON summit_logs.trail = trails.id\n JOIN activitypub_actors sapa ON sapa.id = summit_logs.author\n JOIN activitypub_actors tapa ON tapa.id = trails.author\n UNION\n SELECT\n trails.id,\n trails.id as trail_id,\n activitypub_actors.preferred_username as trail_author_username,\n activitypub_actors.domain as trail_author_domain,\n trails.iri as trail_iri,\n date,\n trails.name,\n description,\n gpx,\n activitypub_actors.iri as author,\n photos,\n distance,\n duration,\n elevation_gain,\n elevation_loss,\n trails.created,\n \"trail\" as type\n FROM\n trails\n JOIN activitypub_actors ON activitypub_actors.id = trails.author\n )\nORDER BY\n created DESC;\n"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("pbc_468398817")
if err != nil {
return err
}
// update collection data
if err := json.Unmarshal([]byte(`{
"viewQuery": "SELECT\n id,\n trail_id,\n trail_author_username,\n trail_author_domain,\n trail_iri,\n date,\n name,\n description,\n gpx,\n author,\n photos,\n distance,\n duration,\n elevation_gain,\n elevation_loss,\n created,\n type\nFROM\n (\n SELECT\n summit_logs.id,\n summit_logs.trail as trail_id,\n tapa.username as trail_author_username,\n tapa.domain as trail_author_domain,\n trails.iri as trail_iri,\n summit_logs.date,\n trails.name,\n text as description,\n summit_logs.gpx,\n sapa.iri as author,\n summit_logs.photos,\n summit_logs.distance,\n summit_logs.duration,\n summit_logs.elevation_gain,\n summit_logs.elevation_loss,\n summit_logs.created,\n \"summit_log\" as type\n FROM\n summit_logs\n JOIN trails ON summit_logs.trail = trails.id\n JOIN activitypub_actors sapa ON sapa.id = summit_logs.author\n JOIN activitypub_actors tapa ON tapa.id = trails.author\n UNION\n SELECT\n trails.id,\n trails.id as trail_id,\n activitypub_actors.username as trail_author_username,\n activitypub_actors.domain as trail_author_domain,\n trails.iri as trail_iri,\n date,\n trails.name,\n description,\n gpx,\n activitypub_actors.iri as author,\n photos,\n distance,\n duration,\n elevation_gain,\n elevation_loss,\n trails.created,\n \"trail\" as type\n FROM\n trails\n JOIN activitypub_actors ON activitypub_actors.id = trails.author\n )\nORDER BY\n created DESC;\n"
}`), &collection); err != nil {
return err
}
return app.Save(collection)
})
}

Some files were not shown because too many files have changed in this diff Show More