Scopes on rights (ADR-041 §4).
The user module hands over a user's rights as
[{:permission kw :scope nil-or-{key value}}], each value fixed or a
:user/<name> source. Resolved (shell.authorization/resolve-rights), a
scope is {key #{value}}, and {} holds everywhere. Rights add up: a
permission is held in each of its scopes.
Safe by default: a scope admits only where every one of its keys is checked.
Scopes on rights (ADR-041 §4).
The user module hands over a user's rights as
`[{:permission kw :scope nil-or-{key value}}]`, each value fixed or a
`:user/<name>` source. Resolved (`shell.authorization/resolve-rights`), a
scope is `{key #{value}}`, and `{}` holds everywhere. Rights add up: a
permission is held in each of its scopes.
Safe by default: a scope admits only where every one of its keys is checked.(everywhere? scopes)Whether one of scopes holds everywhere.
Whether one of `scopes` holds everywhere.
(explain {:keys [platform-admin? rights dropped]} permission record)Why a caller may or may not use permission on record ({scope-key
value}, :everywhere or nil for anywhere: see record-route), decided by
route-decision as a route checking record decides it. rights: the caller's, resolved; dropped: those
whose scope resolved to nothing. A platform admin holds everything.
{:allowed? :via (:platform-admin or :rights) :error :paths [right] :misses [{:right r :reason :scope-mismatch|:unresolved :keys {k {:allowed :value}}}]}
Why a caller may or may not use `permission` on `record` ({scope-key
value}, `:everywhere` or nil for anywhere: see `record-route`), decided by
`route-decision` as a route checking `record` decides it. `rights`: the caller's, resolved; `dropped`: those
whose scope resolved to nothing. A platform admin holds everything.
{:allowed? :via (:platform-admin or :rights) :error :paths [right]
:misses [{:right r :reason :scope-mismatch|:unresolved :keys {k {:allowed :value}}}]}(in-scope? scopes values)Whether one of scopes admits values, {scope-key value}: a record's or a
request's. A scope with a key values lacks does not.
Whether one of `scopes` admits `values`, {scope-key value}: a record's or a
request's. A scope with a key `values` lacks does not.(record-route record)The route :scope and path parameters that check record, {scope-key
value}: a parameter per key. :everywhere: a route without :scope, which
needs the permission held everywhere. Nil: :handler, held anywhere.
The route `:scope` and path parameters that check `record`, {scope-key
value}: a parameter per key. `:everywhere`: a route without `:scope`, which
needs the permission held everywhere. Nil: `:handler`, held anywhere.(rights-diff before after)How resolved rights after differ from before, rights adding up as the
interceptor adds them: :added, the rights after holds where before
holds nothing that covers them, and :removed the reverse. Each
{:permission :scope}, none covered by another in its list.
How resolved rights `after` differ from `before`, rights adding up as the
interceptor adds them: `:added`, the rights `after` holds where `before`
holds nothing that covers them, and `:removed` the reverse. Each
{:permission :scope}, none covered by another in its list.(route-decision scopes route-scope path-params)Whether a holder of scopes (scopes-for the route's permission) may use
a route whose data says route-scope:
{:domain-id :path/domain-id}: one whose scope the path parameters fall
in, and whose scope has no key the route leaves unchecked.:handler: any holder; the handler filters with scope-filter.{:scopes scopes} when admitted, else an error: :forbidden when nothing
here can check their scope, :not-found when a parameter lies outside it,
so its existence does not leak.
Whether a holder of `scopes` (`scopes-for` the route's permission) may use
a route whose data says `route-scope`:
- nil: only one holding it everywhere.
- `{:domain-id :path/domain-id}`: one whose scope the path parameters fall
in, and whose scope has no key the route leaves unchecked.
- `:handler`: any holder; the handler filters with `scope-filter`.
{:scopes scopes} when admitted, else an error: `:forbidden` when nothing
here can check their scope, `:not-found` when a parameter lies outside it,
so its existence does not leak.(route-record route-scope path-params)The record, as record-route reads it, that a route whose data says
route-scope checks, from its path-params.
The record, as `record-route` reads it, that a route whose data says `route-scope` checks, from its `path-params`.
(route-scope? scopes s)Whether s, route data's :scope, is one route-decision reads: absent,
:handler, or a map of keys of scopes (the registry's) to path
parameters, {:domain-id :path/domain-id}.
Whether `s`, route data's `:scope`, is one `route-decision` reads: absent,
`:handler`, or a map of keys of `scopes` (the registry's) to path
parameters, `{:domain-id :path/domain-id}`.(scope-filter scopes fields)A HoneySQL WHERE admitting the rows inside one of scopes, [:= 1 1] when
one holds everywhere. fields maps a scope key to the column it lies in,
:orders.domain_id, or to a fn from the allowed values to a condition, for
a scope on a related record:
{:domain-id (fn [ids] [:in :customer_id {:select [:id] :from [:customers] :where [:in :domain_id ids]}])}
A scope with a key fields does not map admits nothing; so do no scopes:
[:= 1 0].
A HoneySQL WHERE admitting the rows inside one of `scopes`, `[:= 1 1]` when
one holds everywhere. `fields` maps a scope key to the column it lies in,
`:orders.domain_id`, or to a fn from the allowed values to a condition, for
a scope on a related record:
{:domain-id (fn [ids] [:in :customer_id {:select [:id] :from [:customers]
:where [:in :domain_id ids]}])}
A scope with a key `fields` does not map admits nothing; so do no scopes:
`[:= 1 0]`.(scope-schema scopes)The Malli form a stored scope fits, from the registry's scopes: a closed
map of the declared keys, each a value of its :schema (any without one)
or one of its :sources; a source it does not take is refused, unless a
:schema declared without :sources admits it. A key's :entity is kept
as :wagoe/entity.
The Malli form a stored scope fits, from the registry's `scopes`: a closed map of the declared keys, each a value of its `:schema` (any without one) or one of its `:sources`; a source it does not take is refused, unless a `:schema` declared without `:sources` admits it. A key's `:entity` is kept as `:wagoe/entity`.
(scope-values scopes resolve-source k v)What v, the value of scope key k, stands for: a source resolved by
resolve-source, then k's :expand in the registry's scopes.
What `v`, the value of scope key `k`, stands for: a source resolved by `resolve-source`, then `k`'s `:expand` in the registry's `scopes`.
(scopes-for rights permission)The distinct scopes in which resolved rights hold permission, {} for
everywhere. None when they do not hold it.
The distinct scopes in which resolved `rights` hold `permission`, `{}` for
everywhere. None when they do not hold it.(source? v)Whether scope value v is taken from the user, :user/department.
Whether scope value `v` is taken from the user, `:user/department`.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |