Add compatibility routes for converted mastodon instances Closes #1797 See merge request pleroma/pleroma!2572fix/http_secury_plug
@@ -15,6 +15,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). | |||
- **Breaking:** removed `with_move` parameter from notifications timeline. | |||
### Added | |||
- ActivityPub: Added support for existing AP ids for instances migrated from Mastodon. | |||
- Instance: Add `background_image` to configuration and `/api/v1/instance` | |||
- Instance: Extend `/api/v1/instance` with Pleroma-specific information. | |||
- NodeInfo: `pleroma:api/v1/notifications:include_types_filter` to the `features` list. | |||
@@ -21,6 +21,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do | |||
alias Pleroma.Web.ActivityPub.UserView | |||
alias Pleroma.Web.ActivityPub.Utils | |||
alias Pleroma.Web.ActivityPub.Visibility | |||
alias Pleroma.Web.Endpoint | |||
alias Pleroma.Web.FederatingPlug | |||
alias Pleroma.Web.Federator | |||
@@ -75,8 +76,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do | |||
end | |||
end | |||
def object(conn, %{"uuid" => uuid}) do | |||
with ap_id <- o_status_url(conn, :object, uuid), | |||
def object(conn, _) do | |||
with ap_id <- Endpoint.url() <> conn.request_path, | |||
%Object{} = object <- Object.get_cached_by_ap_id(ap_id), | |||
{_, true} <- {:public?, Visibility.is_public?(object)} do | |||
conn | |||
@@ -101,8 +102,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do | |||
conn | |||
end | |||
def activity(conn, %{"uuid" => uuid}) do | |||
with ap_id <- o_status_url(conn, :activity, uuid), | |||
def activity(conn, _params) do | |||
with ap_id <- Endpoint.url() <> conn.request_path, | |||
%Activity{} = activity <- Activity.normalize(ap_id), | |||
{_, true} <- {:public?, Visibility.is_public?(activity)} do | |||
conn | |||
@@ -470,6 +470,8 @@ defmodule Pleroma.Web.CommonAPI.Utils do | |||
|> Enum.map(& &1.ap_id) | |||
recipients ++ subscriber_ids | |||
else | |||
_e -> recipients | |||
end | |||
end | |||
@@ -481,6 +483,8 @@ defmodule Pleroma.Web.CommonAPI.Utils do | |||
|> User.get_followers() | |||
|> Enum.map(& &1.ap_id) | |||
|> Enum.concat(recipients) | |||
else | |||
_e -> recipients | |||
end | |||
end | |||
@@ -32,13 +32,13 @@ defmodule Pleroma.Web.OStatus.OStatusController do | |||
action_fallback(:errors) | |||
def object(%{assigns: %{format: format}} = conn, %{"uuid" => _uuid}) | |||
def object(%{assigns: %{format: format}} = conn, _params) | |||
when format in ["json", "activity+json"] do | |||
ActivityPubController.call(conn, :object) | |||
end | |||
def object(%{assigns: %{format: format}} = conn, %{"uuid" => uuid}) do | |||
with id <- o_status_url(conn, :object, uuid), | |||
def object(%{assigns: %{format: format}} = conn, _params) do | |||
with id <- Endpoint.url() <> conn.request_path, | |||
{_, %Activity{} = activity} <- | |||
{:activity, Activity.get_create_by_object_ap_id_with_object(id)}, | |||
{_, true} <- {:public?, Visibility.is_public?(activity)} do | |||
@@ -54,13 +54,13 @@ defmodule Pleroma.Web.OStatus.OStatusController do | |||
end | |||
end | |||
def activity(%{assigns: %{format: format}} = conn, %{"uuid" => _uuid}) | |||
def activity(%{assigns: %{format: format}} = conn, _params) | |||
when format in ["json", "activity+json"] do | |||
ActivityPubController.call(conn, :activity) | |||
end | |||
def activity(%{assigns: %{format: format}} = conn, %{"uuid" => uuid}) do | |||
with id <- o_status_url(conn, :activity, uuid), | |||
def activity(%{assigns: %{format: format}} = conn, _params) do | |||
with id <- Endpoint.url() <> conn.request_path, | |||
{_, %Activity{} = activity} <- {:activity, Activity.normalize(id)}, | |||
{_, true} <- {:public?, Visibility.is_public?(activity)} do | |||
case format do | |||
@@ -556,6 +556,10 @@ defmodule Pleroma.Web.Router do | |||
get("/notice/:id", OStatus.OStatusController, :notice) | |||
get("/notice/:id/embed_player", OStatus.OStatusController, :notice_player) | |||
# Mastodon compatibility routes | |||
get("/users/:nickname/statuses/:id", OStatus.OStatusController, :object) | |||
get("/users/:nickname/statuses/:id/activity", OStatus.OStatusController, :activity) | |||
get("/users/:nickname/feed", Feed.UserController, :feed, as: :user_feed) | |||
get("/users/:nickname", Feed.UserController, :feed_redirect, as: :user_feed) | |||
@@ -6,7 +6,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do | |||
use Pleroma.Web.ConnCase | |||
use Oban.Testing, repo: Pleroma.Repo | |||
import Pleroma.Factory | |||
alias Pleroma.Activity | |||
alias Pleroma.Config | |||
alias Pleroma.Delivery | |||
@@ -14,13 +13,19 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do | |||
alias Pleroma.Object | |||
alias Pleroma.Tests.ObanHelpers | |||
alias Pleroma.User | |||
alias Pleroma.Web.ActivityPub.ActivityPub | |||
alias Pleroma.Web.ActivityPub.ObjectView | |||
alias Pleroma.Web.ActivityPub.Relay | |||
alias Pleroma.Web.ActivityPub.UserView | |||
alias Pleroma.Web.ActivityPub.Utils | |||
alias Pleroma.Web.CommonAPI | |||
alias Pleroma.Web.Endpoint | |||
alias Pleroma.Workers.ReceiverWorker | |||
import Pleroma.Factory | |||
require Pleroma.Constants | |||
setup_all do | |||
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) | |||
:ok | |||
@@ -168,6 +173,60 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do | |||
end | |||
end | |||
describe "mastodon compatibility routes" do | |||
test "it returns a json representation of the object with accept application/json", %{ | |||
conn: conn | |||
} do | |||
{:ok, object} = | |||
%{ | |||
"type" => "Note", | |||
"content" => "hey", | |||
"id" => Endpoint.url() <> "/users/raymoo/statuses/999999999", | |||
"actor" => Endpoint.url() <> "/users/raymoo", | |||
"to" => [Pleroma.Constants.as_public()] | |||
} | |||
|> Object.create() | |||
conn = | |||
conn | |||
|> put_req_header("accept", "application/json") | |||
|> get("/users/raymoo/statuses/999999999") | |||
assert json_response(conn, 200) == ObjectView.render("object.json", %{object: object}) | |||
end | |||
test "it returns a json representation of the activity with accept application/json", %{ | |||
conn: conn | |||
} do | |||
{:ok, object} = | |||
%{ | |||
"type" => "Note", | |||
"content" => "hey", | |||
"id" => Endpoint.url() <> "/users/raymoo/statuses/999999999", | |||
"actor" => Endpoint.url() <> "/users/raymoo", | |||
"to" => [Pleroma.Constants.as_public()] | |||
} | |||
|> Object.create() | |||
{:ok, activity, _} = | |||
%{ | |||
"id" => object.data["id"] <> "/activity", | |||
"type" => "Create", | |||
"object" => object.data["id"], | |||
"actor" => object.data["actor"], | |||
"to" => object.data["to"] | |||
} | |||
|> ActivityPub.persist(local: true) | |||
conn = | |||
conn | |||
|> put_req_header("accept", "application/json") | |||
|> get("/users/raymoo/statuses/999999999/activity") | |||
assert json_response(conn, 200) == ObjectView.render("object.json", %{object: activity}) | |||
end | |||
end | |||
describe "/objects/:uuid" do | |||
test "it returns a json representation of the object with accept application/json", %{ | |||
conn: conn | |||
@@ -10,7 +10,11 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do | |||
alias Pleroma.Config | |||
alias Pleroma.Object | |||
alias Pleroma.User | |||
alias Pleroma.Web.ActivityPub.ActivityPub | |||
alias Pleroma.Web.CommonAPI | |||
alias Pleroma.Web.Endpoint | |||
require Pleroma.Constants | |||
setup_all do | |||
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) | |||
@@ -19,6 +23,47 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do | |||
setup do: clear_config([:instance, :federating], true) | |||
describe "Mastodon compatibility routes" do | |||
setup %{conn: conn} do | |||
conn = put_req_header(conn, "accept", "text/html") | |||
{:ok, object} = | |||
%{ | |||
"type" => "Note", | |||
"content" => "hey", | |||
"id" => Endpoint.url() <> "/users/raymoo/statuses/999999999", | |||
"actor" => Endpoint.url() <> "/users/raymoo", | |||
"to" => [Pleroma.Constants.as_public()] | |||
} | |||
|> Object.create() | |||
{:ok, activity, _} = | |||
%{ | |||
"id" => object.data["id"] <> "/activity", | |||
"type" => "Create", | |||
"object" => object.data["id"], | |||
"actor" => object.data["actor"], | |||
"to" => object.data["to"] | |||
} | |||
|> ActivityPub.persist(local: true) | |||
%{conn: conn, activity: activity} | |||
end | |||
test "redirects to /notice/:id for html format", %{conn: conn, activity: activity} do | |||
conn = get(conn, "/users/raymoo/statuses/999999999") | |||
assert redirected_to(conn) == "/notice/#{activity.id}" | |||
end | |||
test "redirects to /notice/:id for html format for activity", %{ | |||
conn: conn, | |||
activity: activity | |||
} do | |||
conn = get(conn, "/users/raymoo/statuses/999999999/activity") | |||
assert redirected_to(conn) == "/notice/#{activity.id}" | |||
end | |||
end | |||
# Note: see ActivityPubControllerTest for JSON format tests | |||
describe "GET /objects/:uuid (text/html)" do | |||
setup %{conn: conn} do | |||