Require login to export files; allow downloading the original too
?download=... on GET /api/gpx/file now requires login, same as upload/move/delete/create-folder -- plain viewing (no ?download) stays public. Added ?download=original alongside the existing GeoJSON export, serving the untouched, as-uploaded file directly via send_file -- the file name link still downloads GeoJSON, a new button next to delete downloads the original. Since both are real <a href> links (so right-click/middle-click still work), a logged-out click can't just be left as a plain navigation -- it would land on a raw JSON error page instead of being sent to log in. _download (gpx.js) fetches instead, reuses the existing redirectIfUnauthorized 401 check, and only then turns the response into a blob and clicks a throwaway <a download> to trigger the save. Verified in a real browser: an anonymous click on either download correctly redirects through /login to the real OAuth login page instead of showing raw JSON.
This commit is contained in:
1 parent
ceaaa0bb92
commit
eca8519152
4 files changed
+123
-30
No files matched your search
+27
-13
@@ -343,18 +343,29 @@ name instead — `"ride.gpx"` reads as `"ride.gpx.geojson"`, matching
|
||||
the real cache file sitting next to it on disk — since the GeoJSON,
|
||||
not the original, is what's actually rendered on the map from that
|
||||
point on. The original is never deleted or re-parsed once cached, just
|
||||
not re-shown as itself. Two ways to get that converted form out of the
|
||||
app as an actual file (`GET /api/gpx/file/<path>?download=1`) — the
|
||||
cache is otherwise an implementation detail with no name of its own to
|
||||
expose: the file name itself is a real link (an `<a>`, not a `<span>`,
|
||||
specifically so clicking it downloads instead of also toggling the
|
||||
row's checkbox — a native `<a>`/`<button>` nested inside a `<label>`
|
||||
claims its own click instead of the label forwarding it to the
|
||||
associated control, so the two behaviors don't fight over the same
|
||||
click), and a dedicated download button sits next to delete for anyone
|
||||
who wouldn't guess the name itself is clickable. A directly-uploaded
|
||||
`.geojson` keeps its own name (nothing to convert) and downloads
|
||||
unchanged either way. `Gpx` parses the GPX with REXML: `<wpt>`
|
||||
not re-shown as itself, so both forms need a way out of the app as an
|
||||
actual file: the file name itself (`GET /api/gpx/file/<path>?download=geojson`)
|
||||
is a real link, not a `<span>` — clicking it downloads the GeoJSON
|
||||
rather than also toggling the row's checkbox, since a native
|
||||
`<a>`/`<button>` nested inside a `<label>` claims its own click
|
||||
instead of the label forwarding it to the associated control — and a
|
||||
second button next to delete (`?download=original`) downloads the
|
||||
untouched, as-uploaded file, since the name alone only covers half of
|
||||
what's now downloadable and isn't an obvious click target regardless.
|
||||
A directly-uploaded `.geojson` keeps its own name and both buttons
|
||||
download the same (identical) content — redundant there, not wrong.
|
||||
Both kinds of download require login, same as upload/move/delete/
|
||||
create-folder — `GET /api/gpx/file` itself stays open to anyone
|
||||
(viewing a file on the map isn't a write action), just not
|
||||
`?download=...` on it. Since both links are real `<a href>`s (so
|
||||
right-click/middle-click still do something sensible), a logged-out
|
||||
click can't just be a plain navigation the way delete/upload already
|
||||
aren't — `_download` (`gpx.js`) fetches instead, checks for a 401 the
|
||||
same way `redirectIfUnauthorized` already does for every other write
|
||||
action, and only then turns the response into a blob and clicks a
|
||||
throwaway `<a download>` to trigger the actual save — a plain
|
||||
navigation would otherwise land on a raw JSON error page instead of
|
||||
being sent to log in. `Gpx` parses the GPX with REXML: `<wpt>`
|
||||
waypoints become `Point` features (with `name`, `desc` and `time`
|
||||
carried through as properties), each `<trk>` becomes one
|
||||
`MultiLineString` feature (one line per `<trkseg>`), and each `<rte>`
|
||||
@@ -676,7 +687,10 @@ The GPX store's read endpoints (viewing the map, the folder tree,
|
||||
individual files) are public — anyone with the URL can look. Its write
|
||||
endpoints (`POST /api/gpx`, `POST /api/gpx/folder`, `DELETE
|
||||
/api/gpx/file/*`, `DELETE /api/gpx/folder/*`, `POST /api/gpx/move`)
|
||||
require login, guarded by `require_login!` in `app.rb`.
|
||||
require login, guarded by `require_login!` in `app.rb` — and so does
|
||||
exporting a file (`GET /api/gpx/file/*?download=...`), even though
|
||||
plain viewing of that same URL (no `?download`) doesn't; not a write
|
||||
exactly, but treated the same as the others rather than left open.
|
||||
|
||||
Login delegates to the Gitea instance at `git.priesol.net` via OAuth2
|
||||
(`GET /login` redirects to Gitea's authorize endpoint, `GET
|
||||
|
||||
Reference in new issue
Block a user