Merge branch 'develop' into refactor/subscription
This commit is contained in:
commit
d7457c9165
|
@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
### Security
|
### Security
|
||||||
- OStatus: eliminate the possibility of a protocol downgrade attack.
|
- OStatus: eliminate the possibility of a protocol downgrade attack.
|
||||||
- OStatus: prevent following locked accounts, bypassing the approval process.
|
- OStatus: prevent following locked accounts, bypassing the approval process.
|
||||||
|
- Mastodon API: respect post privacy in `/api/v1/statuses/:id/{favourited,reblogged}_by`
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
- **Breaking:** GNU Social API with Qvitter extensions support
|
- **Breaking:** GNU Social API with Qvitter extensions support
|
||||||
|
|
|
@ -34,79 +34,38 @@ defp param_to_integer(val, default) when is_binary(val) do
|
||||||
|
|
||||||
defp param_to_integer(_, default), do: default
|
defp param_to_integer(_, default), do: default
|
||||||
|
|
||||||
def add_link_headers(
|
def add_link_headers(conn, activities, extra_params \\ %{}) do
|
||||||
conn,
|
case List.last(activities) do
|
||||||
method,
|
%{id: max_id} ->
|
||||||
activities,
|
params =
|
||||||
param \\ nil,
|
conn.params
|
||||||
params \\ %{},
|
|> Map.drop(Map.keys(conn.path_params))
|
||||||
func3 \\ nil,
|
|> Map.drop(["since_id", "max_id", "min_id"])
|
||||||
func4 \\ nil
|
|> Map.merge(extra_params)
|
||||||
) do
|
|
||||||
params =
|
|
||||||
conn.params
|
|
||||||
|> Map.drop(["since_id", "max_id", "min_id"])
|
|
||||||
|> Map.merge(params)
|
|
||||||
|
|
||||||
last = List.last(activities)
|
limit =
|
||||||
|
params
|
||||||
|
|> Map.get("limit", "20")
|
||||||
|
|> String.to_integer()
|
||||||
|
|
||||||
func3 = func3 || (&mastodon_api_url/3)
|
min_id =
|
||||||
func4 = func4 || (&mastodon_api_url/4)
|
if length(activities) <= limit do
|
||||||
|
activities
|
||||||
|
|> List.first()
|
||||||
|
|> Map.get(:id)
|
||||||
|
else
|
||||||
|
activities
|
||||||
|
|> Enum.at(limit * -1)
|
||||||
|
|> Map.get(:id)
|
||||||
|
end
|
||||||
|
|
||||||
if last do
|
next_url = current_url(conn, Map.merge(params, %{max_id: max_id}))
|
||||||
max_id = last.id
|
prev_url = current_url(conn, Map.merge(params, %{min_id: min_id}))
|
||||||
|
|
||||||
limit =
|
put_resp_header(conn, "link", "<#{next_url}>; rel=\"next\", <#{prev_url}>; rel=\"prev\"")
|
||||||
params
|
|
||||||
|> Map.get("limit", "20")
|
|
||||||
|> String.to_integer()
|
|
||||||
|
|
||||||
min_id =
|
_ ->
|
||||||
if length(activities) <= limit do
|
conn
|
||||||
activities
|
|
||||||
|> List.first()
|
|
||||||
|> Map.get(:id)
|
|
||||||
else
|
|
||||||
activities
|
|
||||||
|> Enum.at(limit * -1)
|
|
||||||
|> Map.get(:id)
|
|
||||||
end
|
|
||||||
|
|
||||||
{next_url, prev_url} =
|
|
||||||
if param do
|
|
||||||
{
|
|
||||||
func4.(
|
|
||||||
Pleroma.Web.Endpoint,
|
|
||||||
method,
|
|
||||||
param,
|
|
||||||
Map.merge(params, %{max_id: max_id})
|
|
||||||
),
|
|
||||||
func4.(
|
|
||||||
Pleroma.Web.Endpoint,
|
|
||||||
method,
|
|
||||||
param,
|
|
||||||
Map.merge(params, %{min_id: min_id})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
func3.(
|
|
||||||
Pleroma.Web.Endpoint,
|
|
||||||
method,
|
|
||||||
Map.merge(params, %{max_id: max_id})
|
|
||||||
),
|
|
||||||
func3.(
|
|
||||||
Pleroma.Web.Endpoint,
|
|
||||||
method,
|
|
||||||
Map.merge(params, %{min_id: min_id})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
conn
|
|
||||||
|> put_resp_header("link", "<#{next_url}>; rel=\"next\", <#{prev_url}>; rel=\"prev\"")
|
|
||||||
else
|
|
||||||
conn
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,7 +6,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
||||||
use Pleroma.Web, :controller
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
import Pleroma.Web.ControllerHelper,
|
import Pleroma.Web.ControllerHelper,
|
||||||
only: [json_response: 3, add_link_headers: 5, add_link_headers: 4, add_link_headers: 3]
|
only: [json_response: 3, add_link_headers: 2, add_link_headers: 3]
|
||||||
|
|
||||||
alias Ecto.Changeset
|
alias Ecto.Changeset
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
|
@ -367,7 +367,7 @@ def home_timeline(%{assigns: %{user: user}} = conn, params) do
|
||||||
|> Enum.reverse()
|
|> Enum.reverse()
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> add_link_headers(:home_timeline, activities)
|
|> add_link_headers(activities)
|
||||||
|> put_view(StatusView)
|
|> put_view(StatusView)
|
||||||
|> render("index.json", %{activities: activities, for: user, as: :activity})
|
|> render("index.json", %{activities: activities, for: user, as: :activity})
|
||||||
end
|
end
|
||||||
|
@ -386,7 +386,7 @@ def public_timeline(%{assigns: %{user: user}} = conn, params) do
|
||||||
|> Enum.reverse()
|
|> Enum.reverse()
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> add_link_headers(:public_timeline, activities, false, %{"local" => local_only})
|
|> add_link_headers(activities, %{"local" => local_only})
|
||||||
|> put_view(StatusView)
|
|> put_view(StatusView)
|
||||||
|> render("index.json", %{activities: activities, for: user, as: :activity})
|
|> render("index.json", %{activities: activities, for: user, as: :activity})
|
||||||
end
|
end
|
||||||
|
@ -400,7 +400,7 @@ def user_statuses(%{assigns: %{user: reading_user}} = conn, params) do
|
||||||
activities = ActivityPub.fetch_user_activities(user, reading_user, params)
|
activities = ActivityPub.fetch_user_activities(user, reading_user, params)
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> add_link_headers(:user_statuses, activities, params["id"])
|
|> add_link_headers(activities)
|
||||||
|> put_view(StatusView)
|
|> put_view(StatusView)
|
||||||
|> render("index.json", %{
|
|> render("index.json", %{
|
||||||
activities: activities,
|
activities: activities,
|
||||||
|
@ -424,7 +424,7 @@ def dm_timeline(%{assigns: %{user: user}} = conn, params) do
|
||||||
|> Pagination.fetch_paginated(params)
|
|> Pagination.fetch_paginated(params)
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> add_link_headers(:dm_timeline, activities)
|
|> add_link_headers(activities)
|
||||||
|> put_view(StatusView)
|
|> put_view(StatusView)
|
||||||
|> render("index.json", %{activities: activities, for: user, as: :activity})
|
|> render("index.json", %{activities: activities, for: user, as: :activity})
|
||||||
end
|
end
|
||||||
|
@ -539,7 +539,7 @@ def poll_vote(%{assigns: %{user: user}} = conn, %{"id" => id, "choices" => choic
|
||||||
def scheduled_statuses(%{assigns: %{user: user}} = conn, params) do
|
def scheduled_statuses(%{assigns: %{user: user}} = conn, params) do
|
||||||
with scheduled_activities <- MastodonAPI.get_scheduled_activities(user, params) do
|
with scheduled_activities <- MastodonAPI.get_scheduled_activities(user, params) do
|
||||||
conn
|
conn
|
||||||
|> add_link_headers(:scheduled_statuses, scheduled_activities)
|
|> add_link_headers(scheduled_activities)
|
||||||
|> put_view(ScheduledActivityView)
|
|> put_view(ScheduledActivityView)
|
||||||
|> render("index.json", %{scheduled_activities: scheduled_activities})
|
|> render("index.json", %{scheduled_activities: scheduled_activities})
|
||||||
end
|
end
|
||||||
|
@ -722,7 +722,7 @@ def notifications(%{assigns: %{user: user}} = conn, params) do
|
||||||
notifications = MastodonAPI.get_notifications(user, params)
|
notifications = MastodonAPI.get_notifications(user, params)
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> add_link_headers(:notifications, notifications)
|
|> add_link_headers(notifications)
|
||||||
|> put_view(NotificationView)
|
|> put_view(NotificationView)
|
||||||
|> render("index.json", %{notifications: notifications, for: user})
|
|> render("index.json", %{notifications: notifications, for: user})
|
||||||
end
|
end
|
||||||
|
@ -890,6 +890,7 @@ def get_mascot(%{assigns: %{user: user}} = conn, _params) do
|
||||||
|
|
||||||
def favourited_by(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
def favourited_by(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||||
with %Activity{} = activity <- Activity.get_by_id_with_object(id),
|
with %Activity{} = activity <- Activity.get_by_id_with_object(id),
|
||||||
|
{:visible, true} <- {:visible, Visibility.visible_for_user?(activity, user)},
|
||||||
%Object{data: %{"likes" => likes}} <- Object.normalize(activity) do
|
%Object{data: %{"likes" => likes}} <- Object.normalize(activity) do
|
||||||
q = from(u in User, where: u.ap_id in ^likes)
|
q = from(u in User, where: u.ap_id in ^likes)
|
||||||
|
|
||||||
|
@ -901,12 +902,14 @@ def favourited_by(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||||
|> put_view(AccountView)
|
|> put_view(AccountView)
|
||||||
|> render("accounts.json", %{for: user, users: users, as: :user})
|
|> render("accounts.json", %{for: user, users: users, as: :user})
|
||||||
else
|
else
|
||||||
|
{:visible, false} -> {:error, :not_found}
|
||||||
_ -> json(conn, [])
|
_ -> json(conn, [])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def reblogged_by(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
def reblogged_by(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||||
with %Activity{} = activity <- Activity.get_by_id_with_object(id),
|
with %Activity{} = activity <- Activity.get_by_id_with_object(id),
|
||||||
|
{:visible, true} <- {:visible, Visibility.visible_for_user?(activity, user)},
|
||||||
%Object{data: %{"announcements" => announces}} <- Object.normalize(activity) do
|
%Object{data: %{"announcements" => announces}} <- Object.normalize(activity) do
|
||||||
q = from(u in User, where: u.ap_id in ^announces)
|
q = from(u in User, where: u.ap_id in ^announces)
|
||||||
|
|
||||||
|
@ -918,6 +921,7 @@ def reblogged_by(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||||
|> put_view(AccountView)
|
|> put_view(AccountView)
|
||||||
|> render("accounts.json", %{for: user, users: users, as: :user})
|
|> render("accounts.json", %{for: user, users: users, as: :user})
|
||||||
else
|
else
|
||||||
|
{:visible, false} -> {:error, :not_found}
|
||||||
_ -> json(conn, [])
|
_ -> json(conn, [])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -956,7 +960,7 @@ def hashtag_timeline(%{assigns: %{user: user}} = conn, params) do
|
||||||
|> Enum.reverse()
|
|> Enum.reverse()
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> add_link_headers(:hashtag_timeline, activities, params["tag"], %{"local" => local_only})
|
|> add_link_headers(activities, %{"local" => local_only})
|
||||||
|> put_view(StatusView)
|
|> put_view(StatusView)
|
||||||
|> render("index.json", %{activities: activities, for: user, as: :activity})
|
|> render("index.json", %{activities: activities, for: user, as: :activity})
|
||||||
end
|
end
|
||||||
|
@ -972,7 +976,7 @@ def followers(%{assigns: %{user: for_user}} = conn, %{"id" => id} = params) do
|
||||||
end
|
end
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> add_link_headers(:followers, followers, user)
|
|> add_link_headers(followers)
|
||||||
|> put_view(AccountView)
|
|> put_view(AccountView)
|
||||||
|> render("accounts.json", %{for: for_user, users: followers, as: :user})
|
|> render("accounts.json", %{for: for_user, users: followers, as: :user})
|
||||||
end
|
end
|
||||||
|
@ -989,7 +993,7 @@ def following(%{assigns: %{user: for_user}} = conn, %{"id" => id} = params) do
|
||||||
end
|
end
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> add_link_headers(:following, followers, user)
|
|> add_link_headers(followers)
|
||||||
|> put_view(AccountView)
|
|> put_view(AccountView)
|
||||||
|> render("accounts.json", %{for: for_user, users: followers, as: :user})
|
|> render("accounts.json", %{for: for_user, users: followers, as: :user})
|
||||||
end
|
end
|
||||||
|
@ -1214,7 +1218,7 @@ def favourites(%{assigns: %{user: user}} = conn, params) do
|
||||||
|> Enum.reverse()
|
|> Enum.reverse()
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> add_link_headers(:favourites, activities)
|
|> add_link_headers(activities)
|
||||||
|> put_view(StatusView)
|
|> put_view(StatusView)
|
||||||
|> render("index.json", %{activities: activities, for: user, as: :activity})
|
|> render("index.json", %{activities: activities, for: user, as: :activity})
|
||||||
end
|
end
|
||||||
|
@ -1241,7 +1245,7 @@ def user_favourites(%{assigns: %{user: for_user}} = conn, %{"id" => id} = params
|
||||||
|> Enum.reverse()
|
|> Enum.reverse()
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> add_link_headers(:favourites, activities)
|
|> add_link_headers(activities)
|
||||||
|> put_view(StatusView)
|
|> put_view(StatusView)
|
||||||
|> render("index.json", %{activities: activities, for: for_user, as: :activity})
|
|> render("index.json", %{activities: activities, for: for_user, as: :activity})
|
||||||
else
|
else
|
||||||
|
@ -1262,7 +1266,7 @@ def bookmarks(%{assigns: %{user: user}} = conn, params) do
|
||||||
|> Enum.map(fn b -> Map.put(b.activity, :bookmark, Map.delete(b, :activity)) end)
|
|> Enum.map(fn b -> Map.put(b.activity, :bookmark, Map.delete(b, :activity)) end)
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> add_link_headers(:bookmarks, bookmarks)
|
|> add_link_headers(bookmarks)
|
||||||
|> put_view(StatusView)
|
|> put_view(StatusView)
|
||||||
|> render("index.json", %{activities: activities, for: user, as: :activity})
|
|> render("index.json", %{activities: activities, for: user, as: :activity})
|
||||||
end
|
end
|
||||||
|
@ -1702,7 +1706,7 @@ def conversations(%{assigns: %{user: user}} = conn, params) do
|
||||||
end)
|
end)
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> add_link_headers(:conversations, participations)
|
|> add_link_headers(participations)
|
||||||
|> json(conversations)
|
|> json(conversations)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do
|
defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do
|
||||||
use Pleroma.Web, :controller
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
import Pleroma.Web.ControllerHelper, only: [add_link_headers: 7]
|
import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2]
|
||||||
|
|
||||||
alias Pleroma.Conversation.Participation
|
alias Pleroma.Conversation.Participation
|
||||||
alias Pleroma.Notification
|
alias Pleroma.Notification
|
||||||
|
@ -28,31 +28,22 @@ def conversation_statuses(
|
||||||
%{assigns: %{user: user}} = conn,
|
%{assigns: %{user: user}} = conn,
|
||||||
%{"id" => participation_id} = params
|
%{"id" => participation_id} = params
|
||||||
) do
|
) do
|
||||||
params =
|
participation = Participation.get(participation_id, preload: [:conversation])
|
||||||
params
|
|
||||||
|> Map.put("blocking_user", user)
|
|
||||||
|> Map.put("muting_user", user)
|
|
||||||
|> Map.put("user", user)
|
|
||||||
|
|
||||||
participation =
|
|
||||||
participation_id
|
|
||||||
|> Participation.get(preload: [:conversation])
|
|
||||||
|
|
||||||
if user.id == participation.user_id do
|
if user.id == participation.user_id do
|
||||||
|
params =
|
||||||
|
params
|
||||||
|
|> Map.put("blocking_user", user)
|
||||||
|
|> Map.put("muting_user", user)
|
||||||
|
|> Map.put("user", user)
|
||||||
|
|
||||||
activities =
|
activities =
|
||||||
participation.conversation.ap_id
|
participation.conversation.ap_id
|
||||||
|> ActivityPub.fetch_activities_for_context(params)
|
|> ActivityPub.fetch_activities_for_context(params)
|
||||||
|> Enum.reverse()
|
|> Enum.reverse()
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> add_link_headers(
|
|> add_link_headers(activities)
|
||||||
:conversation_statuses,
|
|
||||||
activities,
|
|
||||||
participation_id,
|
|
||||||
params,
|
|
||||||
nil,
|
|
||||||
&pleroma_api_url/4
|
|
||||||
)
|
|
||||||
|> put_view(StatusView)
|
|> put_view(StatusView)
|
||||||
|> render("index.json", %{activities: activities, for: user, as: :activity})
|
|> render("index.json", %{activities: activities, for: user, as: :activity})
|
||||||
end
|
end
|
||||||
|
|
|
@ -213,7 +213,11 @@ test "all_by_actor_and_id/2" do
|
||||||
|
|
||||||
assert [] == Activity.all_by_actor_and_id(user, [])
|
assert [] == Activity.all_by_actor_and_id(user, [])
|
||||||
|
|
||||||
assert [%Activity{id: ^id2}, %Activity{id: ^id1}] =
|
activities =
|
||||||
Activity.all_by_actor_and_id(user.ap_id, [id1, id2])
|
user.ap_id
|
||||||
|
|> Activity.all_by_actor_and_id([id1, id2])
|
||||||
|
|> Enum.sort(&(&1.id < &2.id))
|
||||||
|
|
||||||
|
assert [%Activity{id: ^id1}, %Activity{id: ^id2}] = activities
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
defmodule Pleroma.Integration.MastodonWebsocketTest do
|
defmodule Pleroma.Integration.MastodonWebsocketTest do
|
||||||
use Pleroma.DataCase
|
use Pleroma.DataCase
|
||||||
|
|
||||||
|
import ExUnit.CaptureLog
|
||||||
import Pleroma.Factory
|
import Pleroma.Factory
|
||||||
|
|
||||||
alias Pleroma.Integration.WebsocketClient
|
alias Pleroma.Integration.WebsocketClient
|
||||||
|
@ -39,13 +40,17 @@ def start_socket(qs \\ nil, headers \\ []) do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "refuses invalid requests" do
|
test "refuses invalid requests" do
|
||||||
assert {:error, {400, _}} = start_socket()
|
capture_log(fn ->
|
||||||
assert {:error, {404, _}} = start_socket("?stream=ncjdk")
|
assert {:error, {400, _}} = start_socket()
|
||||||
|
assert {:error, {404, _}} = start_socket("?stream=ncjdk")
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "requires authentication and a valid token for protected streams" do
|
test "requires authentication and a valid token for protected streams" do
|
||||||
assert {:error, {403, _}} = start_socket("?stream=user&access_token=aaaaaaaaaaaa")
|
capture_log(fn ->
|
||||||
assert {:error, {403, _}} = start_socket("?stream=user")
|
assert {:error, {403, _}} = start_socket("?stream=user&access_token=aaaaaaaaaaaa")
|
||||||
|
assert {:error, {403, _}} = start_socket("?stream=user")
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "allows public streams without authentication" do
|
test "allows public streams without authentication" do
|
||||||
|
@ -100,19 +105,27 @@ test "accepts valid tokens", state do
|
||||||
|
|
||||||
test "accepts the 'user' stream", %{token: token} = _state do
|
test "accepts the 'user' stream", %{token: token} = _state do
|
||||||
assert {:ok, _} = start_socket("?stream=user&access_token=#{token.token}")
|
assert {:ok, _} = start_socket("?stream=user&access_token=#{token.token}")
|
||||||
assert {:error, {403, "Forbidden"}} = start_socket("?stream=user")
|
|
||||||
|
assert capture_log(fn ->
|
||||||
|
assert {:error, {403, "Forbidden"}} = start_socket("?stream=user")
|
||||||
|
end) =~ ":badarg"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "accepts the 'user:notification' stream", %{token: token} = _state do
|
test "accepts the 'user:notification' stream", %{token: token} = _state do
|
||||||
assert {:ok, _} = start_socket("?stream=user:notification&access_token=#{token.token}")
|
assert {:ok, _} = start_socket("?stream=user:notification&access_token=#{token.token}")
|
||||||
assert {:error, {403, "Forbidden"}} = start_socket("?stream=user:notification")
|
|
||||||
|
assert capture_log(fn ->
|
||||||
|
assert {:error, {403, "Forbidden"}} = start_socket("?stream=user:notification")
|
||||||
|
end) =~ ":badarg"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "accepts valid token on Sec-WebSocket-Protocol header", %{token: token} do
|
test "accepts valid token on Sec-WebSocket-Protocol header", %{token: token} do
|
||||||
assert {:ok, _} = start_socket("?stream=user", [{"Sec-WebSocket-Protocol", token.token}])
|
assert {:ok, _} = start_socket("?stream=user", [{"Sec-WebSocket-Protocol", token.token}])
|
||||||
|
|
||||||
assert {:error, {403, "Forbidden"}} =
|
assert capture_log(fn ->
|
||||||
start_socket("?stream=user", [{"Sec-WebSocket-Protocol", "I am a friend"}])
|
assert {:error, {403, "Forbidden"}} =
|
||||||
|
start_socket("?stream=user", [{"Sec-WebSocket-Protocol", "I am a friend"}])
|
||||||
|
end) =~ ":badarg"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
defmodule Pleroma.Web.ActivityPub.PublisherTest do
|
defmodule Pleroma.Web.ActivityPub.PublisherTest do
|
||||||
use Pleroma.DataCase
|
use Pleroma.DataCase
|
||||||
|
|
||||||
|
import ExUnit.CaptureLog
|
||||||
import Pleroma.Factory
|
import Pleroma.Factory
|
||||||
import Tesla.Mock
|
import Tesla.Mock
|
||||||
import Mock
|
import Mock
|
||||||
|
@ -188,7 +189,10 @@ test "it returns inbox for messages involving single recipients in total" do
|
||||||
actor = insert(:user)
|
actor = insert(:user)
|
||||||
inbox = "http://connrefused.site/users/nick1/inbox"
|
inbox = "http://connrefused.site/users/nick1/inbox"
|
||||||
|
|
||||||
assert {:error, _} = Publisher.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1})
|
assert capture_log(fn ->
|
||||||
|
assert {:error, _} =
|
||||||
|
Publisher.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1})
|
||||||
|
end) =~ "connrefused"
|
||||||
|
|
||||||
assert called(Instances.set_unreachable(inbox))
|
assert called(Instances.set_unreachable(inbox))
|
||||||
end
|
end
|
||||||
|
@ -212,14 +216,16 @@ test "it returns inbox for messages involving single recipients in total" do
|
||||||
actor = insert(:user)
|
actor = insert(:user)
|
||||||
inbox = "http://connrefused.site/users/nick1/inbox"
|
inbox = "http://connrefused.site/users/nick1/inbox"
|
||||||
|
|
||||||
assert {:error, _} =
|
assert capture_log(fn ->
|
||||||
Publisher.publish_one(%{
|
assert {:error, _} =
|
||||||
inbox: inbox,
|
Publisher.publish_one(%{
|
||||||
json: "{}",
|
inbox: inbox,
|
||||||
actor: actor,
|
json: "{}",
|
||||||
id: 1,
|
actor: actor,
|
||||||
unreachable_since: NaiveDateTime.utc_now()
|
id: 1,
|
||||||
})
|
unreachable_since: NaiveDateTime.utc_now()
|
||||||
|
})
|
||||||
|
end) =~ "connrefused"
|
||||||
|
|
||||||
refute called(Instances.set_unreachable(inbox))
|
refute called(Instances.set_unreachable(inbox))
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,6 +10,7 @@ defmodule Pleroma.Web.ActivityPub.RelayTest do
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
alias Pleroma.Web.ActivityPub.Relay
|
alias Pleroma.Web.ActivityPub.Relay
|
||||||
|
|
||||||
|
import ExUnit.CaptureLog
|
||||||
import Pleroma.Factory
|
import Pleroma.Factory
|
||||||
import Mock
|
import Mock
|
||||||
|
|
||||||
|
@ -20,7 +21,9 @@ test "gets an actor for the relay" do
|
||||||
|
|
||||||
describe "follow/1" do
|
describe "follow/1" do
|
||||||
test "returns errors when user not found" do
|
test "returns errors when user not found" do
|
||||||
assert Relay.follow("test-ap-id") == {:error, "Could not fetch by AP id"}
|
assert capture_log(fn ->
|
||||||
|
assert Relay.follow("test-ap-id") == {:error, "Could not fetch by AP id"}
|
||||||
|
end) =~ "Could not fetch by AP id"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "returns activity" do
|
test "returns activity" do
|
||||||
|
@ -37,7 +40,9 @@ test "returns activity" do
|
||||||
|
|
||||||
describe "unfollow/1" do
|
describe "unfollow/1" do
|
||||||
test "returns errors when user not found" do
|
test "returns errors when user not found" do
|
||||||
assert Relay.unfollow("test-ap-id") == {:error, "Could not fetch by AP id"}
|
assert capture_log(fn ->
|
||||||
|
assert Relay.unfollow("test-ap-id") == {:error, "Could not fetch by AP id"}
|
||||||
|
end) =~ "Could not fetch by AP id"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "returns activity" do
|
test "returns activity" do
|
||||||
|
@ -78,7 +83,9 @@ test "returns error when object is unknown" do
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
assert Relay.publish(activity) == {:error, nil}
|
assert capture_log(fn ->
|
||||||
|
assert Relay.publish(activity) == {:error, nil}
|
||||||
|
end) =~ "[error] error: nil"
|
||||||
end
|
end
|
||||||
|
|
||||||
test_with_mock "returns announce activity and publish to federate",
|
test_with_mock "returns announce activity and publish to federate",
|
||||||
|
|
|
@ -3890,7 +3890,7 @@ test "returns 404 when poll is private and not available for user", %{conn: conn
|
||||||
build_conn()
|
build_conn()
|
||||||
|> assign(:user, user)
|
|> assign(:user, user)
|
||||||
|
|
||||||
[conn: conn, activity: activity]
|
[conn: conn, activity: activity, user: user]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "returns users who have favorited the status", %{conn: conn, activity: activity} do
|
test "returns users who have favorited the status", %{conn: conn, activity: activity} do
|
||||||
|
@ -3950,6 +3950,32 @@ test "does not fail on an unauthenticated request", %{conn: conn, activity: acti
|
||||||
[%{"id" => id}] = response
|
[%{"id" => id}] = response
|
||||||
assert id == other_user.id
|
assert id == other_user.id
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "requires authentification for private posts", %{conn: conn, user: user} do
|
||||||
|
other_user = insert(:user)
|
||||||
|
|
||||||
|
{:ok, activity} =
|
||||||
|
CommonAPI.post(user, %{
|
||||||
|
"status" => "@#{other_user.nickname} wanna get some #cofe together?",
|
||||||
|
"visibility" => "direct"
|
||||||
|
})
|
||||||
|
|
||||||
|
{:ok, _, _} = CommonAPI.favorite(activity.id, other_user)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> assign(:user, nil)
|
||||||
|
|> get("/api/v1/statuses/#{activity.id}/favourited_by")
|
||||||
|
|> json_response(404)
|
||||||
|
|
||||||
|
response =
|
||||||
|
build_conn()
|
||||||
|
|> assign(:user, other_user)
|
||||||
|
|> get("/api/v1/statuses/#{activity.id}/favourited_by")
|
||||||
|
|> json_response(200)
|
||||||
|
|
||||||
|
[%{"id" => id}] = response
|
||||||
|
assert id == other_user.id
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "GET /api/v1/statuses/:id/reblogged_by" do
|
describe "GET /api/v1/statuses/:id/reblogged_by" do
|
||||||
|
@ -3961,7 +3987,7 @@ test "does not fail on an unauthenticated request", %{conn: conn, activity: acti
|
||||||
build_conn()
|
build_conn()
|
||||||
|> assign(:user, user)
|
|> assign(:user, user)
|
||||||
|
|
||||||
[conn: conn, activity: activity]
|
[conn: conn, activity: activity, user: user]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "returns users who have reblogged the status", %{conn: conn, activity: activity} do
|
test "returns users who have reblogged the status", %{conn: conn, activity: activity} do
|
||||||
|
@ -4021,6 +4047,29 @@ test "does not fail on an unauthenticated request", %{conn: conn, activity: acti
|
||||||
[%{"id" => id}] = response
|
[%{"id" => id}] = response
|
||||||
assert id == other_user.id
|
assert id == other_user.id
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "requires authentification for private posts", %{conn: conn, user: user} do
|
||||||
|
other_user = insert(:user)
|
||||||
|
|
||||||
|
{:ok, activity} =
|
||||||
|
CommonAPI.post(user, %{
|
||||||
|
"status" => "@#{other_user.nickname} wanna get some #cofe together?",
|
||||||
|
"visibility" => "direct"
|
||||||
|
})
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> assign(:user, nil)
|
||||||
|
|> get("/api/v1/statuses/#{activity.id}/reblogged_by")
|
||||||
|
|> json_response(404)
|
||||||
|
|
||||||
|
response =
|
||||||
|
build_conn()
|
||||||
|
|> assign(:user, other_user)
|
||||||
|
|> get("/api/v1/statuses/#{activity.id}/reblogged_by")
|
||||||
|
|> json_response(200)
|
||||||
|
|
||||||
|
assert [] == response
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "POST /auth/password, with valid parameters" do
|
describe "POST /auth/password, with valid parameters" do
|
||||||
|
@ -4155,13 +4204,15 @@ test "returns error", %{conn: conn, user: user} do
|
||||||
Config.put([:suggestions, :enabled], true)
|
Config.put([:suggestions, :enabled], true)
|
||||||
Config.put([:suggestions, :third_party_engine], "http://test500?{{host}}&{{user}}")
|
Config.put([:suggestions, :third_party_engine], "http://test500?{{host}}&{{user}}")
|
||||||
|
|
||||||
res =
|
assert capture_log(fn ->
|
||||||
conn
|
res =
|
||||||
|> assign(:user, user)
|
conn
|
||||||
|> get("/api/v1/suggestions")
|
|> assign(:user, user)
|
||||||
|> json_response(500)
|
|> get("/api/v1/suggestions")
|
||||||
|
|> json_response(500)
|
||||||
|
|
||||||
assert res == "Something went wrong"
|
assert res == "Something went wrong"
|
||||||
|
end) =~ "Could not retrieve suggestions"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "returns suggestions", %{conn: conn, user: user, other_user: other_user} do
|
test "returns suggestions", %{conn: conn, user: user, other_user: other_user} do
|
||||||
|
|
|
@ -8,6 +8,7 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do
|
||||||
alias Pleroma.Repo
|
alias Pleroma.Repo
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
|
import ExUnit.CaptureLog
|
||||||
import Pleroma.Factory
|
import Pleroma.Factory
|
||||||
import Mock
|
import Mock
|
||||||
|
|
||||||
|
@ -338,12 +339,14 @@ test "show follow page if the `acct` is a account link", %{conn: conn} do
|
||||||
test "show follow page with error when user cannot fecth by `acct` link", %{conn: conn} do
|
test "show follow page with error when user cannot fecth by `acct` link", %{conn: conn} do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
||||||
response =
|
assert capture_log(fn ->
|
||||||
conn
|
response =
|
||||||
|> assign(:user, user)
|
conn
|
||||||
|> get("/ostatus_subscribe?acct=https://mastodon.social/users/not_found")
|
|> assign(:user, user)
|
||||||
|
|> get("/ostatus_subscribe?acct=https://mastodon.social/users/not_found")
|
||||||
|
|
||||||
assert html_response(response, 200) =~ "Error fetching user"
|
assert html_response(response, 200) =~ "Error fetching user"
|
||||||
|
end) =~ "Object has been deleted"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
defmodule Pleroma.Web.WebFinger.WebFingerControllerTest do
|
defmodule Pleroma.Web.WebFinger.WebFingerControllerTest do
|
||||||
use Pleroma.Web.ConnCase
|
use Pleroma.Web.ConnCase
|
||||||
|
|
||||||
|
import ExUnit.CaptureLog
|
||||||
import Pleroma.Factory
|
import Pleroma.Factory
|
||||||
import Tesla.Mock
|
import Tesla.Mock
|
||||||
|
|
||||||
|
@ -75,11 +76,13 @@ test "it returns 404 when user isn't found (XML)" do
|
||||||
test "Sends a 404 when invalid format" do
|
test "Sends a 404 when invalid format" do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
||||||
assert_raise Phoenix.NotAcceptableError, fn ->
|
assert capture_log(fn ->
|
||||||
build_conn()
|
assert_raise Phoenix.NotAcceptableError, fn ->
|
||||||
|> put_req_header("accept", "text/html")
|
build_conn()
|
||||||
|> get("/.well-known/webfinger?resource=acct:#{user.nickname}@localhost")
|
|> put_req_header("accept", "text/html")
|
||||||
end
|
|> get("/.well-known/webfinger?resource=acct:#{user.nickname}@localhost")
|
||||||
|
end
|
||||||
|
end) =~ "no supported media type in accept header"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "Sends a 400 when resource param is missing" do
|
test "Sends a 400 when resource param is missing" do
|
||||||
|
|
Loading…
Reference in a new issue