- CSRF over plain HTTP (#189): gorilla/csrf assumed https for its
same-origin check, so setup and every POST returned 403 over plain
HTTP. Gate csrf.PlaintextHTTPRequest on a new UPAAS_PLAINTEXT_HTTP
config value; the default keeps https, correct for a TLS-terminating
reverse proxy. The README plain-HTTP recipe now sets it.
- git image never pulled (#190): ensureImage pulls alpine/git (pinned
digest unchanged) when absent, before the clone container is created.
- port-mapping 500 (#192): the ports delete form used {{ .CSRFField }}
inside {{range .Ports}}, where the dot is a *models.Port; use
{{ $.CSRFField }} like the labels and volumes blocks.
- env-var 403 (#191): the editor read the CSRF token from $el (the
submitting form, which has none) instead of $root, sending an empty
token; read from $root.
Model: opus-4-8
This PR fixes env var handling by consolidating individual add/edit/delete operations into a single monolithic bulk save.
## Changes
- **Template**: Restored original table-based UI with key/value rows, edit/delete buttons, and add form. Uses Alpine.js to manage the env var list client-side. On form submit, all env vars are collected into a hidden textarea and POSTed as a single bulk request.
- **Handler**: `HandleEnvVarSave` atomically replaces all env vars (DELETE all + INSERT full set).
- **Routes**: Single `POST /apps/{id}/env` endpoint replaces individual env var CRUD routes.
- **Models**: Added `DeleteEnvVarsByAppID` and `FindEnvVarsByAppID` for bulk operations.
closes sneak/upaas#156
closes sneak/upaas#163
Co-authored-by: clawbot <clawbot@noreply.git.eeqj.de>
Co-authored-by: Jeffrey Paul <sneak@noreply.example.org>
Co-authored-by: user <user@Mac.lan guest wan>
Reviewed-on: sneak/upaas#158
Co-authored-by: clawbot <clawbot@noreply.example.org>
Co-committed-by: clawbot <clawbot@noreply.example.org>