Where a drop-in notes panel's notes live.
A panel is given a path — ["CRM", "Clients", "Acme"]. The first segment
names the vault, the rest the folder chain inside it, and the panel shows that
folder and everything under it. Nothing exists until it is needed: the first
note or folder creates the vault and the chain (ensure/2).
Two kinds of place share a path:
:shared("everyone here") — an organisation vault of that name, so the admin pages, its managers and its members work on it as on any other. Who may use it through a panel is the host's call: the:authorizehook.:private("only me") — the person's own personal vault of that name. Only they can reach it; the hook is not asked and cannot widen it.
A vault is found by path_key (the slugified first segment), which only a
vault created here carries — an organisation vault that merely happens to be
called "CRM" is not adopted. Names are not unique and slugs are unique across
everyone's vaults, so neither could say which vault a path means.
Notes are kept by path: a path built from something that changes (a client's name) points at a new, empty folder after the change, and the old notes stay where they were. Hosts should put something stable in the path.
Access
config :phoenix_kit_knowledge_base, :authorize, {MyApp.Notes, :can?}can?(action, user, path), with action :view or :edit and path the
panel's path, is asked about shared places only. Unconfigured, any signed-in
user may use a shared place, as with boards. A hook that raises, throws, exits
or answers anything but a boolean is a no — logged without its arguments.
It grants access through a panel, under its path; the admin pages keep their
own rules.
Summary
Functions
Whether user may action (:view / :edit) the place. See "Access".
The place's vault and folder chain, created as needed. Asks authorize/3 for
:edit first.
The vault a place lives in, if it has been created. No side effects — this is what a panel shows before anyone has written anything.
Validates a panel's path and visibility.
Whether relative_path (a note's folder or a folder) sits inside the place's
folder — the fence every panel event checks, so a crafted event cannot reach
the rest of the vault.
Types
@type action() :: :view | :edit
@type t() :: %PhoenixKitKnowledgeBase.Places{ folder: String.t(), key: String.t(), path: [String.t()], vault_name: String.t(), visibility: visibility() }
A parsed panel path. folder is "" for the vault root.
@type visibility() :: :shared | :private
Functions
@spec authorize(action(), PhoenixKit.Users.Auth.User.t() | nil, t()) :: boolean()
Whether user may action (:view / :edit) the place. See "Access".
@spec ensure(t(), PhoenixKit.Users.Auth.User.t() | nil) :: {:ok, PhoenixKitKnowledgeBase.Schemas.Vault.t()} | {:error, term()}
The place's vault and folder chain, created as needed. Asks authorize/3 for
:edit first.
Two people writing the first note at once both reach the insert; the second loses on the unique index, re-reads, and uses the first one's vault.
@spec locate(t(), PhoenixKit.Users.Auth.User.t() | nil) :: PhoenixKitKnowledgeBase.Schemas.Vault.t() | nil
The vault a place lives in, if it has been created. No side effects — this is what a panel shows before anyone has written anything.
Validates a panel's path and visibility.
Every segment must be usable as a file or directory name (Storage.validate_filename/1):
a segment is user-visible text and a directory on disk. An invalid one is a
developer error, reported, never written.
Whether relative_path (a note's folder or a folder) sits inside the place's
folder — the fence every panel event checks, so a crafted event cannot reach
the rest of the vault.