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
30 changed files with 1821 additions and 1811 deletions
|
@ -84,22 +84,11 @@ def get_lists_from_activity(%Activity{actor: ap_id}) do
|
|||
end
|
||||
|
||||
# Get lists to which the account belongs.
|
||||
def get_lists_account_belongs(%User{} = owner, account_id) do
|
||||
user = User.get_cached_by_id(account_id)
|
||||
|
||||
query =
|
||||
from(
|
||||
l in Pleroma.List,
|
||||
where:
|
||||
l.user_id == ^owner.id and
|
||||
fragment(
|
||||
"? = ANY(?)",
|
||||
^user.follower_address,
|
||||
l.following
|
||||
)
|
||||
)
|
||||
|
||||
Repo.all(query)
|
||||
def get_lists_account_belongs(%User{} = owner, user) do
|
||||
Pleroma.List
|
||||
|> where([l], l.user_id == ^owner.id)
|
||||
|> where([l], fragment("? = ANY(?)", ^user.follower_address, l.following))
|
||||
|> Repo.all()
|
||||
end
|
||||
|
||||
def rename(%Pleroma.List{} = list, title) do
|
||||
|
|
|
@ -43,7 +43,7 @@ def render("show.json", %{report: report, user: user, account: account, statuses
|
|||
end
|
||||
|
||||
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}))
|
||||
end
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ def handle_in("new_msg", %{"text" => text}, %{assigns: %{user_name: user_name}}
|
|||
|
||||
if String.length(text) > 0 do
|
||||
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})
|
||||
|
||||
broadcast!(socket, "new_msg", message)
|
||||
|
|
|
@ -68,4 +68,11 @@ def add_link_headers(conn, activities, extra_params \\ %{}) do
|
|||
conn
|
||||
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
|
||||
|
|
304
lib/pleroma/web/mastodon_api/controllers/account_controller.ex
Normal file
304
lib/pleroma/web/mastodon_api/controllers/account_controller.ex
Normal file
|
@ -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
|
||||
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
|
||||
|
||||
@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
|
||||
conn
|
||||
|> put_view(AccountView)
|
||||
|> render("accounts.json", for: user, users: users, as: :user)
|
||||
|> render("index.json", for: user, users: users, as: :user)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -5,14 +5,11 @@
|
|||
defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
||||
use Pleroma.Web, :controller
|
||||
|
||||
import Pleroma.Web.ControllerHelper,
|
||||
only: [json_response: 3, add_link_headers: 2, truthy_param?: 1]
|
||||
import Pleroma.Web.ControllerHelper, only: [add_link_headers: 2]
|
||||
|
||||
alias Ecto.Changeset
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Bookmark
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.Emoji
|
||||
alias Pleroma.HTTP
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Pagination
|
||||
|
@ -26,8 +23,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.MastodonAPI.AccountView
|
||||
alias Pleroma.Web.MastodonAPI.AppView
|
||||
alias Pleroma.Web.MastodonAPI.ListView
|
||||
alias Pleroma.Web.MastodonAPI.MastodonAPI
|
||||
alias Pleroma.Web.MastodonAPI.MastodonView
|
||||
alias Pleroma.Web.MastodonAPI.StatusView
|
||||
alias Pleroma.Web.MediaProxy
|
||||
|
@ -38,20 +33,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
alias Pleroma.Web.TwitterAPI.TwitterAPI
|
||||
|
||||
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, :account_confirmation_resend when action == :account_confirmation_resend)
|
||||
|
||||
@local_mastodon_name "Mastodon-Local"
|
||||
|
||||
|
@ -74,180 +57,6 @@ def create_app(conn, params) do
|
|||
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
|
||||
with %Token{app: %App{} = app} <- Repo.preload(token, :app) do
|
||||
conn
|
||||
|
@ -256,16 +65,6 @@ def verify_app_credentials(%{assigns: %{user: _user, token: token}} = conn, _) d
|
|||
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"
|
||||
|
||||
def masto_instance(conn, _params) do
|
||||
|
@ -318,25 +117,6 @@ def custom_emojis(conn, _params) do
|
|||
json(conn, mastodon_emoji)
|
||||
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
|
||||
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"]),
|
||||
|
@ -387,17 +167,6 @@ def poll_vote(%{assigns: %{user: user}} = conn, %{"id" => id, "choices" => choic
|
|||
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(
|
||||
%{assigns: %{user: user}} = conn,
|
||||
%{"id" => id, "description" => description} = _
|
||||
|
@ -453,65 +222,13 @@ def get_mascot(%{assigns: %{user: user}} = conn, _params) do
|
|||
json(conn, mascot)
|
||||
end
|
||||
|
||||
def followers(%{assigns: %{user: for_user}} = conn, %{"id" => id} = params) 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
|
||||
def follows(%{assigns: %{user: follower}} = conn, %{"uri" => uri}) do
|
||||
with {_, %User{} = followed} <- {:followed, User.get_cached_by_nickname(uri)},
|
||||
{_, true} <- {:followed, follower.id != followed.id},
|
||||
{:ok, follower, followed, _} <- CommonAPI.follow(follower, followed) do
|
||||
conn
|
||||
|> put_view(AccountView)
|
||||
|> render("account.json", %{user: followed, for: follower})
|
||||
|> render("show.json", %{user: followed, for: follower})
|
||||
else
|
||||
{:followed, _} ->
|
||||
{:error, :not_found}
|
||||
|
@ -523,123 +240,20 @@ def follow(%{assigns: %{user: follower}} = conn, %{"uri" => uri}) do
|
|||
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
|
||||
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)
|
||||
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
|
||||
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)
|
||||
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
|
||||
params =
|
||||
params
|
||||
|
@ -657,37 +271,6 @@ def favourites(%{assigns: %{user: user}} = conn, params) do
|
|||
|> render("index.json", %{activities: activities, for: user, as: :activity})
|
||||
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
|
||||
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})
|
||||
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
|
||||
token = get_session(conn, :oauth_token)
|
||||
|
||||
|
@ -721,8 +296,7 @@ def index(%{assigns: %{user: user}} = conn, _params) do
|
|||
|
||||
limit = Config.get([:instance, :limit])
|
||||
|
||||
accounts =
|
||||
Map.put(%{}, user.id, AccountView.render("account.json", %{user: user, for: user}))
|
||||
accounts = Map.put(%{}, user.id, AccountView.render("show.json", %{user: user, for: user}))
|
||||
|
||||
initial_state =
|
||||
%{
|
||||
|
@ -943,49 +517,6 @@ defp fetch_suggestion_id(attrs) do
|
|||
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
|
||||
nickname_or_email = params["email"] || params["nickname"]
|
||||
|
||||
|
@ -1002,16 +533,6 @@ def password_reset(conn, params) do
|
|||
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)
|
||||
when is_binary(target) do
|
||||
case render(conn, target, params) do
|
||||
|
|
|
@ -22,7 +22,7 @@ def account_search(%{assigns: %{user: user}} = conn, %{"q" => query} = params) d
|
|||
|
||||
conn
|
||||
|> put_view(AccountView)
|
||||
|> render("accounts.json", users: accounts, for: user, as: :user)
|
||||
|> render("index.json", users: accounts, for: user, as: :user)
|
||||
end
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
defp resource_search(_, "statuses", query, options) do
|
||||
|
|
|
@ -231,7 +231,7 @@ def favourited_by(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
|||
|
||||
conn
|
||||
|> put_view(AccountView)
|
||||
|> render("accounts.json", for: user, users: users, as: :user)
|
||||
|> render("index.json", for: user, users: users, as: :user)
|
||||
else
|
||||
{:visible, false} -> {:error, :not_found}
|
||||
_ -> json(conn, [])
|
||||
|
@ -251,7 +251,7 @@ def reblogged_by(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
|||
|
||||
conn
|
||||
|> put_view(AccountView)
|
||||
|> render("accounts.json", for: user, users: users, as: :user)
|
||||
|> render("index.json", for: user, users: users, as: :user)
|
||||
else
|
||||
{:visible, false} -> {:error, :not_found}
|
||||
_ -> json(conn, [])
|
||||
|
|
|
@ -11,15 +11,15 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
|
|||
alias Pleroma.Web.MastodonAPI.AccountView
|
||||
alias Pleroma.Web.MediaProxy
|
||||
|
||||
def render("accounts.json", %{users: users} = opts) do
|
||||
def render("index.json", %{users: users} = opts) do
|
||||
users
|
||||
|> render_many(AccountView, "account.json", opts)
|
||||
|> render_many(AccountView, "show.json", opts)
|
||||
|> Enum.filter(&Enum.any?/1)
|
||||
end
|
||||
|
||||
def render("account.json", %{user: user} = opts) do
|
||||
def render("show.json", %{user: user} = opts) do
|
||||
if User.visible_for?(user, opts[:for]),
|
||||
do: do_render("account.json", opts),
|
||||
do: do_render("show.json", opts),
|
||||
else: %{}
|
||||
end
|
||||
|
||||
|
@ -66,7 +66,7 @@ def render("relationships.json", %{user: user, targets: targets}) do
|
|||
render_many(targets, AccountView, "relationship.json", user: user, as: :target)
|
||||
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)
|
||||
|
||||
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(),
|
||||
accounts: render(AccountView, "accounts.json", users: users, as: :user),
|
||||
accounts: render(AccountView, "index.json", users: users, as: :user),
|
||||
unread: !participation.read,
|
||||
last_status: render(StatusView, "show.json", activity: activity, for: user)
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ def render("show.json", %{
|
|||
id: to_string(notification.id),
|
||||
type: mastodon_type,
|
||||
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: %{
|
||||
is_seen: notification.seen
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ def render(
|
|||
id: to_string(activity.id),
|
||||
uri: 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_account_id: nil,
|
||||
reblog: reblogged,
|
||||
|
@ -258,7 +258,7 @@ def render("show.json", %{activity: %{data: %{"object" => _object}} = activity}
|
|||
id: to_string(activity.id),
|
||||
uri: object.data["id"],
|
||||
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_account_id: reply_to_user && to_string(reply_to_user.id),
|
||||
reblog: nil,
|
||||
|
@ -376,7 +376,7 @@ def render("listen.json", %{activity: %Activity{data: %{"type" => "Listen"}} = a
|
|||
|
||||
%{
|
||||
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,
|
||||
title: object.data["title"] |> HTML.strip_tags(),
|
||||
artist: object.data["artist"] |> HTML.strip_tags(),
|
||||
|
|
143
lib/pleroma/web/pleroma_api/controllers/account_controller.ex
Normal file
143
lib/pleroma/web/pleroma_api/controllers/account_controller.ex
Normal file
|
@ -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
|
||||
|
||||
scope "/api/v1/pleroma", Pleroma.Web.PleromaAPI do
|
||||
pipe_through(:authenticated_api)
|
||||
|
||||
scope [] do
|
||||
pipe_through(:authenticated_api)
|
||||
pipe_through(:oauth_read)
|
||||
get("/conversations/:id/statuses", PleromaAPIController, :conversation_statuses)
|
||||
get("/conversations/:id", PleromaAPIController, :conversation)
|
||||
end
|
||||
|
||||
scope [] do
|
||||
pipe_through(:authenticated_api)
|
||||
pipe_through(:oauth_write)
|
||||
patch("/conversations/:id", PleromaAPIController, :update_conversation)
|
||||
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
|
||||
|
||||
scope [] do
|
||||
pipe_through(:oauth_write)
|
||||
post("/scrobble", ScrobbleController, :new_scrobble)
|
||||
pipe_through(:api)
|
||||
pipe_through(:oauth_read_or_public)
|
||||
get("/accounts/:id/favourites", AccountController, :favourites)
|
||||
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
|
||||
|
||||
scope "/api/v1/pleroma", Pleroma.Web.PleromaAPI do
|
||||
|
@ -319,11 +335,11 @@ defmodule Pleroma.Web.Router do
|
|||
scope [] do
|
||||
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("/follow_requests", FollowRequestController, :index)
|
||||
|
@ -364,7 +380,7 @@ defmodule Pleroma.Web.Router do
|
|||
scope [] do
|
||||
pipe_through(:oauth_write)
|
||||
|
||||
patch("/accounts/update_credentials", MastodonAPIController, :update_credentials)
|
||||
patch("/accounts/update_credentials", AccountController, :update_credentials)
|
||||
|
||||
post("/statuses", StatusController, :create)
|
||||
delete("/statuses/:id", StatusController, :delete)
|
||||
|
@ -400,10 +416,6 @@ defmodule Pleroma.Web.Router do
|
|||
put("/filters/:id", FilterController, :update)
|
||||
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)
|
||||
put("/pleroma/mascot", MastodonAPIController, :set_mascot)
|
||||
|
||||
|
@ -413,23 +425,19 @@ defmodule Pleroma.Web.Router do
|
|||
scope [] do
|
||||
pipe_through(:oauth_follow)
|
||||
|
||||
post("/follows", MastodonAPIController, :follow)
|
||||
post("/accounts/:id/follow", MastodonAPIController, :follow)
|
||||
|
||||
post("/accounts/:id/unfollow", MastodonAPIController, :unfollow)
|
||||
post("/accounts/:id/block", MastodonAPIController, :block)
|
||||
post("/accounts/:id/unblock", MastodonAPIController, :unblock)
|
||||
post("/accounts/:id/mute", MastodonAPIController, :mute)
|
||||
post("/accounts/:id/unmute", MastodonAPIController, :unmute)
|
||||
post("/follows", MastodonAPIController, :follows)
|
||||
post("/accounts/:id/follow", AccountController, :follow)
|
||||
post("/accounts/:id/unfollow", AccountController, :unfollow)
|
||||
post("/accounts/:id/block", AccountController, :block)
|
||||
post("/accounts/:id/unblock", AccountController, :unblock)
|
||||
post("/accounts/:id/mute", AccountController, :mute)
|
||||
post("/accounts/:id/unmute", AccountController, :unmute)
|
||||
|
||||
post("/follow_requests/:id/authorize", FollowRequestController, :authorize)
|
||||
post("/follow_requests/:id/reject", FollowRequestController, :reject)
|
||||
|
||||
post("/domain_blocks", DomainBlockController, :create)
|
||||
delete("/domain_blocks", DomainBlockController, :delete)
|
||||
|
||||
post("/pleroma/accounts/:id/subscribe", MastodonAPIController, :subscribe)
|
||||
post("/pleroma/accounts/:id/unsubscribe", MastodonAPIController, :unsubscribe)
|
||||
end
|
||||
|
||||
scope [] do
|
||||
|
@ -451,7 +459,7 @@ defmodule Pleroma.Web.Router do
|
|||
scope "/api/v1", Pleroma.Web.MastodonAPI do
|
||||
pipe_through(:api)
|
||||
|
||||
post("/accounts", MastodonAPIController, :account_register)
|
||||
post("/accounts", AccountController, :create)
|
||||
|
||||
get("/instance", MastodonAPIController, :masto_instance)
|
||||
get("/instance/peers", MastodonAPIController, :peers)
|
||||
|
@ -468,12 +476,6 @@ defmodule Pleroma.Web.Router do
|
|||
|
||||
get("/accounts/search", SearchController, :account_search)
|
||||
|
||||
post(
|
||||
"/pleroma/accounts/confirmation_resend",
|
||||
MastodonAPIController,
|
||||
:account_confirmation_resend
|
||||
)
|
||||
|
||||
scope [] do
|
||||
pipe_through(:oauth_read_or_public)
|
||||
|
||||
|
@ -487,14 +489,12 @@ defmodule Pleroma.Web.Router do
|
|||
|
||||
get("/polls/:id", MastodonAPIController, :get_poll)
|
||||
|
||||
get("/accounts/:id/statuses", MastodonAPIController, :user_statuses)
|
||||
get("/accounts/:id/followers", MastodonAPIController, :followers)
|
||||
get("/accounts/:id/following", MastodonAPIController, :following)
|
||||
get("/accounts/:id", MastodonAPIController, :user)
|
||||
get("/accounts/:id/statuses", AccountController, :statuses)
|
||||
get("/accounts/:id/followers", AccountController, :followers)
|
||||
get("/accounts/:id/following", AccountController, :following)
|
||||
get("/accounts/:id", AccountController, :show)
|
||||
|
||||
get("/search", SearchController, :search)
|
||||
|
||||
get("/pleroma/accounts/:id/favourites", MastodonAPIController, :user_favourites)
|
||||
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_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
|
||||
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
|
||||
refute not_owned_list in lists_2
|
||||
end
|
||||
|
|
|
@ -1231,7 +1231,7 @@ test "it can handle Listen activities" do
|
|||
|
||||
{: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
|
||||
|
||||
|
|
|
@ -21,12 +21,12 @@ test "renders a report" do
|
|||
content: nil,
|
||||
actor:
|
||||
Map.merge(
|
||||
AccountView.render("account.json", %{user: user}),
|
||||
AccountView.render("show.json", %{user: user}),
|
||||
Pleroma.Web.AdminAPI.AccountView.render("show.json", %{user: user})
|
||||
),
|
||||
account:
|
||||
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})
|
||||
),
|
||||
statuses: [],
|
||||
|
@ -53,12 +53,12 @@ test "includes reported statuses" do
|
|||
content: nil,
|
||||
actor:
|
||||
Map.merge(
|
||||
AccountView.render("account.json", %{user: user}),
|
||||
AccountView.render("show.json", %{user: user}),
|
||||
Pleroma.Web.AdminAPI.AccountView.render("show.json", %{user: user})
|
||||
),
|
||||
account:
|
||||
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})
|
||||
),
|
||||
statuses: [StatusView.render("show.json", %{activity: activity})],
|
||||
|
|
852
test/web/mastodon_api/controllers/account_controller_test.exs
Normal file
852
test/web/mastodon_api/controllers/account_controller_test.exs
Normal file
|
@ -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
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.DomainBlockControllerTest do
|
||||
use Pleroma.Web.ConnCase, async: true
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
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
|
||||
|
||||
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 %{
|
||||
pleroma: %{notification_settings: ^notification_settings},
|
||||
source: %{privacy: ^privacy}
|
||||
} = AccountView.render("account.json", %{user: user, for: user})
|
||||
} = AccountView.render("show.json", %{user: user, for: user})
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
test "Represent a deactivated user for an admin" do
|
||||
admin = insert(:user, %{info: %{is_admin: 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
|
||||
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
|
||||
|
||||
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"}}})
|
||||
|
||||
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"}
|
||||
|
||||
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
|
||||
|
||||
result = AccountView.render("account.json", %{user: user, for: user})
|
||||
result = AccountView.render("show.json", %{user: user, for: user})
|
||||
assert result.pleroma[:settings_store] == nil
|
||||
end
|
||||
|
||||
test "sanitizes display names" do
|
||||
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>"
|
||||
end
|
||||
|
||||
|
@ -391,7 +391,7 @@ test "shows when follows/followers stats are hidden and sets follow/follower cou
|
|||
followers_count: 0,
|
||||
following_count: 0,
|
||||
pleroma: %{hide_follows_count: true, hide_followers_count: true}
|
||||
} = AccountView.render("account.json", %{user: user})
|
||||
} = AccountView.render("show.json", %{user: user})
|
||||
end
|
||||
|
||||
test "shows when follows/followers are hidden" do
|
||||
|
@ -404,7 +404,7 @@ test "shows when follows/followers are hidden" do
|
|||
followers_count: 1,
|
||||
following_count: 1,
|
||||
pleroma: %{hide_follows: true, hide_followers: true}
|
||||
} = AccountView.render("account.json", %{user: user})
|
||||
} = AccountView.render("show.json", %{user: user})
|
||||
end
|
||||
|
||||
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 %{
|
||||
followers_count: 1,
|
||||
following_count: 1
|
||||
} = AccountView.render("account.json", %{user: user, for: user})
|
||||
} = AccountView.render("show.json", %{user: user, for: user})
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -425,65 +425,65 @@ test "shows zero when no follow requests are pending" do
|
|||
user = insert(:user)
|
||||
|
||||
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)
|
||||
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||
|
||||
assert %{follow_requests_count: 0} =
|
||||
AccountView.render("account.json", %{user: user, for: user})
|
||||
AccountView.render("show.json", %{user: user, for: user})
|
||||
end
|
||||
|
||||
test "shows non-zero when follow requests are pending" do
|
||||
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)
|
||||
{:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||
|
||||
assert %{locked: true, follow_requests_count: 1} =
|
||||
AccountView.render("account.json", %{user: user, for: user})
|
||||
AccountView.render("show.json", %{user: user, for: user})
|
||||
end
|
||||
|
||||
test "decreases when accepting a follow request" do
|
||||
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)
|
||||
{:ok, other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||
|
||||
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)
|
||||
|
||||
assert %{locked: true, follow_requests_count: 0} =
|
||||
AccountView.render("account.json", %{user: user, for: user})
|
||||
AccountView.render("show.json", %{user: user, for: user})
|
||||
end
|
||||
|
||||
test "decreases when rejecting a follow request" do
|
||||
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)
|
||||
{:ok, other_user, user, _activity} = CommonAPI.follow(other_user, user)
|
||||
|
||||
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)
|
||||
|
||||
assert %{locked: true, follow_requests_count: 0} =
|
||||
AccountView.render("account.json", %{user: user, for: user})
|
||||
AccountView.render("show.json", %{user: user, for: user})
|
||||
end
|
||||
|
||||
test "shows non-zero when historical unapproved requests are present" do
|
||||
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)
|
||||
{: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}))
|
||||
|
||||
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
|
||||
|
|
|
@ -27,7 +27,7 @@ test "Mention notification" do
|
|||
id: to_string(notification.id),
|
||||
pleroma: %{is_seen: false},
|
||||
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}),
|
||||
created_at: Utils.to_masto_date(notification.inserted_at)
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ test "Favourite notification" do
|
|||
id: to_string(notification.id),
|
||||
pleroma: %{is_seen: false},
|
||||
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}),
|
||||
created_at: Utils.to_masto_date(notification.inserted_at)
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ test "Reblog notification" do
|
|||
id: to_string(notification.id),
|
||||
pleroma: %{is_seen: false},
|
||||
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}),
|
||||
created_at: Utils.to_masto_date(notification.inserted_at)
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ test "Follow notification" do
|
|||
id: to_string(notification.id),
|
||||
pleroma: %{is_seen: false},
|
||||
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)
|
||||
}
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@ test "a note activity" do
|
|||
id: to_string(note.id),
|
||||
uri: object_data["id"],
|
||||
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_account_id: nil,
|
||||
card: nil,
|
||||
|
|
395
test/web/pleroma_api/controllers/account_controller_test.exs
Normal file
395
test/web/pleroma_api/controllers/account_controller_test.exs
Normal file
|
@ -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
|
||||
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")
|
||||
|
||||
assert AccountView.render("account.json", %{user: user}) ==
|
||||
AccountView.render("account.json", %{user: fetched_user})
|
||||
assert AccountView.render("show.json", %{user: user}) ==
|
||||
AccountView.render("show.json", %{user: fetched_user})
|
||||
end
|
||||
|
||||
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")
|
||||
|
||||
assert AccountView.render("account.json", %{user: user}) ==
|
||||
AccountView.render("account.json", %{user: fetched_user})
|
||||
assert AccountView.render("show.json", %{user: user}) ==
|
||||
AccountView.render("show.json", %{user: fetched_user})
|
||||
end
|
||||
|
||||
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 AccountView.render("account.json", %{user: user}) ==
|
||||
AccountView.render("account.json", %{user: fetched_user})
|
||||
assert AccountView.render("show.json", %{user: user}) ==
|
||||
AccountView.render("show.json", %{user: fetched_user})
|
||||
end
|
||||
|
||||
test "returns error on invalid token" do
|
||||
|
@ -213,8 +213,8 @@ test "returns error on expired token" do
|
|||
{:ok, user} = TwitterAPI.register_user(data)
|
||||
fetched_user = User.get_cached_by_nickname("vinny")
|
||||
|
||||
assert AccountView.render("account.json", %{user: user}) ==
|
||||
AccountView.render("account.json", %{user: fetched_user})
|
||||
assert AccountView.render("show.json", %{user: user}) ==
|
||||
AccountView.render("show.json", %{user: fetched_user})
|
||||
end
|
||||
|
||||
{: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 AccountView.render("account.json", %{user: user}) ==
|
||||
AccountView.render("account.json", %{user: fetched_user})
|
||||
assert AccountView.render("show.json", %{user: user}) ==
|
||||
AccountView.render("show.json", %{user: fetched_user})
|
||||
|
||||
data = %{
|
||||
"nickname" => "GrimReaper",
|
||||
|
@ -339,8 +339,8 @@ test "returns user on success" do
|
|||
|
||||
refute invite.used
|
||||
|
||||
assert AccountView.render("account.json", %{user: user}) ==
|
||||
AccountView.render("account.json", %{user: fetched_user})
|
||||
assert AccountView.render("show.json", %{user: user}) ==
|
||||
AccountView.render("show.json", %{user: fetched_user})
|
||||
end
|
||||
|
||||
test "error after max uses" do
|
||||
|
@ -363,8 +363,8 @@ test "error after max uses" do
|
|||
invite = Repo.get_by(UserInviteToken, token: invite.token)
|
||||
assert invite.used == true
|
||||
|
||||
assert AccountView.render("account.json", %{user: user}) ==
|
||||
AccountView.render("account.json", %{user: fetched_user})
|
||||
assert AccountView.render("show.json", %{user: user}) ==
|
||||
AccountView.render("show.json", %{user: fetched_user})
|
||||
|
||||
data = %{
|
||||
"nickname" => "GrimReaper",
|
||||
|
|
Loading…
Reference in a new issue