Sub-permission checks for the bundled admin LiveViews.
Core's route gate admits anyone holding the base "shop" key (or a sub,
which implies the base). That is the right granularity for reaching the
admin area, but not for acting inside it: a catalog editor should not be
able to rewrite the security policy, and someone who only runs imports
should not be reading customer contact details out of carts.
Every mutating event handler in this module's admin LiveViews therefore re-checks the specific capability it needs, and the pages that display customer data check on mount.
Scope of enforcement
This is bundled-UI policy, and deliberately so. The public context API
(PhoenixKitEcommerce.create_product/1 and friends, including the
compat/shop.ex re-exports) stays scope-less: it is a library, hosts call
it from their own controllers, workers and scripts, and it cannot know
whose authority those run under. Core says the same — sub-permissions are
capabilities the module checks itself. Where a context function guards
ownership (billing profiles, cart sessions) it keeps doing so
regardless; those are invariants, not UI policy.
Background jobs are authorized at ENQUEUE time by the LiveView that starts them; the workers themselves run without a scope by design.
Summary
Functions
Runs fun when the scope holds capability, otherwise returns the
socket with a denial flash and no side effect.
Mount-time guard for pages whose mere CONTENT is privileged (carts carry customer contact details). Redirects to the shop admin dashboard.
True when the socket's scope holds the given shop capability.
Adds the denial flash without navigating.
Functions
Runs fun when the scope holds capability, otherwise returns the
socket with a denial flash and no side effect.
fun returns the usual {:noreply, socket} (or {:ok, socket} for a
mount-time guard — whatever the caller's contract is).
Mount-time guard for pages whose mere CONTENT is privileged (carts carry customer contact details). Redirects to the shop admin dashboard.
True when the socket's scope holds the given shop capability.
Fails closed: an absent or malformed scope is not authorized.
Adds the denial flash without navigating.