What a reader may open, as the filter of the read that fetches the records: the answer
MishkaCmsCore.Accounts.Checks.AccessPermissions gives for a record's lock, worked out by the
database in the statement that reads the rows, so that no lock is read beforehand.
The reader is the names its actor holds (of/1): a guest holds none, a user's are loaded with the
actor. A lock opens for a reader when it names nothing, or when a name in it is covered by a name
the reader holds, as AccessPermissions.match?/3 asks it of a request from the dashboard:
- a held name with no
*segment covers the same name and nothing else; - a held name with a
*segment covers a name of at least its number of segments whose segments agree with its own, a*standing for any one segment and, as its last segment, for the rest of the name, however many segments that is.*alone covers every name,members:*every name belowmembers; - a name
admin:api:…counts for nobody, whoever holds what.
The held names with no * are compared as they are and the others as anchored regular
expressions. fragment/1 is used for that, and for nothing else of the matching, because Ash has
no operator that tests each element of an array against a list of names and patterns. Everything
else is an Ash expression.
The page that serves a record
A record is also kept from a reader the runtime page that serves its address is locked to. The
pages are those of the site that show the kind of record (page_open/3: extra["record"] is
"blog:post", "blog:category", "blog:tag", "blog:author" or "blog:team"), active and not
archived, and the kind opens for the reader when no page shows it or when one of them names no
permission or names one the reader holds, as the page itself lets them in. It is a subquery of the
read that does not depend on the row, so the database runs it once for the statement and no read
is made beforehand; a site that locks no page opens every kind. The fragment names the table and
the columns of the pages, which MishkaBlog.ReaderLocksTest keeps to the resource's.
Records that inherit
A post opens with its own lock, else with those of the categories it is filed under, each as the nearest category above it, or itself, that names some; it opens when none of them is locked or the reader may open one. A category opens with its own lock, else the nearest above it that names some. A comment opens with its post.
The categories under a lock are found by a recursive query over the site's categories, which Ash
has no operator for either. It is a subquery of the read that does not depend on the row, so the
database runs it once for the statement, and it starts from the categories that name permissions:
a site that locks nothing walks none. The fragments name the tables of the categories and of their
posts, which MishkaBlog.ReaderLocksTest keeps to the resources'.
Summary
Functions
Whether a category opens for the reader, in site: its own lock when it names permissions, else
those of the nearest category above it that does.
Whether a comment opens for the reader, in site: whoever may open its post. A comment whose post
is gone opens, as it does for the posts' read.
The names actor holds, as what a lock is matched against. nil holds none.
Whether a record whose lock is its permissions opens for the reader: it names nothing, or names
something the reader holds.
The site of the record itself, for a record asked for by itself.
Whether the runtime page that serves a record of record ("blog:post", "blog:category",
"blog:tag", "blog:author" or "blog:team") is open to the reader, in site (see site/1):
true when no page shows the kind, or when a page that does names no permission or one the reader
holds.
Whether a post opens for the reader, in site (see site/1): its own lock when it names
permissions, else those of the categories it is filed under. It opens when none of them is locked
or when the reader may open one of them.
The site a read is made in, as the id the categories are walked in: the one a list's query runs for.
Types
Functions
@spec category(t(), Ash.Expr.t()) :: Ash.Expr.t()
Whether a category opens for the reader, in site: its own lock when it names permissions, else
those of the nearest category above it that does.
@spec comment(t(), Ash.Expr.t()) :: Ash.Expr.t()
Whether a comment opens for the reader, in site: whoever may open its post. A comment whose post
is gone opens, as it does for the posts' read.
The names actor holds, as what a lock is matched against. nil holds none.
@spec opens(t()) :: Ash.Expr.t()
Whether a record whose lock is its permissions opens for the reader: it names nothing, or names
something the reader holds.
@spec own_site() :: Ash.Expr.t()
The site of the record itself, for a record asked for by itself.
@spec page_open(t(), String.t(), Ash.Expr.t()) :: Ash.Expr.t()
Whether the runtime page that serves a record of record ("blog:post", "blog:category",
"blog:tag", "blog:author" or "blog:team") is open to the reader, in site (see site/1):
true when no page shows the kind, or when a page that does names no permission or one the reader
holds.
@spec post(t(), Ash.Expr.t()) :: Ash.Expr.t()
Whether a post opens for the reader, in site (see site/1): its own lock when it names
permissions, else those of the categories it is filed under. It opens when none of them is locked
or when the reader may open one of them.
@spec site(String.t()) :: Ash.Expr.t()
The site a read is made in, as the id the categories are walked in: the one a list's query runs for.