From 6fe23c54581437fbaa42d880b57b3464bb439ce4 Mon Sep 17 00:00:00 2001 From: href Date: Mon, 5 Nov 2018 15:19:03 +0100 Subject: [PATCH 1/2] Runtime configured router --- lib/pleroma/plugs/federating_plug.ex | 18 ++++++ .../activity_pub/activity_pub_controller.ex | 1 + .../web/nodeinfo/nodeinfo_controller.ex | 2 + lib/pleroma/web/ostatus/ostatus_controller.ex | 1 + lib/pleroma/web/router.ex | 57 +++++++------------ .../web/twitter_api/twitter_api_controller.ex | 12 ++++ .../web/web_finger/web_finger_controller.ex | 2 + lib/pleroma/web/websub/websub_controller.ex | 9 +++ 8 files changed, 67 insertions(+), 35 deletions(-) create mode 100644 lib/pleroma/plugs/federating_plug.ex diff --git a/lib/pleroma/plugs/federating_plug.ex b/lib/pleroma/plugs/federating_plug.ex new file mode 100644 index 000000000..4108d90af --- /dev/null +++ b/lib/pleroma/plugs/federating_plug.ex @@ -0,0 +1,18 @@ +defmodule Pleroma.Web.FederatingPlug do + import Plug.Conn + + def init(options) do + options + end + + def call(conn, opts) do + if Keyword.get(Application.get_env(:pleroma, :instance), :federating) do + conn + else + conn + |> put_status(404) + |> Phoenix.Controller.render(Pleroma.Web.ErrorView, "404.json") + |> halt() + end + end +end diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex index 531e98237..99342aad9 100644 --- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex +++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex @@ -12,6 +12,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do action_fallback(:errors) + plug(Pleroma.Web.FederatingPlug when action in [:inbox, :relay]) plug(:relay_active? when action in [:relay]) def relay_active?(conn, _) do diff --git a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex index 5446179cb..d58f08881 100644 --- a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex +++ b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex @@ -6,6 +6,8 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do alias Pleroma.{User, Repo} alias Pleroma.Web.ActivityPub.MRF + plug(Pleroma.Web.FederatingPlug) + def schemas(conn, _params) do response = %{ links: [ diff --git a/lib/pleroma/web/ostatus/ostatus_controller.ex b/lib/pleroma/web/ostatus/ostatus_controller.ex index 09d1b1110..2f92935e7 100644 --- a/lib/pleroma/web/ostatus/ostatus_controller.ex +++ b/lib/pleroma/web/ostatus/ostatus_controller.ex @@ -10,6 +10,7 @@ defmodule Pleroma.Web.OStatus.OStatusController do alias Pleroma.Web.ActivityPub.ActivityPubController alias Pleroma.Web.ActivityPub.ActivityPub + plug(Pleroma.Web.FederatingPlug when action in [:salmon_incoming]) action_fallback(:errors) def feed_redirect(conn, %{"nickname" => nickname}) do diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 7b7affe5e..b461def82 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -3,11 +3,6 @@ defmodule Pleroma.Web.Router do alias Pleroma.{Repo, User, Web.Router} - @instance Application.get_env(:pleroma, :instance) - @federating Keyword.get(@instance, :federating) - @public Keyword.get(@instance, :public) - @registrations_open Keyword.get(@instance, :registrations_open) - pipeline :api do plug(:accepts, ["json"]) plug(:fetch_session) @@ -242,11 +237,7 @@ defmodule Pleroma.Web.Router do end scope "/api", Pleroma.Web do - if @public do - pipe_through(:api) - else - pipe_through(:authenticated_api) - end + pipe_through(:api) get("/statuses/public_timeline", TwitterAPI.Controller, :public_timeline) @@ -330,12 +321,10 @@ defmodule Pleroma.Web.Router do get("/users/:nickname/feed", OStatus.OStatusController, :feed) get("/users/:nickname", OStatus.OStatusController, :feed_redirect) - if @federating do - post("/users/:nickname/salmon", OStatus.OStatusController, :salmon_incoming) - post("/push/hub/:nickname", Websub.WebsubController, :websub_subscription_request) - get("/push/subscriptions/:id", Websub.WebsubController, :websub_subscription_confirmation) - post("/push/subscriptions/:id", Websub.WebsubController, :websub_incoming) - end + post("/users/:nickname/salmon", OStatus.OStatusController, :salmon_incoming) + post("/push/hub/:nickname", Websub.WebsubController, :websub_subscription_request) + get("/push/subscriptions/:id", Websub.WebsubController, :websub_subscription_confirmation) + post("/push/subscriptions/:id", Websub.WebsubController, :websub_incoming) end pipeline :activitypub do @@ -352,29 +341,27 @@ defmodule Pleroma.Web.Router do get("/users/:nickname/outbox", ActivityPubController, :outbox) end - if @federating do - scope "/relay", Pleroma.Web.ActivityPub do - pipe_through(:ap_relay) - get("/", ActivityPubController, :relay) - end + scope "/relay", Pleroma.Web.ActivityPub do + pipe_through(:ap_relay) + get("/", ActivityPubController, :relay) + end - scope "/", Pleroma.Web.ActivityPub do - pipe_through(:activitypub) - post("/users/:nickname/inbox", ActivityPubController, :inbox) - post("/inbox", ActivityPubController, :inbox) - end + scope "/", Pleroma.Web.ActivityPub do + pipe_through(:activitypub) + post("/users/:nickname/inbox", ActivityPubController, :inbox) + post("/inbox", ActivityPubController, :inbox) + end - scope "/.well-known", Pleroma.Web do - pipe_through(:well_known) + scope "/.well-known", Pleroma.Web do + pipe_through(:well_known) - get("/host-meta", WebFinger.WebFingerController, :host_meta) - get("/webfinger", WebFinger.WebFingerController, :webfinger) - get("/nodeinfo", Nodeinfo.NodeinfoController, :schemas) - end + get("/host-meta", WebFinger.WebFingerController, :host_meta) + get("/webfinger", WebFinger.WebFingerController, :webfinger) + get("/nodeinfo", Nodeinfo.NodeinfoController, :schemas) + end - scope "/nodeinfo", Pleroma.Web do - get("/:version", Nodeinfo.NodeinfoController, :nodeinfo) - end + scope "/nodeinfo", Pleroma.Web do + get("/:version", Nodeinfo.NodeinfoController, :nodeinfo) end scope "/", Pleroma.Web.MastodonAPI do diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex index 7153a2bd6..3054a8106 100644 --- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex +++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex @@ -11,6 +11,7 @@ defmodule Pleroma.Web.TwitterAPI.Controller do require Logger + plug(:only_if_public_instance when action in [:public_timeline, :public_and_external_timeline]) action_fallback(:errors) def verify_credentials(%{assigns: %{user: user}} = conn, _params) do @@ -518,6 +519,17 @@ defp forbidden_json_reply(conn, error_message) do json_reply(conn, 403, json) end + def only_if_public_instance(conn = %{conn: %{assigns: %{user: _user}}}, _), do: conn + + def only_if_public_instance(conn, _) do + if Keyword.get(Application.get_env(:pleroma, :instance), :public) do + conn + else + conn + |> forbidden_json_reply("Invalid credentials.") + end + end + defp error_json(conn, error_message) do %{"error" => error_message, "request" => conn.request_path} |> Jason.encode!() end diff --git a/lib/pleroma/web/web_finger/web_finger_controller.ex b/lib/pleroma/web/web_finger/web_finger_controller.ex index 50d816256..002353166 100644 --- a/lib/pleroma/web/web_finger/web_finger_controller.ex +++ b/lib/pleroma/web/web_finger/web_finger_controller.ex @@ -3,6 +3,8 @@ defmodule Pleroma.Web.WebFinger.WebFingerController do alias Pleroma.Web.WebFinger + plug(Pleroma.Web.FederatingPlug) + def host_meta(conn, _params) do xml = WebFinger.host_meta() diff --git a/lib/pleroma/web/websub/websub_controller.ex b/lib/pleroma/web/websub/websub_controller.ex index 590dd74a1..c1934ba92 100644 --- a/lib/pleroma/web/websub/websub_controller.ex +++ b/lib/pleroma/web/websub/websub_controller.ex @@ -5,6 +5,15 @@ defmodule Pleroma.Web.Websub.WebsubController do alias Pleroma.Web.Websub.WebsubClientSubscription require Logger + plug( + Pleroma.Web.FederatingPlug + when action in [ + :websub_subscription_request, + :websub_subscription_confirmation, + :websub_incoming + ] + ) + def websub_subscription_request(conn, %{"nickname" => nickname} = params) do user = User.get_cached_by_nickname(nickname) From 013f7ba8c1c4e6519cf30d192e3a41c6c96f8a63 Mon Sep 17 00:00:00 2001 From: href Date: Tue, 6 Nov 2018 14:44:00 +0100 Subject: [PATCH 2/2] Add federating plug & public tests --- .../web/twitter_api/twitter_api_controller.ex | 1 + test/web/node_info_test.exs | 32 ++++++++++++ test/web/plugs/federating_plug_test.exs | 33 ++++++++++++ .../twitter_api_controller_test.exs | 50 +++++++++++++++++++ 4 files changed, 116 insertions(+) create mode 100644 test/web/plugs/federating_plug_test.exs diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex index 3054a8106..83d725f13 100644 --- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex +++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex @@ -527,6 +527,7 @@ def only_if_public_instance(conn, _) do else conn |> forbidden_json_reply("Invalid credentials.") + |> halt() end end diff --git a/test/web/node_info_test.exs b/test/web/node_info_test.exs index d48f40e47..a6376453c 100644 --- a/test/web/node_info_test.exs +++ b/test/web/node_info_test.exs @@ -14,4 +14,36 @@ test "nodeinfo shows staff accounts", %{conn: conn} do assert user.ap_id in result["metadata"]["staffAccounts"] end + + test "returns 404 when federation is disabled" do + instance = + Application.get_env(:pleroma, :instance) + |> Keyword.put(:federating, false) + + Application.put_env(:pleroma, :instance, instance) + + conn + |> get("/.well-known/nodeinfo") + |> json_response(404) + + conn + |> get("/nodeinfo/2.0.json") + |> json_response(404) + + instance = + Application.get_env(:pleroma, :instance) + |> Keyword.put(:federating, true) + + Application.put_env(:pleroma, :instance, instance) + end + + test "returns 200 when federation is enabled" do + conn + |> get("/.well-known/nodeinfo") + |> json_response(200) + + conn + |> get("/nodeinfo/2.0.json") + |> json_response(200) + end end diff --git a/test/web/plugs/federating_plug_test.exs b/test/web/plugs/federating_plug_test.exs new file mode 100644 index 000000000..1455a1c46 --- /dev/null +++ b/test/web/plugs/federating_plug_test.exs @@ -0,0 +1,33 @@ +defmodule Pleroma.Web.FederatingPlugTest do + use Pleroma.Web.ConnCase + + test "returns and halt the conn when federating is disabled" do + instance = + Application.get_env(:pleroma, :instance) + |> Keyword.put(:federating, false) + + Application.put_env(:pleroma, :instance, instance) + + conn = + build_conn() + |> Pleroma.Web.FederatingPlug.call(%{}) + + assert conn.status == 404 + assert conn.halted + + instance = + Application.get_env(:pleroma, :instance) + |> Keyword.put(:federating, true) + + Application.put_env(:pleroma, :instance, instance) + end + + test "does nothing when federating is enabled" do + conn = + build_conn() + |> Pleroma.Web.FederatingPlug.call(%{}) + + refute conn.status + refute conn.halted + end +end diff --git a/test/web/twitter_api/twitter_api_controller_test.exs b/test/web/twitter_api/twitter_api_controller_test.exs index 87bcdaf71..b64f416e3 100644 --- a/test/web/twitter_api/twitter_api_controller_test.exs +++ b/test/web/twitter_api/twitter_api_controller_test.exs @@ -100,6 +100,56 @@ test "returns statuses", %{conn: conn} do assert length(response) == 10 end + + test "returns 403 to unauthenticated request when the instance is not public" do + instance = + Application.get_env(:pleroma, :instance) + |> Keyword.put(:public, false) + + Application.put_env(:pleroma, :instance, instance) + + conn + |> get("/api/statuses/public_timeline.json") + |> json_response(403) + + instance = + Application.get_env(:pleroma, :instance) + |> Keyword.put(:public, true) + + Application.put_env(:pleroma, :instance, instance) + end + + test "returns 200 to unauthenticated request when the instance is public" do + conn + |> get("/api/statuses/public_timeline.json") + |> json_response(200) + end + end + + describe "GET /statuses/public_and_external_timeline.json" do + test "returns 403 to unauthenticated request when the instance is not public" do + instance = + Application.get_env(:pleroma, :instance) + |> Keyword.put(:public, false) + + Application.put_env(:pleroma, :instance, instance) + + conn + |> get("/api/statuses/public_and_external_timeline.json") + |> json_response(403) + + instance = + Application.get_env(:pleroma, :instance) + |> Keyword.put(:public, true) + + Application.put_env(:pleroma, :instance, instance) + end + + test "returns 200 to unauthenticated request when the instance is public" do + conn + |> get("/api/statuses/public_and_external_timeline.json") + |> json_response(200) + end end describe "GET /statuses/show/:id.json" do