Add Site URL editor to admin General Settings (fixes #989)#1069
Draft
ebootheee wants to merge 3 commits into
Draft
Add Site URL editor to admin General Settings (fixes #989)#1069ebootheee wants to merge 3 commits into
ebootheee wants to merge 3 commits into
Conversation
Adds a dedicated GET/POST endpoint at /_emdash/api/settings/site-url and a corresponding "Email Site URL" section in admin General Settings. The endpoint updates the emdash:site_url option, which governs the base URL used in transactional emails (magic-link, invitation, password-reset) via getSiteBaseUrl(). Previously this value was written once during the setup wizard via setIfAbsent() and was not editable from the admin UI, so deployments behind reverse proxies that captured a bogus first-request origin had no way to fix it. Fixes emdash-cms#989. The write is gated on settings:manage. Submitted URLs are validated to http(s) origins only (no path/query/fragment, no XSS-prone schemes), and trailing slashes are stripped. The existing site:url field in Site Identity (used for canonical links and sitemaps) is unchanged.
🦋 Changeset detectedLatest commit: e736a43 The changes in this PR will be included in the next version bump. This PR includes changesets to release 13 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Contributor
|
All contributors have signed the CLA ✍️ ✅ |
@emdash-cms/admin
@emdash-cms/auth
@emdash-cms/blocks
@emdash-cms/cloudflare
emdash
create-emdash
@emdash-cms/gutenberg-to-portable-text
@emdash-cms/x402
@emdash-cms/plugin-ai-moderation
@emdash-cms/plugin-atproto
@emdash-cms/plugin-audit-log
@emdash-cms/plugin-color
@emdash-cms/plugin-embeds
@emdash-cms/plugin-forms
@emdash-cms/plugin-webhook-notifier
commit: |
Author
|
I have read the CLA Document and I hereby sign the CLA |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Adds a dedicated Site URL editor to admin General Settings that updates the
emdash:site_urloption. This is the valuegetSiteBaseUrl()(inpackages/core/src/api/site-url.ts) reads to build URLs in transactional emails (magic-link, invitation, password-reset). Previously this row was written once during the setup wizard viasetIfAbsent()and was not editable from the admin UI, so any site whose first setup request observed a bogus origin (e.g. behind a reverse proxy without a properly forwardedHost/X-Forwarded-Host, or via a dev-bypass call fromlocalhostbefore the public domain was wired up) had no in-product way to correct it. That matches the reproduction in issue #989.Closes #989
Type of change
Why this shape (approach A)
This is approach A from a short menu of two:
Email Site URLsection in General Settings that writesemdash:site_url. Keeps the namespace boundary visible:emdash:*options are internal/security-sensitive (mirrorsemdash:site_title,emdash:setup_complete,emdash:exclusive_hook:*), whilesite:*is presentation. The pre-existingsite:urlfield in Site Identity (used for canonical links and sitemaps) is unchanged.site:urlfield also writeemdash:site_url, or migratesite:urlto be the canonical key. Cleaner long-term, but it touches the migration system and changes the semantics of an existing user-facing field, so it felt out of scope for a fix PR. Happy to take it as a follow-up if maintainers prefer that direction.Implementation notes
GET/POST /_emdash/api/settings/site-urlatpackages/core/src/astro/routes/api/settings/site-url.ts, registered inastro/integration/routes.ts. Sits under/_emdash/api/settings, so the existing middleware scope rules (settings:read/settings:manage) cover it without an extra entry.new URL()and rejects (a) unparseable input, (b) non-http(s) schemes (XSS-prone — this value is interpolated into outgoing email content), and (c) any value carrying a path beyond/, a query string, or a fragment. The stored value is normalized toURL.originsogetSiteBaseUrl()can keep appending/_emdashcleanly.OptionsRepository.set()(notsetIfAbsent()) — the setup wizard's write-once guard exists to prevent Host-spoofing during the setup window, but post-setup the admin needs to be able to update the value. Permission is gated onsettings:manage, which isRole.ADMIN.Email Site URLcard in General Settings, with its own save button and status banner, so it doesn't interleave with the existingsite:urlfield. Help text explains the scope:Sets the base URL used for magic-link, invitation, and password-reset emails. Changes do not affect URLs in emails that have already been sent.Tests
New:
packages/core/tests/integration/astro/settings-site-url.test.ts(12 tests) covers:nullpre-write, requires authsetIfAbsentsemantics)javascript:schemes, paths, query strings, and unparseable URLssettings:readonly) and unauthenticated callersChecklist
pnpm typecheckpasses (whole workspace)pnpm lintpasses (0 errors on changed files; pre-existing warnings elsewhere)pnpm --filter emdash vitest run tests/integration/astro/settings-site-url.test.ts→ 12/12 greenpnpm testclean — see notes belowpnpm formatwould be run before non-draft; happy to run on requesttmacroemdashand@emdash-cms/admin)Not verified
pnpm --filter emdash testhad 9 unrelated failures on my Windows host (tarshell-out path issues inbundle-utils.test, file-based SQLite locking inconnection.test, Vite alias tests using POSIX-only path assertions). All in files that don't touch site-url; happy to re-run on Linux if useful.pnpm --filter @emdash-cms/admin test(Vitest browser/Playwright) showed a large number of pre-existing failures on my Windows host (timeout-basedMatcher did not succeed in time) across unrelated components — none referenceGeneralSettings, and there was no pre-existing test for that component. I didn't add one because the new section is straightforward state + react-query and matches the patterns already in the file.AI-generated code disclosure
Screenshots / test output
Targeted test run:
(Screenshot of the new admin section omitted — happy to add one if a maintainer wants to see it before un-drafting.)