Add Tenants to Administration, and let an account be put in one

A tenant is a separate organisation on one server: its own people,
domains and limits, and an administrator who manages only what is in it.
It gets a section under Access, gated by sysTenantQuery and sysTenantGet,
with a notice on a server that does not report Enterprise, where anyone
inside a tenant is held to an ordinary user's permissions.

The panel edits the tenant's name, logo, role and limits. The logo is an
https address, drawn through the image proxy the strict image policy
requires, or an image data URL. Limits change one quotas/<name> pointer
each, so the four ihasmail does not offer keep their values, and an empty
field is no limit. The role is the most anyone inside can be allowed.

Stalwart keeps no list on a tenant -- each account, group, domain, list and
role names its own -- so what a tenant holds is counted with memberTenantId
queries and shown against its limits. Domains are added and taken out from
the tenant's panel, one memberTenantId change each; only a domain in no
tenant can be added, and its accounts stay where they are. Delete is offered
once every count reads zero.

A tenant does nothing until someone administers it, so the account panel
gains a Tenant choice for an administrator who can read tenants: an
Administrator inside a tenant administers that tenant. Nobody moves their
own account.

The mock has a tenant holding a domain and an administrator, a spare domain
to assign, memberTenantId filters on every query, and Stalwart's rule that
only an administrator outside every tenant may move things into one. A test
of taking a domain back out found that the mock's pointer handling dropped a
top-level null instead of storing it, so nothing had ever been cleared that
way; it stores null now, as the server reads it back.

Nothing about tenants has been written on a live server: production has
none. KNOWN-ISSUES says what was read from source.

Thirty-nine new strings and one plural, in all nine catalogues.
This commit is contained in:
2026-09-15 09:28:39 -07:00
parent 7e46ddeb7d
commit fd104a1f34
29 changed files with 1467 additions and 25 deletions
+40
View File
@@ -247,6 +247,45 @@ export const catalog: Catalog = {
"This role no longer exists. Someone may have deleted it.": "Deze rol bestaat niet meer. Iemand heeft hem mogelijk verwijderd.",
"the default roles": "de standaardrollen",
"The server did not say whether the role was created.": "De server heeft niet gemeld of de rol is aangemaakt.",
"No tenant": "Geen tenant",
"You can't move your own account into a tenant.": "U kunt uw eigen account niet naar een tenant verplaatsen.",
"An account in a tenant is limited by the tenant's role and counts towards its limits, and Administrator means administrator of that tenant.": "Een account in een tenant wordt beperkt door de rol van de tenant en telt mee voor de limieten, en Beheerder betekent beheerder van die tenant.",
"Tenants": "Tenants",
"Storage in GB": "Opslag in GB",
"Default tenant roles": "Standaardrollen voor tenants",
"A tenant needs a name.": "Een tenant heeft een naam nodig.",
"New tenant": "Nieuwe tenant",
"{used} used": "{used} gebruikt",
"Your role lets you view tenants but not change them.": "Met uw rol kunt u tenants bekijken, maar niet wijzigen.",
"Logo": "Logo",
"An https address or a data URL of an image. Stalwart shows it to the tenant's people where it shows a logo.": "Een https-adres of een data-URL van een afbeelding. Stalwart toont het aan de mensen van de tenant waar het een logo toont.",
"What it holds": "Inhoud",
"{n} of {limit}": "{n} van {limit}",
"Limits": "Limieten",
"Stalwart refuses to create more than a limit allows. An empty field is no limit.": "Stalwart weigert meer aan te maken dan een limiet toestaat. Een leeg veld betekent geen limiet.",
"The most anyone in this tenant can be allowed: their own roles are cut down to what these grant. Only roles whose permissions you hold yourself are offered.": "Het meeste dat iemand in deze tenant kan worden toegestaan: hun eigen rollen worden beperkt tot wat deze toekennen. Alleen rollen waarvan u zelf de rechten hebt worden aangeboden.",
"Checking what is still in this tenant…": "Nagaan wat er nog in deze tenant zit…",
"It still holds accounts, domains or other things. Move them out first.": "Er zitten nog accounts, domeinen of andere dingen in. Verplaats die eerst.",
"Create tenant": "Tenant aanmaken",
"Added {domain} to {tenant}": "{domain} aan {tenant} toegevoegd",
"Took {domain} out of {tenant}": "{domain} uit {tenant} gehaald",
"Take {domain} out of the tenant": "{domain} uit de tenant halen",
"No domains in this tenant yet": "Nog geen domeinen in deze tenant",
"Domain to add": "Toe te voegen domein",
"Only domains in no tenant can be added. The accounts already on a domain stay where they are; move each from its own panel.": "Alleen domeinen die in geen enkele tenant zitten kunnen worden toegevoegd. De accounts op een domein blijven waar ze zijn; verplaats elk vanuit het eigen paneel.",
"An empty tenant can be deleted.": "Een lege tenant kan worden verwijderd.",
"Delete tenant…": "Tenant verwijderen…",
"Still holds {things}. Move them out first.": "Bevat nog {things}. Verplaats die eerst.",
"Delete tenant": "Tenant verwijderen",
"Separate organisations on one server, each with its own people, domains and limits.": "Afzonderlijke organisaties op één server, elk met eigen mensen, domeinen en limieten.",
"Tenants are a Stalwart Enterprise feature. This server does not report Enterprise, so anyone inside a tenant has only an ordinary user's permissions.": "Tenants zijn een functie van Stalwart Enterprise. Deze server meldt geen Enterprise, dus iedereen in een tenant heeft alleen de rechten van een gewone gebruiker.",
"Search tenants": "Tenants zoeken",
"No tenants match": "Geen tenants gevonden",
"No tenants yet": "Nog geen tenants",
"Account limit": "Accountlimiet",
"The server allows no more tenants.": "De server staat geen tenants meer toe.",
"This tenant no longer exists. Someone may have deleted it.": "Deze tenant bestaat niet meer. Iemand heeft hem mogelijk verwijderd.",
"The server did not say whether the tenant was created.": "De server heeft niet gemeld of de tenant is aangemaakt.",
"User": "Gebruiker",
"Administrator": "Beheerder",
"Custom role": "Aangepaste rol",
@@ -1645,6 +1684,7 @@ export const catalog: Catalog = {
"{n} recipients": { one: "{n} ontvanger", other: "{n} ontvangers" },
"Grants {n} permissions": { one: "Kent {n} recht toe", other: "Kent {n} rechten toe" },
"{n} roles": { one: "{n} rol", other: "{n} rollen" },
"{n} tenants": { one: "{n} tenant", other: "{n} tenants" },
"{n} DKIM keys": { one: "{n} DKIM-sleutel", other: "{n} DKIM-sleutels" },
"{n} other items": { one: "{n} ander item", other: "{n} andere items" },
// ── Administration ────────────────────────────────────────────────