MishkaCmsCore. Accounts. Validations. GrantWithinActorScope
(Mishka CMS Core v0.0.1)
Copy Markdown
View Source
Refuses a permission grant that would hand out more than the granting actor holds.
What is handed out is what the account does not hold yet: a permission it already holds, sent back as the account form does, is no grant, whoever holds it.
This is what lets a site run itself. A tenant admin holding admin:dashboard:permission and
admin:dashboard:blog:* can make a colleague a blog editor without a master being involved — which
is the point, because a CMS with many sites and many managers cannot route every routine grant
through one person. What it cannot do is reach past its own ceiling: it does not hold * or
admin:dashboard:document:*, so it cannot grant them.
The ceiling is the same wildcard rule every gate uses
(MishkaCmsCore.Accounts.Checks.AccessPermissions.covers?/2), so admin:dashboard:blog:* covers
admin:dashboard:blog:post, and nothing but * covers *. A tenant holding * — a site owner —
may grant anything, and that is still contained: the row policy keeps them to their own site's
users, and require_master gates master actions on site_id, never on permissions. Their * is
site-wide, not system-wide.
A MASTER (a user whose site_id is nil) has a ceiling too: what it holds. A master holding *
grants anything; one holding only admin:dashboard:permission grants nothing it does not hold,
itself included. A call made with authorize?: false (seeds, the installer) is a system call and
has none. Anything else with no actor is refused: a missing actor is nobody, not a master.
Declare it with before_action?: true, on an update, a create or a generic action taking
permission_ids. The ceiling is then asked right before the write, of the actor the action RUNS
with — the actor the policies ask — and not of the one the changeset was built with. A grant built
by a master, by a system call or with no actor, and run by a site's admin, is held to that admin's
ceiling.
update :assign_permissions do
validate {MishkaCmsCore.Accounts.Validations.GrantWithinActorScope, []},
before_action?: true
endEscalation is closed from both directions only in combination with the policy that forbids editing
your own permissions — otherwise two colleagues could raise each other. See
MishkaCmsCore.Accounts.User's assign_permissions policy.