feat(tenants): isPlatformTenant flag replaces PLATFORM_TENANT_SLUG
ci / changes (push) Successful in 4s
ci / tc_portal (push) Has been skipped
ci / tc_booking (push) Has been skipped
ci / tc_website (push) Has been skipped
ci / tc_platform_api (push) Successful in 22s
ci / tc_operator (push) Successful in 22s
ci / build_portal (push) Has been skipped
ci / build_booking (push) Has been skipped
ci / build_operator (push) Successful in 30s
ci / test_platform_api (push) Successful in 34s
ci / build_platform_api (push) Successful in 15s
ci / deploy (push) Successful in 42s
ci / changes (push) Successful in 4s
ci / tc_portal (push) Has been skipped
ci / tc_booking (push) Has been skipped
ci / tc_website (push) Has been skipped
ci / tc_platform_api (push) Successful in 22s
ci / tc_operator (push) Successful in 22s
ci / build_portal (push) Has been skipped
ci / build_booking (push) Has been skipped
ci / build_operator (push) Successful in 30s
ci / test_platform_api (push) Successful in 34s
ci / build_platform_api (push) Successful in 15s
ci / deploy (push) Successful in 42s
Identifying the company tenant by slug in env was fragile — every purge/recreate changed the slug (or id) and the apex guard chased reality through three config flips in one day. The identity now lives ON the tenant document: isPlatformTenant, operator-set from the tenant page (single holder — setting it clears the flag everywhere else), guarded so tenant admins can't set it on themselves through the shared PATCH route. The dezky.eu apex guard reads the flag; PLATFORM_TENANT_SLUG is gone. Dev seed flags its seeded tenant. config-rev 5 rolls platform-api.
This commit is contained in:
@@ -85,6 +85,25 @@ type IntegrationKey = (typeof INTEGRATIONS)[number]
|
||||
// runs; reusable whenever the first invite failed or someone new takes over.
|
||||
const inviteAdminOpen = ref(false)
|
||||
|
||||
// Platform-tenant flag toggle. Single holder — the API clears it from every
|
||||
// other tenant when set. Grants exactly one thing: claiming the dezky.eu
|
||||
// apex as this tenant's customer mail domain.
|
||||
const flagBusy = ref(false)
|
||||
const flagError = ref<string | null>(null)
|
||||
async function setPlatformTenant(value: boolean) {
|
||||
flagBusy.value = true
|
||||
flagError.value = null
|
||||
try {
|
||||
await $fetch(`/api/tenants/${slug.value}`, { method: 'PATCH', body: { isPlatformTenant: value } })
|
||||
await refreshTenant()
|
||||
} catch (err: unknown) {
|
||||
const e = err as { data?: { data?: { message?: string }; message?: string } }
|
||||
flagError.value = e.data?.data?.message ?? e.data?.message ?? String(err)
|
||||
} finally {
|
||||
flagBusy.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// ── Danger-zone state ─────────────────────────────────────────────────────
|
||||
const dangerAction = ref<'suspend' | 'resume' | 'delete' | 'purge' | null>(null)
|
||||
const dangerBusy = ref(false)
|
||||
@@ -145,6 +164,7 @@ async function reconcile() {
|
||||
<template #actions>
|
||||
<Badge :tone="STATUS_TONE[tenant.status]" dot>{{ tenant.status }}</Badge>
|
||||
<Badge tone="neutral">{{ tenant.plan }}</Badge>
|
||||
<Badge v-if="tenant.isPlatformTenant" tone="warn">platform tenant</Badge>
|
||||
<UiButton variant="secondary" @click="inviteAdminOpen = true">
|
||||
<template #leading><UiIcon name="plus" :size="13" /></template>
|
||||
Invite admin
|
||||
@@ -320,6 +340,21 @@ async function reconcile() {
|
||||
|
||||
<!-- DANGER (real) -->
|
||||
<div v-else-if="activeTab === 'danger'" class="grid">
|
||||
<Card>
|
||||
<h2>Platform tenant</h2>
|
||||
<p>
|
||||
Marks this as dezky's own tenant (single holder — setting it here clears it
|
||||
anywhere else). Required to claim <Mono>dezky.eu</Mono> as a customer mail
|
||||
domain; everything else treats it as a normal tenant.
|
||||
</p>
|
||||
<UiButton
|
||||
:variant="tenant.isPlatformTenant ? 'secondary' : 'primary'"
|
||||
:disabled="flagBusy"
|
||||
@click="setPlatformTenant(!tenant.isPlatformTenant)"
|
||||
>{{ tenant.isPlatformTenant ? 'Unmark platform tenant' : 'Mark as platform tenant' }}</UiButton>
|
||||
<p v-if="flagError" class="danger-err">{{ flagError }}</p>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<h2 class="danger">Suspend tenant</h2>
|
||||
<p>
|
||||
|
||||
Reference in New Issue
Block a user