chore(subsite): drop parentSite fetch and switch canCreate to isOfficial gate#749
chore(subsite): drop parentSite fetch and switch canCreate to isOfficial gate#749Germey wants to merge 3 commits into
Conversation
Switch fetchSubsites to push the parent-zone filter down to the new
PlatformBackend origin__endswith filter instead of fetching every
site the user owns and matching client-side on metadata.parent_site_id.
Why: the metadata-based filter silently hid superuser-created subsites
because PlatformBackend's superuser create fast path
(with_site_owner_defaults) does NOT stamp metadata.parent_site_id —
only the regular subsite-create path does. Users with subsites created
via the admin UI / shell saw an empty list.
siteOperator.getAll({
user_id,
origin__endswith: `.${subdomainZone}`,
ordering: '-created_at'
})
The leading dot excludes the parent itself (studio.acedata.cloud)
while matching every subsite (<slug>.studio.acedata.cloud). We keep
loading parentSite for the subdomainZone / maxSubsitesPerUser /
canCreate computeds; only the listing query changes.
Also add origin__endswith + ordering to ISiteQuery so the operator
types match what we send.
Requires: AceDataCloud/PlatformBackend#474.
(user_id, origin__endswith=.{zone}) is already a closed set: the leading
dot in the suffix excludes the parent by DNS hierarchy, so the extra
client-side .filter(s => s.id !== parentId) can never trip. Keeping it
just re-introduces the parent_site_id mental model we're moving away from.
parentSite is still loaded, but only as the source of
parent.features.subsite (subdomainZone / maxSubsitesPerUser / canCreate)
— not as a filter.
…ial gate The Subsite settings tab no longer derives `subdomainZone` / `maxSubsitesPerUser` / `canCreate` from `$store.state.site.features.subsite`. The parent Site row is fetched/seeded elsewhere purely for branding and isn't actually needed here — `subdomainZone` is always the canonical Hub host, and the per-user quota the backend enforces matches our default of 5. Changes ------- * Replace `parentSite` computed + its dependents (`subdomainZone`, `maxSubsitesPerUser`) with constants from `@/constants` and a local `MAX_SUBSITES_PER_USER = 5`. * Rewrite `canCreate` to gate on `isOfficial() && !isSubOfficial()` so the button is hidden on subsites themselves (which can't spawn further subsites) and on any non-Hub host — matching the upstream `Setting.vue` visibility gate. Why --- Pairs with: * PlatformBackend #477 — stops writing `metadata.parent_site_id` and drops the proxy_cname resolver branch that consumed it. * PlatformFrontend #315 — applies the same `isOfficial()`-based `canCreate` rewrite to the Sites console and removes the `parent_site_id` surface from `ISiteMetadata` / `ISiteQuery` / `Advanced.vue` descriptions. After all three land, `parent_site_id` is gone from create / list / gate paths end-to-end. Existing rows aren't touched; the field simply stops being written/read. Backwards compatibility ----------------------- * Existing subsites continue to load — listing is fully scoped by `(user_id, origin__endswith=.{BASE_HOST_HUB})` which is exactly what the parent-derived `subdomainZone` resolved to in practice on `studio.acedata.cloud`. * The `SectionNotice` "official-only hint" + upstream `Setting.vue` gate keep this tab from rendering on subsites, so the `!isSubOfficial()` check is belt-and-suspenders rather than the only line of defense.
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
nexior | d191b18 | Commit Preview URL Branch Preview URL |
May 16 2026, 12:41 AM |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d191b18205
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| subdomainZone(): string { | ||
| const zone = this.parentSite?.features?.subsite?.subdomain_zone; | ||
| if (zone) return zone; | ||
| // Fall back to the bare current host so the create dialog can render | ||
| // even if `state.site` hasn't been hydrated with the subsite block yet. | ||
| if (typeof window !== 'undefined' && window.location?.host) { | ||
| return window.location.host.split(':')[0]; | ||
| } | ||
| return this.parentSite?.origin || ''; | ||
| }, | ||
| maxSubsitesPerUser(): number { | ||
| const max = this.parentSite?.features?.subsite?.max_subsites_per_user; | ||
| return typeof max === 'number' && max > 0 ? max : 5; | ||
| return BASE_HOST_HUB; | ||
| }, |
There was a problem hiding this comment.
Use the studio host for subsite origins
On the only host where the Subsites tab is exposed (isMainOfficial() is studio.acedata.cloud), BASE_HOST_HUB resolves to hub.acedata.cloud (src/constants/endpoint.ts:4,9). Returning it here makes fetchSubsites() filter for origin__endswith=.hub.acedata.cloud and makes onSubmitCreate() post slug.hub.acedata.cloud, so existing *.studio.acedata.cloud subsites disappear and new creations target the wrong parent zone. Use the current/parent main host or a studio-specific constant instead of BASE_HOST_HUB.
Useful? React with 👍 / 👎.
| canCreate(): boolean { | ||
| return Boolean(this.subdomainZone) && Boolean(this.user?.id) && this.items.length < this.maxSubsitesPerUser; | ||
| return ( | ||
| isOfficial() && | ||
| !isSubOfficial() && | ||
| Boolean(this.user?.id) && | ||
| this.items.length < MAX_SUBSITES_PER_USER | ||
| ); |
There was a problem hiding this comment.
Avoid classifying the studio host as a subsite
When this tab is opened on studio.acedata.cloud, isOfficial() is true but isSubOfficial() also returns true because it only compares window.location.host with BASE_HOST_HUB (hub.acedata.cloud). Since Setting.vue exposes the Subsites tab specifically on studio.acedata.cloud, the new !isSubOfficial() check keeps canCreate false for the intended host and disables the normal Create button for all users there. Gate this with the strict main-host helper or fix isSubOfficial() before using it here.
Useful? React with 👍 / 👎.
|
Closing this PR — after PR #746 squash-merged, the meaningful work in this PR (dropping the
The companion PlatformFrontend cleanup (drop Thanks to Codex for catching both bugs before they shipped. |
Summary
The Subsite settings tab (
src/components/setting/Subsite.vue) no longerderives
subdomainZone/maxSubsitesPerUser/canCreatefrom$store.state.site.features.subsite. The parent Site row is fetchedelsewhere for branding purposes, but its subsite block isn't needed
here —
subdomainZoneis always the canonical Hub host(
BASE_HOST_HUB, e.g.studio.acedata.cloud), and the per-user quotathe backend enforces matches our default of 5.
Changes
src/components/setting/Subsite.vueparentSitecomputed and its dependents (subdomainZone,maxSubsitesPerUser).MAX_SUBSITES_PER_USER = 5constant.subdomainZonenow returnsBASE_HOST_HUBunconditionally.canCreatetoisOfficial() && !isSubOfficial() && Boolean(user?.id) && items.length < MAX_SUBSITES_PER_USER— same gate shape as PlatformFrontendconsole/sites/Index.vue(PR #315).isOfficial,isSubOfficialfrom@/utils/isandBASE_HOST_HUBfrom@/constants.change/@acedatacloud-nexior-a1b22f5a-ee2c-4499-ab9e-aba69ee0d718.json— beachball patch bump.Why
This is the last leg of a three-PR cleanup that removes the
parent_site_idsurface and the parent-site-row lookup as aprecondition for subsite UI gating:
metadata.parent_site_id; drop the proxy_cname resolver branch that consumed it. Quota count usesorigin__endswith=.{parent.origin}.parent_site_idfromISiteMetadata/ISiteQuery/Advanced.vuedescriptions; rewritecanCreateto useisOfficial().isOfficial()gate; drop theparent.features.subsitelookup.After all three land,
parent_site_idis gone from the create / list/ gate paths end-to-end. Existing rows are untouched; the field simply
stops being written or read.
Backwards compatibility
(user_id, origin__endswith=.{BASE_HOST_HUB}), which is exactly whatthe old parent-derived
subdomainZoneresolved to in practice onstudio.acedata.cloud. The leading dot excludes the parent andmatches every
<slug>.studio.acedata.cloud.Setting.vuegatealready hides this tab on non-official hosts; the
SectionNotice tone="official"banner also stays. The new!isSubOfficial()check is belt-and-suspenders so the Create buttonnever lights up on a subsite even if the upstream gate is ever
relaxed.
settings dialog only.
Risks
MAX_SUBSITES_PER_USER = 5no longer readsparent.features.subsite.max_subsites_per_user. The backend stillenforces its own quota on
POST /sites/, so a stale UI just gets aduplication / quota error from the API rather than silently
over-creating — same as the PlatformFrontend side.
getAllof theparent site that this code used to depend on (it now isn't fetched
here at all).
Verification
grep -rn 'parentSite\|maxSubsitesPerUser' src/→ no matches.git log --onelineconfirms one logical commit with the beachballchange file alongside.