Restrict mastodon api announcements to logged-in users only

This commit is contained in:
Tusooa Zhu 2022-04-02 02:25:13 -04:00
parent 0c78ab4a88
commit 7d1dae3bef
No known key found for this signature in database
GPG Key ID: 7B467EDE43A08224
4 changed files with 38 additions and 21 deletions

View File

@ -18,6 +18,7 @@ def index_operation do
tags: ["Announcement"], tags: ["Announcement"],
summary: "Retrieve a list of announcements", summary: "Retrieve a list of announcements",
operationId: "MastodonAPI.AnnouncementController.index", operationId: "MastodonAPI.AnnouncementController.index",
security: [%{"oAuth" => []}],
responses: %{ responses: %{
200 => Operation.response("Response", "application/json", list_of_announcements()), 200 => Operation.response("Response", "application/json", list_of_announcements()),
403 => Operation.response("Forbidden", "application/json", ApiError) 403 => Operation.response("Forbidden", "application/json", ApiError)

View File

@ -15,20 +15,18 @@ defmodule Pleroma.Web.MastodonAPI.AnnouncementController do
plug(Pleroma.Web.ApiSpec.CastAndValidate) plug(Pleroma.Web.ApiSpec.CastAndValidate)
# MastodonAPI specs do not have oauth requirements for showing # Mastodon docs say this only requires a user token, no scopes needed
# announcements, but we have "private instance" options. When that # As the op `|` requires at least one scope to be present, we use `&` here.
# is set, require read:accounts scope, symmetric to write:accounts
# for `mark_read`.
plug( plug(
OAuthScopesPlug, OAuthScopesPlug,
%{fallback: :proceed_unauthenticated, scopes: ["read:accounts"]} %{scopes: [], op: :&}
when action in [:show, :index] when action in [:index]
) )
# Same as in MastodonAPI specs # Same as in MastodonAPI specs
plug( plug(
OAuthScopesPlug, OAuthScopesPlug,
%{fallback: :proceed_unauthenticated, scopes: ["write:accounts"]} %{scopes: ["write:accounts"]}
when action in [:mark_read] when action in [:mark_read]
) )

View File

@ -582,6 +582,7 @@ defmodule Pleroma.Web.Router do
get("/timelines/direct", TimelineController, :direct) get("/timelines/direct", TimelineController, :direct)
get("/timelines/list/:list_id", TimelineController, :list) get("/timelines/list/:list_id", TimelineController, :list)
get("/announcements", AnnouncementController, :index)
post("/announcements/:id/dismiss", AnnouncementController, :mark_read) post("/announcements/:id/dismiss", AnnouncementController, :mark_read)
end end
@ -627,8 +628,6 @@ defmodule Pleroma.Web.Router do
get("/polls/:id", PollController, :show) get("/polls/:id", PollController, :show)
get("/directory", DirectoryController, :index) get("/directory", DirectoryController, :index)
get("/announcements", AnnouncementController, :index)
end end
scope "/api/v2", Pleroma.Web.MastodonAPI do scope "/api/v2", Pleroma.Web.MastodonAPI do

View File

@ -11,19 +11,40 @@ defmodule Pleroma.Web.MastodonAPI.AnnouncementControllerTest do
alias Pleroma.AnnouncementReadRelationship alias Pleroma.AnnouncementReadRelationship
describe "GET /api/v1/announcements" do 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) %{id: id} = insert(:announcement)
response = response =
build_conn() conn
|> get("/api/v1/announcements") |> get("/api/v1/announcements")
|> json_response_and_validate_schema(:ok) |> json_response_and_validate_schema(:ok)
assert [%{"id" => ^id}] = response assert [%{"id" => ^id}] = response
refute Map.has_key?(Enum.at(response, 0), "read")
end end
test "it returns time with utc timezone" do test "it returns time with utc timezone", %{conn: conn} do
start_time = start_time =
NaiveDateTime.utc_now() NaiveDateTime.utc_now()
|> NaiveDateTime.add(-999_999, :second) |> 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}) %{id: id} = insert(:announcement, %{starts_at: start_time, ends_at: end_time})
response = response =
build_conn() conn
|> get("/api/v1/announcements") |> get("/api/v1/announcements")
|> json_response_and_validate_schema(:ok) |> 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") assert String.ends_with?(announcement["ends_at"], "Z")
end 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) time = NaiveDateTime.utc_now() |> NaiveDateTime.add(999_999, :second)
insert(:announcement, starts_at: time) insert(:announcement, starts_at: time)
response = response =
build_conn() conn
|> get("/api/v1/announcements") |> get("/api/v1/announcements")
|> json_response_and_validate_schema(:ok) |> json_response_and_validate_schema(:ok)
assert [] = response assert [] = response
end 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) time = NaiveDateTime.utc_now() |> NaiveDateTime.add(-999_999, :second)
insert(:announcement, ends_at: time) insert(:announcement, ends_at: time)
response = response =
build_conn() conn
|> get("/api/v1/announcements") |> get("/api/v1/announcements")
|> json_response_and_validate_schema(:ok) |> json_response_and_validate_schema(:ok)
assert [] = response assert [] = response
end end
test "when authenticated, also expose read property" do test "when authenticated, also expose read property", %{conn: conn} do
%{id: id} = insert(:announcement) %{id: id} = insert(:announcement)
%{conn: conn} = oauth_access(["read:accounts"])
response = response =
conn conn
|> get("/api/v1/announcements") |> get("/api/v1/announcements")