Added conditional routing for feed URLs

This commit is contained in:
Kieran Eglin 2024-03-26 13:11:10 -07:00
parent b7e7992f4d
commit 73b1e60e9f
No known key found for this signature in database
GPG key ID: 193984967FCF432D
4 changed files with 75 additions and 7 deletions

View file

@ -20,8 +20,9 @@ config :pinchflat,
tmpfile_directory: Path.join([System.tmp_dir!(), "pinchflat", "data"]),
# Setting BASIC_AUTH_USERNAME and BASIC_AUTH_PASSWORD implies you want to use basic auth.
# If either is unset, basic auth will not be used.
basic_auth_username: System.get_env("BASIC_AUTH_USERNAME"),
basic_auth_password: System.get_env("BASIC_AUTH_PASSWORD"),
basic_auth_username: "",
basic_auth_password: "",
expose_xml_feed: false,
url_base: System.get_env("BASIC_AUTH_PASSWORD") || "http://localhost:4008",
file_watcher_poll_interval: 1000

View file

@ -47,6 +47,10 @@ if config_env() == :prod do
metadata_path = System.get_env("METADATA_PATH", Path.join([config_path, "metadata"]))
extras_path = System.get_env("EXTRAS_PATH", Path.join([config_path, "extras"]))
# For running PF as a podcast host on self-hosted environments
expose_xml_feed = String.length(System.get_env("EXPOSE_XML_FEED", "")) > 0
url_base = System.get_env("URL_BASE", "")
# We want to force _some_ level of useful logging in production
acceptable_log_levels = ~w(debug info)a
log_level = String.to_existing_atom(System.get_env("LOG_LEVEL", "info"))
@ -65,7 +69,8 @@ if config_env() == :prod do
extras_directory: extras_path,
tmpfile_directory: Path.join([System.tmp_dir!(), "pinchflat", "data"]),
dns_cluster_query: System.get_env("DNS_CLUSTER_QUERY"),
url_base: System.get_env("URL_BASE") || "http://localhost:8945"
url_base: url_base,
expose_xml_feed: expose_xml_feed
config :pinchflat, Pinchflat.Repo,
database: db_path,

View file

@ -17,6 +17,10 @@ defmodule PinchflatWeb.Router do
plug :accepts, ["json"]
end
pipeline :feeds do
plug :maybe_basic_auth
end
scope "/", PinchflatWeb do
pipe_through :browser
@ -30,12 +34,11 @@ defmodule PinchflatWeb.Router do
end
end
# Routes in here are NOT protected by basic auth. This is necessary for
# Routes in here _may not be_ protected by basic auth. This is necessary for
# media streaming to work for RSS podcast feeds.
#
# TODO: consider putting the basic auth here behind a config flag
# so people that want RSS feeds to work can enable it.
scope "/", PinchflatWeb do
pipe_through :feeds
get "/sources/:uuid/feed", Podcasts.PodcastController, :rss_feed
get "/sources/:uuid/feed_image", Podcasts.PodcastController, :feed_image
@ -59,6 +62,14 @@ defmodule PinchflatWeb.Router do
end
end
defp maybe_basic_auth(conn, opts) do
if Application.get_env(:pinchflat, :expose_xml_feed) 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)

View file

@ -1,6 +1,8 @@
defmodule PinchflatWeb.RoutingTest do
use PinchflatWeb.ConnCase
import Pinchflat.SourcesFixtures
describe "basic_auth plug" do
setup do
old_username = Application.get_env(:pinchflat, :basic_auth_username)
@ -54,4 +56,53 @@ defmodule PinchflatWeb.RoutingTest do
assert conn.status == 200
end
end
describe "maybe_basic_auth plug" do
setup do
old_username = Application.get_env(:pinchflat, :basic_auth_username)
old_password = Application.get_env(:pinchflat, :basic_auth_password)
old_expore_xml_feed = Application.get_env(:pinchflat, :expose_xml_feed)
source = source_fixture()
on_exit(fn ->
Application.put_env(:pinchflat, :basic_auth_username, old_username)
Application.put_env(:pinchflat, :basic_auth_password, old_password)
Application.put_env(:pinchflat, :expose_xml_feed, old_expore_xml_feed)
end)
{:ok, source: source}
end
test "uses basic auth when expose_xml_feed is false", %{source: source} do
Application.put_env(:pinchflat, :basic_auth_username, "user")
Application.put_env(:pinchflat, :basic_auth_password, "pass")
Application.put_env(:pinchflat, :expose_xml_feed, false)
conn = get(build_conn(), "/sources/#{source.uuid}/feed")
assert conn.status == 401
assert {"www-authenticate", "Basic realm=\"Pinchflat\""} in conn.resp_headers
end
test "does not use basic auth when expose_xml_feed is true", %{source: source} do
Application.put_env(:pinchflat, :basic_auth_username, "user")
Application.put_env(:pinchflat, :basic_auth_password, "pass")
Application.put_env(:pinchflat, :expose_xml_feed, true)
conn = get(build_conn(), "/sources/#{source.uuid}/feed")
assert conn.status == 200
end
test "does not use basic auth when username/password aren't set", %{source: source} do
Application.put_env(:pinchflat, :basic_auth_username, nil)
Application.put_env(:pinchflat, :basic_auth_password, nil)
Application.put_env(:pinchflat, :expose_xml_feed, false)
conn = get(build_conn(), "/sources/#{source.uuid}/feed")
assert conn.status == 200
end
end
end