Merge branch '1560-non-federating-instances-routes-restrictions' into 'develop'
[#1560] Restricted AP- & OStatus-related routes for non-federating instances Closes #1560 See merge request pleroma/pleroma!2235
This commit is contained in:
commit
fa4ec17c84
|
@ -180,7 +180,7 @@ Post here request with grant_type=refresh_token to obtain new access token. Retu
|
||||||
## Account Registration
|
## Account Registration
|
||||||
`POST /api/v1/accounts`
|
`POST /api/v1/accounts`
|
||||||
|
|
||||||
Has theses additionnal parameters (which are the same as in Pleroma-API):
|
Has theses additional parameters (which are the same as in Pleroma-API):
|
||||||
* `fullname`: optional
|
* `fullname`: optional
|
||||||
* `bio`: optional
|
* `bio`: optional
|
||||||
* `captcha_solution`: optional, contains provider-specific captcha solution,
|
* `captcha_solution`: optional, contains provider-specific captcha solution,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Pleroma Clients
|
# Pleroma Clients
|
||||||
Note: Additionnal clients may be working but theses are officially supporting Pleroma.
|
Note: Additional clients may be working but theses are officially supporting Pleroma.
|
||||||
Feel free to contact us to be added to this list!
|
Feel free to contact us to be added to this list!
|
||||||
|
|
||||||
## Desktop
|
## Desktop
|
||||||
|
|
|
@ -15,9 +15,24 @@ def call(%{assigns: %{user: %User{}}} = conn, _) do
|
||||||
conn
|
conn
|
||||||
end
|
end
|
||||||
|
|
||||||
def call(conn, _) do
|
def call(conn, options) do
|
||||||
|
perform =
|
||||||
|
cond do
|
||||||
|
options[:if_func] -> options[:if_func].()
|
||||||
|
options[:unless_func] -> !options[:unless_func].()
|
||||||
|
true -> true
|
||||||
|
end
|
||||||
|
|
||||||
|
if perform do
|
||||||
|
fail(conn)
|
||||||
|
else
|
||||||
|
conn
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def fail(conn) do
|
||||||
conn
|
conn
|
||||||
|> render_error(:forbidden, "Invalid credentials.")
|
|> render_error(:forbidden, "Invalid credentials.")
|
||||||
|> halt
|
|> halt()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,14 +10,20 @@ def init(options) do
|
||||||
end
|
end
|
||||||
|
|
||||||
def call(conn, _opts) do
|
def call(conn, _opts) do
|
||||||
if Pleroma.Config.get([:instance, :federating]) do
|
if federating?() do
|
||||||
conn
|
conn
|
||||||
else
|
else
|
||||||
conn
|
fail(conn)
|
||||||
|> put_status(404)
|
|
||||||
|> Phoenix.Controller.put_view(Pleroma.Web.ErrorView)
|
|
||||||
|> Phoenix.Controller.render("404.json")
|
|
||||||
|> halt()
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def federating?, do: Pleroma.Config.get([:instance, :federating])
|
||||||
|
|
||||||
|
defp fail(conn) do
|
||||||
|
conn
|
||||||
|
|> put_status(404)
|
||||||
|
|> Phoenix.Controller.put_view(Pleroma.Web.ErrorView)
|
||||||
|
|> Phoenix.Controller.render("404.json")
|
||||||
|
|> halt()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,6 +9,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
|
||||||
alias Pleroma.Delivery
|
alias Pleroma.Delivery
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
alias Pleroma.Object.Fetcher
|
alias Pleroma.Object.Fetcher
|
||||||
|
alias Pleroma.Plugs.EnsureAuthenticatedPlug
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
alias Pleroma.Web.ActivityPub.InternalFetchActor
|
alias Pleroma.Web.ActivityPub.InternalFetchActor
|
||||||
|
@ -18,23 +19,37 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
|
||||||
alias Pleroma.Web.ActivityPub.UserView
|
alias Pleroma.Web.ActivityPub.UserView
|
||||||
alias Pleroma.Web.ActivityPub.Utils
|
alias Pleroma.Web.ActivityPub.Utils
|
||||||
alias Pleroma.Web.ActivityPub.Visibility
|
alias Pleroma.Web.ActivityPub.Visibility
|
||||||
|
alias Pleroma.Web.FederatingPlug
|
||||||
alias Pleroma.Web.Federator
|
alias Pleroma.Web.Federator
|
||||||
|
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
action_fallback(:errors)
|
action_fallback(:errors)
|
||||||
|
|
||||||
|
@federating_only_actions [:internal_fetch, :relay, :relay_following, :relay_followers]
|
||||||
|
|
||||||
|
plug(FederatingPlug when action in @federating_only_actions)
|
||||||
|
|
||||||
|
plug(
|
||||||
|
EnsureAuthenticatedPlug,
|
||||||
|
[unless_func: &FederatingPlug.federating?/0] when action not in @federating_only_actions
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(
|
||||||
|
EnsureAuthenticatedPlug
|
||||||
|
when action in [:read_inbox, :update_outbox, :whoami, :upload_media, :following, :followers]
|
||||||
|
)
|
||||||
|
|
||||||
plug(
|
plug(
|
||||||
Pleroma.Plugs.Cache,
|
Pleroma.Plugs.Cache,
|
||||||
[query_params: false, tracking_fun: &__MODULE__.track_object_fetch/2]
|
[query_params: false, tracking_fun: &__MODULE__.track_object_fetch/2]
|
||||||
when action in [:activity, :object]
|
when action in [:activity, :object]
|
||||||
)
|
)
|
||||||
|
|
||||||
plug(Pleroma.Web.FederatingPlug when action in [:inbox, :relay])
|
|
||||||
plug(:set_requester_reachable when action in [:inbox])
|
plug(:set_requester_reachable when action in [:inbox])
|
||||||
plug(:relay_active? when action in [:relay])
|
plug(:relay_active? when action in [:relay])
|
||||||
|
|
||||||
def relay_active?(conn, _) do
|
defp relay_active?(conn, _) do
|
||||||
if Pleroma.Config.get([:instance, :allow_relay]) do
|
if Pleroma.Config.get([:instance, :allow_relay]) do
|
||||||
conn
|
conn
|
||||||
else
|
else
|
||||||
|
@ -127,11 +142,13 @@ defp set_cache_ttl_for(conn, entity) do
|
||||||
end
|
end
|
||||||
|
|
||||||
# GET /relay/following
|
# GET /relay/following
|
||||||
def following(%{assigns: %{relay: true}} = conn, _params) do
|
def relay_following(conn, _params) do
|
||||||
conn
|
with %{halted: false} = conn <- FederatingPlug.call(conn, []) do
|
||||||
|> put_resp_content_type("application/activity+json")
|
conn
|
||||||
|> put_view(UserView)
|
|> put_resp_content_type("application/activity+json")
|
||||||
|> render("following.json", %{user: Relay.get_actor()})
|
|> put_view(UserView)
|
||||||
|
|> render("following.json", %{user: Relay.get_actor()})
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def following(%{assigns: %{user: for_user}} = conn, %{"nickname" => nickname, "page" => page}) do
|
def following(%{assigns: %{user: for_user}} = conn, %{"nickname" => nickname, "page" => page}) do
|
||||||
|
@ -164,11 +181,13 @@ def following(%{assigns: %{user: for_user}} = conn, %{"nickname" => nickname}) d
|
||||||
end
|
end
|
||||||
|
|
||||||
# GET /relay/followers
|
# GET /relay/followers
|
||||||
def followers(%{assigns: %{relay: true}} = conn, _params) do
|
def relay_followers(conn, _params) do
|
||||||
conn
|
with %{halted: false} = conn <- FederatingPlug.call(conn, []) do
|
||||||
|> put_resp_content_type("application/activity+json")
|
conn
|
||||||
|> put_view(UserView)
|
|> put_resp_content_type("application/activity+json")
|
||||||
|> render("followers.json", %{user: Relay.get_actor()})
|
|> put_view(UserView)
|
||||||
|
|> render("followers.json", %{user: Relay.get_actor()})
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def followers(%{assigns: %{user: for_user}} = conn, %{"nickname" => nickname, "page" => page}) do
|
def followers(%{assigns: %{user: for_user}} = conn, %{"nickname" => nickname, "page" => page}) do
|
||||||
|
@ -200,13 +219,16 @@ def followers(%{assigns: %{user: for_user}} = conn, %{"nickname" => nickname}) d
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def outbox(conn, %{"nickname" => nickname, "page" => page?} = params)
|
def outbox(
|
||||||
|
%{assigns: %{user: for_user}} = conn,
|
||||||
|
%{"nickname" => nickname, "page" => page?} = params
|
||||||
|
)
|
||||||
when page? in [true, "true"] do
|
when page? in [true, "true"] do
|
||||||
with %User{} = user <- User.get_cached_by_nickname(nickname),
|
with %User{} = user <- User.get_cached_by_nickname(nickname),
|
||||||
{:ok, user} <- User.ensure_keys_present(user) do
|
{:ok, user} <- User.ensure_keys_present(user) do
|
||||||
activities =
|
activities =
|
||||||
if params["max_id"] do
|
if params["max_id"] do
|
||||||
ActivityPub.fetch_user_activities(user, nil, %{
|
ActivityPub.fetch_user_activities(user, for_user, %{
|
||||||
"max_id" => params["max_id"],
|
"max_id" => params["max_id"],
|
||||||
# This is a hack because postgres generates inefficient queries when filtering by
|
# This is a hack because postgres generates inefficient queries when filtering by
|
||||||
# 'Answer', poll votes will be hidden by the visibility filter in this case anyway
|
# 'Answer', poll votes will be hidden by the visibility filter in this case anyway
|
||||||
|
@ -214,7 +236,7 @@ def outbox(conn, %{"nickname" => nickname, "page" => page?} = params)
|
||||||
"limit" => 10
|
"limit" => 10
|
||||||
})
|
})
|
||||||
else
|
else
|
||||||
ActivityPub.fetch_user_activities(user, nil, %{
|
ActivityPub.fetch_user_activities(user, for_user, %{
|
||||||
"limit" => 10,
|
"limit" => 10,
|
||||||
"include_poll_votes" => true
|
"include_poll_votes" => true
|
||||||
})
|
})
|
||||||
|
@ -255,8 +277,16 @@ def inbox(%{assigns: %{valid_signature: true}} = conn, params) do
|
||||||
json(conn, "ok")
|
json(conn, "ok")
|
||||||
end
|
end
|
||||||
|
|
||||||
# only accept relayed Creates
|
# POST /relay/inbox -or- POST /internal/fetch/inbox
|
||||||
def inbox(conn, %{"type" => "Create"} = params) do
|
def inbox(conn, params) do
|
||||||
|
if params["type"] == "Create" && FederatingPlug.federating?() do
|
||||||
|
post_inbox_relayed_create(conn, params)
|
||||||
|
else
|
||||||
|
post_inbox_fallback(conn, params)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp post_inbox_relayed_create(conn, params) do
|
||||||
Logger.debug(
|
Logger.debug(
|
||||||
"Signature missing or not from author, relayed Create message, fetching object from source"
|
"Signature missing or not from author, relayed Create message, fetching object from source"
|
||||||
)
|
)
|
||||||
|
@ -266,10 +296,11 @@ def inbox(conn, %{"type" => "Create"} = params) do
|
||||||
json(conn, "ok")
|
json(conn, "ok")
|
||||||
end
|
end
|
||||||
|
|
||||||
def inbox(conn, params) do
|
defp post_inbox_fallback(conn, params) do
|
||||||
headers = Enum.into(conn.req_headers, %{})
|
headers = Enum.into(conn.req_headers, %{})
|
||||||
|
|
||||||
if String.contains?(headers["signature"], params["actor"]) do
|
if headers["signature"] && params["actor"] &&
|
||||||
|
String.contains?(headers["signature"], params["actor"]) do
|
||||||
Logger.debug(
|
Logger.debug(
|
||||||
"Signature validation error for: #{params["actor"]}, make sure you are forwarding the HTTP Host header!"
|
"Signature validation error for: #{params["actor"]}, make sure you are forwarding the HTTP Host header!"
|
||||||
)
|
)
|
||||||
|
@ -277,7 +308,9 @@ def inbox(conn, params) do
|
||||||
Logger.debug(inspect(conn.req_headers))
|
Logger.debug(inspect(conn.req_headers))
|
||||||
end
|
end
|
||||||
|
|
||||||
json(conn, dgettext("errors", "error"))
|
conn
|
||||||
|
|> put_status(:bad_request)
|
||||||
|
|> json(dgettext("errors", "error"))
|
||||||
end
|
end
|
||||||
|
|
||||||
defp represent_service_actor(%User{} = user, conn) do
|
defp represent_service_actor(%User{} = user, conn) do
|
||||||
|
@ -311,10 +344,8 @@ def whoami(%{assigns: %{user: %User{} = user}} = conn, _params) do
|
||||||
|> render("user.json", %{user: user})
|
|> render("user.json", %{user: user})
|
||||||
end
|
end
|
||||||
|
|
||||||
def whoami(_conn, _params), do: {:error, :not_found}
|
|
||||||
|
|
||||||
def read_inbox(
|
def read_inbox(
|
||||||
%{assigns: %{user: %{nickname: nickname} = user}} = conn,
|
%{assigns: %{user: %User{nickname: nickname} = user}} = conn,
|
||||||
%{"nickname" => nickname, "page" => page?} = params
|
%{"nickname" => nickname, "page" => page?} = params
|
||||||
)
|
)
|
||||||
when page? in [true, "true"] do
|
when page? in [true, "true"] do
|
||||||
|
@ -337,7 +368,7 @@ def read_inbox(
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
def read_inbox(%{assigns: %{user: %{nickname: nickname} = user}} = conn, %{
|
def read_inbox(%{assigns: %{user: %User{nickname: nickname} = user}} = conn, %{
|
||||||
"nickname" => nickname
|
"nickname" => nickname
|
||||||
}) do
|
}) do
|
||||||
with {:ok, user} <- User.ensure_keys_present(user) do
|
with {:ok, user} <- User.ensure_keys_present(user) do
|
||||||
|
@ -348,15 +379,7 @@ def read_inbox(%{assigns: %{user: %{nickname: nickname} = user}} = conn, %{
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def read_inbox(%{assigns: %{user: nil}} = conn, %{"nickname" => nickname}) do
|
def read_inbox(%{assigns: %{user: %User{nickname: as_nickname}}} = conn, %{
|
||||||
err = dgettext("errors", "can't read inbox of %{nickname}", nickname: nickname)
|
|
||||||
|
|
||||||
conn
|
|
||||||
|> put_status(:forbidden)
|
|
||||||
|> json(err)
|
|
||||||
end
|
|
||||||
|
|
||||||
def read_inbox(%{assigns: %{user: %{nickname: as_nickname}}} = conn, %{
|
|
||||||
"nickname" => nickname
|
"nickname" => nickname
|
||||||
}) do
|
}) do
|
||||||
err =
|
err =
|
||||||
|
@ -370,7 +393,7 @@ def read_inbox(%{assigns: %{user: %{nickname: as_nickname}}} = conn, %{
|
||||||
|> json(err)
|
|> json(err)
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_user_activity(user, %{"type" => "Create"} = params) do
|
defp handle_user_activity(%User{} = user, %{"type" => "Create"} = params) do
|
||||||
object =
|
object =
|
||||||
params["object"]
|
params["object"]
|
||||||
|> Map.merge(Map.take(params, ["to", "cc"]))
|
|> Map.merge(Map.take(params, ["to", "cc"]))
|
||||||
|
@ -386,7 +409,7 @@ def handle_user_activity(user, %{"type" => "Create"} = params) do
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_user_activity(user, %{"type" => "Delete"} = params) do
|
defp handle_user_activity(%User{} = user, %{"type" => "Delete"} = params) do
|
||||||
with %Object{} = object <- Object.normalize(params["object"]),
|
with %Object{} = object <- Object.normalize(params["object"]),
|
||||||
true <- user.is_moderator || user.ap_id == object.data["actor"],
|
true <- user.is_moderator || user.ap_id == object.data["actor"],
|
||||||
{:ok, delete} <- ActivityPub.delete(object) do
|
{:ok, delete} <- ActivityPub.delete(object) do
|
||||||
|
@ -396,7 +419,7 @@ def handle_user_activity(user, %{"type" => "Delete"} = params) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_user_activity(user, %{"type" => "Like"} = params) do
|
defp handle_user_activity(%User{} = user, %{"type" => "Like"} = params) do
|
||||||
with %Object{} = object <- Object.normalize(params["object"]),
|
with %Object{} = object <- Object.normalize(params["object"]),
|
||||||
{:ok, activity, _object} <- ActivityPub.like(user, object) do
|
{:ok, activity, _object} <- ActivityPub.like(user, object) do
|
||||||
{:ok, activity}
|
{:ok, activity}
|
||||||
|
@ -405,7 +428,7 @@ def handle_user_activity(user, %{"type" => "Like"} = params) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_user_activity(_, _) do
|
defp handle_user_activity(_, _) do
|
||||||
{:error, dgettext("errors", "Unhandled activity type")}
|
{:error, dgettext("errors", "Unhandled activity type")}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -434,7 +457,7 @@ def update_outbox(
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_outbox(%{assigns: %{user: user}} = conn, %{"nickname" => nickname} = _) do
|
def update_outbox(%{assigns: %{user: %User{} = user}} = conn, %{"nickname" => nickname}) do
|
||||||
err =
|
err =
|
||||||
dgettext("errors", "can't update outbox of %{nickname} as %{as_nickname}",
|
dgettext("errors", "can't update outbox of %{nickname} as %{as_nickname}",
|
||||||
nickname: nickname,
|
nickname: nickname,
|
||||||
|
@ -446,13 +469,13 @@ def update_outbox(%{assigns: %{user: user}} = conn, %{"nickname" => nickname} =
|
||||||
|> json(err)
|
|> json(err)
|
||||||
end
|
end
|
||||||
|
|
||||||
def errors(conn, {:error, :not_found}) do
|
defp errors(conn, {:error, :not_found}) do
|
||||||
conn
|
conn
|
||||||
|> put_status(:not_found)
|
|> put_status(:not_found)
|
||||||
|> json(dgettext("errors", "Not found"))
|
|> json(dgettext("errors", "Not found"))
|
||||||
end
|
end
|
||||||
|
|
||||||
def errors(conn, _e) do
|
defp errors(conn, _e) do
|
||||||
conn
|
conn
|
||||||
|> put_status(:internal_server_error)
|
|> put_status(:internal_server_error)
|
||||||
|> json(dgettext("errors", "error"))
|
|> json(dgettext("errors", "error"))
|
||||||
|
@ -492,7 +515,7 @@ defp ensure_user_keys_present_and_maybe_refresh_for_user(user, for_user) do
|
||||||
- HTTP Code: 201 Created
|
- HTTP Code: 201 Created
|
||||||
- HTTP Body: ActivityPub object to be inserted into another's `attachment` field
|
- HTTP Body: ActivityPub object to be inserted into another's `attachment` field
|
||||||
"""
|
"""
|
||||||
def upload_media(%{assigns: %{user: user}} = conn, %{"file" => file} = data) do
|
def upload_media(%{assigns: %{user: %User{} = user}} = conn, %{"file" => file} = data) do
|
||||||
with {:ok, object} <-
|
with {:ok, object} <-
|
||||||
ActivityPub.upload(
|
ActivityPub.upload(
|
||||||
file,
|
file,
|
||||||
|
|
|
@ -25,7 +25,12 @@ def feed_redirect(%{assigns: %{format: "html"}} = conn, %{"nickname" => nickname
|
||||||
|
|
||||||
def feed_redirect(%{assigns: %{format: format}} = conn, _params)
|
def feed_redirect(%{assigns: %{format: format}} = conn, _params)
|
||||||
when format in ["json", "activity+json"] do
|
when format in ["json", "activity+json"] do
|
||||||
ActivityPubController.call(conn, :user)
|
with %{halted: false} = conn <-
|
||||||
|
Pleroma.Plugs.EnsureAuthenticatedPlug.call(conn,
|
||||||
|
unless_func: &Pleroma.Web.FederatingPlug.federating?/0
|
||||||
|
) do
|
||||||
|
ActivityPubController.call(conn, :user)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def feed_redirect(conn, %{"nickname" => nickname}) do
|
def feed_redirect(conn, %{"nickname" => nickname}) do
|
||||||
|
|
|
@ -16,6 +16,10 @@ defmodule Pleroma.Web.OStatus.OStatusController do
|
||||||
alias Pleroma.Web.Metadata.PlayerView
|
alias Pleroma.Web.Metadata.PlayerView
|
||||||
alias Pleroma.Web.Router
|
alias Pleroma.Web.Router
|
||||||
|
|
||||||
|
plug(Pleroma.Plugs.EnsureAuthenticatedPlug,
|
||||||
|
unless_func: &Pleroma.Web.FederatingPlug.federating?/0
|
||||||
|
)
|
||||||
|
|
||||||
plug(
|
plug(
|
||||||
RateLimiter,
|
RateLimiter,
|
||||||
[name: :ap_routes, params: ["uuid"]] when action in [:object, :activity]
|
[name: :ap_routes, params: ["uuid"]] when action in [:object, :activity]
|
||||||
|
@ -135,13 +139,13 @@ def notice_player(conn, %{"id" => id}) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def errors(conn, {:error, :not_found}) do
|
defp errors(conn, {:error, :not_found}) do
|
||||||
render_error(conn, :not_found, "Not found")
|
render_error(conn, :not_found, "Not found")
|
||||||
end
|
end
|
||||||
|
|
||||||
def errors(conn, {:fetch_user, nil}), do: errors(conn, {:error, :not_found})
|
defp errors(conn, {:fetch_user, nil}), do: errors(conn, {:error, :not_found})
|
||||||
|
|
||||||
def errors(conn, _) do
|
defp errors(conn, _) do
|
||||||
render_error(conn, :internal_server_error, "Something went wrong")
|
render_error(conn, :internal_server_error, "Something went wrong")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -541,6 +541,7 @@ defmodule Pleroma.Web.Router do
|
||||||
get("/mailer/unsubscribe/:token", Mailer.SubscriptionController, :unsubscribe)
|
get("/mailer/unsubscribe/:token", Mailer.SubscriptionController, :unsubscribe)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Server to Server (S2S) AP interactions
|
||||||
pipeline :activitypub do
|
pipeline :activitypub do
|
||||||
plug(:accepts, ["activity+json", "json"])
|
plug(:accepts, ["activity+json", "json"])
|
||||||
plug(Pleroma.Web.Plugs.HTTPSignaturePlug)
|
plug(Pleroma.Web.Plugs.HTTPSignaturePlug)
|
||||||
|
@ -554,6 +555,7 @@ defmodule Pleroma.Web.Router do
|
||||||
get("/users/:nickname/outbox", ActivityPubController, :outbox)
|
get("/users/:nickname/outbox", ActivityPubController, :outbox)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Client to Server (C2S) AP interactions
|
||||||
pipeline :activitypub_client do
|
pipeline :activitypub_client do
|
||||||
plug(:accepts, ["activity+json", "json"])
|
plug(:accepts, ["activity+json", "json"])
|
||||||
plug(:fetch_session)
|
plug(:fetch_session)
|
||||||
|
@ -597,8 +599,8 @@ defmodule Pleroma.Web.Router do
|
||||||
post("/inbox", ActivityPubController, :inbox)
|
post("/inbox", ActivityPubController, :inbox)
|
||||||
end
|
end
|
||||||
|
|
||||||
get("/following", ActivityPubController, :following, assigns: %{relay: true})
|
get("/following", ActivityPubController, :relay_following)
|
||||||
get("/followers", ActivityPubController, :followers, assigns: %{relay: true})
|
get("/followers", ActivityPubController, :relay_followers)
|
||||||
end
|
end
|
||||||
|
|
||||||
scope "/internal/fetch", Pleroma.Web.ActivityPub do
|
scope "/internal/fetch", Pleroma.Web.ActivityPub do
|
||||||
|
|
|
@ -17,6 +17,10 @@ defmodule Pleroma.Web.StaticFE.StaticFEController do
|
||||||
plug(:put_view, Pleroma.Web.StaticFE.StaticFEView)
|
plug(:put_view, Pleroma.Web.StaticFE.StaticFEView)
|
||||||
plug(:assign_id)
|
plug(:assign_id)
|
||||||
|
|
||||||
|
plug(Pleroma.Plugs.EnsureAuthenticatedPlug,
|
||||||
|
unless_func: &Pleroma.Web.FederatingPlug.federating?/0
|
||||||
|
)
|
||||||
|
|
||||||
@page_keys ["max_id", "min_id", "limit", "since_id", "order"]
|
@page_keys ["max_id", "min_id", "limit", "since_id", "order"]
|
||||||
|
|
||||||
defp get_title(%Object{data: %{"name" => name}}) when is_binary(name),
|
defp get_title(%Object{data: %{"name" => name}}) when is_binary(name),
|
||||||
|
@ -33,7 +37,7 @@ defp not_found(conn, message) do
|
||||||
|> render("error.html", %{message: message, meta: ""})
|
|> render("error.html", %{message: message, meta: ""})
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_counts(%Activity{} = activity) do
|
defp get_counts(%Activity{} = activity) do
|
||||||
%Object{data: data} = Object.normalize(activity)
|
%Object{data: data} = Object.normalize(activity)
|
||||||
|
|
||||||
%{
|
%{
|
||||||
|
@ -43,9 +47,9 @@ def get_counts(%Activity{} = activity) do
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def represent(%Activity{} = activity), do: represent(activity, false)
|
defp represent(%Activity{} = activity), do: represent(activity, false)
|
||||||
|
|
||||||
def represent(%Activity{object: %Object{data: data}} = activity, selected) do
|
defp represent(%Activity{object: %Object{data: data}} = activity, selected) do
|
||||||
{:ok, user} = User.get_or_fetch(activity.object.data["actor"])
|
{:ok, user} = User.get_or_fetch(activity.object.data["actor"])
|
||||||
|
|
||||||
link =
|
link =
|
||||||
|
@ -147,17 +151,17 @@ def show(%{assigns: %{activity_id: _}} = conn, _params) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def assign_id(%{path_info: ["notice", notice_id]} = conn, _opts),
|
defp assign_id(%{path_info: ["notice", notice_id]} = conn, _opts),
|
||||||
do: assign(conn, :notice_id, notice_id)
|
do: assign(conn, :notice_id, notice_id)
|
||||||
|
|
||||||
def assign_id(%{path_info: ["users", user_id]} = conn, _opts),
|
defp assign_id(%{path_info: ["users", user_id]} = conn, _opts),
|
||||||
do: assign(conn, :username_or_id, user_id)
|
do: assign(conn, :username_or_id, user_id)
|
||||||
|
|
||||||
def assign_id(%{path_info: ["objects", object_id]} = conn, _opts),
|
defp assign_id(%{path_info: ["objects", object_id]} = conn, _opts),
|
||||||
do: assign(conn, :object_id, object_id)
|
do: assign(conn, :object_id, object_id)
|
||||||
|
|
||||||
def assign_id(%{path_info: ["activities", activity_id]} = conn, _opts),
|
defp assign_id(%{path_info: ["activities", activity_id]} = conn, _opts),
|
||||||
do: assign(conn, :activity_id, activity_id)
|
do: assign(conn, :activity_id, activity_id)
|
||||||
|
|
||||||
def assign_id(conn, _opts), do: conn
|
defp assign_id(conn, _opts), do: conn
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,6 +16,8 @@ defmodule Pleroma.Web.TwitterAPI.RemoteFollowController do
|
||||||
|
|
||||||
@status_types ["Article", "Event", "Note", "Video", "Page", "Question"]
|
@status_types ["Article", "Event", "Note", "Video", "Page", "Question"]
|
||||||
|
|
||||||
|
plug(Pleroma.Web.FederatingPlug)
|
||||||
|
|
||||||
# Note: follower can submit the form (with password auth) not being signed in (having no token)
|
# Note: follower can submit the form (with password auth) not being signed in (having no token)
|
||||||
plug(
|
plug(
|
||||||
OAuthScopesPlug,
|
OAuthScopesPlug,
|
||||||
|
|
|
@ -17,6 +17,8 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
alias Pleroma.Web.WebFinger
|
alias Pleroma.Web.WebFinger
|
||||||
|
|
||||||
|
plug(Pleroma.Web.FederatingPlug when action == :remote_subscribe)
|
||||||
|
|
||||||
plug(
|
plug(
|
||||||
OAuthScopesPlug,
|
OAuthScopesPlug,
|
||||||
%{scopes: ["follow", "write:follows"]}
|
%{scopes: ["follow", "write:follows"]}
|
||||||
|
|
|
@ -8,24 +8,62 @@ defmodule Pleroma.Plugs.EnsureAuthenticatedPlugTest do
|
||||||
alias Pleroma.Plugs.EnsureAuthenticatedPlug
|
alias Pleroma.Plugs.EnsureAuthenticatedPlug
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
|
|
||||||
test "it halts if no user is assigned", %{conn: conn} do
|
describe "without :if_func / :unless_func options" do
|
||||||
conn =
|
test "it halts if user is NOT assigned", %{conn: conn} do
|
||||||
conn
|
conn = EnsureAuthenticatedPlug.call(conn, %{})
|
||||||
|> EnsureAuthenticatedPlug.call(%{})
|
|
||||||
|
|
||||||
assert conn.status == 403
|
assert conn.status == 403
|
||||||
assert conn.halted == true
|
assert conn.halted == true
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it continues if a user is assigned", %{conn: conn} do
|
||||||
|
conn = assign(conn, :user, %User{})
|
||||||
|
ret_conn = EnsureAuthenticatedPlug.call(conn, %{})
|
||||||
|
|
||||||
|
assert ret_conn == conn
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it continues if a user is assigned", %{conn: conn} do
|
describe "with :if_func / :unless_func options" do
|
||||||
conn =
|
setup do
|
||||||
conn
|
%{
|
||||||
|> assign(:user, %User{})
|
true_fn: fn -> true end,
|
||||||
|
false_fn: fn -> false end
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
ret_conn =
|
test "it continues if a user is assigned", %{conn: conn, true_fn: true_fn, false_fn: false_fn} do
|
||||||
conn
|
conn = assign(conn, :user, %User{})
|
||||||
|> EnsureAuthenticatedPlug.call(%{})
|
assert EnsureAuthenticatedPlug.call(conn, if_func: true_fn) == conn
|
||||||
|
assert EnsureAuthenticatedPlug.call(conn, if_func: false_fn) == conn
|
||||||
|
assert EnsureAuthenticatedPlug.call(conn, unless_func: true_fn) == conn
|
||||||
|
assert EnsureAuthenticatedPlug.call(conn, unless_func: false_fn) == conn
|
||||||
|
end
|
||||||
|
|
||||||
assert ret_conn == conn
|
test "it continues if a user is NOT assigned but :if_func evaluates to `false`",
|
||||||
|
%{conn: conn, false_fn: false_fn} do
|
||||||
|
assert EnsureAuthenticatedPlug.call(conn, if_func: false_fn) == conn
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it continues if a user is NOT assigned but :unless_func evaluates to `true`",
|
||||||
|
%{conn: conn, true_fn: true_fn} do
|
||||||
|
assert EnsureAuthenticatedPlug.call(conn, unless_func: true_fn) == conn
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it halts if a user is NOT assigned and :if_func evaluates to `true`",
|
||||||
|
%{conn: conn, true_fn: true_fn} do
|
||||||
|
conn = EnsureAuthenticatedPlug.call(conn, if_func: true_fn)
|
||||||
|
|
||||||
|
assert conn.status == 403
|
||||||
|
assert conn.halted == true
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it halts if a user is NOT assigned and :unless_func evaluates to `false`",
|
||||||
|
%{conn: conn, false_fn: false_fn} do
|
||||||
|
conn = EnsureAuthenticatedPlug.call(conn, unless_func: false_fn)
|
||||||
|
|
||||||
|
assert conn.status == 403
|
||||||
|
assert conn.halted == true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -38,7 +38,7 @@ test "with valid token(downcase), it assigns the user", %{conn: conn} = opts do
|
||||||
assert conn.assigns[:user] == opts[:user]
|
assert conn.assigns[:user] == opts[:user]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "with valid token(downcase) in url parameters, it assings the user", opts do
|
test "with valid token(downcase) in url parameters, it assigns the user", opts do
|
||||||
conn =
|
conn =
|
||||||
:get
|
:get
|
||||||
|> build_conn("/?access_token=#{opts[:token]}")
|
|> build_conn("/?access_token=#{opts[:token]}")
|
||||||
|
|
|
@ -26,6 +26,8 @@ defmodule Pleroma.Web.ConnCase do
|
||||||
use Pleroma.Tests.Helpers
|
use Pleroma.Tests.Helpers
|
||||||
import Pleroma.Web.Router.Helpers
|
import Pleroma.Web.Router.Helpers
|
||||||
|
|
||||||
|
alias Pleroma.Config
|
||||||
|
|
||||||
# The default endpoint for testing
|
# The default endpoint for testing
|
||||||
@endpoint Pleroma.Web.Endpoint
|
@endpoint Pleroma.Web.Endpoint
|
||||||
|
|
||||||
|
@ -48,6 +50,28 @@ defp oauth_access(scopes, opts \\ []) do
|
||||||
|
|
||||||
%{user: user, token: token, conn: conn}
|
%{user: user, token: token, conn: conn}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp ensure_federating_or_authenticated(conn, url, user) do
|
||||||
|
initial_setting = Config.get([:instance, :federating])
|
||||||
|
on_exit(fn -> Config.put([:instance, :federating], initial_setting) end)
|
||||||
|
|
||||||
|
Config.put([:instance, :federating], false)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> get(url)
|
||||||
|
|> response(403)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> get(url)
|
||||||
|
|> response(200)
|
||||||
|
|
||||||
|
Config.put([:instance, :federating], true)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> get(url)
|
||||||
|
|> response(200)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
||||||
|
|
||||||
import Pleroma.Factory
|
import Pleroma.Factory
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
|
alias Pleroma.Config
|
||||||
alias Pleroma.Delivery
|
alias Pleroma.Delivery
|
||||||
alias Pleroma.Instances
|
alias Pleroma.Instances
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
|
@ -25,9 +26,9 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
||||||
:ok
|
:ok
|
||||||
end
|
end
|
||||||
|
|
||||||
clear_config_all([:instance, :federating],
|
clear_config([:instance, :federating]) do
|
||||||
do: Pleroma.Config.put([:instance, :federating], true)
|
Config.put([:instance, :federating], true)
|
||||||
)
|
end
|
||||||
|
|
||||||
describe "/relay" do
|
describe "/relay" do
|
||||||
clear_config([:instance, :allow_relay])
|
clear_config([:instance, :allow_relay])
|
||||||
|
@ -42,12 +43,21 @@ test "with the relay active, it returns the relay user", %{conn: conn} do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "with the relay disabled, it returns 404", %{conn: conn} do
|
test "with the relay disabled, it returns 404", %{conn: conn} do
|
||||||
Pleroma.Config.put([:instance, :allow_relay], false)
|
Config.put([:instance, :allow_relay], false)
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> get(activity_pub_path(conn, :relay))
|
|> get(activity_pub_path(conn, :relay))
|
||||||
|> json_response(404)
|
|> json_response(404)
|
||||||
|> assert
|
end
|
||||||
|
|
||||||
|
test "on non-federating instance, it returns 404", %{conn: conn} do
|
||||||
|
Config.put([:instance, :federating], false)
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> get(activity_pub_path(conn, :relay))
|
||||||
|
|> json_response(404)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -60,6 +70,16 @@ test "it returns the internal fetch user", %{conn: conn} do
|
||||||
|
|
||||||
assert res["id"] =~ "/fetch"
|
assert res["id"] =~ "/fetch"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "on non-federating instance, it returns 404", %{conn: conn} do
|
||||||
|
Config.put([:instance, :federating], false)
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> get(activity_pub_path(conn, :internal_fetch))
|
||||||
|
|> json_response(404)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "/users/:nickname" do
|
describe "/users/:nickname" do
|
||||||
|
@ -123,9 +143,34 @@ test "it returns 404 for remote users", %{
|
||||||
|
|
||||||
assert json_response(conn, 404)
|
assert json_response(conn, 404)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "it returns error when user is not found", %{conn: conn} do
|
||||||
|
response =
|
||||||
|
conn
|
||||||
|
|> put_req_header("accept", "application/json")
|
||||||
|
|> get("/users/jimm")
|
||||||
|
|> json_response(404)
|
||||||
|
|
||||||
|
assert response == "Not found"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it requires authentication if instance is NOT federating", %{
|
||||||
|
conn: conn
|
||||||
|
} do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
put_req_header(
|
||||||
|
conn,
|
||||||
|
"accept",
|
||||||
|
"application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""
|
||||||
|
)
|
||||||
|
|
||||||
|
ensure_federating_or_authenticated(conn, "/users/#{user.nickname}.json", user)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "/object/:uuid" do
|
describe "/objects/:uuid" do
|
||||||
test "it returns a json representation of the object with accept application/json", %{
|
test "it returns a json representation of the object with accept application/json", %{
|
||||||
conn: conn
|
conn: conn
|
||||||
} do
|
} do
|
||||||
|
@ -236,6 +281,18 @@ test "cached purged after object deletion", %{conn: conn} do
|
||||||
|
|
||||||
assert "Not found" == json_response(conn2, :not_found)
|
assert "Not found" == json_response(conn2, :not_found)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "it requires authentication if instance is NOT federating", %{
|
||||||
|
conn: conn
|
||||||
|
} do
|
||||||
|
user = insert(:user)
|
||||||
|
note = insert(:note)
|
||||||
|
uuid = String.split(note.data["id"], "/") |> List.last()
|
||||||
|
|
||||||
|
conn = put_req_header(conn, "accept", "application/activity+json")
|
||||||
|
|
||||||
|
ensure_federating_or_authenticated(conn, "/objects/#{uuid}", user)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "/activities/:uuid" do
|
describe "/activities/:uuid" do
|
||||||
|
@ -307,6 +364,18 @@ test "cached purged after activity deletion", %{conn: conn} do
|
||||||
|
|
||||||
assert "Not found" == json_response(conn2, :not_found)
|
assert "Not found" == json_response(conn2, :not_found)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "it requires authentication if instance is NOT federating", %{
|
||||||
|
conn: conn
|
||||||
|
} do
|
||||||
|
user = insert(:user)
|
||||||
|
activity = insert(:note_activity)
|
||||||
|
uuid = String.split(activity.data["id"], "/") |> List.last()
|
||||||
|
|
||||||
|
conn = put_req_header(conn, "accept", "application/activity+json")
|
||||||
|
|
||||||
|
ensure_federating_or_authenticated(conn, "/activities/#{uuid}", user)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "/inbox" do
|
describe "/inbox" do
|
||||||
|
@ -379,6 +448,34 @@ test "accept follow activity", %{conn: conn} do
|
||||||
:ok = Mix.Tasks.Pleroma.Relay.run(["list"])
|
:ok = Mix.Tasks.Pleroma.Relay.run(["list"])
|
||||||
assert_receive {:mix_shell, :info, ["relay.mastodon.host"]}
|
assert_receive {:mix_shell, :info, ["relay.mastodon.host"]}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "without valid signature, " <>
|
||||||
|
"it only accepts Create activities and requires enabled federation",
|
||||||
|
%{conn: conn} do
|
||||||
|
data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!()
|
||||||
|
non_create_data = File.read!("test/fixtures/mastodon-announce.json") |> Poison.decode!()
|
||||||
|
|
||||||
|
conn = put_req_header(conn, "content-type", "application/activity+json")
|
||||||
|
|
||||||
|
Config.put([:instance, :federating], false)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> post("/inbox", data)
|
||||||
|
|> json_response(403)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> post("/inbox", non_create_data)
|
||||||
|
|> json_response(403)
|
||||||
|
|
||||||
|
Config.put([:instance, :federating], true)
|
||||||
|
|
||||||
|
ret_conn = post(conn, "/inbox", data)
|
||||||
|
assert "ok" == json_response(ret_conn, 200)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> post("/inbox", non_create_data)
|
||||||
|
|> json_response(400)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "/users/:nickname/inbox" do
|
describe "/users/:nickname/inbox" do
|
||||||
|
@ -517,22 +614,11 @@ test "it accepts messages from actors that are followed by the user", %{
|
||||||
|
|
||||||
test "it rejects reads from other users", %{conn: conn} do
|
test "it rejects reads from other users", %{conn: conn} do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
otheruser = insert(:user)
|
other_user = insert(:user)
|
||||||
|
|
||||||
conn =
|
|
||||||
conn
|
|
||||||
|> assign(:user, otheruser)
|
|
||||||
|> put_req_header("accept", "application/activity+json")
|
|
||||||
|> get("/users/#{user.nickname}/inbox")
|
|
||||||
|
|
||||||
assert json_response(conn, 403)
|
|
||||||
end
|
|
||||||
|
|
||||||
test "it doesn't crash without an authenticated user", %{conn: conn} do
|
|
||||||
user = insert(:user)
|
|
||||||
|
|
||||||
conn =
|
conn =
|
||||||
conn
|
conn
|
||||||
|
|> assign(:user, other_user)
|
||||||
|> put_req_header("accept", "application/activity+json")
|
|> put_req_header("accept", "application/activity+json")
|
||||||
|> get("/users/#{user.nickname}/inbox")
|
|> get("/users/#{user.nickname}/inbox")
|
||||||
|
|
||||||
|
@ -613,14 +699,30 @@ test "it removes all follower collections but actor's", %{conn: conn} do
|
||||||
refute recipient.follower_address in activity.data["cc"]
|
refute recipient.follower_address in activity.data["cc"]
|
||||||
refute recipient.follower_address in activity.data["to"]
|
refute recipient.follower_address in activity.data["to"]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "it requires authentication", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
conn = put_req_header(conn, "accept", "application/activity+json")
|
||||||
|
|
||||||
|
ret_conn = get(conn, "/users/#{user.nickname}/inbox")
|
||||||
|
assert json_response(ret_conn, 403)
|
||||||
|
|
||||||
|
ret_conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> get("/users/#{user.nickname}/inbox")
|
||||||
|
|
||||||
|
assert json_response(ret_conn, 200)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "/users/:nickname/outbox" do
|
describe "GET /users/:nickname/outbox" do
|
||||||
test "it will not bomb when there is no activity", %{conn: conn} do
|
test "it returns 200 even if there're no activities", %{conn: conn} do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
||||||
conn =
|
conn =
|
||||||
conn
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|> put_req_header("accept", "application/activity+json")
|
|> put_req_header("accept", "application/activity+json")
|
||||||
|> get("/users/#{user.nickname}/outbox")
|
|> get("/users/#{user.nickname}/outbox")
|
||||||
|
|
||||||
|
@ -635,6 +737,7 @@ test "it returns a note activity in a collection", %{conn: conn} do
|
||||||
|
|
||||||
conn =
|
conn =
|
||||||
conn
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|> put_req_header("accept", "application/activity+json")
|
|> put_req_header("accept", "application/activity+json")
|
||||||
|> get("/users/#{user.nickname}/outbox?page=true")
|
|> get("/users/#{user.nickname}/outbox?page=true")
|
||||||
|
|
||||||
|
@ -647,24 +750,38 @@ test "it returns an announce activity in a collection", %{conn: conn} do
|
||||||
|
|
||||||
conn =
|
conn =
|
||||||
conn
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|> put_req_header("accept", "application/activity+json")
|
|> put_req_header("accept", "application/activity+json")
|
||||||
|> get("/users/#{user.nickname}/outbox?page=true")
|
|> get("/users/#{user.nickname}/outbox?page=true")
|
||||||
|
|
||||||
assert response(conn, 200) =~ announce_activity.data["object"]
|
assert response(conn, 200) =~ announce_activity.data["object"]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it rejects posts from other users", %{conn: conn} do
|
test "it requires authentication if instance is NOT federating", %{
|
||||||
|
conn: conn
|
||||||
|
} do
|
||||||
|
user = insert(:user)
|
||||||
|
conn = put_req_header(conn, "accept", "application/activity+json")
|
||||||
|
|
||||||
|
ensure_federating_or_authenticated(conn, "/users/#{user.nickname}/outbox", user)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "POST /users/:nickname/outbox" do
|
||||||
|
test "it rejects posts from other users / unauuthenticated users", %{conn: conn} do
|
||||||
data = File.read!("test/fixtures/activitypub-client-post-activity.json") |> Poison.decode!()
|
data = File.read!("test/fixtures/activitypub-client-post-activity.json") |> Poison.decode!()
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
otheruser = insert(:user)
|
other_user = insert(:user)
|
||||||
|
conn = put_req_header(conn, "content-type", "application/activity+json")
|
||||||
|
|
||||||
conn =
|
conn
|
||||||
conn
|
|> post("/users/#{user.nickname}/outbox", data)
|
||||||
|> assign(:user, otheruser)
|
|> json_response(403)
|
||||||
|> put_req_header("content-type", "application/activity+json")
|
|
||||||
|> post("/users/#{user.nickname}/outbox", data)
|
|
||||||
|
|
||||||
assert json_response(conn, 403)
|
conn
|
||||||
|
|> assign(:user, other_user)
|
||||||
|
|> post("/users/#{user.nickname}/outbox", data)
|
||||||
|
|> json_response(403)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it inserts an incoming create activity into the database", %{conn: conn} do
|
test "it inserts an incoming create activity into the database", %{conn: conn} do
|
||||||
|
@ -779,24 +896,42 @@ test "it returns relay followers", %{conn: conn} do
|
||||||
|
|
||||||
result =
|
result =
|
||||||
conn
|
conn
|
||||||
|> assign(:relay, true)
|
|
||||||
|> get("/relay/followers")
|
|> get("/relay/followers")
|
||||||
|> json_response(200)
|
|> json_response(200)
|
||||||
|
|
||||||
assert result["first"]["orderedItems"] == [user.ap_id]
|
assert result["first"]["orderedItems"] == [user.ap_id]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "on non-federating instance, it returns 404", %{conn: conn} do
|
||||||
|
Config.put([:instance, :federating], false)
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> get("/relay/followers")
|
||||||
|
|> json_response(404)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "/relay/following" do
|
describe "/relay/following" do
|
||||||
test "it returns relay following", %{conn: conn} do
|
test "it returns relay following", %{conn: conn} do
|
||||||
result =
|
result =
|
||||||
conn
|
conn
|
||||||
|> assign(:relay, true)
|
|
||||||
|> get("/relay/following")
|
|> get("/relay/following")
|
||||||
|> json_response(200)
|
|> json_response(200)
|
||||||
|
|
||||||
assert result["first"]["orderedItems"] == []
|
assert result["first"]["orderedItems"] == []
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "on non-federating instance, it returns 404", %{conn: conn} do
|
||||||
|
Config.put([:instance, :federating], false)
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> get("/relay/following")
|
||||||
|
|> json_response(404)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "/users/:nickname/followers" do
|
describe "/users/:nickname/followers" do
|
||||||
|
@ -807,32 +942,36 @@ test "it returns the followers in a collection", %{conn: conn} do
|
||||||
|
|
||||||
result =
|
result =
|
||||||
conn
|
conn
|
||||||
|
|> assign(:user, user_two)
|
||||||
|> get("/users/#{user_two.nickname}/followers")
|
|> get("/users/#{user_two.nickname}/followers")
|
||||||
|> json_response(200)
|
|> json_response(200)
|
||||||
|
|
||||||
assert result["first"]["orderedItems"] == [user.ap_id]
|
assert result["first"]["orderedItems"] == [user.ap_id]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it returns returns a uri if the user has 'hide_followers' set", %{conn: conn} do
|
test "it returns a uri if the user has 'hide_followers' set", %{conn: conn} do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
user_two = insert(:user, hide_followers: true)
|
user_two = insert(:user, hide_followers: true)
|
||||||
User.follow(user, user_two)
|
User.follow(user, user_two)
|
||||||
|
|
||||||
result =
|
result =
|
||||||
conn
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|> get("/users/#{user_two.nickname}/followers")
|
|> get("/users/#{user_two.nickname}/followers")
|
||||||
|> json_response(200)
|
|> json_response(200)
|
||||||
|
|
||||||
assert is_binary(result["first"])
|
assert is_binary(result["first"])
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it returns a 403 error on pages, if the user has 'hide_followers' set and the request is not authenticated",
|
test "it returns a 403 error on pages, if the user has 'hide_followers' set and the request is from another user",
|
||||||
%{conn: conn} do
|
%{conn: conn} do
|
||||||
user = insert(:user, hide_followers: true)
|
user = insert(:user)
|
||||||
|
other_user = insert(:user, hide_followers: true)
|
||||||
|
|
||||||
result =
|
result =
|
||||||
conn
|
conn
|
||||||
|> get("/users/#{user.nickname}/followers?page=1")
|
|> assign(:user, user)
|
||||||
|
|> get("/users/#{other_user.nickname}/followers?page=1")
|
||||||
|
|
||||||
assert result.status == 403
|
assert result.status == 403
|
||||||
assert result.resp_body == ""
|
assert result.resp_body == ""
|
||||||
|
@ -864,6 +1003,7 @@ test "it works for more than 10 users", %{conn: conn} do
|
||||||
|
|
||||||
result =
|
result =
|
||||||
conn
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|> get("/users/#{user.nickname}/followers")
|
|> get("/users/#{user.nickname}/followers")
|
||||||
|> json_response(200)
|
|> json_response(200)
|
||||||
|
|
||||||
|
@ -873,12 +1013,21 @@ test "it works for more than 10 users", %{conn: conn} do
|
||||||
|
|
||||||
result =
|
result =
|
||||||
conn
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|> get("/users/#{user.nickname}/followers?page=2")
|
|> get("/users/#{user.nickname}/followers?page=2")
|
||||||
|> json_response(200)
|
|> json_response(200)
|
||||||
|
|
||||||
assert length(result["orderedItems"]) == 5
|
assert length(result["orderedItems"]) == 5
|
||||||
assert result["totalItems"] == 15
|
assert result["totalItems"] == 15
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "returns 403 if requester is not logged in", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> get("/users/#{user.nickname}/followers")
|
||||||
|
|> json_response(403)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "/users/:nickname/following" do
|
describe "/users/:nickname/following" do
|
||||||
|
@ -889,6 +1038,7 @@ test "it returns the following in a collection", %{conn: conn} do
|
||||||
|
|
||||||
result =
|
result =
|
||||||
conn
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|> get("/users/#{user.nickname}/following")
|
|> get("/users/#{user.nickname}/following")
|
||||||
|> json_response(200)
|
|> json_response(200)
|
||||||
|
|
||||||
|
@ -896,25 +1046,28 @@ test "it returns the following in a collection", %{conn: conn} do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it returns a uri if the user has 'hide_follows' set", %{conn: conn} do
|
test "it returns a uri if the user has 'hide_follows' set", %{conn: conn} do
|
||||||
user = insert(:user, hide_follows: true)
|
user = insert(:user)
|
||||||
user_two = insert(:user)
|
user_two = insert(:user, hide_follows: true)
|
||||||
User.follow(user, user_two)
|
User.follow(user, user_two)
|
||||||
|
|
||||||
result =
|
result =
|
||||||
conn
|
conn
|
||||||
|> get("/users/#{user.nickname}/following")
|
|> assign(:user, user)
|
||||||
|
|> get("/users/#{user_two.nickname}/following")
|
||||||
|> json_response(200)
|
|> json_response(200)
|
||||||
|
|
||||||
assert is_binary(result["first"])
|
assert is_binary(result["first"])
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it returns a 403 error on pages, if the user has 'hide_follows' set and the request is not authenticated",
|
test "it returns a 403 error on pages, if the user has 'hide_follows' set and the request is from another user",
|
||||||
%{conn: conn} do
|
%{conn: conn} do
|
||||||
user = insert(:user, hide_follows: true)
|
user = insert(:user)
|
||||||
|
user_two = insert(:user, hide_follows: true)
|
||||||
|
|
||||||
result =
|
result =
|
||||||
conn
|
conn
|
||||||
|> get("/users/#{user.nickname}/following?page=1")
|
|> assign(:user, user)
|
||||||
|
|> get("/users/#{user_two.nickname}/following?page=1")
|
||||||
|
|
||||||
assert result.status == 403
|
assert result.status == 403
|
||||||
assert result.resp_body == ""
|
assert result.resp_body == ""
|
||||||
|
@ -947,6 +1100,7 @@ test "it works for more than 10 users", %{conn: conn} do
|
||||||
|
|
||||||
result =
|
result =
|
||||||
conn
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|> get("/users/#{user.nickname}/following")
|
|> get("/users/#{user.nickname}/following")
|
||||||
|> json_response(200)
|
|> json_response(200)
|
||||||
|
|
||||||
|
@ -956,12 +1110,21 @@ test "it works for more than 10 users", %{conn: conn} do
|
||||||
|
|
||||||
result =
|
result =
|
||||||
conn
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|> get("/users/#{user.nickname}/following?page=2")
|
|> get("/users/#{user.nickname}/following?page=2")
|
||||||
|> json_response(200)
|
|> json_response(200)
|
||||||
|
|
||||||
assert length(result["orderedItems"]) == 5
|
assert length(result["orderedItems"]) == 5
|
||||||
assert result["totalItems"] == 15
|
assert result["totalItems"] == 15
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "returns 403 if requester is not logged in", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> get("/users/#{user.nickname}/following")
|
||||||
|
|> json_response(403)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "delivery tracking" do
|
describe "delivery tracking" do
|
||||||
|
@ -1046,8 +1209,8 @@ test "it tracks a signed activity fetch when the json is cached", %{conn: conn}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "Additionnal ActivityPub C2S endpoints" do
|
describe "Additional ActivityPub C2S endpoints" do
|
||||||
test "/api/ap/whoami", %{conn: conn} do
|
test "GET /api/ap/whoami", %{conn: conn} do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
||||||
conn =
|
conn =
|
||||||
|
@ -1058,12 +1221,16 @@ test "/api/ap/whoami", %{conn: conn} do
|
||||||
user = User.get_cached_by_id(user.id)
|
user = User.get_cached_by_id(user.id)
|
||||||
|
|
||||||
assert UserView.render("user.json", %{user: user}) == json_response(conn, 200)
|
assert UserView.render("user.json", %{user: user}) == json_response(conn, 200)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> get("/api/ap/whoami")
|
||||||
|
|> json_response(403)
|
||||||
end
|
end
|
||||||
|
|
||||||
clear_config([:media_proxy])
|
clear_config([:media_proxy])
|
||||||
clear_config([Pleroma.Upload])
|
clear_config([Pleroma.Upload])
|
||||||
|
|
||||||
test "uploadMedia", %{conn: conn} do
|
test "POST /api/ap/upload_media", %{conn: conn} do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
||||||
desc = "Description of the image"
|
desc = "Description of the image"
|
||||||
|
@ -1083,6 +1250,10 @@ test "uploadMedia", %{conn: conn} do
|
||||||
assert object["name"] == desc
|
assert object["name"] == desc
|
||||||
assert object["type"] == "Document"
|
assert object["type"] == "Document"
|
||||||
assert object["actor"] == user.ap_id
|
assert object["actor"] == user.ap_id
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> post("/api/ap/upload_media", %{"file" => image, "description" => desc})
|
||||||
|
|> json_response(403)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -23,6 +23,10 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
|
||||||
:ok
|
:ok
|
||||||
end
|
end
|
||||||
|
|
||||||
|
clear_config_all([:instance, :federating]) do
|
||||||
|
Pleroma.Config.put([:instance, :federating], true)
|
||||||
|
end
|
||||||
|
|
||||||
describe "gather_webfinger_links/1" do
|
describe "gather_webfinger_links/1" do
|
||||||
test "it returns links" do
|
test "it returns links" do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
|
@ -8,222 +8,83 @@ defmodule Pleroma.Web.Feed.UserControllerTest do
|
||||||
import Pleroma.Factory
|
import Pleroma.Factory
|
||||||
import SweetXml
|
import SweetXml
|
||||||
|
|
||||||
|
alias Pleroma.Config
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
|
|
||||||
clear_config([:feed])
|
clear_config([:instance, :federating]) do
|
||||||
|
Config.put([:instance, :federating], true)
|
||||||
test "gets a feed", %{conn: conn} do
|
|
||||||
Pleroma.Config.put(
|
|
||||||
[:feed, :post_title],
|
|
||||||
%{max_length: 10, omission: "..."}
|
|
||||||
)
|
|
||||||
|
|
||||||
activity = insert(:note_activity)
|
|
||||||
|
|
||||||
note =
|
|
||||||
insert(:note,
|
|
||||||
data: %{
|
|
||||||
"content" => "This is :moominmamma: note ",
|
|
||||||
"attachment" => [
|
|
||||||
%{
|
|
||||||
"url" => [%{"mediaType" => "image/png", "href" => "https://pleroma.gov/image.png"}]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"inReplyTo" => activity.data["id"]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
note_activity = insert(:note_activity, note: note)
|
|
||||||
user = User.get_cached_by_ap_id(note_activity.data["actor"])
|
|
||||||
|
|
||||||
note2 =
|
|
||||||
insert(:note,
|
|
||||||
user: user,
|
|
||||||
data: %{"content" => "42 This is :moominmamma: note ", "inReplyTo" => activity.data["id"]}
|
|
||||||
)
|
|
||||||
|
|
||||||
_note_activity2 = insert(:note_activity, note: note2)
|
|
||||||
object = Object.normalize(note_activity)
|
|
||||||
|
|
||||||
resp =
|
|
||||||
conn
|
|
||||||
|> put_req_header("content-type", "application/atom+xml")
|
|
||||||
|> get(user_feed_path(conn, :feed, user.nickname))
|
|
||||||
|> response(200)
|
|
||||||
|
|
||||||
activity_titles =
|
|
||||||
resp
|
|
||||||
|> SweetXml.parse()
|
|
||||||
|> SweetXml.xpath(~x"//entry/title/text()"l)
|
|
||||||
|
|
||||||
assert activity_titles == ['42 This...', 'This is...']
|
|
||||||
assert resp =~ object.data["content"]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
test "returns 404 for a missing feed", %{conn: conn} do
|
describe "feed" do
|
||||||
conn =
|
clear_config([:feed])
|
||||||
conn
|
|
||||||
|> put_req_header("content-type", "application/atom+xml")
|
|
||||||
|> get(user_feed_path(conn, :feed, "nonexisting"))
|
|
||||||
|
|
||||||
assert response(conn, 404)
|
test "gets a feed", %{conn: conn} do
|
||||||
|
Config.put(
|
||||||
|
[:feed, :post_title],
|
||||||
|
%{max_length: 10, omission: "..."}
|
||||||
|
)
|
||||||
|
|
||||||
|
activity = insert(:note_activity)
|
||||||
|
|
||||||
|
note =
|
||||||
|
insert(:note,
|
||||||
|
data: %{
|
||||||
|
"content" => "This is :moominmamma: note ",
|
||||||
|
"attachment" => [
|
||||||
|
%{
|
||||||
|
"url" => [
|
||||||
|
%{"mediaType" => "image/png", "href" => "https://pleroma.gov/image.png"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"inReplyTo" => activity.data["id"]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
note_activity = insert(:note_activity, note: note)
|
||||||
|
user = User.get_cached_by_ap_id(note_activity.data["actor"])
|
||||||
|
|
||||||
|
note2 =
|
||||||
|
insert(:note,
|
||||||
|
user: user,
|
||||||
|
data: %{
|
||||||
|
"content" => "42 This is :moominmamma: note ",
|
||||||
|
"inReplyTo" => activity.data["id"]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
_note_activity2 = insert(:note_activity, note: note2)
|
||||||
|
object = Object.normalize(note_activity)
|
||||||
|
|
||||||
|
resp =
|
||||||
|
conn
|
||||||
|
|> put_req_header("content-type", "application/atom+xml")
|
||||||
|
|> get(user_feed_path(conn, :feed, user.nickname))
|
||||||
|
|> response(200)
|
||||||
|
|
||||||
|
activity_titles =
|
||||||
|
resp
|
||||||
|
|> SweetXml.parse()
|
||||||
|
|> SweetXml.xpath(~x"//entry/title/text()"l)
|
||||||
|
|
||||||
|
assert activity_titles == ['42 This...', 'This is...']
|
||||||
|
assert resp =~ object.data["content"]
|
||||||
|
end
|
||||||
|
|
||||||
|
test "returns 404 for a missing feed", %{conn: conn} do
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> put_req_header("content-type", "application/atom+xml")
|
||||||
|
|> get(user_feed_path(conn, :feed, "nonexisting"))
|
||||||
|
|
||||||
|
assert response(conn, 404)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Note: see ActivityPubControllerTest for JSON format tests
|
||||||
describe "feed_redirect" do
|
describe "feed_redirect" do
|
||||||
test "undefined format. it redirects to feed", %{conn: conn} do
|
test "with html format, it redirects to user feed", %{conn: conn} do
|
||||||
note_activity = insert(:note_activity)
|
|
||||||
user = User.get_cached_by_ap_id(note_activity.data["actor"])
|
|
||||||
|
|
||||||
response =
|
|
||||||
conn
|
|
||||||
|> put_req_header("accept", "application/xml")
|
|
||||||
|> get("/users/#{user.nickname}")
|
|
||||||
|> response(302)
|
|
||||||
|
|
||||||
assert response ==
|
|
||||||
"<html><body>You are being <a href=\"#{Pleroma.Web.base_url()}/users/#{
|
|
||||||
user.nickname
|
|
||||||
}/feed.atom\">redirected</a>.</body></html>"
|
|
||||||
end
|
|
||||||
|
|
||||||
test "undefined format. it returns error when user not found", %{conn: conn} do
|
|
||||||
response =
|
|
||||||
conn
|
|
||||||
|> put_req_header("accept", "application/xml")
|
|
||||||
|> get(user_feed_path(conn, :feed, "jimm"))
|
|
||||||
|> response(404)
|
|
||||||
|
|
||||||
assert response == ~S({"error":"Not found"})
|
|
||||||
end
|
|
||||||
|
|
||||||
test "activity+json format. it redirects on actual feed of user", %{conn: conn} do
|
|
||||||
note_activity = insert(:note_activity)
|
|
||||||
user = User.get_cached_by_ap_id(note_activity.data["actor"])
|
|
||||||
|
|
||||||
response =
|
|
||||||
conn
|
|
||||||
|> put_req_header("accept", "application/activity+json")
|
|
||||||
|> get("/users/#{user.nickname}")
|
|
||||||
|> json_response(200)
|
|
||||||
|
|
||||||
assert response["endpoints"] == %{
|
|
||||||
"oauthAuthorizationEndpoint" => "#{Pleroma.Web.base_url()}/oauth/authorize",
|
|
||||||
"oauthRegistrationEndpoint" => "#{Pleroma.Web.base_url()}/api/v1/apps",
|
|
||||||
"oauthTokenEndpoint" => "#{Pleroma.Web.base_url()}/oauth/token",
|
|
||||||
"sharedInbox" => "#{Pleroma.Web.base_url()}/inbox",
|
|
||||||
"uploadMedia" => "#{Pleroma.Web.base_url()}/api/ap/upload_media"
|
|
||||||
}
|
|
||||||
|
|
||||||
assert response["@context"] == [
|
|
||||||
"https://www.w3.org/ns/activitystreams",
|
|
||||||
"http://localhost:4001/schemas/litepub-0.1.jsonld",
|
|
||||||
%{"@language" => "und"}
|
|
||||||
]
|
|
||||||
|
|
||||||
assert Map.take(response, [
|
|
||||||
"followers",
|
|
||||||
"following",
|
|
||||||
"id",
|
|
||||||
"inbox",
|
|
||||||
"manuallyApprovesFollowers",
|
|
||||||
"name",
|
|
||||||
"outbox",
|
|
||||||
"preferredUsername",
|
|
||||||
"summary",
|
|
||||||
"tag",
|
|
||||||
"type",
|
|
||||||
"url"
|
|
||||||
]) == %{
|
|
||||||
"followers" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/followers",
|
|
||||||
"following" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/following",
|
|
||||||
"id" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}",
|
|
||||||
"inbox" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/inbox",
|
|
||||||
"manuallyApprovesFollowers" => false,
|
|
||||||
"name" => user.name,
|
|
||||||
"outbox" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/outbox",
|
|
||||||
"preferredUsername" => user.nickname,
|
|
||||||
"summary" => user.bio,
|
|
||||||
"tag" => [],
|
|
||||||
"type" => "Person",
|
|
||||||
"url" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}"
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
test "activity+json format. it returns error whe use not found", %{conn: conn} do
|
|
||||||
response =
|
|
||||||
conn
|
|
||||||
|> put_req_header("accept", "application/activity+json")
|
|
||||||
|> get("/users/jimm")
|
|
||||||
|> json_response(404)
|
|
||||||
|
|
||||||
assert response == "Not found"
|
|
||||||
end
|
|
||||||
|
|
||||||
test "json format. it redirects on actual feed of user", %{conn: conn} do
|
|
||||||
note_activity = insert(:note_activity)
|
|
||||||
user = User.get_cached_by_ap_id(note_activity.data["actor"])
|
|
||||||
|
|
||||||
response =
|
|
||||||
conn
|
|
||||||
|> put_req_header("accept", "application/json")
|
|
||||||
|> get("/users/#{user.nickname}")
|
|
||||||
|> json_response(200)
|
|
||||||
|
|
||||||
assert response["endpoints"] == %{
|
|
||||||
"oauthAuthorizationEndpoint" => "#{Pleroma.Web.base_url()}/oauth/authorize",
|
|
||||||
"oauthRegistrationEndpoint" => "#{Pleroma.Web.base_url()}/api/v1/apps",
|
|
||||||
"oauthTokenEndpoint" => "#{Pleroma.Web.base_url()}/oauth/token",
|
|
||||||
"sharedInbox" => "#{Pleroma.Web.base_url()}/inbox",
|
|
||||||
"uploadMedia" => "#{Pleroma.Web.base_url()}/api/ap/upload_media"
|
|
||||||
}
|
|
||||||
|
|
||||||
assert response["@context"] == [
|
|
||||||
"https://www.w3.org/ns/activitystreams",
|
|
||||||
"http://localhost:4001/schemas/litepub-0.1.jsonld",
|
|
||||||
%{"@language" => "und"}
|
|
||||||
]
|
|
||||||
|
|
||||||
assert Map.take(response, [
|
|
||||||
"followers",
|
|
||||||
"following",
|
|
||||||
"id",
|
|
||||||
"inbox",
|
|
||||||
"manuallyApprovesFollowers",
|
|
||||||
"name",
|
|
||||||
"outbox",
|
|
||||||
"preferredUsername",
|
|
||||||
"summary",
|
|
||||||
"tag",
|
|
||||||
"type",
|
|
||||||
"url"
|
|
||||||
]) == %{
|
|
||||||
"followers" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/followers",
|
|
||||||
"following" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/following",
|
|
||||||
"id" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}",
|
|
||||||
"inbox" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/inbox",
|
|
||||||
"manuallyApprovesFollowers" => false,
|
|
||||||
"name" => user.name,
|
|
||||||
"outbox" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}/outbox",
|
|
||||||
"preferredUsername" => user.nickname,
|
|
||||||
"summary" => user.bio,
|
|
||||||
"tag" => [],
|
|
||||||
"type" => "Person",
|
|
||||||
"url" => "#{Pleroma.Web.base_url()}/users/#{user.nickname}"
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
test "json format. it returns error whe use not found", %{conn: conn} do
|
|
||||||
response =
|
|
||||||
conn
|
|
||||||
|> put_req_header("accept", "application/json")
|
|
||||||
|> get("/users/jimm")
|
|
||||||
|> json_response(404)
|
|
||||||
|
|
||||||
assert response == "Not found"
|
|
||||||
end
|
|
||||||
|
|
||||||
test "html format. it redirects on actual feed of user", %{conn: conn} do
|
|
||||||
note_activity = insert(:note_activity)
|
note_activity = insert(:note_activity)
|
||||||
user = User.get_cached_by_ap_id(note_activity.data["actor"])
|
user = User.get_cached_by_ap_id(note_activity.data["actor"])
|
||||||
|
|
||||||
|
@ -239,7 +100,7 @@ test "html format. it redirects on actual feed of user", %{conn: conn} do
|
||||||
).resp_body
|
).resp_body
|
||||||
end
|
end
|
||||||
|
|
||||||
test "html format. it returns error when user not found", %{conn: conn} do
|
test "with html format, it returns error when user is not found", %{conn: conn} do
|
||||||
response =
|
response =
|
||||||
conn
|
conn
|
||||||
|> get("/users/jimm")
|
|> get("/users/jimm")
|
||||||
|
@ -247,5 +108,30 @@ test "html format. it returns error when user not found", %{conn: conn} do
|
||||||
|
|
||||||
assert response == %{"error" => "Not found"}
|
assert response == %{"error" => "Not found"}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "with non-html / non-json format, it redirects to user feed in atom format", %{
|
||||||
|
conn: conn
|
||||||
|
} do
|
||||||
|
note_activity = insert(:note_activity)
|
||||||
|
user = User.get_cached_by_ap_id(note_activity.data["actor"])
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> put_req_header("accept", "application/xml")
|
||||||
|
|> get("/users/#{user.nickname}")
|
||||||
|
|
||||||
|
assert conn.status == 302
|
||||||
|
assert redirected_to(conn) == "#{Pleroma.Web.base_url()}/users/#{user.nickname}/feed.atom"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "with non-html / non-json format, it returns error when user is not found", %{conn: conn} do
|
||||||
|
response =
|
||||||
|
conn
|
||||||
|
|> put_req_header("accept", "application/xml")
|
||||||
|
|> get(user_feed_path(conn, :feed, "jimm"))
|
||||||
|
|> response(404)
|
||||||
|
|
||||||
|
assert response == ~S({"error":"Not found"})
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -52,9 +52,8 @@ test "redirects on valid url when filename invalidated", %{conn: conn} do
|
||||||
url = Pleroma.Web.MediaProxy.encode_url("https://google.fn/test.png")
|
url = Pleroma.Web.MediaProxy.encode_url("https://google.fn/test.png")
|
||||||
invalid_url = String.replace(url, "test.png", "test-file.png")
|
invalid_url = String.replace(url, "test.png", "test-file.png")
|
||||||
response = get(conn, invalid_url)
|
response = get(conn, invalid_url)
|
||||||
html = "<html><body>You are being <a href=\"#{url}\">redirected</a>.</body></html>"
|
|
||||||
assert response.status == 302
|
assert response.status == 302
|
||||||
assert response.resp_body == html
|
assert redirected_to(response) == url
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it performs ReverseProxy.call when signature valid", %{conn: conn} do
|
test "it performs ReverseProxy.call when signature valid", %{conn: conn} do
|
||||||
|
|
|
@ -7,6 +7,7 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do
|
||||||
|
|
||||||
import Pleroma.Factory
|
import Pleroma.Factory
|
||||||
|
|
||||||
|
alias Pleroma.Config
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
|
@ -16,22 +17,24 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do
|
||||||
:ok
|
:ok
|
||||||
end
|
end
|
||||||
|
|
||||||
clear_config_all([:instance, :federating]) do
|
clear_config([:instance, :federating]) do
|
||||||
Pleroma.Config.put([:instance, :federating], true)
|
Config.put([:instance, :federating], true)
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "GET object/2" do
|
# Note: see ActivityPubControllerTest for JSON format tests
|
||||||
|
describe "GET /objects/:uuid (text/html)" do
|
||||||
|
setup %{conn: conn} do
|
||||||
|
conn = put_req_header(conn, "accept", "text/html")
|
||||||
|
%{conn: conn}
|
||||||
|
end
|
||||||
|
|
||||||
test "redirects to /notice/id for html format", %{conn: conn} do
|
test "redirects to /notice/id for html format", %{conn: conn} do
|
||||||
note_activity = insert(:note_activity)
|
note_activity = insert(:note_activity)
|
||||||
object = Object.normalize(note_activity)
|
object = Object.normalize(note_activity)
|
||||||
[_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, object.data["id"]))
|
[_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, object.data["id"]))
|
||||||
url = "/objects/#{uuid}"
|
url = "/objects/#{uuid}"
|
||||||
|
|
||||||
conn =
|
conn = get(conn, url)
|
||||||
conn
|
|
||||||
|> put_req_header("accept", "text/html")
|
|
||||||
|> get(url)
|
|
||||||
|
|
||||||
assert redirected_to(conn) == "/notice/#{note_activity.id}"
|
assert redirected_to(conn) == "/notice/#{note_activity.id}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -45,23 +48,25 @@ test "404s on private objects", %{conn: conn} do
|
||||||
|> response(404)
|
|> response(404)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "404s on nonexisting objects", %{conn: conn} do
|
test "404s on non-existing objects", %{conn: conn} do
|
||||||
conn
|
conn
|
||||||
|> get("/objects/123")
|
|> get("/objects/123")
|
||||||
|> response(404)
|
|> response(404)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "GET activity/2" do
|
# Note: see ActivityPubControllerTest for JSON format tests
|
||||||
|
describe "GET /activities/:uuid (text/html)" do
|
||||||
|
setup %{conn: conn} do
|
||||||
|
conn = put_req_header(conn, "accept", "text/html")
|
||||||
|
%{conn: conn}
|
||||||
|
end
|
||||||
|
|
||||||
test "redirects to /notice/id for html format", %{conn: conn} do
|
test "redirects to /notice/id for html format", %{conn: conn} do
|
||||||
note_activity = insert(:note_activity)
|
note_activity = insert(:note_activity)
|
||||||
[_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, note_activity.data["id"]))
|
[_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, note_activity.data["id"]))
|
||||||
|
|
||||||
conn =
|
conn = get(conn, "/activities/#{uuid}")
|
||||||
conn
|
|
||||||
|> put_req_header("accept", "text/html")
|
|
||||||
|> get("/activities/#{uuid}")
|
|
||||||
|
|
||||||
assert redirected_to(conn) == "/notice/#{note_activity.id}"
|
assert redirected_to(conn) == "/notice/#{note_activity.id}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -79,19 +84,6 @@ test "404s on nonexistent activities", %{conn: conn} do
|
||||||
|> get("/activities/123")
|
|> get("/activities/123")
|
||||||
|> response(404)
|
|> response(404)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "gets an activity in AS2 format", %{conn: conn} do
|
|
||||||
note_activity = insert(:note_activity)
|
|
||||||
[_, uuid] = hd(Regex.scan(~r/.+\/([\w-]+)$/, note_activity.data["id"]))
|
|
||||||
url = "/activities/#{uuid}"
|
|
||||||
|
|
||||||
conn =
|
|
||||||
conn
|
|
||||||
|> put_req_header("accept", "application/activity+json")
|
|
||||||
|> get(url)
|
|
||||||
|
|
||||||
assert json_response(conn, 200)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "GET notice/2" do
|
describe "GET notice/2" do
|
||||||
|
@ -170,7 +162,7 @@ test "404s a private notice", %{conn: conn} do
|
||||||
assert response(conn, 404)
|
assert response(conn, 404)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "404s a nonexisting notice", %{conn: conn} do
|
test "404s a non-existing notice", %{conn: conn} do
|
||||||
url = "/notice/123"
|
url = "/notice/123"
|
||||||
|
|
||||||
conn =
|
conn =
|
||||||
|
@ -179,10 +171,21 @@ test "404s a nonexisting notice", %{conn: conn} do
|
||||||
|
|
||||||
assert response(conn, 404)
|
assert response(conn, 404)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "it requires authentication if instance is NOT federating", %{
|
||||||
|
conn: conn
|
||||||
|
} do
|
||||||
|
user = insert(:user)
|
||||||
|
note_activity = insert(:note_activity)
|
||||||
|
|
||||||
|
conn = put_req_header(conn, "accept", "text/html")
|
||||||
|
|
||||||
|
ensure_federating_or_authenticated(conn, "/notice/#{note_activity.id}", user)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "GET /notice/:id/embed_player" do
|
describe "GET /notice/:id/embed_player" do
|
||||||
test "render embed player", %{conn: conn} do
|
setup do
|
||||||
note_activity = insert(:note_activity)
|
note_activity = insert(:note_activity)
|
||||||
object = Pleroma.Object.normalize(note_activity)
|
object = Pleroma.Object.normalize(note_activity)
|
||||||
|
|
||||||
|
@ -204,9 +207,11 @@ test "render embed player", %{conn: conn} do
|
||||||
|> Ecto.Changeset.change(data: object_data)
|
|> Ecto.Changeset.change(data: object_data)
|
||||||
|> Pleroma.Repo.update()
|
|> Pleroma.Repo.update()
|
||||||
|
|
||||||
conn =
|
%{note_activity: note_activity}
|
||||||
conn
|
end
|
||||||
|> get("/notice/#{note_activity.id}/embed_player")
|
|
||||||
|
test "renders embed player", %{conn: conn, note_activity: note_activity} do
|
||||||
|
conn = get(conn, "/notice/#{note_activity.id}/embed_player")
|
||||||
|
|
||||||
assert Plug.Conn.get_resp_header(conn, "x-frame-options") == ["ALLOW"]
|
assert Plug.Conn.get_resp_header(conn, "x-frame-options") == ["ALLOW"]
|
||||||
|
|
||||||
|
@ -272,9 +277,19 @@ test "404s when attachment isn't audio or video", %{conn: conn} do
|
||||||
|> Ecto.Changeset.change(data: object_data)
|
|> Ecto.Changeset.change(data: object_data)
|
||||||
|> Pleroma.Repo.update()
|
|> Pleroma.Repo.update()
|
||||||
|
|
||||||
assert conn
|
conn
|
||||||
|> get("/notice/#{note_activity.id}/embed_player")
|
|> get("/notice/#{note_activity.id}/embed_player")
|
||||||
|> response(404)
|
|> response(404)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it requires authentication if instance is NOT federating", %{
|
||||||
|
conn: conn,
|
||||||
|
note_activity: note_activity
|
||||||
|
} do
|
||||||
|
user = insert(:user)
|
||||||
|
conn = put_req_header(conn, "accept", "text/html")
|
||||||
|
|
||||||
|
ensure_federating_or_authenticated(conn, "/notice/#{note_activity.id}/embed_player", user)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,56 +1,46 @@
|
||||||
defmodule Pleroma.Web.StaticFE.StaticFEControllerTest do
|
defmodule Pleroma.Web.StaticFE.StaticFEControllerTest do
|
||||||
use Pleroma.Web.ConnCase
|
use Pleroma.Web.ConnCase
|
||||||
|
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
|
alias Pleroma.Config
|
||||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
|
|
||||||
import Pleroma.Factory
|
import Pleroma.Factory
|
||||||
|
|
||||||
clear_config_all([:static_fe, :enabled]) do
|
clear_config_all([:static_fe, :enabled]) do
|
||||||
Pleroma.Config.put([:static_fe, :enabled], true)
|
Config.put([:static_fe, :enabled], true)
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "user profile page" do
|
clear_config([:instance, :federating]) do
|
||||||
test "just the profile as HTML", %{conn: conn} do
|
Config.put([:instance, :federating], true)
|
||||||
user = insert(:user)
|
end
|
||||||
|
|
||||||
conn =
|
setup %{conn: conn} do
|
||||||
conn
|
conn = put_req_header(conn, "accept", "text/html")
|
||||||
|> put_req_header("accept", "text/html")
|
user = insert(:user)
|
||||||
|> get("/users/#{user.nickname}")
|
|
||||||
|
%{conn: conn, user: user}
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "user profile html" do
|
||||||
|
test "just the profile as HTML", %{conn: conn, user: user} do
|
||||||
|
conn = get(conn, "/users/#{user.nickname}")
|
||||||
|
|
||||||
assert html_response(conn, 200) =~ user.nickname
|
assert html_response(conn, 200) =~ user.nickname
|
||||||
end
|
end
|
||||||
|
|
||||||
test "renders json unless there's an html accept header", %{conn: conn} do
|
|
||||||
user = insert(:user)
|
|
||||||
|
|
||||||
conn =
|
|
||||||
conn
|
|
||||||
|> put_req_header("accept", "application/json")
|
|
||||||
|> get("/users/#{user.nickname}")
|
|
||||||
|
|
||||||
assert json_response(conn, 200)
|
|
||||||
end
|
|
||||||
|
|
||||||
test "404 when user not found", %{conn: conn} do
|
test "404 when user not found", %{conn: conn} do
|
||||||
conn =
|
conn = get(conn, "/users/limpopo")
|
||||||
conn
|
|
||||||
|> put_req_header("accept", "text/html")
|
|
||||||
|> get("/users/limpopo")
|
|
||||||
|
|
||||||
assert html_response(conn, 404) =~ "not found"
|
assert html_response(conn, 404) =~ "not found"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "profile does not include private messages", %{conn: conn} do
|
test "profile does not include private messages", %{conn: conn, user: user} do
|
||||||
user = insert(:user)
|
|
||||||
CommonAPI.post(user, %{"status" => "public"})
|
CommonAPI.post(user, %{"status" => "public"})
|
||||||
CommonAPI.post(user, %{"status" => "private", "visibility" => "private"})
|
CommonAPI.post(user, %{"status" => "private", "visibility" => "private"})
|
||||||
|
|
||||||
conn =
|
conn = get(conn, "/users/#{user.nickname}")
|
||||||
conn
|
|
||||||
|> put_req_header("accept", "text/html")
|
|
||||||
|> get("/users/#{user.nickname}")
|
|
||||||
|
|
||||||
html = html_response(conn, 200)
|
html = html_response(conn, 200)
|
||||||
|
|
||||||
|
@ -58,14 +48,10 @@ test "profile does not include private messages", %{conn: conn} do
|
||||||
refute html =~ ">private<"
|
refute html =~ ">private<"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "pagination", %{conn: conn} do
|
test "pagination", %{conn: conn, user: user} do
|
||||||
user = insert(:user)
|
|
||||||
Enum.map(1..30, fn i -> CommonAPI.post(user, %{"status" => "test#{i}"}) end)
|
Enum.map(1..30, fn i -> CommonAPI.post(user, %{"status" => "test#{i}"}) end)
|
||||||
|
|
||||||
conn =
|
conn = get(conn, "/users/#{user.nickname}")
|
||||||
conn
|
|
||||||
|> put_req_header("accept", "text/html")
|
|
||||||
|> get("/users/#{user.nickname}")
|
|
||||||
|
|
||||||
html = html_response(conn, 200)
|
html = html_response(conn, 200)
|
||||||
|
|
||||||
|
@ -75,15 +61,11 @@ test "pagination", %{conn: conn} do
|
||||||
refute html =~ ">test1<"
|
refute html =~ ">test1<"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "pagination, page 2", %{conn: conn} do
|
test "pagination, page 2", %{conn: conn, user: user} do
|
||||||
user = insert(:user)
|
|
||||||
activities = Enum.map(1..30, fn i -> CommonAPI.post(user, %{"status" => "test#{i}"}) end)
|
activities = Enum.map(1..30, fn i -> CommonAPI.post(user, %{"status" => "test#{i}"}) end)
|
||||||
{:ok, a11} = Enum.at(activities, 11)
|
{:ok, a11} = Enum.at(activities, 11)
|
||||||
|
|
||||||
conn =
|
conn = get(conn, "/users/#{user.nickname}?max_id=#{a11.id}")
|
||||||
conn
|
|
||||||
|> put_req_header("accept", "text/html")
|
|
||||||
|> get("/users/#{user.nickname}?max_id=#{a11.id}")
|
|
||||||
|
|
||||||
html = html_response(conn, 200)
|
html = html_response(conn, 200)
|
||||||
|
|
||||||
|
@ -92,17 +74,17 @@ test "pagination, page 2", %{conn: conn} do
|
||||||
refute html =~ ">test20<"
|
refute html =~ ">test20<"
|
||||||
refute html =~ ">test29<"
|
refute html =~ ">test29<"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "it requires authentication if instance is NOT federating", %{conn: conn, user: user} do
|
||||||
|
ensure_federating_or_authenticated(conn, "/users/#{user.nickname}", user)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "notice rendering" do
|
describe "notice html" do
|
||||||
test "single notice page", %{conn: conn} do
|
test "single notice page", %{conn: conn, user: user} do
|
||||||
user = insert(:user)
|
|
||||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "testing a thing!"})
|
{:ok, activity} = CommonAPI.post(user, %{"status" => "testing a thing!"})
|
||||||
|
|
||||||
conn =
|
conn = get(conn, "/notice/#{activity.id}")
|
||||||
conn
|
|
||||||
|> put_req_header("accept", "text/html")
|
|
||||||
|> get("/notice/#{activity.id}")
|
|
||||||
|
|
||||||
html = html_response(conn, 200)
|
html = html_response(conn, 200)
|
||||||
assert html =~ "<header>"
|
assert html =~ "<header>"
|
||||||
|
@ -110,8 +92,7 @@ test "single notice page", %{conn: conn} do
|
||||||
assert html =~ "testing a thing!"
|
assert html =~ "testing a thing!"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "shows the whole thread", %{conn: conn} do
|
test "shows the whole thread", %{conn: conn, user: user} do
|
||||||
user = insert(:user)
|
|
||||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "space: the final frontier"})
|
{:ok, activity} = CommonAPI.post(user, %{"status" => "space: the final frontier"})
|
||||||
|
|
||||||
CommonAPI.post(user, %{
|
CommonAPI.post(user, %{
|
||||||
|
@ -119,70 +100,47 @@ test "shows the whole thread", %{conn: conn} do
|
||||||
"in_reply_to_status_id" => activity.id
|
"in_reply_to_status_id" => activity.id
|
||||||
})
|
})
|
||||||
|
|
||||||
conn =
|
conn = get(conn, "/notice/#{activity.id}")
|
||||||
conn
|
|
||||||
|> put_req_header("accept", "text/html")
|
|
||||||
|> get("/notice/#{activity.id}")
|
|
||||||
|
|
||||||
html = html_response(conn, 200)
|
html = html_response(conn, 200)
|
||||||
assert html =~ "the final frontier"
|
assert html =~ "the final frontier"
|
||||||
assert html =~ "voyages"
|
assert html =~ "voyages"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "redirect by AP object ID", %{conn: conn} do
|
test "redirect by AP object ID", %{conn: conn, user: user} do
|
||||||
user = insert(:user)
|
|
||||||
|
|
||||||
{:ok, %Activity{data: %{"object" => object_url}}} =
|
{:ok, %Activity{data: %{"object" => object_url}}} =
|
||||||
CommonAPI.post(user, %{"status" => "beam me up"})
|
CommonAPI.post(user, %{"status" => "beam me up"})
|
||||||
|
|
||||||
conn =
|
conn = get(conn, URI.parse(object_url).path)
|
||||||
conn
|
|
||||||
|> put_req_header("accept", "text/html")
|
|
||||||
|> get(URI.parse(object_url).path)
|
|
||||||
|
|
||||||
assert html_response(conn, 302) =~ "redirected"
|
assert html_response(conn, 302) =~ "redirected"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "redirect by activity ID", %{conn: conn} do
|
test "redirect by activity ID", %{conn: conn, user: user} do
|
||||||
user = insert(:user)
|
|
||||||
|
|
||||||
{:ok, %Activity{data: %{"id" => id}}} =
|
{:ok, %Activity{data: %{"id" => id}}} =
|
||||||
CommonAPI.post(user, %{"status" => "I'm a doctor, not a devops!"})
|
CommonAPI.post(user, %{"status" => "I'm a doctor, not a devops!"})
|
||||||
|
|
||||||
conn =
|
conn = get(conn, URI.parse(id).path)
|
||||||
conn
|
|
||||||
|> put_req_header("accept", "text/html")
|
|
||||||
|> get(URI.parse(id).path)
|
|
||||||
|
|
||||||
assert html_response(conn, 302) =~ "redirected"
|
assert html_response(conn, 302) =~ "redirected"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "404 when notice not found", %{conn: conn} do
|
test "404 when notice not found", %{conn: conn} do
|
||||||
conn =
|
conn = get(conn, "/notice/88c9c317")
|
||||||
conn
|
|
||||||
|> put_req_header("accept", "text/html")
|
|
||||||
|> get("/notice/88c9c317")
|
|
||||||
|
|
||||||
assert html_response(conn, 404) =~ "not found"
|
assert html_response(conn, 404) =~ "not found"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "404 for private status", %{conn: conn} do
|
test "404 for private status", %{conn: conn, user: user} do
|
||||||
user = insert(:user)
|
|
||||||
|
|
||||||
{:ok, activity} =
|
{:ok, activity} =
|
||||||
CommonAPI.post(user, %{"status" => "don't show me!", "visibility" => "private"})
|
CommonAPI.post(user, %{"status" => "don't show me!", "visibility" => "private"})
|
||||||
|
|
||||||
conn =
|
conn = get(conn, "/notice/#{activity.id}")
|
||||||
conn
|
|
||||||
|> put_req_header("accept", "text/html")
|
|
||||||
|> get("/notice/#{activity.id}")
|
|
||||||
|
|
||||||
assert html_response(conn, 404) =~ "not found"
|
assert html_response(conn, 404) =~ "not found"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "302 for remote cached status", %{conn: conn} do
|
test "302 for remote cached status", %{conn: conn, user: user} do
|
||||||
user = insert(:user)
|
|
||||||
|
|
||||||
message = %{
|
message = %{
|
||||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||||
"to" => user.follower_address,
|
"to" => user.follower_address,
|
||||||
|
@ -199,12 +157,15 @@ test "302 for remote cached status", %{conn: conn} do
|
||||||
|
|
||||||
assert {:ok, activity} = Transmogrifier.handle_incoming(message)
|
assert {:ok, activity} = Transmogrifier.handle_incoming(message)
|
||||||
|
|
||||||
conn =
|
conn = get(conn, "/notice/#{activity.id}")
|
||||||
conn
|
|
||||||
|> put_req_header("accept", "text/html")
|
|
||||||
|> get("/notice/#{activity.id}")
|
|
||||||
|
|
||||||
assert html_response(conn, 302) =~ "redirected"
|
assert html_response(conn, 302) =~ "redirected"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "it requires authentication if instance is NOT federating", %{conn: conn, user: user} do
|
||||||
|
{:ok, activity} = CommonAPI.post(user, %{"status" => "testing a thing!"})
|
||||||
|
|
||||||
|
ensure_federating_or_authenticated(conn, "/notice/#{activity.id}", user)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,8 +5,10 @@
|
||||||
defmodule Pleroma.Web.TwitterAPI.RemoteFollowControllerTest do
|
defmodule Pleroma.Web.TwitterAPI.RemoteFollowControllerTest do
|
||||||
use Pleroma.Web.ConnCase
|
use Pleroma.Web.ConnCase
|
||||||
|
|
||||||
|
alias Pleroma.Config
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
|
|
||||||
import ExUnit.CaptureLog
|
import ExUnit.CaptureLog
|
||||||
import Pleroma.Factory
|
import Pleroma.Factory
|
||||||
|
|
||||||
|
@ -15,6 +17,10 @@ defmodule Pleroma.Web.TwitterAPI.RemoteFollowControllerTest do
|
||||||
:ok
|
:ok
|
||||||
end
|
end
|
||||||
|
|
||||||
|
clear_config_all([:instance, :federating]) do
|
||||||
|
Config.put([:instance, :federating], true)
|
||||||
|
end
|
||||||
|
|
||||||
clear_config([:instance])
|
clear_config([:instance])
|
||||||
clear_config([:frontend_configurations, :pleroma_fe])
|
clear_config([:frontend_configurations, :pleroma_fe])
|
||||||
clear_config([:user, :deny_follow_blocked])
|
clear_config([:user, :deny_follow_blocked])
|
||||||
|
|
|
@ -6,6 +6,7 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do
|
||||||
use Pleroma.Web.ConnCase
|
use Pleroma.Web.ConnCase
|
||||||
use Oban.Testing, repo: Pleroma.Repo
|
use Oban.Testing, repo: Pleroma.Repo
|
||||||
|
|
||||||
|
alias Pleroma.Config
|
||||||
alias Pleroma.Tests.ObanHelpers
|
alias Pleroma.Tests.ObanHelpers
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
|
|
||||||
|
@ -178,7 +179,7 @@ test "it updates notification privacy option", %{user: user, conn: conn} do
|
||||||
|
|
||||||
describe "GET /api/statusnet/config" do
|
describe "GET /api/statusnet/config" do
|
||||||
test "it returns config in xml format", %{conn: conn} do
|
test "it returns config in xml format", %{conn: conn} do
|
||||||
instance = Pleroma.Config.get(:instance)
|
instance = Config.get(:instance)
|
||||||
|
|
||||||
response =
|
response =
|
||||||
conn
|
conn
|
||||||
|
@ -195,12 +196,12 @@ test "it returns config in xml format", %{conn: conn} do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it returns config in json format", %{conn: conn} do
|
test "it returns config in json format", %{conn: conn} do
|
||||||
instance = Pleroma.Config.get(:instance)
|
instance = Config.get(:instance)
|
||||||
Pleroma.Config.put([:instance, :managed_config], true)
|
Config.put([:instance, :managed_config], true)
|
||||||
Pleroma.Config.put([:instance, :registrations_open], false)
|
Config.put([:instance, :registrations_open], false)
|
||||||
Pleroma.Config.put([:instance, :invites_enabled], true)
|
Config.put([:instance, :invites_enabled], true)
|
||||||
Pleroma.Config.put([:instance, :public], false)
|
Config.put([:instance, :public], false)
|
||||||
Pleroma.Config.put([:frontend_configurations, :pleroma_fe], %{theme: "asuka-hospital"})
|
Config.put([:frontend_configurations, :pleroma_fe], %{theme: "asuka-hospital"})
|
||||||
|
|
||||||
response =
|
response =
|
||||||
conn
|
conn
|
||||||
|
@ -234,7 +235,7 @@ test "it returns config in json format", %{conn: conn} do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "returns the state of safe_dm_mentions flag", %{conn: conn} do
|
test "returns the state of safe_dm_mentions flag", %{conn: conn} do
|
||||||
Pleroma.Config.put([:instance, :safe_dm_mentions], true)
|
Config.put([:instance, :safe_dm_mentions], true)
|
||||||
|
|
||||||
response =
|
response =
|
||||||
conn
|
conn
|
||||||
|
@ -243,7 +244,7 @@ test "returns the state of safe_dm_mentions flag", %{conn: conn} do
|
||||||
|
|
||||||
assert response["site"]["safeDMMentionsEnabled"] == "1"
|
assert response["site"]["safeDMMentionsEnabled"] == "1"
|
||||||
|
|
||||||
Pleroma.Config.put([:instance, :safe_dm_mentions], false)
|
Config.put([:instance, :safe_dm_mentions], false)
|
||||||
|
|
||||||
response =
|
response =
|
||||||
conn
|
conn
|
||||||
|
@ -254,8 +255,8 @@ test "returns the state of safe_dm_mentions flag", %{conn: conn} do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it returns the managed config", %{conn: conn} do
|
test "it returns the managed config", %{conn: conn} do
|
||||||
Pleroma.Config.put([:instance, :managed_config], false)
|
Config.put([:instance, :managed_config], false)
|
||||||
Pleroma.Config.put([:frontend_configurations, :pleroma_fe], %{theme: "asuka-hospital"})
|
Config.put([:frontend_configurations, :pleroma_fe], %{theme: "asuka-hospital"})
|
||||||
|
|
||||||
response =
|
response =
|
||||||
conn
|
conn
|
||||||
|
@ -264,7 +265,7 @@ test "it returns the managed config", %{conn: conn} do
|
||||||
|
|
||||||
refute response["site"]["pleromafe"]
|
refute response["site"]["pleromafe"]
|
||||||
|
|
||||||
Pleroma.Config.put([:instance, :managed_config], true)
|
Config.put([:instance, :managed_config], true)
|
||||||
|
|
||||||
response =
|
response =
|
||||||
conn
|
conn
|
||||||
|
@ -287,7 +288,7 @@ test "returns everything in :pleroma, :frontend_configurations", %{conn: conn} d
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
Pleroma.Config.put(:frontend_configurations, config)
|
Config.put(:frontend_configurations, config)
|
||||||
|
|
||||||
response =
|
response =
|
||||||
conn
|
conn
|
||||||
|
@ -320,7 +321,7 @@ test "returns json with custom emoji with tags", %{conn: conn} do
|
||||||
clear_config([:instance, :healthcheck])
|
clear_config([:instance, :healthcheck])
|
||||||
|
|
||||||
test "returns 503 when healthcheck disabled", %{conn: conn} do
|
test "returns 503 when healthcheck disabled", %{conn: conn} do
|
||||||
Pleroma.Config.put([:instance, :healthcheck], false)
|
Config.put([:instance, :healthcheck], false)
|
||||||
|
|
||||||
response =
|
response =
|
||||||
conn
|
conn
|
||||||
|
@ -331,7 +332,7 @@ test "returns 503 when healthcheck disabled", %{conn: conn} do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "returns 200 when healthcheck enabled and all ok", %{conn: conn} do
|
test "returns 200 when healthcheck enabled and all ok", %{conn: conn} do
|
||||||
Pleroma.Config.put([:instance, :healthcheck], true)
|
Config.put([:instance, :healthcheck], true)
|
||||||
|
|
||||||
with_mock Pleroma.Healthcheck,
|
with_mock Pleroma.Healthcheck,
|
||||||
system_info: fn -> %Pleroma.Healthcheck{healthy: true} end do
|
system_info: fn -> %Pleroma.Healthcheck{healthy: true} end do
|
||||||
|
@ -351,7 +352,7 @@ test "returns 200 when healthcheck enabled and all ok", %{conn: conn} do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "returns 503 when healthcheck enabled and health is false", %{conn: conn} do
|
test "returns 503 when healthcheck enabled and health is false", %{conn: conn} do
|
||||||
Pleroma.Config.put([:instance, :healthcheck], true)
|
Config.put([:instance, :healthcheck], true)
|
||||||
|
|
||||||
with_mock Pleroma.Healthcheck,
|
with_mock Pleroma.Healthcheck,
|
||||||
system_info: fn -> %Pleroma.Healthcheck{healthy: false} end do
|
system_info: fn -> %Pleroma.Healthcheck{healthy: false} end do
|
||||||
|
@ -426,6 +427,10 @@ test "it returns version in json format", %{conn: conn} do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "POST /main/ostatus - remote_subscribe/2" do
|
describe "POST /main/ostatus - remote_subscribe/2" do
|
||||||
|
clear_config([:instance, :federating]) do
|
||||||
|
Config.put([:instance, :federating], true)
|
||||||
|
end
|
||||||
|
|
||||||
test "renders subscribe form", %{conn: conn} do
|
test "renders subscribe form", %{conn: conn} do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue