I’ve created this plug from the POW example to check if a user has been soft deleted or not.
defmodule InventoryWeb.Plugs.EnsureUserNotDeleted do
@moduledoc """
This plug ensures that a user isn't deleted.
## Example
plug MyAppWeb.EnsureUserNotDeleted
"""
alias InventoryWeb.Router.Helpers, as: Routes
alias Phoenix.Controller
alias Plug.Conn
alias Pow.Plug
@doc false
@spec init(any()) :: any()
def init(opts), do: opts
@doc false
@spec call(Conn.t(), any()) :: Conn.t()
def call(conn, _opts) do
conn
|> Plug.current_user()
|> deleted?()
|> maybe_halt(conn)
end
defp deleted?(%{deleted_at: deleted_at}) when not is_nil(deleted_at), do: true
defp deleted?(_user), do: false
defp maybe_halt(true, conn) do
{:ok, conn} = Plug.clear_authenticated_user(conn)
conn
#|> Controller.put_flash(:error, "This account has been deleted.")
|> Controller.redirect(to: Routes.pow_session_path(conn, :new))
end
defp maybe_halt(_any, conn), do: conn
end
This code works when placed in endpoint.ex
plug Pow.Plug.Session,
otp_app: :inventory
plug InventoryWeb.Plugs.EnsureUserNotDeleted
plug PowPersistentSession.Plug.Cookie
plug InventoryWeb.Router
When placed in my browser pipeline I get an infinite loop of redirects
defmodule InventoryWeb.Router do
use InventoryWeb, :router
use Pow.Phoenix.Router
use Pow.Extension.Phoenix.Router,
otp_app: :inventory
use Plug.ErrorHandler
use Sentry.Plug
pipeline :browser do
plug(:accepts, ["html", "json"])
plug(:fetch_session)
plug(:fetch_flash)
plug(:protect_from_forgery)
plug(:put_secure_browser_headers)
end
pipeline :protected do
plug Pow.Plug.RequireAuthenticated,
error_handler: Pow.Phoenix.PlugErrorHandler
end
pipeline :id do
plug(:put_layout, {InventoryWeb.Id.LayoutView, :id})
end
pipeline :app do
plug(:put_layout, {InventoryWeb.App.LayoutView, :app})
end
pipeline :admin do
plug(:put_layout, {InventoryWeb.Admin.LayoutView, :admin})
end
# ----------------------------------------------------------------------------
scope "/" do
pipe_through [:browser, :id]
pow_session_routes()
pow_extension_routes()
get "/session", Redirect, to: "/session/new"
end
scope "/", InventoryWeb.App do
pipe_through [:browser, :protected, :app]
get "/", DashboardController, :index
end
scope "/admin", InventoryWeb.Admin, as: :admin do
pipe_through [:browser, :protected, :admin]
get "/", DashboardController, :index
resources "/users", UserController
resources "/customers", CustomerController
resources "/inventory", InventoryController
resources "/instructions", InstructionController
resources "/uploads", UploadController
resources "/folders", FolderController
resources "/notes", NoteController
get "/print", InventoryController, :print
delete "/mass_delete", InventoryController, :mass_delete
patch "/mass_shipped_update", InventoryController, :mass_shipped_update
get "/xlsx_report", InventoryController, :xlsx_export
get "/send_comment", InventoryController, :send_comment
end
def subdomain(subdomain) do
endpoint = Application.get_env(:inventory, InventoryWeb.Endpoint)
%URI{
host: "#{subdomain}.#{endpoint[:url][:host]}",
port: endpoint[:url][:port] || endpoint[:http][:port]
}
end
if Mix.env() == :dev do
forward "/sent_emails", Bamboo.SentEmailViewerPlug
end
end
I can live with it working in endpoint.ex but I’d just like to learn the reasoning behind why it works in the endpoint.ex but not in the browser pipeline. Also you will notice that I have the put_flash commented out. I am unable to send a put_flash on redirect without and error. Any thoughts on that would be great as well. Thanks