From 3efc533fb7f5fcae9230e5eeb21c3b0557625269 Mon Sep 17 00:00:00 2001 From: Kieran Date: Wed, 21 Feb 2024 17:37:25 -0800 Subject: [PATCH] Added optional basic auth (#31) --- config/config.exs | 6 +++- lib/pinchflat_web/router.ex | 12 ++++++++ test/pinchflat_web/routing_test.exs | 48 +++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 test/pinchflat_web/routing_test.exs diff --git a/config/config.exs b/config/config.exs index 238bf64..a8957b3 100644 --- a/config/config.exs +++ b/config/config.exs @@ -14,7 +14,11 @@ config :pinchflat, yt_dlp_executable: System.find_executable("yt-dlp"), yt_dlp_runner: Pinchflat.MediaClient.Backends.YtDlp.CommandRunner, media_directory: "/downloads", - metadata_directory: Path.join([System.tmp_dir!(), "pinchflat", "metadata"]) + metadata_directory: Path.join([System.tmp_dir!(), "pinchflat", "metadata"]), + # Setting AUTH_USERNAME and 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("AUTH_USERNAME"), + basic_auth_password: System.get_env("AUTH_PASSWORD") # Configures the endpoint config :pinchflat, PinchflatWeb.Endpoint, diff --git a/lib/pinchflat_web/router.ex b/lib/pinchflat_web/router.ex index 187a2d0..3326764 100644 --- a/lib/pinchflat_web/router.ex +++ b/lib/pinchflat_web/router.ex @@ -2,6 +2,7 @@ defmodule PinchflatWeb.Router do use PinchflatWeb, :router pipeline :browser do + plug :basic_auth plug :accepts, ["html"] plug :fetch_session plug :fetch_live_flash @@ -48,4 +49,15 @@ defmodule PinchflatWeb.Router do forward "/mailbox", Plug.Swoosh.MailboxPreview 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 username && password do + Plug.BasicAuth.basic_auth(conn, username: username, password: password, realm: "Pinchflat") + else + conn + end + end end diff --git a/test/pinchflat_web/routing_test.exs b/test/pinchflat_web/routing_test.exs new file mode 100644 index 0000000..a7ee8a8 --- /dev/null +++ b/test/pinchflat_web/routing_test.exs @@ -0,0 +1,48 @@ +defmodule PinchflatWeb.RoutingTest do + use PinchflatWeb.ConnCase + + describe "basic_auth plug" do + setup do + old_username = Application.get_env(:pinchflat, :basic_auth_username) + old_password = Application.get_env(:pinchflat, :basic_auth_password) + + on_exit(fn -> + Application.put_env(:pinchflat, :basic_auth_username, old_username) + Application.put_env(:pinchflat, :basic_auth_password, old_password) + end) + + :ok + end + + test "it uses basic auth when both username and password are set", %{conn: conn} do + Application.put_env(:pinchflat, :basic_auth_username, "user") + Application.put_env(:pinchflat, :basic_auth_password, "pass") + + conn = get(conn, "/") + + assert conn.status == 401 + assert {"www-authenticate", "Basic realm=\"Pinchflat\""} in conn.resp_headers + end + + test "providing the username and password allows access", %{conn: conn} do + Application.put_env(:pinchflat, :basic_auth_username, "user") + Application.put_env(:pinchflat, :basic_auth_password, "pass") + + conn = + conn + |> put_req_header("authorization", Plug.BasicAuth.encode_basic_auth("user", "pass")) + |> get("/") + + assert conn.status == 200 + end + + test "it does not use basic auth when either username or password is not set", %{conn: conn} do + Application.put_env(:pinchflat, :basic_auth_username, nil) + Application.put_env(:pinchflat, :basic_auth_password, "pass") + + conn = get(conn, "/") + + assert conn.status == 200 + end + end +end