Repository navigation
Shorten a viewer map URL the caller can open #272
Description
The viewer asks the backend to shorten the map URL it is about to share. The browser does not call tinyurl.com.
The caller sends the map URL. It sends the HttpOnly viewer_access_token cookie when the browser has one.
No cookie. The anonymous filter principal is public. That is the public visitor. publicAuthClearGuard clears viewer_access_token on /public/**, so a public map has no cookie. Allow the request when that principal can open the application and territory in the URL. The gate is the same one as GET /api/config/client/profile/{appId}/{terrId}: findApplicationByUserApplicationAndTerritory for username public. mayAccessApplication only rejects a private application. It does not check the territory. No matching pair returns 403, with the same problem response the profile endpoint returns.
The built-in public user has no password and does not receive viewer_access_token. The public visitor is the request with no cookie. A cookie that identifies a registered user is allowed when that user can open the same application and territory. A cookie that does not identify a registered user returns 401. The admin cookie and a mobile Bearer token are this case. A missing cookie is not.
Provider
The endpoint does not branch on the provider name. It resolves the caller, refuses a URL that is not this deployment's viewer map, refuses a map the caller cannot open, then calls the selected ShortUrlProvider. A later definitive provider is a new implementation and a new config value. The endpoint stays as it is.
sitmun:
short-url:
provider: none
tinyurl-legacy:
endpoint: https://tinyurl.com/api-create.phpsitmun.short-url.provider is the id. Shipped ids are none and tinyurl-legacy. The default is none. Each provider is a Spring bean with that id. Startup indexes the beans by id and fails when the configured id is missing or when two beans share an id. A missing property is none.
none is a provider. It returns the submitted URL and calls no host. It is not a null check in the endpoint.
tinyurl-legacy reads only sitmun.short-url.tinyurl-legacy. It POSTs the map URL to that endpoint, which defaults to https://tinyurl.com/api-create.php.
A definitive provider adds its own id, its own bean, and its own sitmun.short-url.<id> block for a token or base URL. It does not read the TinyURL block. The viewer still receives a URL or an error and does not learn the provider id.
Each provider returns one of three results.
- Original. The submitted URL. Only
nonereturns this. - Shortened. A different URL.
- Failed. A message. The endpoint does not replace that with the original URL.
The map-URL check runs before shorten(), so every provider, including a future one, refuses the same foreign destinations.
Responses
- Original.
200and the URL the caller sent. - Shortened.
200and the short URL. - The caller cannot open that application and territory.
403, the same problem response as the profile. - A cookie is present and it does not identify the public user or a registered user.
401. - Failed, or a URL that is not this viewer map. An error response with a message.
Legacy TinyURL
Checked on 2026-10-04.
- A server POST to
https://tinyurl.com/api-create.phpwith no account returned HTTP 200 andhttps://tinyurl.com/22wyblfp.access-control-allow-originwashttps://tinyurl.comonly, which is why the viewer page cannot read it. POST https://api.tinyurl.com/createwith no token returned HTTP 401Unauthenticated.- TinyURL's own posts say
http://tinyurl.com/api-create.phpwas never officially supported and is deprecated. Links created with it show an interstitial before the destination. TinyURL cannot attach those links to an account, edit them, or delete them. No end date is set. Sources: Retiring Our Old API Endpoint and Why Does My TinyURL Link Show an Ad or Preview Screen. - The pricing page the same day lists a free plan at 30 links a month and Pro at $9 a month for 125 links. The documented API still requires a bearer token. This issue does not call that API.
tinyurl-legacy is the first provider that calls a shortener. A server POST still returns a short URL with no account. TinyURL does not support that endpoint. The definitive provider replaces it by config. Until an operator sets tinyurl-legacy, the default none returns the original map URL.
Acceptance
- No cookie, when the public user can open the application and territory in the URL, is allowed.
sitmun.short-url.provider=nonereturns the submitted map URL and does not call a shortener. - No cookie, and the public user cannot open that pair, returns 403.
- A valid registered viewer cookie is allowed when that user can open the pair, and returns 403 when they cannot.
- A cookie that does not identify a registered user returns 401.
- A caller who can open the pair, with
sitmun.short-url.provider=tinyurl-legacy, receives the short URL fromapi-create.php. The browser never sees that host. - A missing property behaves as
none. - A failed provider call returns an error message and does not return the original URL.
- A URL that is not this viewer map returns an error before any provider runs.
- Adding a provider does not add a branch to the endpoint. It adds one
ShortUrlProviderbean, one id, and that provider's own config block. - The admin cookie and a Bearer mobile token do not authorize this route.
Parent: sitmun/sitmun-viewer-app#189
Activity
[-]Shorten a viewer map URL for an identified session[/-][+]Shorten a viewer map URL the caller can open[/+]fjlopez commentedon Oct 4, 2026
Corrected the no-cookie rule.
A missing
viewer_access_tokenis the anonymous principalpublic, not a 401. Allow it when that principal can open the application and territory in the URL. The gate isfindApplicationByUserApplicationAndTerritory, the same one asGET /api/config/client/profile/{appId}/{terrId}.mayAccessApplicationonly rejects a private application and does not check the territory. No pair is 403. 401 stays for a cookie that does not identify the built-in public user or a registered user, including the admin cookie and a mobile Bearer token.fjlopez commentedon Oct 4, 2026
The built-in public user does not receive
viewer_access_token. Login keeps that password null, andROLE_PUBLICexists only on the anonymous filter. The public visitor is the request with no cookie. A viewer cookie is a registered user.fjlopez commentedon Oct 4, 2026
Verified
POST /api/config/client/short-urlwith no cookie.http://localhost:9000/viewer/public/map/12/4?mapState=abcreturns 200 and the same URL (sitmun.short-url.providerisnone).https://evil.example/viewer/public/map/12/4returns 400URL is not a viewer map. The provider is not called.http://localhost:9000/viewer/public/map/99999/99999returns 403.The TinyURL provider uses OkHttp. The default provider does not call TinyURL.
fjlopez commentedon Oct 4, 2026
Landed on
devwith sitmun/sitmun-application-stack#81.A public map on
http://localhost:4200/public/map/12/4shortened throughPOST /api/config/client/short-url. The request went tohttp://localhost:9000/backend/api/config/client/short-urland the response kept the same map URL. The default provider isnone.fjlopez commentedon Oct 4, 2026
The caller can shorten a viewer map URL they can open.