This guide shows how to use PermitEx with Phoenix controllers and LiveView.
Configure the Repo
config :permit_ex, repo: MyApp.RepoLoad Permission Data into Your Scope
PermitEx does not replace your authentication system. Use phx.gen.auth,
Guardian, Pow, OAuth, or your existing session flow to identify the current
user. After authentication, load roles and permissions into your app scope.
For an app without tenants or workspaces:
scope = PermitEx.Scope.for_user(user)For a SaaS app:
scope = PermitEx.Scope.for_user(user, workspace)To enrich your own scope struct:
%MyApp.Accounts.Scope{user: user, workspace: workspace}
|> PermitEx.Scope.put_permission_data(user, workspace)Your scope must be assigned to :current_scope by default:
assign(conn, :current_scope, scope)Controllers
Require one permission:
plug PermitEx.Plug.RequirePermission, "orders:manage"Require one role:
plug PermitEx.Plug.RequireRole, "admin"Use the general guard for richer checks:
plug PermitEx.Plug.RequireAuthorization,
any_permissions: ["orders:manage", "settings:manage"],
role: "admin"If your scope is stored under another assign:
plug PermitEx.Plug.RequirePermission,
"orders:manage",
assign_key: :auth_scopeLiveView
Add guards to a live_session:
live_session :app,
on_mount: [
{MyAppWeb.UserAuth, :require_authenticated},
{PermitEx.LiveView.RequirePermission, "orders:view"}
] do
live "/orders", OrderLive.Index, :index
endUse RequireAuthorization for redirects and flash messages:
{PermitEx.LiveView.RequireAuthorization,
permission: "settings:manage",
redirect_to: "/app",
flash: {:error, "You cannot access that page."}}Event Handlers
Route guards protect page access. For mutations, check again inside event handlers:
def handle_event("delete", %{"id" => id}, socket) do
with :ok <- PermitEx.authorize(socket.assigns.current_scope, "orders:manage") do
# delete order
{:noreply, socket}
else
{:error, :unauthorized} ->
{:noreply, put_flash(socket, :error, "Not allowed.")}
end
endNotes
- PermitEx is authorization, not authentication.
- Use contexts only when your app needs scoped roles.
- For long-lived LiveViews, reload the scope after changing a user's roles.