Merge branch 'split-masto-api/accounts' into 'develop'
Extract account actions from `MastodonAPIController` to `AccountController` See merge request pleroma/pleroma!1731
This commit is contained in:
commit
905bb11747
|
@ -84,22 +84,11 @@ def get_lists_from_activity(%Activity{actor: ap_id}) do
|
||||||
end
|
end
|
||||||
|
|
||||||
# Get lists to which the account belongs.
|
# Get lists to which the account belongs.
|
||||||
def get_lists_account_belongs(%User{} = owner, account_id) do
|
def get_lists_account_belongs(%User{} = owner, user) do
|
||||||
user = User.get_cached_by_id(account_id)
|
Pleroma.List
|
||||||
|
|> where([l], l.user_id == ^owner.id)
|
||||||
query =
|
|> where([l], fragment("? = ANY(?)", ^user.follower_address, l.following))
|
||||||
from(
|
|> Repo.all()
|
||||||
l in Pleroma.List,
|
|
||||||
where:
|
|
||||||
l.user_id == ^owner.id and
|
|
||||||
fragment(
|
|
||||||
"? = ANY(?)",
|
|
||||||
^user.follower_address,
|
|
||||||
l.following
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
Repo.all(query)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def rename(%Pleroma.List{} = list, title) do
|
def rename(%Pleroma.List{} = list, title) do
|
||||||
|
|
|
@ -43,7 +43,7 @@ def render("show.json", %{report: report, user: user, account: account, statuses
|
||||||
end
|
end
|
||||||
|
|
||||||
defp merge_account_views(%User{} = user) do
|
defp merge_account_views(%User{} = user) do
|
||||||
Pleroma.Web.MastodonAPI.AccountView.render("account.json", %{user: user})
|
Pleroma.Web.MastodonAPI.AccountView.render("show.json", %{user: user})
|
||||||
|> Map.merge(Pleroma.Web.AdminAPI.AccountView.render("show.json", %{user: user}))
|
|> Map.merge(Pleroma.Web.AdminAPI.AccountView.render("show.json", %{user: user}))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ def handle_in("new_msg", %{"text" => text}, %{assigns: %{user_name: user_name}}
|
||||||
|
|
||||||
if String.length(text) > 0 do
|
if String.length(text) > 0 do
|
||||||
author = User.get_cached_by_nickname(user_name)
|
author = User.get_cached_by_nickname(user_name)
|
||||||
author = Pleroma.Web.MastodonAPI.AccountView.render("account.json", user: author)
|
author = Pleroma.Web.MastodonAPI.AccountView.render("show.json", user: author)
|
||||||
message = ChatChannelState.add_message(%{text: text, author: author})
|
message = ChatChannelState.add_message(%{text: text, author: author})
|
||||||
|
|
||||||
broadcast!(socket, "new_msg", message)
|
broadcast!(socket, "new_msg", message)
|
||||||
|
|
|
@ -68,4 +68,11 @@ def add_link_headers(conn, activities, extra_params \\ %{}) do
|
||||||
conn
|
conn
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def assign_account_by_id(%{params: %{"id" => id}} = conn, _) do
|
||||||
|
case Pleroma.User.get_cached_by_id(id) do
|
||||||
|
%Pleroma.User{} = account -> assign(conn, :account, account)
|
||||||
|
nil -> Pleroma.Web.MastodonAPI.FallbackController.call(conn, {:error, :not_found}) |> halt()
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,304 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.MastodonAPI.AccountController do
|
||||||
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
|
import Pleroma.Web.ControllerHelper,
|
||||||
|
only: [add_link_headers: 2, truthy_param?: 1, assign_account_by_id: 2, json_response: 3]
|
||||||
|
|
||||||
|
alias Pleroma.Emoji
|
||||||
|
alias Pleroma.Plugs.RateLimiter
|
||||||
|
alias Pleroma.User
|
||||||
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
|
alias Pleroma.Web.CommonAPI
|
||||||
|
alias Pleroma.Web.MastodonAPI.ListView
|
||||||
|
alias Pleroma.Web.MastodonAPI.MastodonAPI
|
||||||
|
alias Pleroma.Web.MastodonAPI.StatusView
|
||||||
|
alias Pleroma.Web.OAuth.Token
|
||||||
|
alias Pleroma.Web.TwitterAPI.TwitterAPI
|
||||||
|
|
||||||
|
@relations [:follow, :unfollow]
|
||||||
|
@needs_account ~W(followers following lists follow unfollow mute unmute block unblock)a
|
||||||
|
|
||||||
|
plug(RateLimiter, {:relations_id_action, params: ["id", "uri"]} when action in @relations)
|
||||||
|
plug(RateLimiter, :relations_actions when action in @relations)
|
||||||
|
plug(RateLimiter, :app_account_creation when action == :create)
|
||||||
|
plug(:assign_account_by_id when action in @needs_account)
|
||||||
|
|
||||||
|
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
||||||
|
|
||||||
|
@doc "POST /api/v1/accounts"
|
||||||
|
def create(
|
||||||
|
%{assigns: %{app: app}} = conn,
|
||||||
|
%{"username" => nickname, "email" => _, "password" => _, "agreement" => true} = params
|
||||||
|
) do
|
||||||
|
params =
|
||||||
|
params
|
||||||
|
|> Map.take([
|
||||||
|
"email",
|
||||||
|
"captcha_solution",
|
||||||
|
"captcha_token",
|
||||||
|
"captcha_answer_data",
|
||||||
|
"token",
|
||||||
|
"password"
|
||||||
|
])
|
||||||
|
|> Map.put("nickname", nickname)
|
||||||
|
|> Map.put("fullname", params["fullname"] || nickname)
|
||||||
|
|> Map.put("bio", params["bio"] || "")
|
||||||
|
|> Map.put("confirm", params["password"])
|
||||||
|
|
||||||
|
with {:ok, user} <- TwitterAPI.register_user(params, need_confirmation: true),
|
||||||
|
{:ok, token} <- Token.create_token(app, user, %{scopes: app.scopes}) do
|
||||||
|
json(conn, %{
|
||||||
|
token_type: "Bearer",
|
||||||
|
access_token: token.token,
|
||||||
|
scope: app.scopes,
|
||||||
|
created_at: Token.Utils.format_created_at(token)
|
||||||
|
})
|
||||||
|
else
|
||||||
|
{:error, errors} -> json_response(conn, :bad_request, errors)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def create(%{assigns: %{app: _app}} = conn, _) do
|
||||||
|
render_error(conn, :bad_request, "Missing parameters")
|
||||||
|
end
|
||||||
|
|
||||||
|
def create(conn, _) do
|
||||||
|
render_error(conn, :forbidden, "Invalid credentials")
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc "GET /api/v1/accounts/verify_credentials"
|
||||||
|
def verify_credentials(%{assigns: %{user: user}} = conn, _) do
|
||||||
|
chat_token = Phoenix.Token.sign(conn, "user socket", user.id)
|
||||||
|
|
||||||
|
render(conn, "show.json",
|
||||||
|
user: user,
|
||||||
|
for: user,
|
||||||
|
with_pleroma_settings: true,
|
||||||
|
with_chat_token: chat_token
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc "PATCH /api/v1/accounts/update_credentials"
|
||||||
|
def update_credentials(%{assigns: %{user: original_user}} = conn, params) do
|
||||||
|
user = original_user
|
||||||
|
|
||||||
|
user_params =
|
||||||
|
%{}
|
||||||
|
|> add_if_present(params, "display_name", :name)
|
||||||
|
|> add_if_present(params, "note", :bio, fn value -> {:ok, User.parse_bio(value, user)} end)
|
||||||
|
|> add_if_present(params, "avatar", :avatar, fn value ->
|
||||||
|
with %Plug.Upload{} <- value,
|
||||||
|
{:ok, object} <- ActivityPub.upload(value, type: :avatar) do
|
||||||
|
{:ok, object.data}
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
emojis_text = (user_params["display_name"] || "") <> (user_params["note"] || "")
|
||||||
|
|
||||||
|
user_info_emojis =
|
||||||
|
user.info
|
||||||
|
|> Map.get(:emoji, [])
|
||||||
|
|> Enum.concat(Emoji.Formatter.get_emoji_map(emojis_text))
|
||||||
|
|> Enum.dedup()
|
||||||
|
|
||||||
|
info_params =
|
||||||
|
[
|
||||||
|
:no_rich_text,
|
||||||
|
:locked,
|
||||||
|
:hide_followers_count,
|
||||||
|
:hide_follows_count,
|
||||||
|
:hide_followers,
|
||||||
|
:hide_follows,
|
||||||
|
:hide_favorites,
|
||||||
|
:show_role,
|
||||||
|
:skip_thread_containment,
|
||||||
|
:discoverable
|
||||||
|
]
|
||||||
|
|> Enum.reduce(%{}, fn key, acc ->
|
||||||
|
add_if_present(acc, params, to_string(key), key, &{:ok, truthy_param?(&1)})
|
||||||
|
end)
|
||||||
|
|> add_if_present(params, "default_scope", :default_scope)
|
||||||
|
|> add_if_present(params, "fields", :fields, fn fields ->
|
||||||
|
fields = Enum.map(fields, fn f -> Map.update!(f, "value", &AutoLinker.link(&1)) end)
|
||||||
|
|
||||||
|
{:ok, fields}
|
||||||
|
end)
|
||||||
|
|> add_if_present(params, "fields", :raw_fields)
|
||||||
|
|> add_if_present(params, "pleroma_settings_store", :pleroma_settings_store, fn value ->
|
||||||
|
{:ok, Map.merge(user.info.pleroma_settings_store, value)}
|
||||||
|
end)
|
||||||
|
|> add_if_present(params, "header", :banner, fn value ->
|
||||||
|
with %Plug.Upload{} <- value,
|
||||||
|
{:ok, object} <- ActivityPub.upload(value, type: :banner) do
|
||||||
|
{:ok, object.data}
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|> add_if_present(params, "pleroma_background_image", :background, fn value ->
|
||||||
|
with %Plug.Upload{} <- value,
|
||||||
|
{:ok, object} <- ActivityPub.upload(value, type: :background) do
|
||||||
|
{:ok, object.data}
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|> Map.put(:emoji, user_info_emojis)
|
||||||
|
|
||||||
|
changeset =
|
||||||
|
user
|
||||||
|
|> User.update_changeset(user_params)
|
||||||
|
|> User.change_info(&User.Info.profile_update(&1, info_params))
|
||||||
|
|
||||||
|
with {:ok, user} <- User.update_and_set_cache(changeset) do
|
||||||
|
if original_user != user, do: CommonAPI.update(user)
|
||||||
|
|
||||||
|
render(conn, "show.json", user: user, for: user, with_pleroma_settings: true)
|
||||||
|
else
|
||||||
|
_e -> render_error(conn, :forbidden, "Invalid request")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp add_if_present(map, params, params_field, map_field, value_function \\ &{:ok, &1}) do
|
||||||
|
with true <- Map.has_key?(params, params_field),
|
||||||
|
{:ok, new_value} <- value_function.(params[params_field]) do
|
||||||
|
Map.put(map, map_field, new_value)
|
||||||
|
else
|
||||||
|
_ -> map
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc "GET /api/v1/accounts/relationships"
|
||||||
|
def relationships(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||||
|
targets = User.get_all_by_ids(List.wrap(id))
|
||||||
|
|
||||||
|
render(conn, "relationships.json", user: user, targets: targets)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Instead of returning a 400 when no "id" params is present, Mastodon returns an empty array.
|
||||||
|
def relationships(%{assigns: %{user: _user}} = conn, _), do: json(conn, [])
|
||||||
|
|
||||||
|
@doc "GET /api/v1/accounts/:id"
|
||||||
|
def show(%{assigns: %{user: for_user}} = conn, %{"id" => nickname_or_id}) do
|
||||||
|
with %User{} = user <- User.get_cached_by_nickname_or_id(nickname_or_id, for: for_user),
|
||||||
|
true <- User.auth_active?(user) || user.id == for_user.id || User.superuser?(for_user) do
|
||||||
|
render(conn, "show.json", user: user, for: for_user)
|
||||||
|
else
|
||||||
|
_e -> render_error(conn, :not_found, "Can't find user")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc "GET /api/v1/accounts/:id/statuses"
|
||||||
|
def statuses(%{assigns: %{user: reading_user}} = conn, params) do
|
||||||
|
with %User{} = user <- User.get_cached_by_nickname_or_id(params["id"], for: reading_user) do
|
||||||
|
params = Map.put(params, "tag", params["tagged"])
|
||||||
|
activities = ActivityPub.fetch_user_activities(user, reading_user, params)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> add_link_headers(activities)
|
||||||
|
|> put_view(StatusView)
|
||||||
|
|> render("index.json", activities: activities, for: reading_user, as: :activity)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc "GET /api/v1/accounts/:id/followers"
|
||||||
|
def followers(%{assigns: %{user: for_user, account: user}} = conn, params) do
|
||||||
|
followers =
|
||||||
|
cond do
|
||||||
|
for_user && user.id == for_user.id -> MastodonAPI.get_followers(user, params)
|
||||||
|
user.info.hide_followers -> []
|
||||||
|
true -> MastodonAPI.get_followers(user, params)
|
||||||
|
end
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> add_link_headers(followers)
|
||||||
|
|> render("index.json", for: for_user, users: followers, as: :user)
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc "GET /api/v1/accounts/:id/following"
|
||||||
|
def following(%{assigns: %{user: for_user, account: user}} = conn, params) do
|
||||||
|
followers =
|
||||||
|
cond do
|
||||||
|
for_user && user.id == for_user.id -> MastodonAPI.get_friends(user, params)
|
||||||
|
user.info.hide_follows -> []
|
||||||
|
true -> MastodonAPI.get_friends(user, params)
|
||||||
|
end
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> add_link_headers(followers)
|
||||||
|
|> render("index.json", for: for_user, users: followers, as: :user)
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc "GET /api/v1/accounts/:id/lists"
|
||||||
|
def lists(%{assigns: %{user: user, account: account}} = conn, _params) do
|
||||||
|
lists = Pleroma.List.get_lists_account_belongs(user, account)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_view(ListView)
|
||||||
|
|> render("index.json", lists: lists)
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc "POST /api/v1/accounts/:id/follow"
|
||||||
|
def follow(%{assigns: %{user: %{id: id}, account: %{id: id}}}, _params) do
|
||||||
|
{:error, :not_found}
|
||||||
|
end
|
||||||
|
|
||||||
|
def follow(%{assigns: %{user: follower, account: followed}} = conn, _params) do
|
||||||
|
with {:ok, follower} <- MastodonAPI.follow(follower, followed, conn.params) do
|
||||||
|
render(conn, "relationship.json", user: follower, target: followed)
|
||||||
|
else
|
||||||
|
{:error, message} -> json_response(conn, :forbidden, %{error: message})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc "POST /api/v1/accounts/:id/unfollow"
|
||||||
|
def unfollow(%{assigns: %{user: %{id: id}, account: %{id: id}}}, _params) do
|
||||||
|
{:error, :not_found}
|
||||||
|
end
|
||||||
|
|
||||||
|
def unfollow(%{assigns: %{user: follower, account: followed}} = conn, _params) do
|
||||||
|
with {:ok, follower} <- CommonAPI.unfollow(follower, followed) do
|
||||||
|
render(conn, "relationship.json", user: follower, target: followed)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc "POST /api/v1/accounts/:id/mute"
|
||||||
|
def mute(%{assigns: %{user: muter, account: muted}} = conn, params) do
|
||||||
|
notifications? = params |> Map.get("notifications", true) |> truthy_param?()
|
||||||
|
|
||||||
|
with {:ok, muter} <- User.mute(muter, muted, notifications?) do
|
||||||
|
render(conn, "relationship.json", user: muter, target: muted)
|
||||||
|
else
|
||||||
|
{:error, message} -> json_response(conn, :forbidden, %{error: message})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc "POST /api/v1/accounts/:id/unmute"
|
||||||
|
def unmute(%{assigns: %{user: muter, account: muted}} = conn, _params) do
|
||||||
|
with {:ok, muter} <- User.unmute(muter, muted) do
|
||||||
|
render(conn, "relationship.json", user: muter, target: muted)
|
||||||
|
else
|
||||||
|
{:error, message} -> json_response(conn, :forbidden, %{error: message})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc "POST /api/v1/accounts/:id/block"
|
||||||
|
def block(%{assigns: %{user: blocker, account: blocked}} = conn, _params) do
|
||||||
|
with {:ok, blocker} <- User.block(blocker, blocked),
|
||||||
|
{:ok, _activity} <- ActivityPub.block(blocker, blocked) do
|
||||||
|
render(conn, "relationship.json", user: blocker, target: blocked)
|
||||||
|
else
|
||||||
|
{:error, message} -> json_response(conn, :forbidden, %{error: message})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc "POST /api/v1/accounts/:id/unblock"
|
||||||
|
def unblock(%{assigns: %{user: blocker, account: blocked}} = conn, _params) do
|
||||||
|
with {:ok, blocker} <- User.unblock(blocker, blocked),
|
||||||
|
{:ok, _activity} <- ActivityPub.unblock(blocker, blocked) do
|
||||||
|
render(conn, "relationship.json", user: blocker, target: blocked)
|
||||||
|
else
|
||||||
|
{:error, message} -> json_response(conn, :forbidden, %{error: message})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -17,7 +17,7 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestController do
|
||||||
def index(%{assigns: %{user: followed}} = conn, _params) do
|
def index(%{assigns: %{user: followed}} = conn, _params) do
|
||||||
follow_requests = User.get_follow_requests(followed)
|
follow_requests = User.get_follow_requests(followed)
|
||||||
|
|
||||||
render(conn, "accounts.json", for: followed, users: follow_requests, as: :user)
|
render(conn, "index.json", for: followed, users: follow_requests, as: :user)
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc "POST /api/v1/follow_requests/:id/authorize"
|
@doc "POST /api/v1/follow_requests/:id/authorize"
|
||||||
|
|
|
@ -49,7 +49,7 @@ def list_accounts(%{assigns: %{user: user, list: list}} = conn, _) do
|
||||||
with {:ok, users} <- Pleroma.List.get_following(list) do
|
with {:ok, users} <- Pleroma.List.get_following(list) do
|
||||||
conn
|
conn
|
||||||
|> put_view(AccountView)
|
|> put_view(AccountView)
|
||||||
|> render("accounts.json", for: user, users: users, as: :user)
|
|> render("index.json", for: user, users: users, as: :user)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -5,14 +5,11 @@
|
||||||
defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
||||||
use Pleroma.Web, :controller
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
import Pleroma.Web.ControllerHelper,
|
import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2]
|
||||||
only: [json_response: 3, add_link_headers: 2, truthy_param?: 1]
|
|
||||||
|
|
||||||
alias Ecto.Changeset
|
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
alias Pleroma.Bookmark
|
alias Pleroma.Bookmark
|
||||||
alias Pleroma.Config
|
alias Pleroma.Config
|
||||||
alias Pleroma.Emoji
|
|
||||||
alias Pleroma.HTTP
|
alias Pleroma.HTTP
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
alias Pleroma.Pagination
|
alias Pleroma.Pagination
|
||||||
|
@ -26,8 +23,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
alias Pleroma.Web.MastodonAPI.AccountView
|
alias Pleroma.Web.MastodonAPI.AccountView
|
||||||
alias Pleroma.Web.MastodonAPI.AppView
|
alias Pleroma.Web.MastodonAPI.AppView
|
||||||
alias Pleroma.Web.MastodonAPI.ListView
|
|
||||||
alias Pleroma.Web.MastodonAPI.MastodonAPI
|
|
||||||
alias Pleroma.Web.MastodonAPI.MastodonView
|
alias Pleroma.Web.MastodonAPI.MastodonView
|
||||||
alias Pleroma.Web.MastodonAPI.StatusView
|
alias Pleroma.Web.MastodonAPI.StatusView
|
||||||
alias Pleroma.Web.MediaProxy
|
alias Pleroma.Web.MediaProxy
|
||||||
|
@ -38,20 +33,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
||||||
alias Pleroma.Web.TwitterAPI.TwitterAPI
|
alias Pleroma.Web.TwitterAPI.TwitterAPI
|
||||||
|
|
||||||
require Logger
|
require Logger
|
||||||
require Pleroma.Constants
|
|
||||||
|
|
||||||
@rate_limited_relations_actions ~w(follow unfollow)a
|
|
||||||
|
|
||||||
plug(
|
|
||||||
RateLimiter,
|
|
||||||
{:relations_id_action, params: ["id", "uri"]} when action in @rate_limited_relations_actions
|
|
||||||
)
|
|
||||||
|
|
||||||
plug(RateLimiter, :relations_actions when action in @rate_limited_relations_actions)
|
|
||||||
plug(RateLimiter, :app_account_creation when action == :account_register)
|
|
||||||
plug(RateLimiter, :search when action in [:search, :search2, :account_search])
|
|
||||||
plug(RateLimiter, :password_reset when action == :password_reset)
|
plug(RateLimiter, :password_reset when action == :password_reset)
|
||||||
plug(RateLimiter, :account_confirmation_resend when action == :account_confirmation_resend)
|
|
||||||
|
|
||||||
@local_mastodon_name "Mastodon-Local"
|
@local_mastodon_name "Mastodon-Local"
|
||||||
|
|
||||||
|
@ -74,180 +57,6 @@ def create_app(conn, params) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp add_if_present(
|
|
||||||
map,
|
|
||||||
params,
|
|
||||||
params_field,
|
|
||||||
map_field,
|
|
||||||
value_function \\ fn x -> {:ok, x} end
|
|
||||||
) do
|
|
||||||
if Map.has_key?(params, params_field) do
|
|
||||||
case value_function.(params[params_field]) do
|
|
||||||
{:ok, new_value} -> Map.put(map, map_field, new_value)
|
|
||||||
:error -> map
|
|
||||||
end
|
|
||||||
else
|
|
||||||
map
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def update_credentials(%{assigns: %{user: user}} = conn, params) do
|
|
||||||
original_user = user
|
|
||||||
|
|
||||||
user_params =
|
|
||||||
%{}
|
|
||||||
|> add_if_present(params, "display_name", :name)
|
|
||||||
|> add_if_present(params, "note", :bio, fn value -> {:ok, User.parse_bio(value, user)} end)
|
|
||||||
|> add_if_present(params, "avatar", :avatar, fn value ->
|
|
||||||
with %Plug.Upload{} <- value,
|
|
||||||
{:ok, object} <- ActivityPub.upload(value, type: :avatar) do
|
|
||||||
{:ok, object.data}
|
|
||||||
else
|
|
||||||
_ -> :error
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
emojis_text = (user_params["display_name"] || "") <> (user_params["note"] || "")
|
|
||||||
|
|
||||||
user_info_emojis =
|
|
||||||
user.info
|
|
||||||
|> Map.get(:emoji, [])
|
|
||||||
|> Enum.concat(Emoji.Formatter.get_emoji_map(emojis_text))
|
|
||||||
|> Enum.dedup()
|
|
||||||
|
|
||||||
info_params =
|
|
||||||
[
|
|
||||||
:no_rich_text,
|
|
||||||
:locked,
|
|
||||||
:hide_followers_count,
|
|
||||||
:hide_follows_count,
|
|
||||||
:hide_followers,
|
|
||||||
:hide_follows,
|
|
||||||
:hide_favorites,
|
|
||||||
:show_role,
|
|
||||||
:skip_thread_containment,
|
|
||||||
:discoverable
|
|
||||||
]
|
|
||||||
|> Enum.reduce(%{}, fn key, acc ->
|
|
||||||
add_if_present(acc, params, to_string(key), key, fn value ->
|
|
||||||
{:ok, truthy_param?(value)}
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
|> add_if_present(params, "default_scope", :default_scope)
|
|
||||||
|> add_if_present(params, "fields", :fields, fn fields ->
|
|
||||||
fields = Enum.map(fields, fn f -> Map.update!(f, "value", &AutoLinker.link(&1)) end)
|
|
||||||
|
|
||||||
{:ok, fields}
|
|
||||||
end)
|
|
||||||
|> add_if_present(params, "fields", :raw_fields)
|
|
||||||
|> add_if_present(params, "pleroma_settings_store", :pleroma_settings_store, fn value ->
|
|
||||||
{:ok, Map.merge(user.info.pleroma_settings_store, value)}
|
|
||||||
end)
|
|
||||||
|> add_if_present(params, "header", :banner, fn value ->
|
|
||||||
with %Plug.Upload{} <- value,
|
|
||||||
{:ok, object} <- ActivityPub.upload(value, type: :banner) do
|
|
||||||
{:ok, object.data}
|
|
||||||
else
|
|
||||||
_ -> :error
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|> add_if_present(params, "pleroma_background_image", :background, fn value ->
|
|
||||||
with %Plug.Upload{} <- value,
|
|
||||||
{:ok, object} <- ActivityPub.upload(value, type: :background) do
|
|
||||||
{:ok, object.data}
|
|
||||||
else
|
|
||||||
_ -> :error
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|> Map.put(:emoji, user_info_emojis)
|
|
||||||
|
|
||||||
changeset =
|
|
||||||
user
|
|
||||||
|> User.update_changeset(user_params)
|
|
||||||
|> User.change_info(&User.Info.profile_update(&1, info_params))
|
|
||||||
|
|
||||||
with {:ok, user} <- User.update_and_set_cache(changeset) do
|
|
||||||
if original_user != user, do: CommonAPI.update(user)
|
|
||||||
|
|
||||||
json(
|
|
||||||
conn,
|
|
||||||
AccountView.render("account.json", %{user: user, for: user, with_pleroma_settings: true})
|
|
||||||
)
|
|
||||||
else
|
|
||||||
_e -> render_error(conn, :forbidden, "Invalid request")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def update_avatar(%{assigns: %{user: user}} = conn, %{"img" => ""}) do
|
|
||||||
change = Changeset.change(user, %{avatar: nil})
|
|
||||||
{:ok, user} = User.update_and_set_cache(change)
|
|
||||||
CommonAPI.update(user)
|
|
||||||
|
|
||||||
json(conn, %{url: nil})
|
|
||||||
end
|
|
||||||
|
|
||||||
def update_avatar(%{assigns: %{user: user}} = conn, params) do
|
|
||||||
{:ok, object} = ActivityPub.upload(params, type: :avatar)
|
|
||||||
change = Changeset.change(user, %{avatar: object.data})
|
|
||||||
{:ok, user} = User.update_and_set_cache(change)
|
|
||||||
CommonAPI.update(user)
|
|
||||||
%{"url" => [%{"href" => href} | _]} = object.data
|
|
||||||
|
|
||||||
json(conn, %{url: href})
|
|
||||||
end
|
|
||||||
|
|
||||||
def update_banner(%{assigns: %{user: user}} = conn, %{"banner" => ""}) do
|
|
||||||
new_info = %{"banner" => %{}}
|
|
||||||
|
|
||||||
with {:ok, user} <- User.update_info(user, &User.Info.profile_update(&1, new_info)) do
|
|
||||||
CommonAPI.update(user)
|
|
||||||
json(conn, %{url: nil})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def update_banner(%{assigns: %{user: user}} = conn, params) do
|
|
||||||
with {:ok, object} <- ActivityPub.upload(%{"img" => params["banner"]}, type: :banner),
|
|
||||||
new_info <- %{"banner" => object.data},
|
|
||||||
{:ok, user} <- User.update_info(user, &User.Info.profile_update(&1, new_info)) do
|
|
||||||
CommonAPI.update(user)
|
|
||||||
%{"url" => [%{"href" => href} | _]} = object.data
|
|
||||||
|
|
||||||
json(conn, %{url: href})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def update_background(%{assigns: %{user: user}} = conn, %{"img" => ""}) do
|
|
||||||
new_info = %{"background" => %{}}
|
|
||||||
|
|
||||||
with {:ok, _user} <- User.update_info(user, &User.Info.profile_update(&1, new_info)) do
|
|
||||||
json(conn, %{url: nil})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def update_background(%{assigns: %{user: user}} = conn, params) do
|
|
||||||
with {:ok, object} <- ActivityPub.upload(params, type: :background),
|
|
||||||
new_info <- %{"background" => object.data},
|
|
||||||
{:ok, _user} <- User.update_info(user, &User.Info.profile_update(&1, new_info)) do
|
|
||||||
%{"url" => [%{"href" => href} | _]} = object.data
|
|
||||||
|
|
||||||
json(conn, %{url: href})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def verify_credentials(%{assigns: %{user: user}} = conn, _) do
|
|
||||||
chat_token = Phoenix.Token.sign(conn, "user socket", user.id)
|
|
||||||
|
|
||||||
account =
|
|
||||||
AccountView.render("account.json", %{
|
|
||||||
user: user,
|
|
||||||
for: user,
|
|
||||||
with_pleroma_settings: true,
|
|
||||||
with_chat_token: chat_token
|
|
||||||
})
|
|
||||||
|
|
||||||
json(conn, account)
|
|
||||||
end
|
|
||||||
|
|
||||||
def verify_app_credentials(%{assigns: %{user: _user, token: token}} = conn, _) do
|
def verify_app_credentials(%{assigns: %{user: _user, token: token}} = conn, _) do
|
||||||
with %Token{app: %App{} = app} <- Repo.preload(token, :app) do
|
with %Token{app: %App{} = app} <- Repo.preload(token, :app) do
|
||||||
conn
|
conn
|
||||||
|
@ -256,16 +65,6 @@ def verify_app_credentials(%{assigns: %{user: _user, token: token}} = conn, _) d
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def user(%{assigns: %{user: for_user}} = conn, %{"id" => nickname_or_id}) do
|
|
||||||
with %User{} = user <- User.get_cached_by_nickname_or_id(nickname_or_id, for: for_user),
|
|
||||||
true <- User.auth_active?(user) || user.id == for_user.id || User.superuser?(for_user) do
|
|
||||||
account = AccountView.render("account.json", %{user: user, for: for_user})
|
|
||||||
json(conn, account)
|
|
||||||
else
|
|
||||||
_e -> render_error(conn, :not_found, "Can't find user")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
@mastodon_api_level "2.7.2"
|
@mastodon_api_level "2.7.2"
|
||||||
|
|
||||||
def masto_instance(conn, _params) do
|
def masto_instance(conn, _params) do
|
||||||
|
@ -318,25 +117,6 @@ def custom_emojis(conn, _params) do
|
||||||
json(conn, mastodon_emoji)
|
json(conn, mastodon_emoji)
|
||||||
end
|
end
|
||||||
|
|
||||||
def user_statuses(%{assigns: %{user: reading_user}} = conn, params) do
|
|
||||||
with %User{} = user <- User.get_cached_by_nickname_or_id(params["id"], for: reading_user) do
|
|
||||||
params =
|
|
||||||
params
|
|
||||||
|> Map.put("tag", params["tagged"])
|
|
||||||
|
|
||||||
activities = ActivityPub.fetch_user_activities(user, reading_user, params)
|
|
||||||
|
|
||||||
conn
|
|
||||||
|> add_link_headers(activities)
|
|
||||||
|> put_view(StatusView)
|
|
||||||
|> render("index.json", %{
|
|
||||||
activities: activities,
|
|
||||||
for: reading_user,
|
|
||||||
as: :activity
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def get_poll(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
def get_poll(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||||
with %Object{} = object <- Object.get_by_id_and_maybe_refetch(id, interval: 60),
|
with %Object{} = object <- Object.get_by_id_and_maybe_refetch(id, interval: 60),
|
||||||
%Activity{} = activity <- Activity.get_create_by_object_ap_id(object.data["id"]),
|
%Activity{} = activity <- Activity.get_create_by_object_ap_id(object.data["id"]),
|
||||||
|
@ -387,17 +167,6 @@ def poll_vote(%{assigns: %{user: user}} = conn, %{"id" => id, "choices" => choic
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def relationships(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
|
||||||
targets = User.get_all_by_ids(List.wrap(id))
|
|
||||||
|
|
||||||
conn
|
|
||||||
|> put_view(AccountView)
|
|
||||||
|> render("relationships.json", %{user: user, targets: targets})
|
|
||||||
end
|
|
||||||
|
|
||||||
# Instead of returning a 400 when no "id" params is present, Mastodon returns an empty array.
|
|
||||||
def relationships(%{assigns: %{user: _user}} = conn, _), do: json(conn, [])
|
|
||||||
|
|
||||||
def update_media(
|
def update_media(
|
||||||
%{assigns: %{user: user}} = conn,
|
%{assigns: %{user: user}} = conn,
|
||||||
%{"id" => id, "description" => description} = _
|
%{"id" => id, "description" => description} = _
|
||||||
|
@ -453,65 +222,13 @@ def get_mascot(%{assigns: %{user: user}} = conn, _params) do
|
||||||
json(conn, mascot)
|
json(conn, mascot)
|
||||||
end
|
end
|
||||||
|
|
||||||
def followers(%{assigns: %{user: for_user}} = conn, %{"id" => id} = params) do
|
def follows(%{assigns: %{user: follower}} = conn, %{"uri" => uri}) do
|
||||||
with %User{} = user <- User.get_cached_by_id(id),
|
|
||||||
followers <- MastodonAPI.get_followers(user, params) do
|
|
||||||
followers =
|
|
||||||
cond do
|
|
||||||
for_user && user.id == for_user.id -> followers
|
|
||||||
user.info.hide_followers -> []
|
|
||||||
true -> followers
|
|
||||||
end
|
|
||||||
|
|
||||||
conn
|
|
||||||
|> add_link_headers(followers)
|
|
||||||
|> put_view(AccountView)
|
|
||||||
|> render("accounts.json", %{for: for_user, users: followers, as: :user})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def following(%{assigns: %{user: for_user}} = conn, %{"id" => id} = params) do
|
|
||||||
with %User{} = user <- User.get_cached_by_id(id),
|
|
||||||
followers <- MastodonAPI.get_friends(user, params) do
|
|
||||||
followers =
|
|
||||||
cond do
|
|
||||||
for_user && user.id == for_user.id -> followers
|
|
||||||
user.info.hide_follows -> []
|
|
||||||
true -> followers
|
|
||||||
end
|
|
||||||
|
|
||||||
conn
|
|
||||||
|> add_link_headers(followers)
|
|
||||||
|> put_view(AccountView)
|
|
||||||
|> render("accounts.json", %{for: for_user, users: followers, as: :user})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def follow(%{assigns: %{user: follower}} = conn, %{"id" => id}) do
|
|
||||||
with {_, %User{} = followed} <- {:followed, User.get_cached_by_id(id)},
|
|
||||||
{_, true} <- {:followed, follower.id != followed.id},
|
|
||||||
{:ok, follower} <- MastodonAPI.follow(follower, followed, conn.params) do
|
|
||||||
conn
|
|
||||||
|> put_view(AccountView)
|
|
||||||
|> render("relationship.json", %{user: follower, target: followed})
|
|
||||||
else
|
|
||||||
{:followed, _} ->
|
|
||||||
{:error, :not_found}
|
|
||||||
|
|
||||||
{:error, message} ->
|
|
||||||
conn
|
|
||||||
|> put_status(:forbidden)
|
|
||||||
|> json(%{error: message})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def follow(%{assigns: %{user: follower}} = conn, %{"uri" => uri}) do
|
|
||||||
with {_, %User{} = followed} <- {:followed, User.get_cached_by_nickname(uri)},
|
with {_, %User{} = followed} <- {:followed, User.get_cached_by_nickname(uri)},
|
||||||
{_, true} <- {:followed, follower.id != followed.id},
|
{_, true} <- {:followed, follower.id != followed.id},
|
||||||
{:ok, follower, followed, _} <- CommonAPI.follow(follower, followed) do
|
{:ok, follower, followed, _} <- CommonAPI.follow(follower, followed) do
|
||||||
conn
|
conn
|
||||||
|> put_view(AccountView)
|
|> put_view(AccountView)
|
||||||
|> render("account.json", %{user: followed, for: follower})
|
|> render("show.json", %{user: followed, for: follower})
|
||||||
else
|
else
|
||||||
{:followed, _} ->
|
{:followed, _} ->
|
||||||
{:error, :not_found}
|
{:error, :not_found}
|
||||||
|
@ -523,123 +240,20 @@ def follow(%{assigns: %{user: follower}} = conn, %{"uri" => uri}) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def unfollow(%{assigns: %{user: follower}} = conn, %{"id" => id}) do
|
|
||||||
with {_, %User{} = followed} <- {:followed, User.get_cached_by_id(id)},
|
|
||||||
{_, true} <- {:followed, follower.id != followed.id},
|
|
||||||
{:ok, follower} <- CommonAPI.unfollow(follower, followed) do
|
|
||||||
conn
|
|
||||||
|> put_view(AccountView)
|
|
||||||
|> render("relationship.json", %{user: follower, target: followed})
|
|
||||||
else
|
|
||||||
{:followed, _} ->
|
|
||||||
{:error, :not_found}
|
|
||||||
|
|
||||||
error ->
|
|
||||||
error
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def mute(%{assigns: %{user: muter}} = conn, %{"id" => id} = params) do
|
|
||||||
notifications =
|
|
||||||
if Map.has_key?(params, "notifications"),
|
|
||||||
do: params["notifications"] in [true, "True", "true", "1"],
|
|
||||||
else: true
|
|
||||||
|
|
||||||
with %User{} = muted <- User.get_cached_by_id(id),
|
|
||||||
{:ok, muter} <- User.mute(muter, muted, notifications) do
|
|
||||||
conn
|
|
||||||
|> put_view(AccountView)
|
|
||||||
|> render("relationship.json", %{user: muter, target: muted})
|
|
||||||
else
|
|
||||||
{:error, message} ->
|
|
||||||
conn
|
|
||||||
|> put_status(:forbidden)
|
|
||||||
|> json(%{error: message})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def unmute(%{assigns: %{user: muter}} = conn, %{"id" => id}) do
|
|
||||||
with %User{} = muted <- User.get_cached_by_id(id),
|
|
||||||
{:ok, muter} <- User.unmute(muter, muted) do
|
|
||||||
conn
|
|
||||||
|> put_view(AccountView)
|
|
||||||
|> render("relationship.json", %{user: muter, target: muted})
|
|
||||||
else
|
|
||||||
{:error, message} ->
|
|
||||||
conn
|
|
||||||
|> put_status(:forbidden)
|
|
||||||
|> json(%{error: message})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def mutes(%{assigns: %{user: user}} = conn, _) do
|
def mutes(%{assigns: %{user: user}} = conn, _) do
|
||||||
with muted_accounts <- User.muted_users(user) do
|
with muted_accounts <- User.muted_users(user) do
|
||||||
res = AccountView.render("accounts.json", users: muted_accounts, for: user, as: :user)
|
res = AccountView.render("index.json", users: muted_accounts, for: user, as: :user)
|
||||||
json(conn, res)
|
json(conn, res)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def block(%{assigns: %{user: blocker}} = conn, %{"id" => id}) do
|
|
||||||
with %User{} = blocked <- User.get_cached_by_id(id),
|
|
||||||
{:ok, blocker} <- User.block(blocker, blocked),
|
|
||||||
{:ok, _activity} <- ActivityPub.block(blocker, blocked) do
|
|
||||||
conn
|
|
||||||
|> put_view(AccountView)
|
|
||||||
|> render("relationship.json", %{user: blocker, target: blocked})
|
|
||||||
else
|
|
||||||
{:error, message} ->
|
|
||||||
conn
|
|
||||||
|> put_status(:forbidden)
|
|
||||||
|> json(%{error: message})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def unblock(%{assigns: %{user: blocker}} = conn, %{"id" => id}) do
|
|
||||||
with %User{} = blocked <- User.get_cached_by_id(id),
|
|
||||||
{:ok, blocker} <- User.unblock(blocker, blocked),
|
|
||||||
{:ok, _activity} <- ActivityPub.unblock(blocker, blocked) do
|
|
||||||
conn
|
|
||||||
|> put_view(AccountView)
|
|
||||||
|> render("relationship.json", %{user: blocker, target: blocked})
|
|
||||||
else
|
|
||||||
{:error, message} ->
|
|
||||||
conn
|
|
||||||
|> put_status(:forbidden)
|
|
||||||
|> json(%{error: message})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def blocks(%{assigns: %{user: user}} = conn, _) do
|
def blocks(%{assigns: %{user: user}} = conn, _) do
|
||||||
with blocked_accounts <- User.blocked_users(user) do
|
with blocked_accounts <- User.blocked_users(user) do
|
||||||
res = AccountView.render("accounts.json", users: blocked_accounts, for: user, as: :user)
|
res = AccountView.render("index.json", users: blocked_accounts, for: user, as: :user)
|
||||||
json(conn, res)
|
json(conn, res)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def subscribe(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
|
||||||
with %User{} = subscription_target <- User.get_cached_by_id(id),
|
|
||||||
{:ok, subscription_target} = User.subscribe(user, subscription_target) do
|
|
||||||
conn
|
|
||||||
|> put_view(AccountView)
|
|
||||||
|> render("relationship.json", %{user: user, target: subscription_target})
|
|
||||||
else
|
|
||||||
nil -> {:error, :not_found}
|
|
||||||
e -> e
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def unsubscribe(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
|
||||||
with %User{} = subscription_target <- User.get_cached_by_id(id),
|
|
||||||
{:ok, subscription_target} = User.unsubscribe(user, subscription_target) do
|
|
||||||
conn
|
|
||||||
|> put_view(AccountView)
|
|
||||||
|> render("relationship.json", %{user: user, target: subscription_target})
|
|
||||||
else
|
|
||||||
nil -> {:error, :not_found}
|
|
||||||
e -> e
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def favourites(%{assigns: %{user: user}} = conn, params) do
|
def favourites(%{assigns: %{user: user}} = conn, params) do
|
||||||
params =
|
params =
|
||||||
params
|
params
|
||||||
|
@ -657,37 +271,6 @@ def favourites(%{assigns: %{user: user}} = conn, params) do
|
||||||
|> render("index.json", %{activities: activities, for: user, as: :activity})
|
|> render("index.json", %{activities: activities, for: user, as: :activity})
|
||||||
end
|
end
|
||||||
|
|
||||||
def user_favourites(%{assigns: %{user: for_user}} = conn, %{"id" => id} = params) do
|
|
||||||
with %User{} = user <- User.get_by_id(id),
|
|
||||||
false <- user.info.hide_favorites do
|
|
||||||
params =
|
|
||||||
params
|
|
||||||
|> Map.put("type", "Create")
|
|
||||||
|> Map.put("favorited_by", user.ap_id)
|
|
||||||
|> Map.put("blocking_user", for_user)
|
|
||||||
|
|
||||||
recipients =
|
|
||||||
if for_user do
|
|
||||||
[Pleroma.Constants.as_public()] ++ [for_user.ap_id | for_user.following]
|
|
||||||
else
|
|
||||||
[Pleroma.Constants.as_public()]
|
|
||||||
end
|
|
||||||
|
|
||||||
activities =
|
|
||||||
recipients
|
|
||||||
|> ActivityPub.fetch_activities(params)
|
|
||||||
|> Enum.reverse()
|
|
||||||
|
|
||||||
conn
|
|
||||||
|> add_link_headers(activities)
|
|
||||||
|> put_view(StatusView)
|
|
||||||
|> render("index.json", %{activities: activities, for: for_user, as: :activity})
|
|
||||||
else
|
|
||||||
nil -> {:error, :not_found}
|
|
||||||
true -> render_error(conn, :forbidden, "Can't get favorites")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def bookmarks(%{assigns: %{user: user}} = conn, params) do
|
def bookmarks(%{assigns: %{user: user}} = conn, params) do
|
||||||
user = User.get_cached_by_id(user.id)
|
user = User.get_cached_by_id(user.id)
|
||||||
|
|
||||||
|
@ -705,14 +288,6 @@ def bookmarks(%{assigns: %{user: user}} = conn, params) do
|
||||||
|> render("index.json", %{activities: activities, for: user, as: :activity})
|
|> render("index.json", %{activities: activities, for: user, as: :activity})
|
||||||
end
|
end
|
||||||
|
|
||||||
def account_lists(%{assigns: %{user: user}} = conn, %{"id" => account_id}) do
|
|
||||||
lists = Pleroma.List.get_lists_account_belongs(user, account_id)
|
|
||||||
|
|
||||||
conn
|
|
||||||
|> put_view(ListView)
|
|
||||||
|> render("index.json", %{lists: lists})
|
|
||||||
end
|
|
||||||
|
|
||||||
def index(%{assigns: %{user: user}} = conn, _params) do
|
def index(%{assigns: %{user: user}} = conn, _params) do
|
||||||
token = get_session(conn, :oauth_token)
|
token = get_session(conn, :oauth_token)
|
||||||
|
|
||||||
|
@ -721,8 +296,7 @@ def index(%{assigns: %{user: user}} = conn, _params) do
|
||||||
|
|
||||||
limit = Config.get([:instance, :limit])
|
limit = Config.get([:instance, :limit])
|
||||||
|
|
||||||
accounts =
|
accounts = Map.put(%{}, user.id, AccountView.render("show.json", %{user: user, for: user}))
|
||||||
Map.put(%{}, user.id, AccountView.render("account.json", %{user: user, for: user}))
|
|
||||||
|
|
||||||
initial_state =
|
initial_state =
|
||||||
%{
|
%{
|
||||||
|
@ -943,49 +517,6 @@ defp fetch_suggestion_id(attrs) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def account_register(
|
|
||||||
%{assigns: %{app: app}} = conn,
|
|
||||||
%{"username" => nickname, "email" => _, "password" => _, "agreement" => true} = params
|
|
||||||
) do
|
|
||||||
params =
|
|
||||||
params
|
|
||||||
|> Map.take([
|
|
||||||
"email",
|
|
||||||
"captcha_solution",
|
|
||||||
"captcha_token",
|
|
||||||
"captcha_answer_data",
|
|
||||||
"token",
|
|
||||||
"password"
|
|
||||||
])
|
|
||||||
|> Map.put("nickname", nickname)
|
|
||||||
|> Map.put("fullname", params["fullname"] || nickname)
|
|
||||||
|> Map.put("bio", params["bio"] || "")
|
|
||||||
|> Map.put("confirm", params["password"])
|
|
||||||
|
|
||||||
with {:ok, user} <- TwitterAPI.register_user(params, need_confirmation: true),
|
|
||||||
{:ok, token} <- Token.create_token(app, user, %{scopes: app.scopes}) do
|
|
||||||
json(conn, %{
|
|
||||||
token_type: "Bearer",
|
|
||||||
access_token: token.token,
|
|
||||||
scope: app.scopes,
|
|
||||||
created_at: Token.Utils.format_created_at(token)
|
|
||||||
})
|
|
||||||
else
|
|
||||||
{:error, errors} ->
|
|
||||||
conn
|
|
||||||
|> put_status(:bad_request)
|
|
||||||
|> json(errors)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def account_register(%{assigns: %{app: _app}} = conn, _) do
|
|
||||||
render_error(conn, :bad_request, "Missing parameters")
|
|
||||||
end
|
|
||||||
|
|
||||||
def account_register(conn, _) do
|
|
||||||
render_error(conn, :forbidden, "Invalid credentials")
|
|
||||||
end
|
|
||||||
|
|
||||||
def password_reset(conn, params) do
|
def password_reset(conn, params) do
|
||||||
nickname_or_email = params["email"] || params["nickname"]
|
nickname_or_email = params["email"] || params["nickname"]
|
||||||
|
|
||||||
|
@ -1002,16 +533,6 @@ def password_reset(conn, params) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def account_confirmation_resend(conn, params) do
|
|
||||||
nickname_or_email = params["email"] || params["nickname"]
|
|
||||||
|
|
||||||
with %User{} = user <- User.get_by_nickname_or_email(nickname_or_email),
|
|
||||||
{:ok, _} <- User.try_send_confirmation_email(user) do
|
|
||||||
conn
|
|
||||||
|> json_response(:no_content, "")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def try_render(conn, target, params)
|
def try_render(conn, target, params)
|
||||||
when is_binary(target) do
|
when is_binary(target) do
|
||||||
case render(conn, target, params) do
|
case render(conn, target, params) do
|
||||||
|
|
|
@ -22,7 +22,7 @@ def account_search(%{assigns: %{user: user}} = conn, %{"q" => query} = params) d
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_view(AccountView)
|
|> put_view(AccountView)
|
||||||
|> render("accounts.json", users: accounts, for: user, as: :user)
|
|> render("index.json", users: accounts, for: user, as: :user)
|
||||||
end
|
end
|
||||||
|
|
||||||
def search2(conn, params), do: do_search(:v2, conn, params)
|
def search2(conn, params), do: do_search(:v2, conn, params)
|
||||||
|
@ -72,7 +72,7 @@ defp search_options(params, user) do
|
||||||
|
|
||||||
defp resource_search(_, "accounts", query, options) do
|
defp resource_search(_, "accounts", query, options) do
|
||||||
accounts = with_fallback(fn -> User.search(query, options) end)
|
accounts = with_fallback(fn -> User.search(query, options) end)
|
||||||
AccountView.render("accounts.json", users: accounts, for: options[:for_user], as: :user)
|
AccountView.render("index.json", users: accounts, for: options[:for_user], as: :user)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp resource_search(_, "statuses", query, options) do
|
defp resource_search(_, "statuses", query, options) do
|
||||||
|
|
|
@ -231,7 +231,7 @@ def favourited_by(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_view(AccountView)
|
|> put_view(AccountView)
|
||||||
|> render("accounts.json", for: user, users: users, as: :user)
|
|> render("index.json", for: user, users: users, as: :user)
|
||||||
else
|
else
|
||||||
{:visible, false} -> {:error, :not_found}
|
{:visible, false} -> {:error, :not_found}
|
||||||
_ -> json(conn, [])
|
_ -> json(conn, [])
|
||||||
|
@ -251,7 +251,7 @@ def reblogged_by(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_view(AccountView)
|
|> put_view(AccountView)
|
||||||
|> render("accounts.json", for: user, users: users, as: :user)
|
|> render("index.json", for: user, users: users, as: :user)
|
||||||
else
|
else
|
||||||
{:visible, false} -> {:error, :not_found}
|
{:visible, false} -> {:error, :not_found}
|
||||||
_ -> json(conn, [])
|
_ -> json(conn, [])
|
||||||
|
|
|
@ -11,15 +11,15 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
|
||||||
alias Pleroma.Web.MastodonAPI.AccountView
|
alias Pleroma.Web.MastodonAPI.AccountView
|
||||||
alias Pleroma.Web.MediaProxy
|
alias Pleroma.Web.MediaProxy
|
||||||
|
|
||||||
def render("accounts.json", %{users: users} = opts) do
|
def render("index.json", %{users: users} = opts) do
|
||||||
users
|
users
|
||||||
|> render_many(AccountView, "account.json", opts)
|
|> render_many(AccountView, "show.json", opts)
|
||||||
|> Enum.filter(&Enum.any?/1)
|
|> Enum.filter(&Enum.any?/1)
|
||||||
end
|
end
|
||||||
|
|
||||||
def render("account.json", %{user: user} = opts) do
|
def render("show.json", %{user: user} = opts) do
|
||||||
if User.visible_for?(user, opts[:for]),
|
if User.visible_for?(user, opts[:for]),
|
||||||
do: do_render("account.json", opts),
|
do: do_render("show.json", opts),
|
||||||
else: %{}
|
else: %{}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ def render("relationships.json", %{user: user, targets: targets}) do
|
||||||
render_many(targets, AccountView, "relationship.json", user: user, as: :target)
|
render_many(targets, AccountView, "relationship.json", user: user, as: :target)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp do_render("account.json", %{user: user} = opts) do
|
defp do_render("show.json", %{user: user} = opts) do
|
||||||
display_name = HTML.strip_tags(user.name || user.nickname)
|
display_name = HTML.strip_tags(user.name || user.nickname)
|
||||||
|
|
||||||
image = User.avatar_url(user) |> MediaProxy.url()
|
image = User.avatar_url(user) |> MediaProxy.url()
|
||||||
|
|
|
@ -32,7 +32,7 @@ def render("participation.json", %{participation: participation, for: user}) do
|
||||||
|
|
||||||
%{
|
%{
|
||||||
id: participation.id |> to_string(),
|
id: participation.id |> to_string(),
|
||||||
accounts: render(AccountView, "accounts.json", users: users, as: :user),
|
accounts: render(AccountView, "index.json", users: users, as: :user),
|
||||||
unread: !participation.read,
|
unread: !participation.read,
|
||||||
last_status: render(StatusView, "show.json", activity: activity, for: user)
|
last_status: render(StatusView, "show.json", activity: activity, for: user)
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ def render("show.json", %{
|
||||||
id: to_string(notification.id),
|
id: to_string(notification.id),
|
||||||
type: mastodon_type,
|
type: mastodon_type,
|
||||||
created_at: CommonAPI.Utils.to_masto_date(notification.inserted_at),
|
created_at: CommonAPI.Utils.to_masto_date(notification.inserted_at),
|
||||||
account: AccountView.render("account.json", %{user: actor, for: user}),
|
account: AccountView.render("show.json", %{user: actor, for: user}),
|
||||||
pleroma: %{
|
pleroma: %{
|
||||||
is_seen: notification.seen
|
is_seen: notification.seen
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,7 +108,7 @@ def render(
|
||||||
id: to_string(activity.id),
|
id: to_string(activity.id),
|
||||||
uri: activity_object.data["id"],
|
uri: activity_object.data["id"],
|
||||||
url: activity_object.data["id"],
|
url: activity_object.data["id"],
|
||||||
account: AccountView.render("account.json", %{user: user, for: opts[:for]}),
|
account: AccountView.render("show.json", %{user: user, for: opts[:for]}),
|
||||||
in_reply_to_id: nil,
|
in_reply_to_id: nil,
|
||||||
in_reply_to_account_id: nil,
|
in_reply_to_account_id: nil,
|
||||||
reblog: reblogged,
|
reblog: reblogged,
|
||||||
|
@ -258,7 +258,7 @@ def render("show.json", %{activity: %{data: %{"object" => _object}} = activity}
|
||||||
id: to_string(activity.id),
|
id: to_string(activity.id),
|
||||||
uri: object.data["id"],
|
uri: object.data["id"],
|
||||||
url: url,
|
url: url,
|
||||||
account: AccountView.render("account.json", %{user: user, for: opts[:for]}),
|
account: AccountView.render("show.json", %{user: user, for: opts[:for]}),
|
||||||
in_reply_to_id: reply_to && to_string(reply_to.id),
|
in_reply_to_id: reply_to && to_string(reply_to.id),
|
||||||
in_reply_to_account_id: reply_to_user && to_string(reply_to_user.id),
|
in_reply_to_account_id: reply_to_user && to_string(reply_to_user.id),
|
||||||
reblog: nil,
|
reblog: nil,
|
||||||
|
@ -376,7 +376,7 @@ def render("listen.json", %{activity: %Activity{data: %{"type" => "Listen"}} = a
|
||||||
|
|
||||||
%{
|
%{
|
||||||
id: activity.id,
|
id: activity.id,
|
||||||
account: AccountView.render("account.json", %{user: user, for: opts[:for]}),
|
account: AccountView.render("show.json", %{user: user, for: opts[:for]}),
|
||||||
created_at: created_at,
|
created_at: created_at,
|
||||||
title: object.data["title"] |> HTML.strip_tags(),
|
title: object.data["title"] |> HTML.strip_tags(),
|
||||||
artist: object.data["artist"] |> HTML.strip_tags(),
|
artist: object.data["artist"] |> HTML.strip_tags(),
|
||||||
|
|
|
@ -0,0 +1,143 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.PleromaAPI.AccountController do
|
||||||
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
|
import Pleroma.Web.ControllerHelper,
|
||||||
|
only: [json_response: 3, add_link_headers: 2, assign_account_by_id: 2]
|
||||||
|
|
||||||
|
alias Ecto.Changeset
|
||||||
|
alias Pleroma.Plugs.RateLimiter
|
||||||
|
alias Pleroma.User
|
||||||
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
|
alias Pleroma.Web.CommonAPI
|
||||||
|
alias Pleroma.Web.MastodonAPI.StatusView
|
||||||
|
|
||||||
|
require Pleroma.Constants
|
||||||
|
|
||||||
|
plug(RateLimiter, :account_confirmation_resend when action == :confirmation_resend)
|
||||||
|
plug(:assign_account_by_id when action in [:favourites, :subscribe, :unsubscribe])
|
||||||
|
plug(:put_view, Pleroma.Web.MastodonAPI.AccountView)
|
||||||
|
|
||||||
|
@doc "POST /api/v1/pleroma/accounts/confirmation_resend"
|
||||||
|
def confirmation_resend(conn, params) do
|
||||||
|
nickname_or_email = params["email"] || params["nickname"]
|
||||||
|
|
||||||
|
with %User{} = user <- User.get_by_nickname_or_email(nickname_or_email),
|
||||||
|
{:ok, _} <- User.try_send_confirmation_email(user) do
|
||||||
|
json_response(conn, :no_content, "")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc "PATCH /api/v1/pleroma/accounts/update_avatar"
|
||||||
|
def update_avatar(%{assigns: %{user: user}} = conn, %{"img" => ""}) do
|
||||||
|
{:ok, user} =
|
||||||
|
user
|
||||||
|
|> Changeset.change(%{avatar: nil})
|
||||||
|
|> User.update_and_set_cache()
|
||||||
|
|
||||||
|
CommonAPI.update(user)
|
||||||
|
|
||||||
|
json(conn, %{url: nil})
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_avatar(%{assigns: %{user: user}} = conn, params) do
|
||||||
|
{:ok, %{data: data}} = ActivityPub.upload(params, type: :avatar)
|
||||||
|
{:ok, user} = user |> Changeset.change(%{avatar: data}) |> User.update_and_set_cache()
|
||||||
|
%{"url" => [%{"href" => href} | _]} = data
|
||||||
|
|
||||||
|
CommonAPI.update(user)
|
||||||
|
|
||||||
|
json(conn, %{url: href})
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc "PATCH /api/v1/pleroma/accounts/update_banner"
|
||||||
|
def update_banner(%{assigns: %{user: user}} = conn, %{"banner" => ""}) do
|
||||||
|
new_info = %{"banner" => %{}}
|
||||||
|
|
||||||
|
with {:ok, user} <- User.update_info(user, &User.Info.profile_update(&1, new_info)) do
|
||||||
|
CommonAPI.update(user)
|
||||||
|
json(conn, %{url: nil})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_banner(%{assigns: %{user: user}} = conn, params) do
|
||||||
|
with {:ok, object} <- ActivityPub.upload(%{"img" => params["banner"]}, type: :banner),
|
||||||
|
new_info <- %{"banner" => object.data},
|
||||||
|
{:ok, user} <- User.update_info(user, &User.Info.profile_update(&1, new_info)) do
|
||||||
|
CommonAPI.update(user)
|
||||||
|
%{"url" => [%{"href" => href} | _]} = object.data
|
||||||
|
|
||||||
|
json(conn, %{url: href})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc "PATCH /api/v1/pleroma/accounts/update_background"
|
||||||
|
def update_background(%{assigns: %{user: user}} = conn, %{"img" => ""}) do
|
||||||
|
new_info = %{"background" => %{}}
|
||||||
|
|
||||||
|
with {:ok, _user} <- User.update_info(user, &User.Info.profile_update(&1, new_info)) do
|
||||||
|
json(conn, %{url: nil})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_background(%{assigns: %{user: user}} = conn, params) do
|
||||||
|
with {:ok, object} <- ActivityPub.upload(params, type: :background),
|
||||||
|
new_info <- %{"background" => object.data},
|
||||||
|
{:ok, _user} <- User.update_info(user, &User.Info.profile_update(&1, new_info)) do
|
||||||
|
%{"url" => [%{"href" => href} | _]} = object.data
|
||||||
|
|
||||||
|
json(conn, %{url: href})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc "GET /api/v1/pleroma/accounts/:id/favourites"
|
||||||
|
def favourites(%{assigns: %{account: %{info: %{hide_favorites: true}}}} = conn, _params) do
|
||||||
|
render_error(conn, :forbidden, "Can't get favorites")
|
||||||
|
end
|
||||||
|
|
||||||
|
def favourites(%{assigns: %{user: for_user, account: user}} = conn, params) do
|
||||||
|
params =
|
||||||
|
params
|
||||||
|
|> Map.put("type", "Create")
|
||||||
|
|> Map.put("favorited_by", user.ap_id)
|
||||||
|
|> Map.put("blocking_user", for_user)
|
||||||
|
|
||||||
|
recipients =
|
||||||
|
if for_user do
|
||||||
|
[Pleroma.Constants.as_public()] ++ [for_user.ap_id | for_user.following]
|
||||||
|
else
|
||||||
|
[Pleroma.Constants.as_public()]
|
||||||
|
end
|
||||||
|
|
||||||
|
activities =
|
||||||
|
recipients
|
||||||
|
|> ActivityPub.fetch_activities(params)
|
||||||
|
|> Enum.reverse()
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> add_link_headers(activities)
|
||||||
|
|> put_view(StatusView)
|
||||||
|
|> render("index.json", activities: activities, for: for_user, as: :activity)
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc "POST /api/v1/pleroma/accounts/:id/subscribe"
|
||||||
|
def subscribe(%{assigns: %{user: user, account: subscription_target}} = conn, _params) do
|
||||||
|
with {:ok, subscription_target} <- User.subscribe(user, subscription_target) do
|
||||||
|
render(conn, "relationship.json", user: user, target: subscription_target)
|
||||||
|
else
|
||||||
|
{:error, message} -> json_response(conn, :forbidden, %{error: message})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc "POST /api/v1/pleroma/accounts/:id/unsubscribe"
|
||||||
|
def unsubscribe(%{assigns: %{user: user, account: subscription_target}} = conn, _params) do
|
||||||
|
with {:ok, subscription_target} <- User.unsubscribe(user, subscription_target) do
|
||||||
|
render(conn, "relationship.json", user: user, target: subscription_target)
|
||||||
|
else
|
||||||
|
{:error, message} -> json_response(conn, :forbidden, %{error: message})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -287,24 +287,40 @@ defmodule Pleroma.Web.Router do
|
||||||
end
|
end
|
||||||
|
|
||||||
scope "/api/v1/pleroma", Pleroma.Web.PleromaAPI do
|
scope "/api/v1/pleroma", Pleroma.Web.PleromaAPI do
|
||||||
pipe_through(:authenticated_api)
|
|
||||||
|
|
||||||
scope [] do
|
scope [] do
|
||||||
|
pipe_through(:authenticated_api)
|
||||||
pipe_through(:oauth_read)
|
pipe_through(:oauth_read)
|
||||||
get("/conversations/:id/statuses", PleromaAPIController, :conversation_statuses)
|
get("/conversations/:id/statuses", PleromaAPIController, :conversation_statuses)
|
||||||
get("/conversations/:id", PleromaAPIController, :conversation)
|
get("/conversations/:id", PleromaAPIController, :conversation)
|
||||||
end
|
end
|
||||||
|
|
||||||
scope [] do
|
scope [] do
|
||||||
|
pipe_through(:authenticated_api)
|
||||||
pipe_through(:oauth_write)
|
pipe_through(:oauth_write)
|
||||||
patch("/conversations/:id", PleromaAPIController, :update_conversation)
|
patch("/conversations/:id", PleromaAPIController, :update_conversation)
|
||||||
post("/notifications/read", PleromaAPIController, :read_notification)
|
post("/notifications/read", PleromaAPIController, :read_notification)
|
||||||
|
|
||||||
|
patch("/accounts/update_avatar", AccountController, :update_avatar)
|
||||||
|
patch("/accounts/update_banner", AccountController, :update_banner)
|
||||||
|
patch("/accounts/update_background", AccountController, :update_background)
|
||||||
|
post("/scrobble", ScrobbleController, :new_scrobble)
|
||||||
end
|
end
|
||||||
|
|
||||||
scope [] do
|
scope [] do
|
||||||
pipe_through(:oauth_write)
|
pipe_through(:api)
|
||||||
post("/scrobble", ScrobbleController, :new_scrobble)
|
pipe_through(:oauth_read_or_public)
|
||||||
|
get("/accounts/:id/favourites", AccountController, :favourites)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
scope [] do
|
||||||
|
pipe_through(:authenticated_api)
|
||||||
|
pipe_through(:oauth_follow)
|
||||||
|
|
||||||
|
post("/accounts/:id/subscribe", AccountController, :subscribe)
|
||||||
|
post("/accounts/:id/unsubscribe", AccountController, :unsubscribe)
|
||||||
|
end
|
||||||
|
|
||||||
|
post("/accounts/confirmation_resend", AccountController, :confirmation_resend)
|
||||||
end
|
end
|
||||||
|
|
||||||
scope "/api/v1/pleroma", Pleroma.Web.PleromaAPI do
|
scope "/api/v1/pleroma", Pleroma.Web.PleromaAPI do
|
||||||
|
@ -319,11 +335,11 @@ defmodule Pleroma.Web.Router do
|
||||||
scope [] do
|
scope [] do
|
||||||
pipe_through(:oauth_read)
|
pipe_through(:oauth_read)
|
||||||
|
|
||||||
get("/accounts/verify_credentials", MastodonAPIController, :verify_credentials)
|
get("/accounts/verify_credentials", AccountController, :verify_credentials)
|
||||||
|
|
||||||
get("/accounts/relationships", MastodonAPIController, :relationships)
|
get("/accounts/relationships", AccountController, :relationships)
|
||||||
|
|
||||||
get("/accounts/:id/lists", MastodonAPIController, :account_lists)
|
get("/accounts/:id/lists", AccountController, :lists)
|
||||||
get("/accounts/:id/identity_proofs", MastodonAPIController, :empty_array)
|
get("/accounts/:id/identity_proofs", MastodonAPIController, :empty_array)
|
||||||
|
|
||||||
get("/follow_requests", FollowRequestController, :index)
|
get("/follow_requests", FollowRequestController, :index)
|
||||||
|
@ -364,7 +380,7 @@ defmodule Pleroma.Web.Router do
|
||||||
scope [] do
|
scope [] do
|
||||||
pipe_through(:oauth_write)
|
pipe_through(:oauth_write)
|
||||||
|
|
||||||
patch("/accounts/update_credentials", MastodonAPIController, :update_credentials)
|
patch("/accounts/update_credentials", AccountController, :update_credentials)
|
||||||
|
|
||||||
post("/statuses", StatusController, :create)
|
post("/statuses", StatusController, :create)
|
||||||
delete("/statuses/:id", StatusController, :delete)
|
delete("/statuses/:id", StatusController, :delete)
|
||||||
|
@ -400,10 +416,6 @@ defmodule Pleroma.Web.Router do
|
||||||
put("/filters/:id", FilterController, :update)
|
put("/filters/:id", FilterController, :update)
|
||||||
delete("/filters/:id", FilterController, :delete)
|
delete("/filters/:id", FilterController, :delete)
|
||||||
|
|
||||||
patch("/pleroma/accounts/update_avatar", MastodonAPIController, :update_avatar)
|
|
||||||
patch("/pleroma/accounts/update_banner", MastodonAPIController, :update_banner)
|
|
||||||
patch("/pleroma/accounts/update_background", MastodonAPIController, :update_background)
|
|
||||||
|
|
||||||
get("/pleroma/mascot", MastodonAPIController, :get_mascot)
|
get("/pleroma/mascot", MastodonAPIController, :get_mascot)
|
||||||
put("/pleroma/mascot", MastodonAPIController, :set_mascot)
|
put("/pleroma/mascot", MastodonAPIController, :set_mascot)
|
||||||
|
|
||||||
|
@ -413,23 +425,19 @@ defmodule Pleroma.Web.Router do
|
||||||
scope [] do
|
scope [] do
|
||||||
pipe_through(:oauth_follow)
|
pipe_through(:oauth_follow)
|
||||||
|
|
||||||
post("/follows", MastodonAPIController, :follow)
|
post("/follows", MastodonAPIController, :follows)
|
||||||
post("/accounts/:id/follow", MastodonAPIController, :follow)
|
post("/accounts/:id/follow", AccountController, :follow)
|
||||||
|
post("/accounts/:id/unfollow", AccountController, :unfollow)
|
||||||
post("/accounts/:id/unfollow", MastodonAPIController, :unfollow)
|
post("/accounts/:id/block", AccountController, :block)
|
||||||
post("/accounts/:id/block", MastodonAPIController, :block)
|
post("/accounts/:id/unblock", AccountController, :unblock)
|
||||||
post("/accounts/:id/unblock", MastodonAPIController, :unblock)
|
post("/accounts/:id/mute", AccountController, :mute)
|
||||||
post("/accounts/:id/mute", MastodonAPIController, :mute)
|
post("/accounts/:id/unmute", AccountController, :unmute)
|
||||||
post("/accounts/:id/unmute", MastodonAPIController, :unmute)
|
|
||||||
|
|
||||||
post("/follow_requests/:id/authorize", FollowRequestController, :authorize)
|
post("/follow_requests/:id/authorize", FollowRequestController, :authorize)
|
||||||
post("/follow_requests/:id/reject", FollowRequestController, :reject)
|
post("/follow_requests/:id/reject", FollowRequestController, :reject)
|
||||||
|
|
||||||
post("/domain_blocks", DomainBlockController, :create)
|
post("/domain_blocks", DomainBlockController, :create)
|
||||||
delete("/domain_blocks", DomainBlockController, :delete)
|
delete("/domain_blocks", DomainBlockController, :delete)
|
||||||
|
|
||||||
post("/pleroma/accounts/:id/subscribe", MastodonAPIController, :subscribe)
|
|
||||||
post("/pleroma/accounts/:id/unsubscribe", MastodonAPIController, :unsubscribe)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
scope [] do
|
scope [] do
|
||||||
|
@ -451,7 +459,7 @@ defmodule Pleroma.Web.Router do
|
||||||
scope "/api/v1", Pleroma.Web.MastodonAPI do
|
scope "/api/v1", Pleroma.Web.MastodonAPI do
|
||||||
pipe_through(:api)
|
pipe_through(:api)
|
||||||
|
|
||||||
post("/accounts", MastodonAPIController, :account_register)
|
post("/accounts", AccountController, :create)
|
||||||
|
|
||||||
get("/instance", MastodonAPIController, :masto_instance)
|
get("/instance", MastodonAPIController, :masto_instance)
|
||||||
get("/instance/peers", MastodonAPIController, :peers)
|
get("/instance/peers", MastodonAPIController, :peers)
|
||||||
|
@ -468,12 +476,6 @@ defmodule Pleroma.Web.Router do
|
||||||
|
|
||||||
get("/accounts/search", SearchController, :account_search)
|
get("/accounts/search", SearchController, :account_search)
|
||||||
|
|
||||||
post(
|
|
||||||
"/pleroma/accounts/confirmation_resend",
|
|
||||||
MastodonAPIController,
|
|
||||||
:account_confirmation_resend
|
|
||||||
)
|
|
||||||
|
|
||||||
scope [] do
|
scope [] do
|
||||||
pipe_through(:oauth_read_or_public)
|
pipe_through(:oauth_read_or_public)
|
||||||
|
|
||||||
|
@ -487,14 +489,12 @@ defmodule Pleroma.Web.Router do
|
||||||
|
|
||||||
get("/polls/:id", MastodonAPIController, :get_poll)
|
get("/polls/:id", MastodonAPIController, :get_poll)
|
||||||
|
|
||||||
get("/accounts/:id/statuses", MastodonAPIController, :user_statuses)
|
get("/accounts/:id/statuses", AccountController, :statuses)
|
||||||
get("/accounts/:id/followers", MastodonAPIController, :followers)
|
get("/accounts/:id/followers", AccountController, :followers)
|
||||||
get("/accounts/:id/following", MastodonAPIController, :following)
|
get("/accounts/:id/following", AccountController, :following)
|
||||||
get("/accounts/:id", MastodonAPIController, :user)
|
get("/accounts/:id", AccountController, :show)
|
||||||
|
|
||||||
get("/search", SearchController, :search)
|
get("/search", SearchController, :search)
|
||||||
|
|
||||||
get("/pleroma/accounts/:id/favourites", MastodonAPIController, :user_favourites)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -113,10 +113,10 @@ test "getting own lists a given user belongs to" do
|
||||||
{:ok, not_owned_list} = Pleroma.List.follow(not_owned_list, member_1)
|
{:ok, not_owned_list} = Pleroma.List.follow(not_owned_list, member_1)
|
||||||
{:ok, not_owned_list} = Pleroma.List.follow(not_owned_list, member_2)
|
{:ok, not_owned_list} = Pleroma.List.follow(not_owned_list, member_2)
|
||||||
|
|
||||||
lists_1 = Pleroma.List.get_lists_account_belongs(owner, member_1.id)
|
lists_1 = Pleroma.List.get_lists_account_belongs(owner, member_1)
|
||||||
assert owned_list in lists_1
|
assert owned_list in lists_1
|
||||||
refute not_owned_list in lists_1
|
refute not_owned_list in lists_1
|
||||||
lists_2 = Pleroma.List.get_lists_account_belongs(owner, member_2.id)
|
lists_2 = Pleroma.List.get_lists_account_belongs(owner, member_2)
|
||||||
assert owned_list in lists_2
|
assert owned_list in lists_2
|
||||||
refute not_owned_list in lists_2
|
refute not_owned_list in lists_2
|
||||||
end
|
end
|
||||||
|
|
|
@ -1231,7 +1231,7 @@ test "it can handle Listen activities" do
|
||||||
|
|
||||||
{:ok, activity} = CommonAPI.listen(user, %{"title" => "lain radio episode 1"})
|
{:ok, activity} = CommonAPI.listen(user, %{"title" => "lain radio episode 1"})
|
||||||
|
|
||||||
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
|
{:ok, _modified} = Transmogrifier.prepare_outgoing(activity.data)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -21,12 +21,12 @@ test "renders a report" do
|
||||||
content: nil,
|
content: nil,
|
||||||
actor:
|
actor:
|
||||||
Map.merge(
|
Map.merge(
|
||||||
AccountView.render("account.json", %{user: user}),
|
AccountView.render("show.json", %{user: user}),
|
||||||
Pleroma.Web.AdminAPI.AccountView.render("show.json", %{user: user})
|
Pleroma.Web.AdminAPI.AccountView.render("show.json", %{user: user})
|
||||||
),
|
),
|
||||||
account:
|
account:
|
||||||
Map.merge(
|
Map.merge(
|
||||||
AccountView.render("account.json", %{user: other_user}),
|
AccountView.render("show.json", %{user: other_user}),
|
||||||
Pleroma.Web.AdminAPI.AccountView.render("show.json", %{user: other_user})
|
Pleroma.Web.AdminAPI.AccountView.render("show.json", %{user: other_user})
|
||||||
),
|
),
|
||||||
statuses: [],
|
statuses: [],
|
||||||
|
@ -53,12 +53,12 @@ test "includes reported statuses" do
|
||||||
content: nil,
|
content: nil,
|
||||||
actor:
|
actor:
|
||||||
Map.merge(
|
Map.merge(
|
||||||
AccountView.render("account.json", %{user: user}),
|
AccountView.render("show.json", %{user: user}),
|
||||||
Pleroma.Web.AdminAPI.AccountView.render("show.json", %{user: user})
|
Pleroma.Web.AdminAPI.AccountView.render("show.json", %{user: user})
|
||||||
),
|
),
|
||||||
account:
|
account:
|
||||||
Map.merge(
|
Map.merge(
|
||||||
AccountView.render("account.json", %{user: other_user}),
|
AccountView.render("show.json", %{user: other_user}),
|
||||||
Pleroma.Web.AdminAPI.AccountView.render("show.json", %{user: other_user})
|
Pleroma.Web.AdminAPI.AccountView.render("show.json", %{user: other_user})
|
||||||
),
|
),
|
||||||
statuses: [StatusView.render("show.json", %{activity: activity})],
|
statuses: [StatusView.render("show.json", %{activity: activity})],
|
||||||
|
|
|
@ -0,0 +1,852 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|
||||||
|
use Pleroma.Web.ConnCase
|
||||||
|
|
||||||
|
alias Pleroma.Repo
|
||||||
|
alias Pleroma.User
|
||||||
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
|
alias Pleroma.Web.CommonAPI
|
||||||
|
alias Pleroma.Web.OAuth.Token
|
||||||
|
|
||||||
|
import Pleroma.Factory
|
||||||
|
|
||||||
|
describe "account fetching" do
|
||||||
|
test "works by id" do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
build_conn()
|
||||||
|
|> get("/api/v1/accounts/#{user.id}")
|
||||||
|
|
||||||
|
assert %{"id" => id} = json_response(conn, 200)
|
||||||
|
assert id == to_string(user.id)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
build_conn()
|
||||||
|
|> get("/api/v1/accounts/-1")
|
||||||
|
|
||||||
|
assert %{"error" => "Can't find user"} = json_response(conn, 404)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "works by nickname" do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
build_conn()
|
||||||
|
|> get("/api/v1/accounts/#{user.nickname}")
|
||||||
|
|
||||||
|
assert %{"id" => id} = json_response(conn, 200)
|
||||||
|
assert id == user.id
|
||||||
|
end
|
||||||
|
|
||||||
|
test "works by nickname for remote users" do
|
||||||
|
limit_to_local = Pleroma.Config.get([:instance, :limit_to_local_content])
|
||||||
|
Pleroma.Config.put([:instance, :limit_to_local_content], false)
|
||||||
|
user = insert(:user, nickname: "user@example.com", local: false)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
build_conn()
|
||||||
|
|> get("/api/v1/accounts/#{user.nickname}")
|
||||||
|
|
||||||
|
Pleroma.Config.put([:instance, :limit_to_local_content], limit_to_local)
|
||||||
|
assert %{"id" => id} = json_response(conn, 200)
|
||||||
|
assert id == user.id
|
||||||
|
end
|
||||||
|
|
||||||
|
test "respects limit_to_local_content == :all for remote user nicknames" do
|
||||||
|
limit_to_local = Pleroma.Config.get([:instance, :limit_to_local_content])
|
||||||
|
Pleroma.Config.put([:instance, :limit_to_local_content], :all)
|
||||||
|
|
||||||
|
user = insert(:user, nickname: "user@example.com", local: false)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
build_conn()
|
||||||
|
|> get("/api/v1/accounts/#{user.nickname}")
|
||||||
|
|
||||||
|
Pleroma.Config.put([:instance, :limit_to_local_content], limit_to_local)
|
||||||
|
assert json_response(conn, 404)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "respects limit_to_local_content == :unauthenticated for remote user nicknames" do
|
||||||
|
limit_to_local = Pleroma.Config.get([:instance, :limit_to_local_content])
|
||||||
|
Pleroma.Config.put([:instance, :limit_to_local_content], :unauthenticated)
|
||||||
|
|
||||||
|
user = insert(:user, nickname: "user@example.com", local: false)
|
||||||
|
reading_user = insert(:user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
build_conn()
|
||||||
|
|> get("/api/v1/accounts/#{user.nickname}")
|
||||||
|
|
||||||
|
assert json_response(conn, 404)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
build_conn()
|
||||||
|
|> assign(:user, reading_user)
|
||||||
|
|> get("/api/v1/accounts/#{user.nickname}")
|
||||||
|
|
||||||
|
Pleroma.Config.put([:instance, :limit_to_local_content], limit_to_local)
|
||||||
|
assert %{"id" => id} = json_response(conn, 200)
|
||||||
|
assert id == user.id
|
||||||
|
end
|
||||||
|
|
||||||
|
test "accounts fetches correct account for nicknames beginning with numbers", %{conn: conn} do
|
||||||
|
# Need to set an old-style integer ID to reproduce the problem
|
||||||
|
# (these are no longer assigned to new accounts but were preserved
|
||||||
|
# for existing accounts during the migration to flakeIDs)
|
||||||
|
user_one = insert(:user, %{id: 1212})
|
||||||
|
user_two = insert(:user, %{nickname: "#{user_one.id}garbage"})
|
||||||
|
|
||||||
|
resp_one =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/accounts/#{user_one.id}")
|
||||||
|
|
||||||
|
resp_two =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/accounts/#{user_two.nickname}")
|
||||||
|
|
||||||
|
resp_three =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/accounts/#{user_two.id}")
|
||||||
|
|
||||||
|
acc_one = json_response(resp_one, 200)
|
||||||
|
acc_two = json_response(resp_two, 200)
|
||||||
|
acc_three = json_response(resp_three, 200)
|
||||||
|
refute acc_one == acc_two
|
||||||
|
assert acc_two == acc_three
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "user timelines" do
|
||||||
|
test "gets a users statuses", %{conn: conn} do
|
||||||
|
user_one = insert(:user)
|
||||||
|
user_two = insert(:user)
|
||||||
|
user_three = insert(:user)
|
||||||
|
|
||||||
|
{:ok, user_three} = User.follow(user_three, user_one)
|
||||||
|
|
||||||
|
{:ok, activity} = CommonAPI.post(user_one, %{"status" => "HI!!!"})
|
||||||
|
|
||||||
|
{:ok, direct_activity} =
|
||||||
|
CommonAPI.post(user_one, %{
|
||||||
|
"status" => "Hi, @#{user_two.nickname}.",
|
||||||
|
"visibility" => "direct"
|
||||||
|
})
|
||||||
|
|
||||||
|
{:ok, private_activity} =
|
||||||
|
CommonAPI.post(user_one, %{"status" => "private", "visibility" => "private"})
|
||||||
|
|
||||||
|
resp =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/accounts/#{user_one.id}/statuses")
|
||||||
|
|
||||||
|
assert [%{"id" => id}] = json_response(resp, 200)
|
||||||
|
assert id == to_string(activity.id)
|
||||||
|
|
||||||
|
resp =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user_two)
|
||||||
|
|> get("/api/v1/accounts/#{user_one.id}/statuses")
|
||||||
|
|
||||||
|
assert [%{"id" => id_one}, %{"id" => id_two}] = json_response(resp, 200)
|
||||||
|
assert id_one == to_string(direct_activity.id)
|
||||||
|
assert id_two == to_string(activity.id)
|
||||||
|
|
||||||
|
resp =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user_three)
|
||||||
|
|> get("/api/v1/accounts/#{user_one.id}/statuses")
|
||||||
|
|
||||||
|
assert [%{"id" => id_one}, %{"id" => id_two}] = json_response(resp, 200)
|
||||||
|
assert id_one == to_string(private_activity.id)
|
||||||
|
assert id_two == to_string(activity.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "unimplemented pinned statuses feature", %{conn: conn} do
|
||||||
|
note = insert(:note_activity)
|
||||||
|
user = User.get_cached_by_ap_id(note.data["actor"])
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
|
||||||
|
|
||||||
|
assert json_response(conn, 200) == []
|
||||||
|
end
|
||||||
|
|
||||||
|
test "gets an users media", %{conn: conn} do
|
||||||
|
note = insert(:note_activity)
|
||||||
|
user = User.get_cached_by_ap_id(note.data["actor"])
|
||||||
|
|
||||||
|
file = %Plug.Upload{
|
||||||
|
content_type: "image/jpg",
|
||||||
|
path: Path.absname("test/fixtures/image.jpg"),
|
||||||
|
filename: "an_image.jpg"
|
||||||
|
}
|
||||||
|
|
||||||
|
{:ok, %{id: media_id}} = ActivityPub.upload(file, actor: user.ap_id)
|
||||||
|
|
||||||
|
{:ok, image_post} = CommonAPI.post(user, %{"status" => "cofe", "media_ids" => [media_id]})
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/accounts/#{user.id}/statuses", %{"only_media" => "true"})
|
||||||
|
|
||||||
|
assert [%{"id" => id}] = json_response(conn, 200)
|
||||||
|
assert id == to_string(image_post.id)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
build_conn()
|
||||||
|
|> get("/api/v1/accounts/#{user.id}/statuses", %{"only_media" => "1"})
|
||||||
|
|
||||||
|
assert [%{"id" => id}] = json_response(conn, 200)
|
||||||
|
assert id == to_string(image_post.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "gets a user's statuses without reblogs", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
{:ok, post} = CommonAPI.post(user, %{"status" => "HI!!!"})
|
||||||
|
{:ok, _, _} = CommonAPI.repeat(post.id, user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/accounts/#{user.id}/statuses", %{"exclude_reblogs" => "true"})
|
||||||
|
|
||||||
|
assert [%{"id" => id}] = json_response(conn, 200)
|
||||||
|
assert id == to_string(post.id)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/accounts/#{user.id}/statuses", %{"exclude_reblogs" => "1"})
|
||||||
|
|
||||||
|
assert [%{"id" => id}] = json_response(conn, 200)
|
||||||
|
assert id == to_string(post.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "filters user's statuses by a hashtag", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
{:ok, post} = CommonAPI.post(user, %{"status" => "#hashtag"})
|
||||||
|
{:ok, _post} = CommonAPI.post(user, %{"status" => "hashtag"})
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/accounts/#{user.id}/statuses", %{"tagged" => "hashtag"})
|
||||||
|
|
||||||
|
assert [%{"id" => id}] = json_response(conn, 200)
|
||||||
|
assert id == to_string(post.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "followers" do
|
||||||
|
test "getting followers", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
other_user = insert(:user)
|
||||||
|
{:ok, user} = User.follow(user, other_user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/accounts/#{other_user.id}/followers")
|
||||||
|
|
||||||
|
assert [%{"id" => id}] = json_response(conn, 200)
|
||||||
|
assert id == to_string(user.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "getting followers, hide_followers", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
other_user = insert(:user, %{info: %{hide_followers: true}})
|
||||||
|
{:ok, _user} = User.follow(user, other_user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/accounts/#{other_user.id}/followers")
|
||||||
|
|
||||||
|
assert [] == json_response(conn, 200)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "getting followers, hide_followers, same user requesting", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
other_user = insert(:user, %{info: %{hide_followers: true}})
|
||||||
|
{:ok, _user} = User.follow(user, other_user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, other_user)
|
||||||
|
|> get("/api/v1/accounts/#{other_user.id}/followers")
|
||||||
|
|
||||||
|
refute [] == json_response(conn, 200)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "getting followers, pagination", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
follower1 = insert(:user)
|
||||||
|
follower2 = insert(:user)
|
||||||
|
follower3 = insert(:user)
|
||||||
|
{:ok, _} = User.follow(follower1, user)
|
||||||
|
{:ok, _} = User.follow(follower2, user)
|
||||||
|
{:ok, _} = User.follow(follower3, user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|
||||||
|
res_conn =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/accounts/#{user.id}/followers?since_id=#{follower1.id}")
|
||||||
|
|
||||||
|
assert [%{"id" => id3}, %{"id" => id2}] = json_response(res_conn, 200)
|
||||||
|
assert id3 == follower3.id
|
||||||
|
assert id2 == follower2.id
|
||||||
|
|
||||||
|
res_conn =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/accounts/#{user.id}/followers?max_id=#{follower3.id}")
|
||||||
|
|
||||||
|
assert [%{"id" => id2}, %{"id" => id1}] = json_response(res_conn, 200)
|
||||||
|
assert id2 == follower2.id
|
||||||
|
assert id1 == follower1.id
|
||||||
|
|
||||||
|
res_conn =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/accounts/#{user.id}/followers?limit=1&max_id=#{follower3.id}")
|
||||||
|
|
||||||
|
assert [%{"id" => id2}] = json_response(res_conn, 200)
|
||||||
|
assert id2 == follower2.id
|
||||||
|
|
||||||
|
assert [link_header] = get_resp_header(res_conn, "link")
|
||||||
|
assert link_header =~ ~r/min_id=#{follower2.id}/
|
||||||
|
assert link_header =~ ~r/max_id=#{follower2.id}/
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "following" do
|
||||||
|
test "getting following", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
other_user = insert(:user)
|
||||||
|
{:ok, user} = User.follow(user, other_user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/accounts/#{user.id}/following")
|
||||||
|
|
||||||
|
assert [%{"id" => id}] = json_response(conn, 200)
|
||||||
|
assert id == to_string(other_user.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "getting following, hide_follows", %{conn: conn} do
|
||||||
|
user = insert(:user, %{info: %{hide_follows: true}})
|
||||||
|
other_user = insert(:user)
|
||||||
|
{:ok, user} = User.follow(user, other_user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/accounts/#{user.id}/following")
|
||||||
|
|
||||||
|
assert [] == json_response(conn, 200)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "getting following, hide_follows, same user requesting", %{conn: conn} do
|
||||||
|
user = insert(:user, %{info: %{hide_follows: true}})
|
||||||
|
other_user = insert(:user)
|
||||||
|
{:ok, user} = User.follow(user, other_user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> get("/api/v1/accounts/#{user.id}/following")
|
||||||
|
|
||||||
|
refute [] == json_response(conn, 200)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "getting following, pagination", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
following1 = insert(:user)
|
||||||
|
following2 = insert(:user)
|
||||||
|
following3 = insert(:user)
|
||||||
|
{:ok, _} = User.follow(user, following1)
|
||||||
|
{:ok, _} = User.follow(user, following2)
|
||||||
|
{:ok, _} = User.follow(user, following3)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|
||||||
|
res_conn =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/accounts/#{user.id}/following?since_id=#{following1.id}")
|
||||||
|
|
||||||
|
assert [%{"id" => id3}, %{"id" => id2}] = json_response(res_conn, 200)
|
||||||
|
assert id3 == following3.id
|
||||||
|
assert id2 == following2.id
|
||||||
|
|
||||||
|
res_conn =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/accounts/#{user.id}/following?max_id=#{following3.id}")
|
||||||
|
|
||||||
|
assert [%{"id" => id2}, %{"id" => id1}] = json_response(res_conn, 200)
|
||||||
|
assert id2 == following2.id
|
||||||
|
assert id1 == following1.id
|
||||||
|
|
||||||
|
res_conn =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/accounts/#{user.id}/following?limit=1&max_id=#{following3.id}")
|
||||||
|
|
||||||
|
assert [%{"id" => id2}] = json_response(res_conn, 200)
|
||||||
|
assert id2 == following2.id
|
||||||
|
|
||||||
|
assert [link_header] = get_resp_header(res_conn, "link")
|
||||||
|
assert link_header =~ ~r/min_id=#{following2.id}/
|
||||||
|
assert link_header =~ ~r/max_id=#{following2.id}/
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "follow/unfollow" do
|
||||||
|
test "following / unfollowing a user", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
other_user = insert(:user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> post("/api/v1/accounts/#{other_user.id}/follow")
|
||||||
|
|
||||||
|
assert %{"id" => _id, "following" => true} = json_response(conn, 200)
|
||||||
|
|
||||||
|
user = User.get_cached_by_id(user.id)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
build_conn()
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> post("/api/v1/accounts/#{other_user.id}/unfollow")
|
||||||
|
|
||||||
|
assert %{"id" => _id, "following" => false} = json_response(conn, 200)
|
||||||
|
|
||||||
|
user = User.get_cached_by_id(user.id)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
build_conn()
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> post("/api/v1/follows", %{"uri" => other_user.nickname})
|
||||||
|
|
||||||
|
assert %{"id" => id} = json_response(conn, 200)
|
||||||
|
assert id == to_string(other_user.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "following without reblogs" do
|
||||||
|
follower = insert(:user)
|
||||||
|
followed = insert(:user)
|
||||||
|
other_user = insert(:user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
build_conn()
|
||||||
|
|> assign(:user, follower)
|
||||||
|
|> post("/api/v1/accounts/#{followed.id}/follow?reblogs=false")
|
||||||
|
|
||||||
|
assert %{"showing_reblogs" => false} = json_response(conn, 200)
|
||||||
|
|
||||||
|
{:ok, activity} = CommonAPI.post(other_user, %{"status" => "hey"})
|
||||||
|
{:ok, reblog, _} = CommonAPI.repeat(activity.id, followed)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
build_conn()
|
||||||
|
|> assign(:user, User.get_cached_by_id(follower.id))
|
||||||
|
|> get("/api/v1/timelines/home")
|
||||||
|
|
||||||
|
assert [] == json_response(conn, 200)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
build_conn()
|
||||||
|
|> assign(:user, follower)
|
||||||
|
|> post("/api/v1/accounts/#{followed.id}/follow?reblogs=true")
|
||||||
|
|
||||||
|
assert %{"showing_reblogs" => true} = json_response(conn, 200)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
build_conn()
|
||||||
|
|> assign(:user, User.get_cached_by_id(follower.id))
|
||||||
|
|> get("/api/v1/timelines/home")
|
||||||
|
|
||||||
|
expected_activity_id = reblog.id
|
||||||
|
assert [%{"id" => ^expected_activity_id}] = json_response(conn, 200)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "following / unfollowing errors" do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
build_conn()
|
||||||
|
|> assign(:user, user)
|
||||||
|
|
||||||
|
# self follow
|
||||||
|
conn_res = post(conn, "/api/v1/accounts/#{user.id}/follow")
|
||||||
|
assert %{"error" => "Record not found"} = json_response(conn_res, 404)
|
||||||
|
|
||||||
|
# self unfollow
|
||||||
|
user = User.get_cached_by_id(user.id)
|
||||||
|
conn_res = post(conn, "/api/v1/accounts/#{user.id}/unfollow")
|
||||||
|
assert %{"error" => "Record not found"} = json_response(conn_res, 404)
|
||||||
|
|
||||||
|
# self follow via uri
|
||||||
|
user = User.get_cached_by_id(user.id)
|
||||||
|
conn_res = post(conn, "/api/v1/follows", %{"uri" => user.nickname})
|
||||||
|
assert %{"error" => "Record not found"} = json_response(conn_res, 404)
|
||||||
|
|
||||||
|
# follow non existing user
|
||||||
|
conn_res = post(conn, "/api/v1/accounts/doesntexist/follow")
|
||||||
|
assert %{"error" => "Record not found"} = json_response(conn_res, 404)
|
||||||
|
|
||||||
|
# follow non existing user via uri
|
||||||
|
conn_res = post(conn, "/api/v1/follows", %{"uri" => "doesntexist"})
|
||||||
|
assert %{"error" => "Record not found"} = json_response(conn_res, 404)
|
||||||
|
|
||||||
|
# unfollow non existing user
|
||||||
|
conn_res = post(conn, "/api/v1/accounts/doesntexist/unfollow")
|
||||||
|
assert %{"error" => "Record not found"} = json_response(conn_res, 404)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "mute/unmute" do
|
||||||
|
test "with notifications", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
other_user = insert(:user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> post("/api/v1/accounts/#{other_user.id}/mute")
|
||||||
|
|
||||||
|
response = json_response(conn, 200)
|
||||||
|
|
||||||
|
assert %{"id" => _id, "muting" => true, "muting_notifications" => true} = response
|
||||||
|
user = User.get_cached_by_id(user.id)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
build_conn()
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> post("/api/v1/accounts/#{other_user.id}/unmute")
|
||||||
|
|
||||||
|
response = json_response(conn, 200)
|
||||||
|
assert %{"id" => _id, "muting" => false, "muting_notifications" => false} = response
|
||||||
|
end
|
||||||
|
|
||||||
|
test "without notifications", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
other_user = insert(:user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> post("/api/v1/accounts/#{other_user.id}/mute", %{"notifications" => "false"})
|
||||||
|
|
||||||
|
response = json_response(conn, 200)
|
||||||
|
|
||||||
|
assert %{"id" => _id, "muting" => true, "muting_notifications" => false} = response
|
||||||
|
user = User.get_cached_by_id(user.id)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
build_conn()
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> post("/api/v1/accounts/#{other_user.id}/unmute")
|
||||||
|
|
||||||
|
response = json_response(conn, 200)
|
||||||
|
assert %{"id" => _id, "muting" => false, "muting_notifications" => false} = response
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "pinned statuses" do
|
||||||
|
setup do
|
||||||
|
user = insert(:user)
|
||||||
|
{:ok, activity} = CommonAPI.post(user, %{"status" => "HI!!!"})
|
||||||
|
|
||||||
|
[user: user, activity: activity]
|
||||||
|
end
|
||||||
|
|
||||||
|
test "returns pinned statuses", %{conn: conn, user: user, activity: activity} do
|
||||||
|
{:ok, _} = CommonAPI.pin(activity.id, user)
|
||||||
|
|
||||||
|
result =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
|
||||||
|
|> json_response(200)
|
||||||
|
|
||||||
|
id_str = to_string(activity.id)
|
||||||
|
|
||||||
|
assert [%{"id" => ^id_str, "pinned" => true}] = result
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
test "blocking / unblocking a user", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
other_user = insert(:user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> post("/api/v1/accounts/#{other_user.id}/block")
|
||||||
|
|
||||||
|
assert %{"id" => _id, "blocking" => true} = json_response(conn, 200)
|
||||||
|
|
||||||
|
user = User.get_cached_by_id(user.id)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
build_conn()
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> post("/api/v1/accounts/#{other_user.id}/unblock")
|
||||||
|
|
||||||
|
assert %{"id" => _id, "blocking" => false} = json_response(conn, 200)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "create account by app" do
|
||||||
|
setup do
|
||||||
|
valid_params = %{
|
||||||
|
username: "lain",
|
||||||
|
email: "lain@example.org",
|
||||||
|
password: "PlzDontHackLain",
|
||||||
|
agreement: true
|
||||||
|
}
|
||||||
|
|
||||||
|
[valid_params: valid_params]
|
||||||
|
end
|
||||||
|
|
||||||
|
test "Account registration via Application", %{conn: conn} do
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> post("/api/v1/apps", %{
|
||||||
|
client_name: "client_name",
|
||||||
|
redirect_uris: "urn:ietf:wg:oauth:2.0:oob",
|
||||||
|
scopes: "read, write, follow"
|
||||||
|
})
|
||||||
|
|
||||||
|
%{
|
||||||
|
"client_id" => client_id,
|
||||||
|
"client_secret" => client_secret,
|
||||||
|
"id" => _,
|
||||||
|
"name" => "client_name",
|
||||||
|
"redirect_uri" => "urn:ietf:wg:oauth:2.0:oob",
|
||||||
|
"vapid_key" => _,
|
||||||
|
"website" => nil
|
||||||
|
} = json_response(conn, 200)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> post("/oauth/token", %{
|
||||||
|
grant_type: "client_credentials",
|
||||||
|
client_id: client_id,
|
||||||
|
client_secret: client_secret
|
||||||
|
})
|
||||||
|
|
||||||
|
assert %{"access_token" => token, "refresh_token" => refresh, "scope" => scope} =
|
||||||
|
json_response(conn, 200)
|
||||||
|
|
||||||
|
assert token
|
||||||
|
token_from_db = Repo.get_by(Token, token: token)
|
||||||
|
assert token_from_db
|
||||||
|
assert refresh
|
||||||
|
assert scope == "read write follow"
|
||||||
|
|
||||||
|
conn =
|
||||||
|
build_conn()
|
||||||
|
|> put_req_header("authorization", "Bearer " <> token)
|
||||||
|
|> post("/api/v1/accounts", %{
|
||||||
|
username: "lain",
|
||||||
|
email: "lain@example.org",
|
||||||
|
password: "PlzDontHackLain",
|
||||||
|
bio: "Test Bio",
|
||||||
|
agreement: true
|
||||||
|
})
|
||||||
|
|
||||||
|
%{
|
||||||
|
"access_token" => token,
|
||||||
|
"created_at" => _created_at,
|
||||||
|
"scope" => _scope,
|
||||||
|
"token_type" => "Bearer"
|
||||||
|
} = json_response(conn, 200)
|
||||||
|
|
||||||
|
token_from_db = Repo.get_by(Token, token: token)
|
||||||
|
assert token_from_db
|
||||||
|
token_from_db = Repo.preload(token_from_db, :user)
|
||||||
|
assert token_from_db.user
|
||||||
|
|
||||||
|
assert token_from_db.user.info.confirmation_pending
|
||||||
|
end
|
||||||
|
|
||||||
|
test "returns error when user already registred", %{conn: conn, valid_params: valid_params} do
|
||||||
|
_user = insert(:user, email: "lain@example.org")
|
||||||
|
app_token = insert(:oauth_token, user: nil)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> put_req_header("authorization", "Bearer " <> app_token.token)
|
||||||
|
|
||||||
|
res = post(conn, "/api/v1/accounts", valid_params)
|
||||||
|
assert json_response(res, 400) == %{"error" => "{\"email\":[\"has already been taken\"]}"}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "rate limit", %{conn: conn} do
|
||||||
|
app_token = insert(:oauth_token, user: nil)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
put_req_header(conn, "authorization", "Bearer " <> app_token.token)
|
||||||
|
|> Map.put(:remote_ip, {15, 15, 15, 15})
|
||||||
|
|
||||||
|
for i <- 1..5 do
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> post("/api/v1/accounts", %{
|
||||||
|
username: "#{i}lain",
|
||||||
|
email: "#{i}lain@example.org",
|
||||||
|
password: "PlzDontHackLain",
|
||||||
|
agreement: true
|
||||||
|
})
|
||||||
|
|
||||||
|
%{
|
||||||
|
"access_token" => token,
|
||||||
|
"created_at" => _created_at,
|
||||||
|
"scope" => _scope,
|
||||||
|
"token_type" => "Bearer"
|
||||||
|
} = json_response(conn, 200)
|
||||||
|
|
||||||
|
token_from_db = Repo.get_by(Token, token: token)
|
||||||
|
assert token_from_db
|
||||||
|
token_from_db = Repo.preload(token_from_db, :user)
|
||||||
|
assert token_from_db.user
|
||||||
|
|
||||||
|
assert token_from_db.user.info.confirmation_pending
|
||||||
|
end
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> post("/api/v1/accounts", %{
|
||||||
|
username: "6lain",
|
||||||
|
email: "6lain@example.org",
|
||||||
|
password: "PlzDontHackLain",
|
||||||
|
agreement: true
|
||||||
|
})
|
||||||
|
|
||||||
|
assert json_response(conn, :too_many_requests) == %{"error" => "Throttled"}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "returns bad_request if missing required params", %{
|
||||||
|
conn: conn,
|
||||||
|
valid_params: valid_params
|
||||||
|
} do
|
||||||
|
app_token = insert(:oauth_token, user: nil)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> put_req_header("authorization", "Bearer " <> app_token.token)
|
||||||
|
|
||||||
|
res = post(conn, "/api/v1/accounts", valid_params)
|
||||||
|
assert json_response(res, 200)
|
||||||
|
|
||||||
|
[{127, 0, 0, 1}, {127, 0, 0, 2}, {127, 0, 0, 3}, {127, 0, 0, 4}]
|
||||||
|
|> Stream.zip(valid_params)
|
||||||
|
|> Enum.each(fn {ip, {attr, _}} ->
|
||||||
|
res =
|
||||||
|
conn
|
||||||
|
|> Map.put(:remote_ip, ip)
|
||||||
|
|> post("/api/v1/accounts", Map.delete(valid_params, attr))
|
||||||
|
|> json_response(400)
|
||||||
|
|
||||||
|
assert res == %{"error" => "Missing parameters"}
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "returns forbidden if token is invalid", %{conn: conn, valid_params: valid_params} do
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> put_req_header("authorization", "Bearer " <> "invalid-token")
|
||||||
|
|
||||||
|
res = post(conn, "/api/v1/accounts", valid_params)
|
||||||
|
assert json_response(res, 403) == %{"error" => "Invalid credentials"}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "GET /api/v1/accounts/:id/lists - account_lists" do
|
||||||
|
test "returns lists to which the account belongs", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
other_user = insert(:user)
|
||||||
|
assert {:ok, %Pleroma.List{} = list} = Pleroma.List.create("Test List", user)
|
||||||
|
{:ok, %{following: _following}} = Pleroma.List.follow(list, other_user)
|
||||||
|
|
||||||
|
res =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> get("/api/v1/accounts/#{other_user.id}/lists")
|
||||||
|
|> json_response(200)
|
||||||
|
|
||||||
|
assert res == [%{"id" => to_string(list.id), "title" => "Test List"}]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "verify_credentials" do
|
||||||
|
test "verify_credentials", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> get("/api/v1/accounts/verify_credentials")
|
||||||
|
|
||||||
|
response = json_response(conn, 200)
|
||||||
|
|
||||||
|
assert %{"id" => id, "source" => %{"privacy" => "public"}} = response
|
||||||
|
assert response["pleroma"]["chat_token"]
|
||||||
|
assert id == to_string(user.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "verify_credentials default scope unlisted", %{conn: conn} do
|
||||||
|
user = insert(:user, %{info: %User.Info{default_scope: "unlisted"}})
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> get("/api/v1/accounts/verify_credentials")
|
||||||
|
|
||||||
|
assert %{"id" => id, "source" => %{"privacy" => "unlisted"}} = json_response(conn, 200)
|
||||||
|
assert id == to_string(user.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "locked accounts", %{conn: conn} do
|
||||||
|
user = insert(:user, %{info: %User.Info{default_scope: "private"}})
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> get("/api/v1/accounts/verify_credentials")
|
||||||
|
|
||||||
|
assert %{"id" => id, "source" => %{"privacy" => "private"}} = json_response(conn, 200)
|
||||||
|
assert id == to_string(user.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "user relationships" do
|
||||||
|
test "returns the relationships for the current user", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
other_user = insert(:user)
|
||||||
|
{:ok, user} = User.follow(user, other_user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> get("/api/v1/accounts/relationships", %{"id" => [other_user.id]})
|
||||||
|
|
||||||
|
assert [relationship] = json_response(conn, 200)
|
||||||
|
|
||||||
|
assert to_string(other_user.id) == relationship["id"]
|
||||||
|
end
|
||||||
|
|
||||||
|
test "returns an empty list on a bad request", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> get("/api/v1/accounts/relationships", %{})
|
||||||
|
|
||||||
|
assert [] = json_response(conn, 200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -3,7 +3,7 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
defmodule Pleroma.Web.MastodonAPI.DomainBlockControllerTest do
|
defmodule Pleroma.Web.MastodonAPI.DomainBlockControllerTest do
|
||||||
use Pleroma.Web.ConnCase, async: true
|
use Pleroma.Web.ConnCase
|
||||||
|
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -88,7 +88,7 @@ test "Represent a user account" do
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert expected == AccountView.render("account.json", %{user: user})
|
assert expected == AccountView.render("show.json", %{user: user})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "Represent the user account for the account owner" do
|
test "Represent the user account for the account owner" do
|
||||||
|
@ -106,7 +106,7 @@ test "Represent the user account for the account owner" do
|
||||||
assert %{
|
assert %{
|
||||||
pleroma: %{notification_settings: ^notification_settings},
|
pleroma: %{notification_settings: ^notification_settings},
|
||||||
source: %{privacy: ^privacy}
|
source: %{privacy: ^privacy}
|
||||||
} = AccountView.render("account.json", %{user: user, for: user})
|
} = AccountView.render("show.json", %{user: user, for: user})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "Represent a Service(bot) account" do
|
test "Represent a Service(bot) account" do
|
||||||
|
@ -160,13 +160,13 @@ test "Represent a Service(bot) account" do
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert expected == AccountView.render("account.json", %{user: user})
|
assert expected == AccountView.render("show.json", %{user: user})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "Represent a deactivated user for an admin" do
|
test "Represent a deactivated user for an admin" do
|
||||||
admin = insert(:user, %{info: %{is_admin: true}})
|
admin = insert(:user, %{info: %{is_admin: true}})
|
||||||
deactivated_user = insert(:user, %{info: %{deactivated: true}})
|
deactivated_user = insert(:user, %{info: %{deactivated: true}})
|
||||||
represented = AccountView.render("account.json", %{user: deactivated_user, for: admin})
|
represented = AccountView.render("show.json", %{user: deactivated_user, for: admin})
|
||||||
assert represented[:pleroma][:deactivated] == true
|
assert represented[:pleroma][:deactivated] == true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -348,27 +348,27 @@ test "represent an embedded relationship" do
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert expected == AccountView.render("account.json", %{user: user, for: other_user})
|
assert expected == AccountView.render("show.json", %{user: user, for: other_user})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "returns the settings store if the requesting user is the represented user and it's requested specifically" do
|
test "returns the settings store if the requesting user is the represented user and it's requested specifically" do
|
||||||
user = insert(:user, %{info: %User.Info{pleroma_settings_store: %{fe: "test"}}})
|
user = insert(:user, %{info: %User.Info{pleroma_settings_store: %{fe: "test"}}})
|
||||||
|
|
||||||
result =
|
result =
|
||||||
AccountView.render("account.json", %{user: user, for: user, with_pleroma_settings: true})
|
AccountView.render("show.json", %{user: user, for: user, with_pleroma_settings: true})
|
||||||
|
|
||||||
assert result.pleroma.settings_store == %{:fe => "test"}
|
assert result.pleroma.settings_store == %{:fe => "test"}
|
||||||
|
|
||||||
result = AccountView.render("account.json", %{user: user, with_pleroma_settings: true})
|
result = AccountView.render("show.json", %{user: user, with_pleroma_settings: true})
|
||||||
assert result.pleroma[:settings_store] == nil
|
assert result.pleroma[:settings_store] == nil
|
||||||
|
|
||||||
result = AccountView.render("account.json", %{user: user, for: user})
|
result = AccountView.render("show.json", %{user: user, for: user})
|
||||||
assert result.pleroma[:settings_store] == nil
|
assert result.pleroma[:settings_store] == nil
|
||||||
end
|
end
|
||||||
|
|
||||||
test "sanitizes display names" do
|
test "sanitizes display names" do
|
||||||
user = insert(:user, name: "<marquee> username </marquee>")
|
user = insert(:user, name: "<marquee> username </marquee>")
|
||||||
result = AccountView.render("account.json", %{user: user})
|
result = AccountView.render("show.json", %{user: user})
|
||||||
refute result.display_name == "<marquee> username </marquee>"
|
refute result.display_name == "<marquee> username </marquee>"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -391,7 +391,7 @@ test "shows when follows/followers stats are hidden and sets follow/follower cou
|
||||||
followers_count: 0,
|
followers_count: 0,
|
||||||
following_count: 0,
|
following_count: 0,
|
||||||
pleroma: %{hide_follows_count: true, hide_followers_count: true}
|
pleroma: %{hide_follows_count: true, hide_followers_count: true}
|
||||||
} = AccountView.render("account.json", %{user: user})
|
} = AccountView.render("show.json", %{user: user})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "shows when follows/followers are hidden" do
|
test "shows when follows/followers are hidden" do
|
||||||
|
@ -404,7 +404,7 @@ test "shows when follows/followers are hidden" do
|
||||||
followers_count: 1,
|
followers_count: 1,
|
||||||
following_count: 1,
|
following_count: 1,
|
||||||
pleroma: %{hide_follows: true, hide_followers: true}
|
pleroma: %{hide_follows: true, hide_followers: true}
|
||||||
} = AccountView.render("account.json", %{user: user})
|
} = AccountView.render("show.json", %{user: user})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "shows actual follower/following count to the account owner" do
|
test "shows actual follower/following count to the account owner" do
|
||||||
|
@ -416,7 +416,7 @@ test "shows actual follower/following count to the account owner" do
|
||||||
assert %{
|
assert %{
|
||||||
followers_count: 1,
|
followers_count: 1,
|
||||||
following_count: 1
|
following_count: 1
|
||||||
} = AccountView.render("account.json", %{user: user, for: user})
|
} = AccountView.render("show.json", %{user: user, for: user})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -425,65 +425,65 @@ test "shows zero when no follow requests are pending" do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
||||||
assert %{follow_requests_count: 0} =
|
assert %{follow_requests_count: 0} =
|
||||||
AccountView.render("account.json", %{user: user, for: user})
|
AccountView.render("show.json", %{user: user, for: user})
|
||||||
|
|
||||||
other_user = insert(:user)
|
other_user = insert(:user)
|
||||||
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||||
|
|
||||||
assert %{follow_requests_count: 0} =
|
assert %{follow_requests_count: 0} =
|
||||||
AccountView.render("account.json", %{user: user, for: user})
|
AccountView.render("show.json", %{user: user, for: user})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "shows non-zero when follow requests are pending" do
|
test "shows non-zero when follow requests are pending" do
|
||||||
user = insert(:user, %{info: %{locked: true}})
|
user = insert(:user, %{info: %{locked: true}})
|
||||||
|
|
||||||
assert %{locked: true} = AccountView.render("account.json", %{user: user, for: user})
|
assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user})
|
||||||
|
|
||||||
other_user = insert(:user)
|
other_user = insert(:user)
|
||||||
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||||
|
|
||||||
assert %{locked: true, follow_requests_count: 1} =
|
assert %{locked: true, follow_requests_count: 1} =
|
||||||
AccountView.render("account.json", %{user: user, for: user})
|
AccountView.render("show.json", %{user: user, for: user})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "decreases when accepting a follow request" do
|
test "decreases when accepting a follow request" do
|
||||||
user = insert(:user, %{info: %{locked: true}})
|
user = insert(:user, %{info: %{locked: true}})
|
||||||
|
|
||||||
assert %{locked: true} = AccountView.render("account.json", %{user: user, for: user})
|
assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user})
|
||||||
|
|
||||||
other_user = insert(:user)
|
other_user = insert(:user)
|
||||||
{:ok, other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
{:ok, other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||||
|
|
||||||
assert %{locked: true, follow_requests_count: 1} =
|
assert %{locked: true, follow_requests_count: 1} =
|
||||||
AccountView.render("account.json", %{user: user, for: user})
|
AccountView.render("show.json", %{user: user, for: user})
|
||||||
|
|
||||||
{:ok, _other_user} = CommonAPI.accept_follow_request(other_user, user)
|
{:ok, _other_user} = CommonAPI.accept_follow_request(other_user, user)
|
||||||
|
|
||||||
assert %{locked: true, follow_requests_count: 0} =
|
assert %{locked: true, follow_requests_count: 0} =
|
||||||
AccountView.render("account.json", %{user: user, for: user})
|
AccountView.render("show.json", %{user: user, for: user})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "decreases when rejecting a follow request" do
|
test "decreases when rejecting a follow request" do
|
||||||
user = insert(:user, %{info: %{locked: true}})
|
user = insert(:user, %{info: %{locked: true}})
|
||||||
|
|
||||||
assert %{locked: true} = AccountView.render("account.json", %{user: user, for: user})
|
assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user})
|
||||||
|
|
||||||
other_user = insert(:user)
|
other_user = insert(:user)
|
||||||
{:ok, other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
{:ok, other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||||
|
|
||||||
assert %{locked: true, follow_requests_count: 1} =
|
assert %{locked: true, follow_requests_count: 1} =
|
||||||
AccountView.render("account.json", %{user: user, for: user})
|
AccountView.render("show.json", %{user: user, for: user})
|
||||||
|
|
||||||
{:ok, _other_user} = CommonAPI.reject_follow_request(other_user, user)
|
{:ok, _other_user} = CommonAPI.reject_follow_request(other_user, user)
|
||||||
|
|
||||||
assert %{locked: true, follow_requests_count: 0} =
|
assert %{locked: true, follow_requests_count: 0} =
|
||||||
AccountView.render("account.json", %{user: user, for: user})
|
AccountView.render("show.json", %{user: user, for: user})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "shows non-zero when historical unapproved requests are present" do
|
test "shows non-zero when historical unapproved requests are present" do
|
||||||
user = insert(:user, %{info: %{locked: true}})
|
user = insert(:user, %{info: %{locked: true}})
|
||||||
|
|
||||||
assert %{locked: true} = AccountView.render("account.json", %{user: user, for: user})
|
assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user})
|
||||||
|
|
||||||
other_user = insert(:user)
|
other_user = insert(:user)
|
||||||
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||||
|
@ -491,7 +491,7 @@ test "shows non-zero when historical unapproved requests are present" do
|
||||||
{:ok, user} = User.update_info(user, &User.Info.user_upgrade(&1, %{locked: false}))
|
{:ok, user} = User.update_info(user, &User.Info.user_upgrade(&1, %{locked: false}))
|
||||||
|
|
||||||
assert %{locked: false, follow_requests_count: 1} =
|
assert %{locked: false, follow_requests_count: 1} =
|
||||||
AccountView.render("account.json", %{user: user, for: user})
|
AccountView.render("show.json", %{user: user, for: user})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -27,7 +27,7 @@ test "Mention notification" do
|
||||||
id: to_string(notification.id),
|
id: to_string(notification.id),
|
||||||
pleroma: %{is_seen: false},
|
pleroma: %{is_seen: false},
|
||||||
type: "mention",
|
type: "mention",
|
||||||
account: AccountView.render("account.json", %{user: user, for: mentioned_user}),
|
account: AccountView.render("show.json", %{user: user, for: mentioned_user}),
|
||||||
status: StatusView.render("show.json", %{activity: activity, for: mentioned_user}),
|
status: StatusView.render("show.json", %{activity: activity, for: mentioned_user}),
|
||||||
created_at: Utils.to_masto_date(notification.inserted_at)
|
created_at: Utils.to_masto_date(notification.inserted_at)
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ test "Favourite notification" do
|
||||||
id: to_string(notification.id),
|
id: to_string(notification.id),
|
||||||
pleroma: %{is_seen: false},
|
pleroma: %{is_seen: false},
|
||||||
type: "favourite",
|
type: "favourite",
|
||||||
account: AccountView.render("account.json", %{user: another_user, for: user}),
|
account: AccountView.render("show.json", %{user: another_user, for: user}),
|
||||||
status: StatusView.render("show.json", %{activity: create_activity, for: user}),
|
status: StatusView.render("show.json", %{activity: create_activity, for: user}),
|
||||||
created_at: Utils.to_masto_date(notification.inserted_at)
|
created_at: Utils.to_masto_date(notification.inserted_at)
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ test "Reblog notification" do
|
||||||
id: to_string(notification.id),
|
id: to_string(notification.id),
|
||||||
pleroma: %{is_seen: false},
|
pleroma: %{is_seen: false},
|
||||||
type: "reblog",
|
type: "reblog",
|
||||||
account: AccountView.render("account.json", %{user: another_user, for: user}),
|
account: AccountView.render("show.json", %{user: another_user, for: user}),
|
||||||
status: StatusView.render("show.json", %{activity: reblog_activity, for: user}),
|
status: StatusView.render("show.json", %{activity: reblog_activity, for: user}),
|
||||||
created_at: Utils.to_masto_date(notification.inserted_at)
|
created_at: Utils.to_masto_date(notification.inserted_at)
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ test "Follow notification" do
|
||||||
id: to_string(notification.id),
|
id: to_string(notification.id),
|
||||||
pleroma: %{is_seen: false},
|
pleroma: %{is_seen: false},
|
||||||
type: "follow",
|
type: "follow",
|
||||||
account: AccountView.render("account.json", %{user: follower, for: followed}),
|
account: AccountView.render("show.json", %{user: follower, for: followed}),
|
||||||
created_at: Utils.to_masto_date(notification.inserted_at)
|
created_at: Utils.to_masto_date(notification.inserted_at)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -103,7 +103,7 @@ test "a note activity" do
|
||||||
id: to_string(note.id),
|
id: to_string(note.id),
|
||||||
uri: object_data["id"],
|
uri: object_data["id"],
|
||||||
url: Pleroma.Web.Router.Helpers.o_status_url(Pleroma.Web.Endpoint, :notice, note),
|
url: Pleroma.Web.Router.Helpers.o_status_url(Pleroma.Web.Endpoint, :notice, note),
|
||||||
account: AccountView.render("account.json", %{user: user}),
|
account: AccountView.render("show.json", %{user: user}),
|
||||||
in_reply_to_id: nil,
|
in_reply_to_id: nil,
|
||||||
in_reply_to_account_id: nil,
|
in_reply_to_account_id: nil,
|
||||||
card: nil,
|
card: nil,
|
||||||
|
|
|
@ -0,0 +1,395 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do
|
||||||
|
use Pleroma.Web.ConnCase
|
||||||
|
|
||||||
|
alias Pleroma.Config
|
||||||
|
alias Pleroma.Repo
|
||||||
|
alias Pleroma.Tests.ObanHelpers
|
||||||
|
alias Pleroma.User
|
||||||
|
alias Pleroma.Web.CommonAPI
|
||||||
|
|
||||||
|
import Pleroma.Factory
|
||||||
|
import Swoosh.TestAssertions
|
||||||
|
|
||||||
|
@image "data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7"
|
||||||
|
|
||||||
|
describe "POST /api/v1/pleroma/accounts/confirmation_resend" do
|
||||||
|
setup do
|
||||||
|
{:ok, user} =
|
||||||
|
insert(:user)
|
||||||
|
|> User.change_info(&User.Info.confirmation_changeset(&1, need_confirmation: true))
|
||||||
|
|> Repo.update()
|
||||||
|
|
||||||
|
assert user.info.confirmation_pending
|
||||||
|
|
||||||
|
[user: user]
|
||||||
|
end
|
||||||
|
|
||||||
|
clear_config([:instance, :account_activation_required]) do
|
||||||
|
Config.put([:instance, :account_activation_required], true)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "resend account confirmation email", %{conn: conn, user: user} do
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> post("/api/v1/pleroma/accounts/confirmation_resend?email=#{user.email}")
|
||||||
|
|> json_response(:no_content)
|
||||||
|
|
||||||
|
ObanHelpers.perform_all()
|
||||||
|
|
||||||
|
email = Pleroma.Emails.UserEmail.account_confirmation_email(user)
|
||||||
|
notify_email = Config.get([:instance, :notify_email])
|
||||||
|
instance_name = Config.get([:instance, :name])
|
||||||
|
|
||||||
|
assert_email_sent(
|
||||||
|
from: {instance_name, notify_email},
|
||||||
|
to: {user.name, user.email},
|
||||||
|
html_body: email.html_body
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "PATCH /api/v1/pleroma/accounts/update_avatar" do
|
||||||
|
test "user avatar can be set", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
avatar_image = File.read!("test/fixtures/avatar_data_uri")
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> patch("/api/v1/pleroma/accounts/update_avatar", %{img: avatar_image})
|
||||||
|
|
||||||
|
user = refresh_record(user)
|
||||||
|
|
||||||
|
assert %{
|
||||||
|
"name" => _,
|
||||||
|
"type" => _,
|
||||||
|
"url" => [
|
||||||
|
%{
|
||||||
|
"href" => _,
|
||||||
|
"mediaType" => _,
|
||||||
|
"type" => _
|
||||||
|
}
|
||||||
|
]
|
||||||
|
} = user.avatar
|
||||||
|
|
||||||
|
assert %{"url" => _} = json_response(conn, 200)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "user avatar can be reset", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> patch("/api/v1/pleroma/accounts/update_avatar", %{img: ""})
|
||||||
|
|
||||||
|
user = User.get_cached_by_id(user.id)
|
||||||
|
|
||||||
|
assert user.avatar == nil
|
||||||
|
|
||||||
|
assert %{"url" => nil} = json_response(conn, 200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "PATCH /api/v1/pleroma/accounts/update_banner" do
|
||||||
|
test "can set profile banner", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> patch("/api/v1/pleroma/accounts/update_banner", %{"banner" => @image})
|
||||||
|
|
||||||
|
user = refresh_record(user)
|
||||||
|
assert user.info.banner["type"] == "Image"
|
||||||
|
|
||||||
|
assert %{"url" => _} = json_response(conn, 200)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "can reset profile banner", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> patch("/api/v1/pleroma/accounts/update_banner", %{"banner" => ""})
|
||||||
|
|
||||||
|
user = refresh_record(user)
|
||||||
|
assert user.info.banner == %{}
|
||||||
|
|
||||||
|
assert %{"url" => nil} = json_response(conn, 200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "PATCH /api/v1/pleroma/accounts/update_background" do
|
||||||
|
test "background image can be set", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> patch("/api/v1/pleroma/accounts/update_background", %{"img" => @image})
|
||||||
|
|
||||||
|
user = refresh_record(user)
|
||||||
|
assert user.info.background["type"] == "Image"
|
||||||
|
assert %{"url" => _} = json_response(conn, 200)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "background image can be reset", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> patch("/api/v1/pleroma/accounts/update_background", %{"img" => ""})
|
||||||
|
|
||||||
|
user = refresh_record(user)
|
||||||
|
assert user.info.background == %{}
|
||||||
|
assert %{"url" => nil} = json_response(conn, 200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "getting favorites timeline of specified user" do
|
||||||
|
setup do
|
||||||
|
[current_user, user] = insert_pair(:user, %{info: %{hide_favorites: false}})
|
||||||
|
[current_user: current_user, user: user]
|
||||||
|
end
|
||||||
|
|
||||||
|
test "returns list of statuses favorited by specified user", %{
|
||||||
|
conn: conn,
|
||||||
|
current_user: current_user,
|
||||||
|
user: user
|
||||||
|
} do
|
||||||
|
[activity | _] = insert_pair(:note_activity)
|
||||||
|
CommonAPI.favorite(activity.id, user)
|
||||||
|
|
||||||
|
response =
|
||||||
|
conn
|
||||||
|
|> assign(:user, current_user)
|
||||||
|
|> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
|
||||||
|
|> json_response(:ok)
|
||||||
|
|
||||||
|
[like] = response
|
||||||
|
|
||||||
|
assert length(response) == 1
|
||||||
|
assert like["id"] == activity.id
|
||||||
|
end
|
||||||
|
|
||||||
|
test "returns favorites for specified user_id when user is not logged in", %{
|
||||||
|
conn: conn,
|
||||||
|
user: user
|
||||||
|
} do
|
||||||
|
activity = insert(:note_activity)
|
||||||
|
CommonAPI.favorite(activity.id, user)
|
||||||
|
|
||||||
|
response =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
|
||||||
|
|> json_response(:ok)
|
||||||
|
|
||||||
|
assert length(response) == 1
|
||||||
|
end
|
||||||
|
|
||||||
|
test "returns favorited DM only when user is logged in and he is one of recipients", %{
|
||||||
|
conn: conn,
|
||||||
|
current_user: current_user,
|
||||||
|
user: user
|
||||||
|
} do
|
||||||
|
{:ok, direct} =
|
||||||
|
CommonAPI.post(current_user, %{
|
||||||
|
"status" => "Hi @#{user.nickname}!",
|
||||||
|
"visibility" => "direct"
|
||||||
|
})
|
||||||
|
|
||||||
|
CommonAPI.favorite(direct.id, user)
|
||||||
|
|
||||||
|
response =
|
||||||
|
conn
|
||||||
|
|> assign(:user, current_user)
|
||||||
|
|> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
|
||||||
|
|> json_response(:ok)
|
||||||
|
|
||||||
|
assert length(response) == 1
|
||||||
|
|
||||||
|
anonymous_response =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
|
||||||
|
|> json_response(:ok)
|
||||||
|
|
||||||
|
assert Enum.empty?(anonymous_response)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "does not return others' favorited DM when user is not one of recipients", %{
|
||||||
|
conn: conn,
|
||||||
|
current_user: current_user,
|
||||||
|
user: user
|
||||||
|
} do
|
||||||
|
user_two = insert(:user)
|
||||||
|
|
||||||
|
{:ok, direct} =
|
||||||
|
CommonAPI.post(user_two, %{
|
||||||
|
"status" => "Hi @#{user.nickname}!",
|
||||||
|
"visibility" => "direct"
|
||||||
|
})
|
||||||
|
|
||||||
|
CommonAPI.favorite(direct.id, user)
|
||||||
|
|
||||||
|
response =
|
||||||
|
conn
|
||||||
|
|> assign(:user, current_user)
|
||||||
|
|> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
|
||||||
|
|> json_response(:ok)
|
||||||
|
|
||||||
|
assert Enum.empty?(response)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "paginates favorites using since_id and max_id", %{
|
||||||
|
conn: conn,
|
||||||
|
current_user: current_user,
|
||||||
|
user: user
|
||||||
|
} do
|
||||||
|
activities = insert_list(10, :note_activity)
|
||||||
|
|
||||||
|
Enum.each(activities, fn activity ->
|
||||||
|
CommonAPI.favorite(activity.id, user)
|
||||||
|
end)
|
||||||
|
|
||||||
|
third_activity = Enum.at(activities, 2)
|
||||||
|
seventh_activity = Enum.at(activities, 6)
|
||||||
|
|
||||||
|
response =
|
||||||
|
conn
|
||||||
|
|> assign(:user, current_user)
|
||||||
|
|> get("/api/v1/pleroma/accounts/#{user.id}/favourites", %{
|
||||||
|
since_id: third_activity.id,
|
||||||
|
max_id: seventh_activity.id
|
||||||
|
})
|
||||||
|
|> json_response(:ok)
|
||||||
|
|
||||||
|
assert length(response) == 3
|
||||||
|
refute third_activity in response
|
||||||
|
refute seventh_activity in response
|
||||||
|
end
|
||||||
|
|
||||||
|
test "limits favorites using limit parameter", %{
|
||||||
|
conn: conn,
|
||||||
|
current_user: current_user,
|
||||||
|
user: user
|
||||||
|
} do
|
||||||
|
7
|
||||||
|
|> insert_list(:note_activity)
|
||||||
|
|> Enum.each(fn activity ->
|
||||||
|
CommonAPI.favorite(activity.id, user)
|
||||||
|
end)
|
||||||
|
|
||||||
|
response =
|
||||||
|
conn
|
||||||
|
|> assign(:user, current_user)
|
||||||
|
|> get("/api/v1/pleroma/accounts/#{user.id}/favourites", %{limit: "3"})
|
||||||
|
|> json_response(:ok)
|
||||||
|
|
||||||
|
assert length(response) == 3
|
||||||
|
end
|
||||||
|
|
||||||
|
test "returns empty response when user does not have any favorited statuses", %{
|
||||||
|
conn: conn,
|
||||||
|
current_user: current_user,
|
||||||
|
user: user
|
||||||
|
} do
|
||||||
|
response =
|
||||||
|
conn
|
||||||
|
|> assign(:user, current_user)
|
||||||
|
|> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
|
||||||
|
|> json_response(:ok)
|
||||||
|
|
||||||
|
assert Enum.empty?(response)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "returns 404 error when specified user is not exist", %{conn: conn} do
|
||||||
|
conn = get(conn, "/api/v1/pleroma/accounts/test/favourites")
|
||||||
|
|
||||||
|
assert json_response(conn, 404) == %{"error" => "Record not found"}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "returns 403 error when user has hidden own favorites", %{
|
||||||
|
conn: conn,
|
||||||
|
current_user: current_user
|
||||||
|
} do
|
||||||
|
user = insert(:user, %{info: %{hide_favorites: true}})
|
||||||
|
activity = insert(:note_activity)
|
||||||
|
CommonAPI.favorite(activity.id, user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, current_user)
|
||||||
|
|> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
|
||||||
|
|
||||||
|
assert json_response(conn, 403) == %{"error" => "Can't get favorites"}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "hides favorites for new users by default", %{conn: conn, current_user: current_user} do
|
||||||
|
user = insert(:user)
|
||||||
|
activity = insert(:note_activity)
|
||||||
|
CommonAPI.favorite(activity.id, user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, current_user)
|
||||||
|
|> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
|
||||||
|
|
||||||
|
assert user.info.hide_favorites
|
||||||
|
assert json_response(conn, 403) == %{"error" => "Can't get favorites"}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "subscribing / unsubscribing" do
|
||||||
|
test "subscribing / unsubscribing to a user", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
subscription_target = insert(:user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> post("/api/v1/pleroma/accounts/#{subscription_target.id}/subscribe")
|
||||||
|
|
||||||
|
assert %{"id" => _id, "subscribing" => true} = json_response(conn, 200)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
build_conn()
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> post("/api/v1/pleroma/accounts/#{subscription_target.id}/unsubscribe")
|
||||||
|
|
||||||
|
assert %{"id" => _id, "subscribing" => false} = json_response(conn, 200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "subscribing" do
|
||||||
|
test "returns 404 when subscription_target not found", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> post("/api/v1/pleroma/accounts/target_id/subscribe")
|
||||||
|
|
||||||
|
assert %{"error" => "Record not found"} = json_response(conn, 404)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "unsubscribing" do
|
||||||
|
test "returns 404 when subscription_target not found", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> post("/api/v1/pleroma/accounts/target_id/unsubscribe")
|
||||||
|
|
||||||
|
assert %{"error" => "Record not found"} = json_response(conn, 404)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,3 +1,7 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
|
defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
|
||||||
use Pleroma.Web.ConnCase
|
use Pleroma.Web.ConnCase
|
||||||
|
|
|
@ -29,8 +29,8 @@ test "it registers a new user and returns the user." do
|
||||||
|
|
||||||
fetched_user = User.get_cached_by_nickname("lain")
|
fetched_user = User.get_cached_by_nickname("lain")
|
||||||
|
|
||||||
assert AccountView.render("account.json", %{user: user}) ==
|
assert AccountView.render("show.json", %{user: user}) ==
|
||||||
AccountView.render("account.json", %{user: fetched_user})
|
AccountView.render("show.json", %{user: fetched_user})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it registers a new user with empty string in bio and returns the user." do
|
test "it registers a new user with empty string in bio and returns the user." do
|
||||||
|
@ -47,8 +47,8 @@ test "it registers a new user with empty string in bio and returns the user." do
|
||||||
|
|
||||||
fetched_user = User.get_cached_by_nickname("lain")
|
fetched_user = User.get_cached_by_nickname("lain")
|
||||||
|
|
||||||
assert AccountView.render("account.json", %{user: user}) ==
|
assert AccountView.render("show.json", %{user: user}) ==
|
||||||
AccountView.render("account.json", %{user: fetched_user})
|
AccountView.render("show.json", %{user: fetched_user})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it sends confirmation email if :account_activation_required is specified in instance config" do
|
test "it sends confirmation email if :account_activation_required is specified in instance config" do
|
||||||
|
@ -148,8 +148,8 @@ test "returns user on success" do
|
||||||
|
|
||||||
assert invite.used == true
|
assert invite.used == true
|
||||||
|
|
||||||
assert AccountView.render("account.json", %{user: user}) ==
|
assert AccountView.render("show.json", %{user: user}) ==
|
||||||
AccountView.render("account.json", %{user: fetched_user})
|
AccountView.render("show.json", %{user: fetched_user})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "returns error on invalid token" do
|
test "returns error on invalid token" do
|
||||||
|
@ -213,8 +213,8 @@ test "returns error on expired token" do
|
||||||
{:ok, user} = TwitterAPI.register_user(data)
|
{:ok, user} = TwitterAPI.register_user(data)
|
||||||
fetched_user = User.get_cached_by_nickname("vinny")
|
fetched_user = User.get_cached_by_nickname("vinny")
|
||||||
|
|
||||||
assert AccountView.render("account.json", %{user: user}) ==
|
assert AccountView.render("show.json", %{user: user}) ==
|
||||||
AccountView.render("account.json", %{user: fetched_user})
|
AccountView.render("show.json", %{user: fetched_user})
|
||||||
end
|
end
|
||||||
|
|
||||||
{:ok, data: data, check_fn: check_fn}
|
{:ok, data: data, check_fn: check_fn}
|
||||||
|
@ -288,8 +288,8 @@ test "returns user on success, after him registration fails" do
|
||||||
|
|
||||||
assert invite.used == true
|
assert invite.used == true
|
||||||
|
|
||||||
assert AccountView.render("account.json", %{user: user}) ==
|
assert AccountView.render("show.json", %{user: user}) ==
|
||||||
AccountView.render("account.json", %{user: fetched_user})
|
AccountView.render("show.json", %{user: fetched_user})
|
||||||
|
|
||||||
data = %{
|
data = %{
|
||||||
"nickname" => "GrimReaper",
|
"nickname" => "GrimReaper",
|
||||||
|
@ -339,8 +339,8 @@ test "returns user on success" do
|
||||||
|
|
||||||
refute invite.used
|
refute invite.used
|
||||||
|
|
||||||
assert AccountView.render("account.json", %{user: user}) ==
|
assert AccountView.render("show.json", %{user: user}) ==
|
||||||
AccountView.render("account.json", %{user: fetched_user})
|
AccountView.render("show.json", %{user: fetched_user})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "error after max uses" do
|
test "error after max uses" do
|
||||||
|
@ -363,8 +363,8 @@ test "error after max uses" do
|
||||||
invite = Repo.get_by(UserInviteToken, token: invite.token)
|
invite = Repo.get_by(UserInviteToken, token: invite.token)
|
||||||
assert invite.used == true
|
assert invite.used == true
|
||||||
|
|
||||||
assert AccountView.render("account.json", %{user: user}) ==
|
assert AccountView.render("show.json", %{user: user}) ==
|
||||||
AccountView.render("account.json", %{user: fetched_user})
|
AccountView.render("show.json", %{user: fetched_user})
|
||||||
|
|
||||||
data = %{
|
data = %{
|
||||||
"nickname" => "GrimReaper",
|
"nickname" => "GrimReaper",
|
||||||
|
|
Loading…
Reference in New Issue