From b65fbdd1285f2b3ec88a62e89a2e412779add4e2 Mon Sep 17 00:00:00 2001 From: Flomp Date: Tue, 13 Jan 2026 10:01:05 -0800 Subject: [PATCH] fix trail privacy (#719) * fix trail privacy * adds privacy setting to integrations --------- Co-authored-by: Christian Beutel <> --- db/integrations/komoot/komoot.go | 20 +++++-- db/integrations/komoot/models.go | 1 + db/integrations/strava/models.go | 1 + db/integrations/strava/strava.go | 54 +++++++++++++++---- .../integrations/komoot_settings_modal.svelte | 29 +++++++++- .../integrations/strava_settings_modal.svelte | 34 ++++++++++-- web/src/lib/i18n/locales/de.json | 8 ++- web/src/lib/i18n/locales/en.json | 8 ++- web/src/lib/i18n/locales/es.json | 7 +++ web/src/lib/i18n/locales/eu.json | 7 +++ web/src/lib/i18n/locales/fr.json | 7 +++ web/src/lib/i18n/locales/hu.json | 7 +++ web/src/lib/i18n/locales/it.json | 7 +++ web/src/lib/i18n/locales/nl.json | 7 +++ web/src/lib/i18n/locales/pl.json | 7 +++ web/src/lib/i18n/locales/pt.json | 7 +++ web/src/lib/i18n/locales/ru.json | 7 +++ web/src/lib/i18n/locales/zh.json | 7 +++ web/src/lib/models/api/integration_schema.ts | 4 +- web/src/lib/models/integration.ts | 2 + web/src/lib/util/authorization_util.ts | 4 +- web/src/routes/api/v1/trail/upload/+server.ts | 2 + 22 files changed, 210 insertions(+), 27 deletions(-) diff --git a/db/integrations/komoot/komoot.go b/db/integrations/komoot/komoot.go index 51b62ee8..744e485f 100644 --- a/db/integrations/komoot/komoot.go +++ b/db/integrations/komoot/komoot.go @@ -205,7 +205,7 @@ func syncTrailWithTours(app core.App, k *KomootApi, i KomootIntegration, user st app.Logger().Warn(fmt.Sprintf("Unable to generate GPX for tour '%s': %v", tour.Name, err)) continue } - trailid, err := createTrailFromTour(app, k, detailedTour, gpx, actor) + trailid, err := createTrailFromTour(app, k, detailedTour, gpx, user, actor, i.Privacy) if err != nil { app.Logger().Warn(fmt.Sprintf("Unable to create trail for tour '%s': %v", tour.Name, err)) continue @@ -220,7 +220,7 @@ func syncTrailWithTours(app core.App, k *KomootApi, i KomootIntegration, user st return hasNewTours, nil } -func createTrailFromTour(app core.App, k *KomootApi, detailedTour *DetailedKomootTour, gpx *filesystem.File, actor string) (string, error) { +func createTrailFromTour(app core.App, k *KomootApi, detailedTour *DetailedKomootTour, gpx *filesystem.File, user string, actor string, privacy string) (string, error) { trailid := security.RandomStringWithAlphabet(core.DefaultIdLength, core.DefaultIdAlphabet) collection, err := app.FindCollectionByNameOrId("trails") @@ -266,10 +266,24 @@ func createTrailFromTour(app core.App, k *KomootApi, detailedTour *DetailedKomoo diffculty = "easy" } + public := detailedTour.Status == "public" + if privacy == "settings" { + privacySettings := struct { + Trails string `json:"trails"` + }{} + + settings, _ := app.FindFirstRecordByData("settings", "user", user) + err = settings.UnmarshalJSONField("privacy", &privacySettings) + if err != nil { + return "", err + } + public = privacySettings.Trails == "public" + } + record.Load(map[string]any{ "id": trailid, "name": detailedTour.Name, - "public": detailedTour.Status == "public", + "public": public, "distance": detailedTour.Distance, "elevation_gain": detailedTour.ElevationUp, "elevation_loss": detailedTour.ElevationDown, diff --git a/db/integrations/komoot/models.go b/db/integrations/komoot/models.go index addd8d7c..fd378130 100644 --- a/db/integrations/komoot/models.go +++ b/db/integrations/komoot/models.go @@ -8,6 +8,7 @@ type KomootIntegration struct { Password string `json:"password"` Planned bool `json:"planned"` Completed bool `json:"completed"` + Privacy string `json:"privacy"` } type LoginResponse struct { diff --git a/db/integrations/strava/models.go b/db/integrations/strava/models.go index 8fa4f0fd..d381f18a 100644 --- a/db/integrations/strava/models.go +++ b/db/integrations/strava/models.go @@ -29,6 +29,7 @@ type StravaIntegration struct { AccessToken string `json:"accessToken,omitempty"` RefreshToken string `json:"refreshToken,omitempty"` ExpiresAt int64 `json:"expiresAt,omitempty"` + Privacy string `json:"privacy"` After string `json:"after,omitempty"` } type StravaRoute struct { diff --git a/db/integrations/strava/strava.go b/db/integrations/strava/strava.go index bf347381..d9250b02 100644 --- a/db/integrations/strava/strava.go +++ b/db/integrations/strava/strava.go @@ -102,7 +102,7 @@ func SyncStrava(app core.App) error { app.Logger().Warn(warning) break } - err = syncTrailsWithRoutes(app, r.AccessToken, userId, actorId, routes) + err = syncTrailsWithRoutes(app, stravaIntegration, r.AccessToken, userId, actorId, routes) if err != nil { warning := fmt.Sprintf("error syncing strava routes with trails: %v\n", err) fmt.Print(warning) @@ -134,7 +134,7 @@ func SyncStrava(app core.App) error { app.Logger().Warn(warning) break } - err = syncTrailsWithActivities(app, r.AccessToken, actorId, activities) + err = syncTrailsWithActivities(app, stravaIntegration, r.AccessToken, userId, actorId, activities) if err != nil { warning := fmt.Sprintf("error syncing strava activities with trails: %v", err) @@ -248,7 +248,7 @@ func fetchStravaActivities(accessToken string, page int, after int64) ([]StravaA return activities, nil } -func syncTrailsWithRoutes(app core.App, accessToken string, user string, actor string, routes []StravaRoute) error { +func syncTrailsWithRoutes(app core.App, i StravaIntegration, accessToken string, user string, actor string, routes []StravaRoute) error { for _, route := range routes { trails, err := app.FindRecordsByFilter("trails", "external_id = {:id}", "", 1, 0, dbx.Params{"id": route.IDStr}) if err != nil { @@ -262,7 +262,7 @@ func syncTrailsWithRoutes(app core.App, accessToken string, user string, actor s app.Logger().Warn(fmt.Sprintf("Unable to fetch GPX for route '%s': %v", route.Name, err)) continue } - trailid, err := createTrailFromRoute(app, route, gpx, actor) + trailid, err := createTrailFromRoute(app, route, gpx, user, actor, i.Privacy) if err != nil { app.Logger().Warn(fmt.Sprintf("Unable to create trail for route '%s': %v", route.Name, err)) continue @@ -315,7 +315,7 @@ func fetchRouteGPX(route StravaRoute, accessToken string) (*filesystem.File, err return gpxFile, nil } -func createTrailFromRoute(app core.App, route StravaRoute, gpx *filesystem.File, actor string) (string, error) { +func createTrailFromRoute(app core.App, route StravaRoute, gpx *filesystem.File, user string, actor string, privacy string) (string, error) { trailid := security.RandomStringWithAlphabet(core.DefaultIdLength, core.DefaultIdAlphabet) collection, err := app.FindCollectionByNameOrId("trails") @@ -348,11 +348,27 @@ func createTrailFromRoute(app core.App, route StravaRoute, gpx *filesystem.File, category = hikeCategory.Id } + public := !route.Private + + if privacy == "settings" { + privacySettings := struct { + Trails string `json:"trails"` + }{} + + settings, _ := app.FindFirstRecordByData("settings", "user", user) + err = settings.UnmarshalJSONField("privacy", &privacySettings) + if err != nil { + return "", err + } + + public = privacySettings.Trails == "public" + } + record.Load(map[string]any{ "id": trailid, "name": route.Name, "description": route.Description, - "public": !route.Private, + "public": public, "distance": route.Distance, "elevation_gain": route.ElevationGain, "duration": route.EstimatedMovingTime, @@ -404,7 +420,7 @@ func createWaypointsFromRoute(app core.App, route StravaRoute, user string, trai return nil } -func syncTrailsWithActivities(app core.App, accessToken string, actor string, activities []StravaActivity) error { +func syncTrailsWithActivities(app core.App, i StravaIntegration, accessToken string, user string, actor string, activities []StravaActivity) error { for _, activity := range activities { trails, err := app.FindRecordsByFilter("trails", "external_id = {:id}", "", 1, 0, dbx.Params{"id": strconv.Itoa(int(activity.ID))}) if err != nil { @@ -423,7 +439,7 @@ func syncTrailsWithActivities(app core.App, accessToken string, actor string, ac app.Logger().Warn(fmt.Sprintf("Unable to fetch GPX for activity '%s': %v", activity.Name, err)) continue } - err = createTrailFromActivity(app, detailedActivity, gpx, actor) + err = createTrailFromActivity(app, detailedActivity, gpx, user, actor, i.Privacy) if err != nil { app.Logger().Warn(fmt.Sprintf("Unable to create trail from activity '%s': %v", activity.Name, err)) continue @@ -460,7 +476,7 @@ func fetchDetailedActivity(activity StravaActivity, accessToken string) (*Detail return &detailedActivity, nil } -func createTrailFromActivity(app core.App, activity *DetailedStravaActivity, gpx *filesystem.File, user string) error { +func createTrailFromActivity(app core.App, activity *DetailedStravaActivity, gpx *filesystem.File, user string, actor string, privacy string) error { if len(activity.StartLatlng) < 2 { return nil } @@ -526,10 +542,26 @@ func createTrailFromActivity(app core.App, activity *DetailedStravaActivity, gpx categoryId = category.Id } + public := !activity.Private + + if privacy == "settings" { + privacySettings := struct { + Trails string `json:"trails"` + }{} + + settings, _ := app.FindFirstRecordByData("settings", "user", user) + err = settings.UnmarshalJSONField("privacy", &privacySettings) + if err != nil { + return err + } + + public = privacySettings.Trails == "public" + } + record.Load(map[string]any{ "name": activity.Name, "description": activity.Description, - "public": !activity.Private, + "public": public, "distance": activity.Distance, "elevation_gain": activity.TotalElevationGain, "duration": activity.ElapsedTime, @@ -540,7 +572,7 @@ func createTrailFromActivity(app core.App, activity *DetailedStravaActivity, gpx "lon": activity.StartLatlng[1], "difficulty": "easy", "category": categoryId, - "author": user, + "author": actor, }) if photo != nil { diff --git a/web/src/lib/components/settings/integrations/komoot_settings_modal.svelte b/web/src/lib/components/settings/integrations/komoot_settings_modal.svelte index b6d3af68..d857b2b0 100644 --- a/web/src/lib/components/settings/integrations/komoot_settings_modal.svelte +++ b/web/src/lib/components/settings/integrations/komoot_settings_modal.svelte @@ -1,5 +1,8 @@