# `MishkaBlog.Resources.Preparations.OpenToActor`
[🔗](https://github.com/mishka-group/mishka_blog/blob/v0.0.1/lib/mishka_blog/resources/__preparations/open_to_actor.ex#L5)

Keeps a public read to the records its reader may open, by the rule the record's page keeps: a
record whose lock names permissions opens only for a reader holding one of them
(`AccessPermissions.match?/3`), and never for a visitor who is not signed in. A list leaves out,
in its own query, every record the reader may not open, so its pages and its count are of what
the reader sees; asking for one of them by itself finds nothing, as an id nothing is stored at
does.

    prepare {OpenToActor, kind: :post}

THE READER is the actor of an authorized read: the visitor a page reads for, as the blog's
components pass it — `nil` for a visitor who is not signed in — and the JSON:API's caller.

    Ash.Query.for_read(MishkaBlog.BlogPost, :public_list, %{},
      actor: current_user,
      tenant: site_id
    )

A read made with `authorize?: false` is the system's — the lock a page's head hands its gate, the
components a site's stylesheet has to carry — and is not filtered.

A record is also left out when the runtime page that serves its address is locked to permissions
the reader does not hold: while every page that shows a post, a category, a tag, a blogger or a
team (`/blog/:slug`, whatever path the page was given) is, no record of that kind is read, counted
or listed for the reader, a comment of such a post included, and one asked for alone is not found.
The pages are read in the statement of the read itself
(`MishkaBlog.Resources.Preparations.ReaderLocks`), from the `pages` table, for the JSON:API and
GraphQL as for a page of the site.

WHAT A READ IS KEPT TO is a filter on the read itself, built from the names the reader holds
(`MishkaBlog.Resources.Preparations.ReaderLocks`), so the database answers it beside the rows
and nothing is read beforehand, whether anything is locked or not:

  * a category — by its own lock, or the nearest one above it;
  * a tag — by its own lock;
  * a post — by its own lock; one that names none, unless it is filed under a locked category and
    under none the reader may open;
  * a comment (`:comment`) — by its post's.

A record asked for by itself (`get?`) is read with whether it opens for the reader beside it, and
is left out of the result when it does not, so it is not found.

IN A READ OF CATEGORIES, TAGS OR BLOGGERS, what is counted, sorted by or asked of their posts is of
the posts the reader may open: an aggregate over them, such as a category's `published_post_count`
or a blogger's `post_count`, in a list or asked for alone, and an `exists(tenant_posts, …)` filter,
such as a block's leaving out of rows with nothing to read.

## Options

* `:kind` - Required. `:post`, `:category`, `:tag`, `:comment`, `:blogger` or `:team`. The last two
  are left out only by the page that serves them: they carry no lock of their own.

# `opens?`

```elixir
@spec opens?([String.t()] | nil, map() | nil) :: boolean()
```

Whether `actor` may open a record that opens with `required`: anyone when it names none, else an
actor holding one of them, as the record's page asks (`AccessPermissions.match?/3`).

# `supports`

# `temporal_safe?`

---

*Consult [api-reference.md](api-reference.md) for complete listing*
