From 7d1dae3befbecbeeb72768afe4f5a23a59ba4f05 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Sat, 2 Apr 2022 02:25:13 -0400 Subject: [PATCH] Restrict mastodon api announcements to logged-in users only --- .../operations/announcement_operation.ex | 1 + .../controllers/announcement_controller.ex | 12 +++--- lib/pleroma/web/router.ex | 3 +- .../announcement_controller_test.exs | 43 +++++++++++++------ 4 files changed, 38 insertions(+), 21 deletions(-) diff --git a/lib/pleroma/web/api_spec/operations/announcement_operation.ex b/lib/pleroma/web/api_spec/operations/announcement_operation.ex index a66073b8b..71be0002a 100644 --- a/lib/pleroma/web/api_spec/operations/announcement_operation.ex +++ b/lib/pleroma/web/api_spec/operations/announcement_operation.ex @@ -18,6 +18,7 @@ def index_operation do tags: ["Announcement"], summary: "Retrieve a list of announcements", operationId: "MastodonAPI.AnnouncementController.index", + security: [%{"oAuth" => []}], responses: %{ 200 => Operation.response("Response", "application/json", list_of_announcements()), 403 => Operation.response("Forbidden", "application/json", ApiError) diff --git a/lib/pleroma/web/mastodon_api/controllers/announcement_controller.ex b/lib/pleroma/web/mastodon_api/controllers/announcement_controller.ex index e6da7892c..080af96d5 100644 --- a/lib/pleroma/web/mastodon_api/controllers/announcement_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/announcement_controller.ex @@ -15,20 +15,18 @@ defmodule Pleroma.Web.MastodonAPI.AnnouncementController do plug(Pleroma.Web.ApiSpec.CastAndValidate) - # MastodonAPI specs do not have oauth requirements for showing - # announcements, but we have "private instance" options. When that - # is set, require read:accounts scope, symmetric to write:accounts - # for `mark_read`. + # Mastodon docs say this only requires a user token, no scopes needed + # As the op `|` requires at least one scope to be present, we use `&` here. plug( OAuthScopesPlug, - %{fallback: :proceed_unauthenticated, scopes: ["read:accounts"]} - when action in [:show, :index] + %{scopes: [], op: :&} + when action in [:index] ) # Same as in MastodonAPI specs plug( OAuthScopesPlug, - %{fallback: :proceed_unauthenticated, scopes: ["write:accounts"]} + %{scopes: ["write:accounts"]} when action in [:mark_read] ) diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index af56494a2..7bbc20275 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -582,6 +582,7 @@ defmodule Pleroma.Web.Router do get("/timelines/direct", TimelineController, :direct) get("/timelines/list/:list_id", TimelineController, :list) + get("/announcements", AnnouncementController, :index) post("/announcements/:id/dismiss", AnnouncementController, :mark_read) end @@ -627,8 +628,6 @@ defmodule Pleroma.Web.Router do get("/polls/:id", PollController, :show) get("/directory", DirectoryController, :index) - - get("/announcements", AnnouncementController, :index) end scope "/api/v2", Pleroma.Web.MastodonAPI do diff --git a/test/pleroma/web/mastodon_api/controllers/announcement_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/announcement_controller_test.exs index 3957cc3ed..60c9978c2 100644 --- a/test/pleroma/web/mastodon_api/controllers/announcement_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/announcement_controller_test.exs @@ -11,19 +11,40 @@ defmodule Pleroma.Web.MastodonAPI.AnnouncementControllerTest do alias Pleroma.AnnouncementReadRelationship describe "GET /api/v1/announcements" do - test "it lists all announcements" do + setup do + %{conn: conn} = oauth_access([]) + {:ok, conn: conn} + end + + test "it does not allow guests", %{conn: conn} do + _response = + conn + |> assign(:token, nil) + |> get("/api/v1/announcements") + |> json_response_and_validate_schema(:forbidden) + end + + test "it allows users with scopes" do + %{conn: conn} = oauth_access(["read:accounts"]) + + _response = + conn + |> get("/api/v1/announcements") + |> json_response_and_validate_schema(:ok) + end + + test "it lists all announcements", %{conn: conn} do %{id: id} = insert(:announcement) response = - build_conn() + conn |> get("/api/v1/announcements") |> json_response_and_validate_schema(:ok) assert [%{"id" => ^id}] = response - refute Map.has_key?(Enum.at(response, 0), "read") end - test "it returns time with utc timezone" do + test "it returns time with utc timezone", %{conn: conn} do start_time = NaiveDateTime.utc_now() |> NaiveDateTime.add(-999_999, :second) @@ -37,7 +58,7 @@ test "it returns time with utc timezone" do %{id: id} = insert(:announcement, %{starts_at: start_time, ends_at: end_time}) response = - build_conn() + conn |> get("/api/v1/announcements") |> json_response_and_validate_schema(:ok) @@ -47,35 +68,33 @@ test "it returns time with utc timezone" do assert String.ends_with?(announcement["ends_at"], "Z") end - test "it does not list announcements starting after current time" do + test "it does not list announcements starting after current time", %{conn: conn} do time = NaiveDateTime.utc_now() |> NaiveDateTime.add(999_999, :second) insert(:announcement, starts_at: time) response = - build_conn() + conn |> get("/api/v1/announcements") |> json_response_and_validate_schema(:ok) assert [] = response end - test "it does not list announcements ending before current time" do + test "it does not list announcements ending before current time", %{conn: conn} do time = NaiveDateTime.utc_now() |> NaiveDateTime.add(-999_999, :second) insert(:announcement, ends_at: time) response = - build_conn() + conn |> get("/api/v1/announcements") |> json_response_and_validate_schema(:ok) assert [] = response end - test "when authenticated, also expose read property" do + test "when authenticated, also expose read property", %{conn: conn} do %{id: id} = insert(:announcement) - %{conn: conn} = oauth_access(["read:accounts"]) - response = conn |> get("/api/v1/announcements")