diff --git a/lib/pinchflat_web/plugs.ex b/lib/pinchflat_web/plugs.ex new file mode 100644 index 0000000..5c78530 --- /dev/null +++ b/lib/pinchflat_web/plugs.ex @@ -0,0 +1,42 @@ +defmodule PinchflatWeb.Plugs do + use PinchflatWeb, :router + + # TODO: doc and test + def maybe_basic_auth(conn, opts) do + if Application.get_env(:pinchflat, :expose_feed_endpoints) do + conn + else + basic_auth(conn, opts) + end + end + + def basic_auth(conn, _opts) do + username = Application.get_env(:pinchflat, :basic_auth_username) + password = Application.get_env(:pinchflat, :basic_auth_password) + + if credential_set?(username) && credential_set?(password) do + Plug.BasicAuth.basic_auth(conn, username: username, password: password, realm: "Pinchflat") + else + conn + end + end + + def allow_iframe_embed(conn, _opts) do + delete_resp_header(conn, "x-frame-options") + end + + def token_protected_route(%{query_params: %{"route_token" => route_token}} = conn, _opts) do + # TODO: make this match against the token in the database + conn + end + + def token_protected_route(conn, _opts) do + conn + |> send_resp(:unauthorized, "Unauthorized") + |> halt() + end + + defp credential_set?(credential) do + credential && credential != "" + end +end diff --git a/lib/pinchflat_web/router.ex b/lib/pinchflat_web/router.ex index f7b7875..6195bcf 100644 --- a/lib/pinchflat_web/router.ex +++ b/lib/pinchflat_web/router.ex @@ -1,5 +1,6 @@ defmodule PinchflatWeb.Router do use PinchflatWeb, :router + import PinchflatWeb.Plugs import Phoenix.LiveDashboard.Router # IMPORTANT: `strip_trailing_extension` in endpoint.ex removes @@ -15,20 +16,19 @@ defmodule PinchflatWeb.Router do plug :allow_iframe_embed end - pipeline :api do - plug :accepts, ["json"] - end + pipeline :api, do: plug(:accepts, ["json"]) - pipeline :feeds do - plug :maybe_basic_auth + scope "/", PinchflatWeb do + pipe_through [:maybe_basic_auth, :token_protected_route] + + # has to match before /sources/:id + get "/sources/opml", Podcasts.PodcastController, :opml_feed end # Routes in here _may not be_ protected by basic auth. This is necessary for # media streaming to work for RSS podcast feeds. scope "/", PinchflatWeb do - pipe_through :feeds - # has to match before /sources/:id - get "/sources/opml", Podcasts.PodcastController, :opml_feed + pipe_through :maybe_basic_auth get "/sources/:uuid/feed", Podcasts.PodcastController, :rss_feed get "/sources/:uuid/feed_image", Podcasts.PodcastController, :feed_image @@ -76,31 +76,4 @@ defmodule PinchflatWeb.Router do metrics: PinchflatWeb.Telemetry, ecto_repos: [Pinchflat.Repo] end - - defp maybe_basic_auth(conn, opts) do - if Application.get_env(:pinchflat, :expose_feed_endpoints) do - conn - else - basic_auth(conn, opts) - end - end - - defp basic_auth(conn, _opts) do - username = Application.get_env(:pinchflat, :basic_auth_username) - password = Application.get_env(:pinchflat, :basic_auth_password) - - if credential_set?(username) && credential_set?(password) do - Plug.BasicAuth.basic_auth(conn, username: username, password: password, realm: "Pinchflat") - else - conn - end - end - - defp credential_set?(credential) do - credential && credential != "" - end - - defp allow_iframe_embed(conn, _opts) do - delete_resp_header(conn, "x-frame-options") - end end