Sites, masters and global records

v0.0.1

One Mishka CMS installation can serve many websites. Each website is a site, with its own domain, pages, accounts and settings. This page explains what a site is, who a master is, which records belong to one site, and which records every site shares.

Sites

A site is a row on the Sites screen. It holds a name, a host, a mode, an active switch, a priority, an optional frontend domain, the allowed origins for browser API calls, and a master flag.

The host decides which site answers. The CMS reads the host name from the request, drops the port, and looks for a site with exactly that host. Nearly everything a visitor sees then comes from that site alone: its pages, layouts, error pages, media, redirects, settings and accounts. Each record carries its site's id, and the code calls the site the tenant.

Masters and site accounts

An account either belongs to a site or belongs to none.

  • A site account belongs to one site. What it holds counts on that site only.
  • A master belongs to no site. The Users screen shows Global in its Site column.

Only the missing site makes a master. Holding * does not. A site account with * holds every permission on its own site and nothing on another. The installer creates the first master and gives it *, which for a master covers every site.

The CMS keeps the two kinds apart:

  • An action written for masters, such as creating a site or adding a permission name, is refused to a site account with This action requires a master user, an account that belongs to no site.
  • An action that names another site is refused to a site account with A site user can act only on their own site.
  • A master cannot take an email address that a site account already holds: This email exists and cannot be used as a master account.

The admin JSON:API has the same split, under /api/json/v1/master/admin/ and /api/json/v1/tenant/admin/. See Read content over the JSON:API.

The master site

One site carries the master flag. The installer makes the first site the master site. Masters sign in on that site's address and nowhere else, because a master's session is recognised only on a request the master site leaves without a tenant. Every other site scopes each request to itself, so a master's password and token do not work there.

A master signs in on that site at /auth?master_user=true. Sign in as a master, and back as a site user below explains it.

To move the flag, click Set Master in the other site's View dialog. The CMS asks you to confirm, because masters will then sign in only at the new host, and you are signed out of the old one.

The CMS refuses changes that would lock every master out:

  • Switching off, archiving, deleting or unmarking the master site, or making it API Only.
  • Moving the flag to a site that is inactive or API Only: Masters sign in on the master site's web pages, so it must be switched on and take web visits.
  • Marking a second site: Another site is the master site. Use Set Master to move it to this one.

Sign in as a master, and back as a site user

A master signs in on the master site's address at /auth?master_user=true. If the site puts the language first in every address, the language comes first here too, as in /en/auth?master_user=true.

The master site's sign-in page signs in one kind of account at a time, and the address picks which:

  • /auth?master_user=true signs in the masters.
  • /auth?master_user=false signs in the site's own accounts, the ones that belong to the master site.

Only true and false mean anything. Any other value leaves the choice as it was.

The CMS keeps the choice in your browser session, so the sign-in form does not repeat it when it sends your email and password on. The links in a password reset, sign-in link and account confirmation email carry it for you: a master's end in ?master_user=true and a site account's in ?master_user=false.

The choice only picks which accounts the sign-in pages use. It grants no access, and it takes effect on the sign-in pages alone. Once you are signed in, your account decides what you are: opening ?master_user=false does not sign a master out, and a signed-in site account stays on its site whatever the address says.

Back as a site user

The choice stays in your session until you open ?master_user=false or sign out, and signing out clears the whole session. So if you opened ?master_user=true and left without signing in, the sign-in page still takes masters on your next visit.

To sign in with a site account after working as a master, sign out, open /auth?master_user=false on the master site, and sign in with the site account's email and password. If the page still signs in masters when you want a site account, open the same address. It switches the page back.

Other sites ignore the choice

Only the master site reads master_user. Every other site signs in its own accounts only: it ignores the parameter, drops a choice left in the session, and tells a plugin on web:request:master_sign_in_refused when a request asks for true. A site account on its own domain never needs the parameter, and a master cannot sign in there. See Plugin events.

Records that belong to one site

These records always belong to a site: pages, error pages, media and media folders, redirects, and the records of the Mishka Blog and Mishka Document extensions. A site account reads and writes its own site's records and no others.

A record cannot point at a record of another site, such as a bookmark that names another site's post. The CMS refuses that write with not found or does not belong to your site. A record on another site and a record that does not exist get the same answer, so the reply never reveals which ids exist elsewhere. Each refusal fires the plugin event runtime:tenant:cross_site_refused. See Plugin events.

Global records

A global record belongs to no site, and every site can use it. These kinds can be global: layouts, components, JS hooks, stylesheets, translations and snippets. A master makes a layout, component, JS hook, stylesheet or translation global by choosing Global (no site) in the Site field of its form. A master makes a snippet global by saving it to All sites. In the editor's Components tab, a G badge marks a global component and a T badge one that belongs to a single site.

A site account reads the global records and cannot change them. Changing a global layout, for example, is refused with Cannot modify global layout. Global layouts can only be modified by master users.

Settings follow the same split

On the Settings screen a master picks a scope, Global or one site, and each field carries a badge: Global, This site or Just for you. Each setting declares how it behaves:

The setting isIn the Global viewIn a site's view
GlobalEditableRead-only
MasterEditableHidden
SiteHiddenEditable
BothEditable, a defaultEditable, and it overrides the default

A few settings keep each scope apart instead. A site's email provider and its captcha keys are its own, and the Global value is never a fallback for them.

Example: an agency with two clients

An agency runs acme-docs and bright-shop on one installation, and its team signs in on the master site.

  1. A master adds both sites. Neither is the master site.
  2. A master creates a footer layout with Site set to Global (no site). Both sites can use it.
  3. A master creates an account for each client, with that client's site in Site.
  4. The Acme admin edits Acme's pages. The admin cannot see Bright Shop's pages and cannot edit the footer layout.