<% else %>
diff --git a/lib/pleroma/web/templates/static_fe/static_fe/_user_card.html.eex b/lib/pleroma/web/templates/static_fe/static_fe/_user_card.html.eex
index 2a7582d45..977b894d3 100644
--- a/lib/pleroma/web/templates/static_fe/static_fe/_user_card.html.eex
+++ b/lib/pleroma/web/templates/static_fe/static_fe/_user_card.html.eex
@@ -1,10 +1,10 @@
-
+
- <%= raw (@user.name |> Formatter.emojify(emoji_for_user(@user))) %>
+ <%= raw Formatter.emojify(@user.name, @user.emoji) %>
<%= @user.nickname %>
diff --git a/lib/pleroma/web/templates/static_fe/static_fe/profile.html.eex b/lib/pleroma/web/templates/static_fe/static_fe/profile.html.eex
index e7d2aecad..3191bf450 100644
--- a/lib/pleroma/web/templates/static_fe/static_fe/profile.html.eex
+++ b/lib/pleroma/web/templates/static_fe/static_fe/profile.html.eex
@@ -7,7 +7,7 @@
- <%= raw Formatter.emojify(@user.name, emoji_for_user(@user)) %> |
+ <%= raw Formatter.emojify(@user.name, @user.emoji) %> |
<%= link "@#{@user.nickname}@#{Endpoint.host()}", to: (@user.uri || @user.ap_id) %>
<%= raw @user.bio %>
diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex
index 537f9f778..fd2aee175 100644
--- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex
+++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex
@@ -25,13 +25,6 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
when action == :follow_import
)
- # Note: follower can submit the form (with password auth) not being signed in (having no token)
- plug(
- OAuthScopesPlug,
- %{fallback: :proceed_unauthenticated, scopes: ["follow", "write:follows"]}
- when action == :do_remote_follow
- )
-
plug(OAuthScopesPlug, %{scopes: ["follow", "write:blocks"]} when action == :blocks_import)
plug(
@@ -199,15 +192,16 @@ def follow_import(conn, %{"list" => %Plug.Upload{} = listfile}) do
end
def follow_import(%{assigns: %{user: follower}} = conn, %{"list" => list}) do
- with lines <- String.split(list, "\n"),
- followed_identifiers <-
- Enum.map(lines, fn line ->
- String.split(line, ",") |> List.first()
- end)
- |> List.delete("Account address") do
- User.follow_import(follower, followed_identifiers)
- json(conn, "job started")
- end
+ followed_identifiers =
+ list
+ |> String.split("\n")
+ |> Enum.map(&(&1 |> String.split(",") |> List.first()))
+ |> List.delete("Account address")
+ |> Enum.map(&(&1 |> String.trim() |> String.trim_leading("@")))
+ |> Enum.reject(&(&1 == ""))
+
+ User.follow_import(follower, followed_identifiers)
+ json(conn, "job started")
end
def blocks_import(conn, %{"list" => %Plug.Upload{} = listfile}) do
@@ -215,10 +209,9 @@ def blocks_import(conn, %{"list" => %Plug.Upload{} = listfile}) do
end
def blocks_import(%{assigns: %{user: blocker}} = conn, %{"list" => list}) do
- with blocked_identifiers <- String.split(list) do
- User.blocks_import(blocker, blocked_identifiers)
- json(conn, "job started")
- end
+ blocked_identifiers = list |> String.split() |> Enum.map(&String.trim_leading(&1, "@"))
+ User.blocks_import(blocker, blocked_identifiers)
+ json(conn, "job started")
end
def change_password(%{assigns: %{user: user}} = conn, params) do
diff --git a/lib/pleroma/web/twitter_api/twitter_api.ex b/lib/pleroma/web/twitter_api/twitter_api.ex
index f9c0994da..cf1d9c74c 100644
--- a/lib/pleroma/web/twitter_api/twitter_api.ex
+++ b/lib/pleroma/web/twitter_api/twitter_api.ex
@@ -12,72 +12,57 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
require Pleroma.Constants
def register_user(params, opts \\ []) do
- token = params["token"]
+ params =
+ params
+ |> Map.take([
+ :nickname,
+ :password,
+ :captcha_solution,
+ :captcha_token,
+ :captcha_answer_data,
+ :token,
+ :email,
+ :trusted_app
+ ])
+ |> Map.put(:bio, User.parse_bio(params[:bio] || ""))
+ |> Map.put(:name, params.fullname)
+ |> Map.put(:password_confirmation, params[:confirm])
- params = %{
- nickname: params["nickname"],
- name: params["fullname"],
- bio: User.parse_bio(params["bio"]),
- email: params["email"],
- password: params["password"],
- password_confirmation: params["confirm"],
- captcha_solution: params["captcha_solution"],
- captcha_token: params["captcha_token"],
- captcha_answer_data: params["captcha_answer_data"]
- }
+ case validate_captcha(params) do
+ :ok ->
+ if Pleroma.Config.get([:instance, :registrations_open]) do
+ create_user(params, opts)
+ else
+ create_user_with_invite(params, opts)
+ end
- captcha_enabled = Pleroma.Config.get([Pleroma.Captcha, :enabled])
- # true if captcha is disabled or enabled and valid, false otherwise
- captcha_ok =
- if not captcha_enabled do
- :ok
- else
- Pleroma.Captcha.validate(
- params[:captcha_token],
- params[:captcha_solution],
- params[:captcha_answer_data]
- )
- end
+ {:error, error} ->
+ # I have no idea how this error handling works
+ {:error, %{error: Jason.encode!(%{captcha: [error]})}}
+ end
+ end
- # Captcha invalid
- if captcha_ok != :ok do
- {:error, error} = captcha_ok
- # I have no idea how this error handling works
- {:error, %{error: Jason.encode!(%{captcha: [error]})}}
+ defp validate_captcha(params) do
+ if params[:trusted_app] || not Pleroma.Config.get([Pleroma.Captcha, :enabled]) do
+ :ok
else
- registration_process(
- params,
- %{
- registrations_open: Pleroma.Config.get([:instance, :registrations_open]),
- token: token
- },
- opts
+ Pleroma.Captcha.validate(
+ params.captcha_token,
+ params.captcha_solution,
+ params.captcha_answer_data
)
end
end
- defp registration_process(params, %{registrations_open: true}, opts) do
- create_user(params, opts)
- end
-
- defp registration_process(params, %{token: token}, opts) do
- invite =
- unless is_nil(token) do
- Repo.get_by(UserInviteToken, %{token: token})
- end
-
- valid_invite? = invite && UserInviteToken.valid_invite?(invite)
-
- case invite do
- nil ->
- {:error, "Invalid token"}
-
- invite when valid_invite? ->
- UserInviteToken.update_usage!(invite)
- create_user(params, opts)
-
- _ ->
- {:error, "Expired token"}
+ defp create_user_with_invite(params, opts) do
+ with %{token: token} when is_binary(token) <- params,
+ %UserInviteToken{} = invite <- Repo.get_by(UserInviteToken, %{token: token}),
+ true <- UserInviteToken.valid_invite?(invite) do
+ UserInviteToken.update_usage!(invite)
+ create_user(params, opts)
+ else
+ nil -> {:error, "Invalid token"}
+ _ -> {:error, "Expired token"}
end
end
diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex
index 0229aea97..c2de26b0b 100644
--- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex
+++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex
@@ -6,6 +6,7 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
use Pleroma.Web, :controller
alias Pleroma.Notification
+ alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
alias Pleroma.Plugs.OAuthScopesPlug
alias Pleroma.User
alias Pleroma.Web.OAuth.Token
@@ -13,9 +14,17 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
require Logger
- plug(OAuthScopesPlug, %{scopes: ["write:notifications"]} when action == :notifications_read)
+ plug(
+ OAuthScopesPlug,
+ %{scopes: ["write:notifications"]} when action == :mark_notifications_as_read
+ )
- plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug)
+ plug(
+ :skip_plug,
+ [OAuthScopesPlug, EnsurePublicOrAuthenticatedPlug] when action == :confirm_email
+ )
+
+ plug(:skip_plug, OAuthScopesPlug when action in [:oauth_tokens, :revoke_token])
action_fallback(:errors)
@@ -44,13 +53,13 @@ def revoke_token(%{assigns: %{user: user}} = conn, %{"id" => id} = _params) do
json_reply(conn, 201, "")
end
- def errors(conn, {:param_cast, _}) do
+ defp errors(conn, {:param_cast, _}) do
conn
|> put_status(400)
|> json("Invalid parameters")
end
- def errors(conn, _) do
+ defp errors(conn, _) do
conn
|> put_status(500)
|> json("Something went wrong")
@@ -62,7 +71,10 @@ defp json_reply(conn, status, json) do
|> send_resp(status, json)
end
- def notifications_read(%{assigns: %{user: user}} = conn, %{"latest_id" => latest_id} = params) do
+ def mark_notifications_as_read(
+ %{assigns: %{user: user}} = conn,
+ %{"latest_id" => latest_id} = params
+ ) do
Notification.set_read_up_to(user, latest_id)
notifications = Notification.for_user(user, params)
@@ -73,7 +85,7 @@ def notifications_read(%{assigns: %{user: user}} = conn, %{"latest_id" => latest
|> render("index.json", %{notifications: notifications, for: user})
end
- def notifications_read(%{assigns: %{user: _user}} = conn, _) do
+ def mark_notifications_as_read(%{assigns: %{user: _user}} = conn, _) do
bad_request_reply(conn, "You need to specify latest_id")
end
diff --git a/lib/pleroma/web/web.ex b/lib/pleroma/web/web.ex
index cf3ac1287..08e42a7e5 100644
--- a/lib/pleroma/web/web.ex
+++ b/lib/pleroma/web/web.ex
@@ -2,6 +2,11 @@
# Copyright © 2017-2020 Pleroma Authors
# SPDX-License-Identifier: AGPL-3.0-only
+defmodule Pleroma.Web.Plug do
+ # Substitute for `call/2` which is defined with `use Pleroma.Web, :plug`
+ @callback perform(Plug.Conn.t(), Plug.opts()) :: Plug.Conn.t()
+end
+
defmodule Pleroma.Web do
@moduledoc """
A module that keeps using definitions for controllers,
@@ -20,11 +25,19 @@ defmodule Pleroma.Web do
below.
"""
+ alias Pleroma.Plugs.EnsureAuthenticatedPlug
+ alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
+ alias Pleroma.Plugs.ExpectAuthenticatedCheckPlug
+ alias Pleroma.Plugs.ExpectPublicOrAuthenticatedCheckPlug
+ alias Pleroma.Plugs.OAuthScopesPlug
+ alias Pleroma.Plugs.PlugHelper
+
def controller do
quote do
use Phoenix.Controller, namespace: Pleroma.Web
import Plug.Conn
+
import Pleroma.Web.Gettext
import Pleroma.Web.Router.Helpers
import Pleroma.Web.TranslationHelpers
@@ -34,6 +47,79 @@ def controller do
defp set_put_layout(conn, _) do
put_layout(conn, Pleroma.Config.get(:app_layout, "app.html"))
end
+
+ # Marks plugs intentionally skipped and blocks their execution if present in plugs chain
+ defp skip_plug(conn, plug_modules) do
+ plug_modules
+ |> List.wrap()
+ |> Enum.reduce(
+ conn,
+ fn plug_module, conn ->
+ try do
+ plug_module.skip_plug(conn)
+ rescue
+ UndefinedFunctionError ->
+ raise "`#{plug_module}` is not skippable. Append `use Pleroma.Web, :plug` to its code."
+ end
+ end
+ )
+ end
+
+ # Executed just before actual controller action, invokes before-action hooks (callbacks)
+ defp action(conn, params) do
+ with %{halted: false} = conn <- maybe_drop_authentication_if_oauth_check_ignored(conn),
+ %{halted: false} = conn <- maybe_perform_public_or_authenticated_check(conn),
+ %{halted: false} = conn <- maybe_perform_authenticated_check(conn),
+ %{halted: false} = conn <- maybe_halt_on_missing_oauth_scopes_check(conn) do
+ super(conn, params)
+ end
+ end
+
+ # For non-authenticated API actions, drops auth info if OAuth scopes check was ignored
+ # (neither performed nor explicitly skipped)
+ defp maybe_drop_authentication_if_oauth_check_ignored(conn) do
+ if PlugHelper.plug_called?(conn, ExpectPublicOrAuthenticatedCheckPlug) and
+ not PlugHelper.plug_called_or_skipped?(conn, OAuthScopesPlug) do
+ OAuthScopesPlug.drop_auth_info(conn)
+ else
+ conn
+ end
+ end
+
+ # Ensures instance is public -or- user is authenticated if such check was scheduled
+ defp maybe_perform_public_or_authenticated_check(conn) do
+ if PlugHelper.plug_called?(conn, ExpectPublicOrAuthenticatedCheckPlug) do
+ EnsurePublicOrAuthenticatedPlug.call(conn, %{})
+ else
+ conn
+ end
+ end
+
+ # Ensures user is authenticated if such check was scheduled
+ # Note: runs prior to action even if it was already executed earlier in plug chain
+ # (since OAuthScopesPlug has option of proceeding unauthenticated)
+ defp maybe_perform_authenticated_check(conn) do
+ if PlugHelper.plug_called?(conn, ExpectAuthenticatedCheckPlug) do
+ EnsureAuthenticatedPlug.call(conn, %{})
+ else
+ conn
+ end
+ end
+
+ # Halts if authenticated API action neither performs nor explicitly skips OAuth scopes check
+ defp maybe_halt_on_missing_oauth_scopes_check(conn) do
+ if PlugHelper.plug_called?(conn, ExpectAuthenticatedCheckPlug) and
+ not PlugHelper.plug_called_or_skipped?(conn, OAuthScopesPlug) do
+ conn
+ |> render_error(
+ :forbidden,
+ "Security violation: OAuth scopes check was neither handled nor explicitly skipped."
+ )
+ |> halt()
+ else
+ conn
+ end
+ end
end
end
@@ -96,6 +182,44 @@ def channel do
end
end
+ def plug do
+ quote do
+ @behaviour Pleroma.Web.Plug
+ @behaviour Plug
+
+ @doc """
+ Marks a plug intentionally skipped and blocks its execution if it's present in plugs chain.
+ """
+ def skip_plug(conn) do
+ PlugHelper.append_to_private_list(
+ conn,
+ PlugHelper.skipped_plugs_list_id(),
+ __MODULE__
+ )
+ end
+
+ @impl Plug
+ @doc """
+ If marked as skipped, returns `conn`, otherwise calls `perform/2`.
+ Note: multiple invocations of the same plug (with different or same options) are allowed.
+ """
+ def call(%Plug.Conn{} = conn, options) do
+ if PlugHelper.plug_skipped?(conn, __MODULE__) do
+ conn
+ else
+ conn =
+ PlugHelper.append_to_private_list(
+ conn,
+ PlugHelper.called_plugs_list_id(),
+ __MODULE__
+ )
+
+ apply(__MODULE__, :perform, [conn, options])
+ end
+ end
+ end
+ end
+
@doc """
When used, dispatch to the appropriate controller/view/etc.
"""
diff --git a/lib/pleroma/workers/background_worker.ex b/lib/pleroma/workers/background_worker.ex
index 0f8ece2c4..57c3a9c3a 100644
--- a/lib/pleroma/workers/background_worker.ex
+++ b/lib/pleroma/workers/background_worker.ex
@@ -35,7 +35,7 @@ def perform(
_job
) do
blocker = User.get_cached_by_id(blocker_id)
- User.perform(:blocks_import, blocker, blocked_identifiers)
+ {:ok, User.perform(:blocks_import, blocker, blocked_identifiers)}
end
def perform(
@@ -47,7 +47,7 @@ def perform(
_job
) do
follower = User.get_cached_by_id(follower_id)
- User.perform(:follow_import, follower, followed_identifiers)
+ {:ok, User.perform(:follow_import, follower, followed_identifiers)}
end
def perform(%{"op" => "media_proxy_preload", "message" => message}, _job) do
diff --git a/mix.exs b/mix.exs
index c5e5fd432..beb05aab9 100644
--- a/mix.exs
+++ b/mix.exs
@@ -189,7 +189,9 @@ defp deps do
ref: "e0f16822d578866e186a0974d65ad58cddc1e2ab"},
{:mox, "~> 0.5", only: :test},
{:restarter, path: "./restarter"},
- {:open_api_spex, "~> 3.6"}
+ {:open_api_spex,
+ git: "https://git.pleroma.social/pleroma/elixir-libraries/open_api_spex.git",
+ ref: "b862ebd78de0df95875cf46feb6e9607130dc2a8"}
] ++ oauth_deps()
end
@@ -221,19 +223,26 @@ defp version(version) do
identifier_filter = ~r/[^0-9a-z\-]+/i
# Pre-release version, denoted from patch version with a hyphen
+ {tag, tag_err} =
+ System.cmd("git", ["describe", "--tags", "--abbrev=0"], stderr_to_stdout: true)
+
+ {describe, describe_err} = System.cmd("git", ["describe", "--tags", "--abbrev=8"])
+ {commit_hash, commit_hash_err} = System.cmd("git", ["rev-parse", "--short", "HEAD"])
+
git_pre_release =
- with {tag, 0} <-
- System.cmd("git", ["describe", "--tags", "--abbrev=0"], stderr_to_stdout: true),
- {describe, 0} <- System.cmd("git", ["describe", "--tags", "--abbrev=8"]) do
- describe
- |> String.trim()
- |> String.replace(String.trim(tag), "")
- |> String.trim_leading("-")
- |> String.trim()
- else
- _ ->
- {commit_hash, 0} = System.cmd("git", ["rev-parse", "--short", "HEAD"])
+ cond do
+ tag_err == 0 and describe_err == 0 ->
+ describe
+ |> String.trim()
+ |> String.replace(String.trim(tag), "")
+ |> String.trim_leading("-")
+ |> String.trim()
+
+ commit_hash_err == 0 ->
"0-g" <> String.trim(commit_hash)
+
+ true ->
+ ""
end
# Branch name as pre-release version component, denoted with a dot
@@ -251,6 +260,8 @@ defp version(version) do
|> String.replace(identifier_filter, "-")
branch_name
+ else
+ _ -> "stable"
end
build_name =
diff --git a/mix.lock b/mix.lock
index 38adc45e3..b46e4e903 100644
--- a/mix.lock
+++ b/mix.lock
@@ -74,7 +74,7 @@
"nimble_parsec": {:hex, :nimble_parsec, "0.5.1", "c90796ecee0289dbb5ad16d3ad06f957b0cd1199769641c961cfe0b97db190e0", [:mix], [], "hexpm", "00e3ebdc821fb3a36957320d49e8f4bfa310d73ea31c90e5f925dc75e030da8f"},
"nodex": {:git, "https://git.pleroma.social/pleroma/nodex", "cb6730f943cfc6aad674c92161be23a8411f15d1", [ref: "cb6730f943cfc6aad674c92161be23a8411f15d1"]},
"oban": {:hex, :oban, "1.2.0", "7cca94d341be43d220571e28f69131c4afc21095b25257397f50973d3fc59b07", [:mix], [{:ecto_sql, "~> 3.1", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.14", [hex: :postgrex, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ba5f8b3f7d76967b3e23cf8014f6a13e4ccb33431e4808f036709a7f822362ee"},
- "open_api_spex": {:hex, :open_api_spex, "3.6.0", "64205aba9f2607f71b08fd43e3351b9c5e9898ec5ef49fc0ae35890da502ade9", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:poison, "~> 3.1", [hex: :poison, repo: "hexpm", optional: true]}], "hexpm", "126ba3473966277132079cb1d5bf1e3df9e36fe2acd00166e75fd125cecb59c5"},
+ "open_api_spex": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/open_api_spex.git", "b862ebd78de0df95875cf46feb6e9607130dc2a8", [ref: "b862ebd78de0df95875cf46feb6e9607130dc2a8"]},
"parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm", "17ef63abde837ad30680ea7f857dd9e7ced9476cdd7b0394432af4bfc241b960"},
"pbkdf2_elixir": {:hex, :pbkdf2_elixir, "0.12.4", "8dd29ed783f2e12195d7e0a4640effc0a7c37e6537da491f1db01839eee6d053", [:mix], [], "hexpm", "595d09db74cb093b1903381c9de423276a931a2480a46a1a5dc7f932a2a6375b"},
"phoenix": {:hex, :phoenix, "1.4.10", "619e4a545505f562cd294df52294372d012823f4fd9d34a6657a8b242898c255", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.8.1 or ~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "256ad7a140efadc3f0290470369da5bd3de985ec7c706eba07c2641b228974be"},
diff --git a/priv/repo/migrations/20200227122417_add_trusted_to_apps.exs b/priv/repo/migrations/20200227122417_add_trusted_to_apps.exs
new file mode 100644
index 000000000..4e2a62af0
--- /dev/null
+++ b/priv/repo/migrations/20200227122417_add_trusted_to_apps.exs
@@ -0,0 +1,9 @@
+defmodule Pleroma.Repo.Migrations.AddTrustedToApps do
+ use Ecto.Migration
+
+ def change do
+ alter table(:apps) do
+ add(:trusted, :boolean, default: false)
+ end
+ end
+end
diff --git a/priv/repo/migrations/20200401030751_users_add_public_key.exs b/priv/repo/migrations/20200401030751_users_add_public_key.exs
new file mode 100644
index 000000000..04e5ad1e2
--- /dev/null
+++ b/priv/repo/migrations/20200401030751_users_add_public_key.exs
@@ -0,0 +1,17 @@
+defmodule Pleroma.Repo.Migrations.UsersAddPublicKey do
+ use Ecto.Migration
+
+ def up do
+ alter table(:users) do
+ add_if_not_exists(:public_key, :text)
+ end
+
+ execute("UPDATE users SET public_key = source_data->'publicKey'->>'publicKeyPem'")
+ end
+
+ def down do
+ alter table(:users) do
+ remove_if_exists(:public_key, :text)
+ end
+ end
+end
diff --git a/priv/repo/migrations/20200401072456_users_add_inboxes.exs b/priv/repo/migrations/20200401072456_users_add_inboxes.exs
new file mode 100644
index 000000000..0947f0ab2
--- /dev/null
+++ b/priv/repo/migrations/20200401072456_users_add_inboxes.exs
@@ -0,0 +1,20 @@
+defmodule Pleroma.Repo.Migrations.UsersAddInboxes do
+ use Ecto.Migration
+
+ def up do
+ alter table(:users) do
+ add_if_not_exists(:inbox, :text)
+ add_if_not_exists(:shared_inbox, :text)
+ end
+
+ execute("UPDATE users SET inbox = source_data->>'inbox'")
+ execute("UPDATE users SET shared_inbox = source_data->'endpoints'->>'sharedInbox'")
+ end
+
+ def down do
+ alter table(:users) do
+ remove_if_exists(:inbox, :text)
+ remove_if_exists(:shared_inbox, :text)
+ end
+ end
+end
diff --git a/priv/repo/migrations/20200406100225_users_add_emoji.exs b/priv/repo/migrations/20200406100225_users_add_emoji.exs
new file mode 100644
index 000000000..f248108de
--- /dev/null
+++ b/priv/repo/migrations/20200406100225_users_add_emoji.exs
@@ -0,0 +1,38 @@
+defmodule Pleroma.Repo.Migrations.UsersPopulateEmoji do
+ use Ecto.Migration
+
+ import Ecto.Query
+
+ alias Pleroma.User
+ alias Pleroma.Repo
+
+ def up do
+ execute("ALTER TABLE users ALTER COLUMN emoji SET DEFAULT '{}'::jsonb")
+ execute("UPDATE users SET emoji = DEFAULT WHERE emoji = '[]'::jsonb")
+
+ from(u in User)
+ |> select([u], struct(u, [:id, :ap_id, :source_data]))
+ |> Repo.stream()
+ |> Enum.each(fn user ->
+ emoji =
+ user.source_data
+ |> Map.get("tag", [])
+ |> Enum.filter(fn
+ %{"type" => "Emoji"} -> true
+ _ -> false
+ end)
+ |> Enum.reduce(%{}, fn %{"icon" => %{"url" => url}, "name" => name}, acc ->
+ Map.put(acc, String.trim(name, ":"), url)
+ end)
+
+ user
+ |> Ecto.Changeset.cast(%{emoji: emoji}, [:emoji])
+ |> Repo.update()
+ end)
+ end
+
+ def down do
+ execute("ALTER TABLE users ALTER COLUMN emoji SET DEFAULT '[]'::jsonb")
+ execute("UPDATE users SET emoji = DEFAULT WHERE emoji = '{}'::jsonb")
+ end
+end
diff --git a/priv/repo/migrations/20200406105422_users_remove_source_data.exs b/priv/repo/migrations/20200406105422_users_remove_source_data.exs
new file mode 100644
index 000000000..9812d480f
--- /dev/null
+++ b/priv/repo/migrations/20200406105422_users_remove_source_data.exs
@@ -0,0 +1,15 @@
+defmodule Pleroma.Repo.Migrations.UsersRemoveSourceData do
+ use Ecto.Migration
+
+ def up do
+ alter table(:users) do
+ remove_if_exists(:source_data, :map)
+ end
+ end
+
+ def down do
+ alter table(:users) do
+ add_if_not_exists(:source_data, :map, default: %{})
+ end
+ end
+end
diff --git a/priv/static/adminfe/app.85534e14.css b/priv/static/adminfe/app.796ca6d4.css
similarity index 68%
rename from priv/static/adminfe/app.85534e14.css
rename to priv/static/adminfe/app.796ca6d4.css
index 473ec1b86..1b83a8a39 100644
Binary files a/priv/static/adminfe/app.85534e14.css and b/priv/static/adminfe/app.796ca6d4.css differ
diff --git a/priv/static/adminfe/chunk-15fa.5a5f973d.css b/priv/static/adminfe/chunk-0558.af0d89cd.css
similarity index 100%
rename from priv/static/adminfe/chunk-15fa.5a5f973d.css
rename to priv/static/adminfe/chunk-0558.af0d89cd.css
diff --git a/priv/static/adminfe/chunk-0778.d9e7180a.css b/priv/static/adminfe/chunk-0778.d9e7180a.css
new file mode 100644
index 000000000..9d730019a
Binary files /dev/null and b/priv/static/adminfe/chunk-0778.d9e7180a.css differ
diff --git a/priv/static/adminfe/chunk-876c.90dffac4.css b/priv/static/adminfe/chunk-0961.d3692214.css
similarity index 100%
rename from priv/static/adminfe/chunk-876c.90dffac4.css
rename to priv/static/adminfe/chunk-0961.d3692214.css
diff --git a/priv/static/adminfe/chunk-0d8f.d85f5a29.css b/priv/static/adminfe/chunk-0d8f.d85f5a29.css
deleted file mode 100644
index 931620872..000000000
Binary files a/priv/static/adminfe/chunk-0d8f.d85f5a29.css and /dev/null differ
diff --git a/priv/static/adminfe/chunk-13e9.98eaadba.css b/priv/static/adminfe/chunk-13e9.98eaadba.css
deleted file mode 100644
index 9f377eee2..000000000
Binary files a/priv/static/adminfe/chunk-13e9.98eaadba.css and /dev/null differ
diff --git a/priv/static/adminfe/chunk-22d2.813009b9.css b/priv/static/adminfe/chunk-22d2.813009b9.css
new file mode 100644
index 000000000..f0a98583e
Binary files /dev/null and b/priv/static/adminfe/chunk-22d2.813009b9.css differ
diff --git a/priv/static/adminfe/chunk-2b9c.feb61a2b.css b/priv/static/adminfe/chunk-2b9c.feb61a2b.css
deleted file mode 100644
index f54eca1f5..000000000
Binary files a/priv/static/adminfe/chunk-2b9c.feb61a2b.css and /dev/null differ
diff --git a/priv/static/adminfe/chunk-136a.f1130f8e.css b/priv/static/adminfe/chunk-3384.2278f87c.css
similarity index 64%
rename from priv/static/adminfe/chunk-136a.f1130f8e.css
rename to priv/static/adminfe/chunk-3384.2278f87c.css
index f492b37d0..96e3273eb 100644
Binary files a/priv/static/adminfe/chunk-136a.f1130f8e.css and b/priv/static/adminfe/chunk-3384.2278f87c.css differ
diff --git a/priv/static/adminfe/chunk-4011.c4799067.css b/priv/static/adminfe/chunk-4011.c4799067.css
new file mode 100644
index 000000000..1fb099c0c
Binary files /dev/null and b/priv/static/adminfe/chunk-4011.c4799067.css differ
diff --git a/priv/static/adminfe/chunk-46ef.145de4f9.css b/priv/static/adminfe/chunk-46ef.145de4f9.css
deleted file mode 100644
index deb5249ac..000000000
Binary files a/priv/static/adminfe/chunk-46ef.145de4f9.css and /dev/null differ
diff --git a/priv/static/adminfe/chunk-6b68.0cc00484.css b/priv/static/adminfe/chunk-6b68.0cc00484.css
new file mode 100644
index 000000000..7061b3d03
Binary files /dev/null and b/priv/static/adminfe/chunk-6b68.0cc00484.css differ
diff --git a/priv/static/adminfe/chunk-4ffb.dd09fe2e.css b/priv/static/adminfe/chunk-6e81.0e80d020.css
similarity index 100%
rename from priv/static/adminfe/chunk-4ffb.dd09fe2e.css
rename to priv/static/adminfe/chunk-6e81.0e80d020.css
diff --git a/priv/static/adminfe/chunk-7637.941c4edb.css b/priv/static/adminfe/chunk-7637.941c4edb.css
new file mode 100644
index 000000000..be1d183a9
Binary files /dev/null and b/priv/static/adminfe/chunk-7637.941c4edb.css differ
diff --git a/priv/static/adminfe/chunk-87b3.3c6ede9c.css b/priv/static/adminfe/chunk-87b3.3c6ede9c.css
deleted file mode 100644
index f0e6bf4ee..000000000
Binary files a/priv/static/adminfe/chunk-87b3.3c6ede9c.css and /dev/null differ
diff --git a/priv/static/adminfe/chunk-88c9.184084df.css b/priv/static/adminfe/chunk-88c9.184084df.css
deleted file mode 100644
index f3299f33b..000000000
Binary files a/priv/static/adminfe/chunk-88c9.184084df.css and /dev/null differ
diff --git a/priv/static/adminfe/chunk-970d.f59cca8c.css b/priv/static/adminfe/chunk-970d.f59cca8c.css
new file mode 100644
index 000000000..15511f12f
Binary files /dev/null and b/priv/static/adminfe/chunk-970d.f59cca8c.css differ
diff --git a/priv/static/adminfe/chunk-cf57.26596375.css b/priv/static/adminfe/chunk-cf57.26596375.css
deleted file mode 100644
index 9f72b88c1..000000000
Binary files a/priv/static/adminfe/chunk-cf57.26596375.css and /dev/null differ
diff --git a/priv/static/adminfe/chunk-d38a.cabdc22e.css b/priv/static/adminfe/chunk-d38a.cabdc22e.css
new file mode 100644
index 000000000..4a2bf472b
Binary files /dev/null and b/priv/static/adminfe/chunk-d38a.cabdc22e.css differ
diff --git a/priv/static/adminfe/chunk-e458.f88bafea.css b/priv/static/adminfe/chunk-e458.f88bafea.css
new file mode 100644
index 000000000..085bdf076
Binary files /dev/null and b/priv/static/adminfe/chunk-e458.f88bafea.css differ
diff --git a/priv/static/adminfe/index.html b/priv/static/adminfe/index.html
index 3651c1cf0..a236dd0f7 100644
--- a/priv/static/adminfe/index.html
+++ b/priv/static/adminfe/index.html
@@ -1 +1 @@
-
Admin FE
\ No newline at end of file
+
Admin FE
\ No newline at end of file
diff --git a/priv/static/adminfe/static/js/app.203f69f8.js b/priv/static/adminfe/static/js/app.203f69f8.js
new file mode 100644
index 000000000..d06fdf71d
Binary files /dev/null and b/priv/static/adminfe/static/js/app.203f69f8.js differ
diff --git a/priv/static/adminfe/static/js/app.203f69f8.js.map b/priv/static/adminfe/static/js/app.203f69f8.js.map
new file mode 100644
index 000000000..eb78cd464
Binary files /dev/null and b/priv/static/adminfe/static/js/app.203f69f8.js.map differ
diff --git a/priv/static/adminfe/static/js/app.d898cc2b.js b/priv/static/adminfe/static/js/app.d898cc2b.js
deleted file mode 100644
index 9d60db06b..000000000
Binary files a/priv/static/adminfe/static/js/app.d898cc2b.js and /dev/null differ
diff --git a/priv/static/adminfe/static/js/app.d898cc2b.js.map b/priv/static/adminfe/static/js/app.d898cc2b.js.map
deleted file mode 100644
index 1c4ec7590..000000000
Binary files a/priv/static/adminfe/static/js/app.d898cc2b.js.map and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-15fa.34070731.js b/priv/static/adminfe/static/js/chunk-0558.75954137.js
similarity index 98%
rename from priv/static/adminfe/static/js/chunk-15fa.34070731.js
rename to priv/static/adminfe/static/js/chunk-0558.75954137.js
index 937908d00..7b29707fa 100644
Binary files a/priv/static/adminfe/static/js/chunk-15fa.34070731.js and b/priv/static/adminfe/static/js/chunk-0558.75954137.js differ
diff --git a/priv/static/adminfe/static/js/chunk-15fa.34070731.js.map b/priv/static/adminfe/static/js/chunk-0558.75954137.js.map
similarity index 99%
rename from priv/static/adminfe/static/js/chunk-15fa.34070731.js.map
rename to priv/static/adminfe/static/js/chunk-0558.75954137.js.map
index d3830be7c..e9e2affb6 100644
Binary files a/priv/static/adminfe/static/js/chunk-15fa.34070731.js.map and b/priv/static/adminfe/static/js/chunk-0558.75954137.js.map differ
diff --git a/priv/static/adminfe/static/js/chunk-0778.b17650df.js b/priv/static/adminfe/static/js/chunk-0778.b17650df.js
new file mode 100644
index 000000000..1a174cc1e
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-0778.b17650df.js differ
diff --git a/priv/static/adminfe/static/js/chunk-0778.b17650df.js.map b/priv/static/adminfe/static/js/chunk-0778.b17650df.js.map
new file mode 100644
index 000000000..1f96c3236
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-0778.b17650df.js.map differ
diff --git a/priv/static/adminfe/static/js/chunk-876c.e4ceccca.js b/priv/static/adminfe/static/js/chunk-0961.ef33e81b.js
similarity index 97%
rename from priv/static/adminfe/static/js/chunk-876c.e4ceccca.js
rename to priv/static/adminfe/static/js/chunk-0961.ef33e81b.js
index 841ceb9dc..e090bb93c 100644
Binary files a/priv/static/adminfe/static/js/chunk-876c.e4ceccca.js and b/priv/static/adminfe/static/js/chunk-0961.ef33e81b.js differ
diff --git a/priv/static/adminfe/static/js/chunk-876c.e4ceccca.js.map b/priv/static/adminfe/static/js/chunk-0961.ef33e81b.js.map
similarity index 99%
rename from priv/static/adminfe/static/js/chunk-876c.e4ceccca.js.map
rename to priv/static/adminfe/static/js/chunk-0961.ef33e81b.js.map
index 88976a4fe..97c6a4b54 100644
Binary files a/priv/static/adminfe/static/js/chunk-876c.e4ceccca.js.map and b/priv/static/adminfe/static/js/chunk-0961.ef33e81b.js.map differ
diff --git a/priv/static/adminfe/static/js/chunk-0d8f.6d50ff86.js b/priv/static/adminfe/static/js/chunk-0d8f.6d50ff86.js
deleted file mode 100644
index 4b0945f57..000000000
Binary files a/priv/static/adminfe/static/js/chunk-0d8f.6d50ff86.js and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-0d8f.6d50ff86.js.map b/priv/static/adminfe/static/js/chunk-0d8f.6d50ff86.js.map
deleted file mode 100644
index da24cbef5..000000000
Binary files a/priv/static/adminfe/static/js/chunk-0d8f.6d50ff86.js.map and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-136a.c4719e3e.js b/priv/static/adminfe/static/js/chunk-136a.c4719e3e.js
deleted file mode 100644
index 0c2f1a52e..000000000
Binary files a/priv/static/adminfe/static/js/chunk-136a.c4719e3e.js and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-136a.c4719e3e.js.map b/priv/static/adminfe/static/js/chunk-136a.c4719e3e.js.map
deleted file mode 100644
index 4b137fd49..000000000
Binary files a/priv/static/adminfe/static/js/chunk-136a.c4719e3e.js.map and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-13e9.79da1569.js b/priv/static/adminfe/static/js/chunk-13e9.79da1569.js
deleted file mode 100644
index b98177b82..000000000
Binary files a/priv/static/adminfe/static/js/chunk-13e9.79da1569.js and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-13e9.79da1569.js.map b/priv/static/adminfe/static/js/chunk-13e9.79da1569.js.map
deleted file mode 100644
index 118a47034..000000000
Binary files a/priv/static/adminfe/static/js/chunk-13e9.79da1569.js.map and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-22d2.a0cf7976.js b/priv/static/adminfe/static/js/chunk-22d2.a0cf7976.js
new file mode 100644
index 000000000..903f553b0
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-22d2.a0cf7976.js differ
diff --git a/priv/static/adminfe/static/js/chunk-22d2.a0cf7976.js.map b/priv/static/adminfe/static/js/chunk-22d2.a0cf7976.js.map
new file mode 100644
index 000000000..68735ed26
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-22d2.a0cf7976.js.map differ
diff --git a/priv/static/adminfe/static/js/chunk-2b9c.cf321c74.js b/priv/static/adminfe/static/js/chunk-2b9c.cf321c74.js
deleted file mode 100644
index f06da0268..000000000
Binary files a/priv/static/adminfe/static/js/chunk-2b9c.cf321c74.js and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-2b9c.cf321c74.js.map b/priv/static/adminfe/static/js/chunk-2b9c.cf321c74.js.map
deleted file mode 100644
index 1ec750dd1..000000000
Binary files a/priv/static/adminfe/static/js/chunk-2b9c.cf321c74.js.map and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-3384.458ffaf1.js b/priv/static/adminfe/static/js/chunk-3384.458ffaf1.js
new file mode 100644
index 000000000..eb2b55d37
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-3384.458ffaf1.js differ
diff --git a/priv/static/adminfe/static/js/chunk-3384.458ffaf1.js.map b/priv/static/adminfe/static/js/chunk-3384.458ffaf1.js.map
new file mode 100644
index 000000000..0bb577aab
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-3384.458ffaf1.js.map differ
diff --git a/priv/static/adminfe/static/js/chunk-4011.67fb1692.js b/priv/static/adminfe/static/js/chunk-4011.67fb1692.js
new file mode 100644
index 000000000..775ed26f1
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-4011.67fb1692.js differ
diff --git a/priv/static/adminfe/static/js/chunk-4011.67fb1692.js.map b/priv/static/adminfe/static/js/chunk-4011.67fb1692.js.map
new file mode 100644
index 000000000..6df398cbc
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-4011.67fb1692.js.map differ
diff --git a/priv/static/adminfe/static/js/chunk-46ef.671cac7d.js b/priv/static/adminfe/static/js/chunk-46ef.671cac7d.js
deleted file mode 100644
index 805cdea13..000000000
Binary files a/priv/static/adminfe/static/js/chunk-46ef.671cac7d.js and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-46ef.671cac7d.js.map b/priv/static/adminfe/static/js/chunk-46ef.671cac7d.js.map
deleted file mode 100644
index f6b420bb2..000000000
Binary files a/priv/static/adminfe/static/js/chunk-46ef.671cac7d.js.map and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-6b68.fbc0f684.js b/priv/static/adminfe/static/js/chunk-6b68.fbc0f684.js
new file mode 100644
index 000000000..bfdf936f8
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-6b68.fbc0f684.js differ
diff --git a/priv/static/adminfe/static/js/chunk-6b68.fbc0f684.js.map b/priv/static/adminfe/static/js/chunk-6b68.fbc0f684.js.map
new file mode 100644
index 000000000..d1d728b80
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-6b68.fbc0f684.js.map differ
diff --git a/priv/static/adminfe/static/js/chunk-4ffb.0e8f3772.js b/priv/static/adminfe/static/js/chunk-6e81.3733ace2.js
similarity index 85%
rename from priv/static/adminfe/static/js/chunk-4ffb.0e8f3772.js
rename to priv/static/adminfe/static/js/chunk-6e81.3733ace2.js
index 5a7aa9f59..c888ce03f 100644
Binary files a/priv/static/adminfe/static/js/chunk-4ffb.0e8f3772.js and b/priv/static/adminfe/static/js/chunk-6e81.3733ace2.js differ
diff --git a/priv/static/adminfe/static/js/chunk-4ffb.0e8f3772.js.map b/priv/static/adminfe/static/js/chunk-6e81.3733ace2.js.map
similarity index 98%
rename from priv/static/adminfe/static/js/chunk-4ffb.0e8f3772.js.map
rename to priv/static/adminfe/static/js/chunk-6e81.3733ace2.js.map
index 7c020768c..63128dd67 100644
Binary files a/priv/static/adminfe/static/js/chunk-4ffb.0e8f3772.js.map and b/priv/static/adminfe/static/js/chunk-6e81.3733ace2.js.map differ
diff --git a/priv/static/adminfe/static/js/chunk-7637.8f5fb36e.js b/priv/static/adminfe/static/js/chunk-7637.8f5fb36e.js
new file mode 100644
index 000000000..b38644b98
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-7637.8f5fb36e.js differ
diff --git a/priv/static/adminfe/static/js/chunk-7637.8f5fb36e.js.map b/priv/static/adminfe/static/js/chunk-7637.8f5fb36e.js.map
new file mode 100644
index 000000000..ddd53f1cd
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-7637.8f5fb36e.js.map differ
diff --git a/priv/static/adminfe/static/js/chunk-87b3.3c11ef09.js b/priv/static/adminfe/static/js/chunk-87b3.3c11ef09.js
deleted file mode 100644
index 3899ff190..000000000
Binary files a/priv/static/adminfe/static/js/chunk-87b3.3c11ef09.js and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-87b3.3c11ef09.js.map b/priv/static/adminfe/static/js/chunk-87b3.3c11ef09.js.map
deleted file mode 100644
index 6c6a85667..000000000
Binary files a/priv/static/adminfe/static/js/chunk-87b3.3c11ef09.js.map and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-88c9.e3583744.js b/priv/static/adminfe/static/js/chunk-88c9.e3583744.js
deleted file mode 100644
index 0070fc30a..000000000
Binary files a/priv/static/adminfe/static/js/chunk-88c9.e3583744.js and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-88c9.e3583744.js.map b/priv/static/adminfe/static/js/chunk-88c9.e3583744.js.map
deleted file mode 100644
index 20e503d0c..000000000
Binary files a/priv/static/adminfe/static/js/chunk-88c9.e3583744.js.map and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-970d.2457e066.js b/priv/static/adminfe/static/js/chunk-970d.2457e066.js
new file mode 100644
index 000000000..0f99d835e
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-970d.2457e066.js differ
diff --git a/priv/static/adminfe/static/js/chunk-970d.2457e066.js.map b/priv/static/adminfe/static/js/chunk-970d.2457e066.js.map
new file mode 100644
index 000000000..6896407b0
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-970d.2457e066.js.map differ
diff --git a/priv/static/adminfe/static/js/chunk-cf57.3e45f57f.js b/priv/static/adminfe/static/js/chunk-cf57.3e45f57f.js
deleted file mode 100644
index 2b4fd918f..000000000
Binary files a/priv/static/adminfe/static/js/chunk-cf57.3e45f57f.js and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-cf57.3e45f57f.js.map b/priv/static/adminfe/static/js/chunk-cf57.3e45f57f.js.map
deleted file mode 100644
index 6457630bd..000000000
Binary files a/priv/static/adminfe/static/js/chunk-cf57.3e45f57f.js.map and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-d38a.a851004a.js b/priv/static/adminfe/static/js/chunk-d38a.a851004a.js
new file mode 100644
index 000000000..c302af310
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-d38a.a851004a.js differ
diff --git a/priv/static/adminfe/static/js/chunk-d38a.a851004a.js.map b/priv/static/adminfe/static/js/chunk-d38a.a851004a.js.map
new file mode 100644
index 000000000..6779f6dc1
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-d38a.a851004a.js.map differ
diff --git a/priv/static/adminfe/static/js/chunk-e458.4e5aad44.js b/priv/static/adminfe/static/js/chunk-e458.4e5aad44.js
new file mode 100644
index 000000000..a02c83110
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-e458.4e5aad44.js differ
diff --git a/priv/static/adminfe/static/js/chunk-e458.4e5aad44.js.map b/priv/static/adminfe/static/js/chunk-e458.4e5aad44.js.map
new file mode 100644
index 000000000..e623af23d
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-e458.4e5aad44.js.map differ
diff --git a/priv/static/adminfe/static/js/runtime.1b4f6ce0.js b/priv/static/adminfe/static/js/runtime.1b4f6ce0.js
new file mode 100644
index 000000000..6558531ba
Binary files /dev/null and b/priv/static/adminfe/static/js/runtime.1b4f6ce0.js differ
diff --git a/priv/static/adminfe/static/js/runtime.1b4f6ce0.js.map b/priv/static/adminfe/static/js/runtime.1b4f6ce0.js.map
new file mode 100644
index 000000000..9295ac636
Binary files /dev/null and b/priv/static/adminfe/static/js/runtime.1b4f6ce0.js.map differ
diff --git a/priv/static/adminfe/static/js/runtime.cb26bbd1.js b/priv/static/adminfe/static/js/runtime.cb26bbd1.js
deleted file mode 100644
index 7180cc6e3..000000000
Binary files a/priv/static/adminfe/static/js/runtime.cb26bbd1.js and /dev/null differ
diff --git a/priv/static/adminfe/static/js/runtime.cb26bbd1.js.map b/priv/static/adminfe/static/js/runtime.cb26bbd1.js.map
deleted file mode 100644
index 631198682..000000000
Binary files a/priv/static/adminfe/static/js/runtime.cb26bbd1.js.map and /dev/null differ
diff --git a/priv/static/font/fontello.1575660578688.eot b/priv/static/font/fontello.1575660578688.eot
deleted file mode 100644
index 31a66127f..000000000
Binary files a/priv/static/font/fontello.1575660578688.eot and /dev/null differ
diff --git a/priv/static/font/fontello.1575660578688.svg b/priv/static/font/fontello.1575660578688.svg
deleted file mode 100644
index 19fa56ba4..000000000
--- a/priv/static/font/fontello.1575660578688.svg
+++ /dev/null
@@ -1,126 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/priv/static/font/fontello.1575660578688.ttf b/priv/static/font/fontello.1575660578688.ttf
deleted file mode 100644
index 7e990495e..000000000
Binary files a/priv/static/font/fontello.1575660578688.ttf and /dev/null differ
diff --git a/priv/static/font/fontello.1575660578688.woff b/priv/static/font/fontello.1575660578688.woff
deleted file mode 100644
index 239190cba..000000000
Binary files a/priv/static/font/fontello.1575660578688.woff and /dev/null differ
diff --git a/priv/static/font/fontello.1575660578688.woff2 b/priv/static/font/fontello.1575660578688.woff2
deleted file mode 100644
index b4d3537c5..000000000
Binary files a/priv/static/font/fontello.1575660578688.woff2 and /dev/null differ
diff --git a/priv/static/font/fontello.1575662648966.eot b/priv/static/font/fontello.1575662648966.eot
deleted file mode 100644
index a5cb925ad..000000000
Binary files a/priv/static/font/fontello.1575662648966.eot and /dev/null differ
diff --git a/priv/static/font/fontello.1575662648966.svg b/priv/static/font/fontello.1575662648966.svg
deleted file mode 100644
index 19fa56ba4..000000000
--- a/priv/static/font/fontello.1575662648966.svg
+++ /dev/null
@@ -1,126 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/priv/static/font/fontello.1575662648966.ttf b/priv/static/font/fontello.1575662648966.ttf
deleted file mode 100644
index ec67a3d00..000000000
Binary files a/priv/static/font/fontello.1575662648966.ttf and /dev/null differ
diff --git a/priv/static/font/fontello.1575662648966.woff b/priv/static/font/fontello.1575662648966.woff
deleted file mode 100644
index feee99308..000000000
Binary files a/priv/static/font/fontello.1575662648966.woff and /dev/null differ
diff --git a/priv/static/font/fontello.1575662648966.woff2 b/priv/static/font/fontello.1575662648966.woff2
deleted file mode 100644
index a126c585f..000000000
Binary files a/priv/static/font/fontello.1575662648966.woff2 and /dev/null differ
diff --git a/priv/static/fontello.1575660578688.css b/priv/static/fontello.1575660578688.css
deleted file mode 100644
index f232f5600..000000000
Binary files a/priv/static/fontello.1575660578688.css and /dev/null differ
diff --git a/priv/static/fontello.1575662648966.css b/priv/static/fontello.1575662648966.css
deleted file mode 100644
index a47f73e3a..000000000
Binary files a/priv/static/fontello.1575662648966.css and /dev/null differ
diff --git a/priv/static/index.html b/priv/static/index.html
index 4304bdcbb..66c9b53de 100644
--- a/priv/static/index.html
+++ b/priv/static/index.html
@@ -1 +1 @@
-
Pleroma
\ No newline at end of file
+
Pleroma
\ No newline at end of file
diff --git a/priv/static/static/font/fontello.1583594169021.woff2 b/priv/static/static/font/fontello.1583594169021.woff2
deleted file mode 100644
index b963e9489..000000000
Binary files a/priv/static/static/font/fontello.1583594169021.woff2 and /dev/null differ
diff --git a/priv/static/static/font/fontello.1583594169021.eot b/priv/static/static/font/fontello.1587147224637.eot
similarity index 99%
rename from priv/static/static/font/fontello.1583594169021.eot
rename to priv/static/static/font/fontello.1587147224637.eot
index f822a48a3..523e14f27 100644
Binary files a/priv/static/static/font/fontello.1583594169021.eot and b/priv/static/static/font/fontello.1587147224637.eot differ
diff --git a/priv/static/static/font/fontello.1583594169021.svg b/priv/static/static/font/fontello.1587147224637.svg
similarity index 100%
rename from priv/static/static/font/fontello.1583594169021.svg
rename to priv/static/static/font/fontello.1587147224637.svg
diff --git a/priv/static/static/font/fontello.1583594169021.ttf b/priv/static/static/font/fontello.1587147224637.ttf
similarity index 99%
rename from priv/static/static/font/fontello.1583594169021.ttf
rename to priv/static/static/font/fontello.1587147224637.ttf
index 5ed36e9aa..ec6f7f9b4 100644
Binary files a/priv/static/static/font/fontello.1583594169021.ttf and b/priv/static/static/font/fontello.1587147224637.ttf differ
diff --git a/priv/static/static/font/fontello.1583594169021.woff b/priv/static/static/font/fontello.1587147224637.woff
similarity index 98%
rename from priv/static/static/font/fontello.1583594169021.woff
rename to priv/static/static/font/fontello.1587147224637.woff
index 408c26afb..da56c9221 100644
Binary files a/priv/static/static/font/fontello.1583594169021.woff and b/priv/static/static/font/fontello.1587147224637.woff differ
diff --git a/priv/static/static/font/fontello.1587147224637.woff2 b/priv/static/static/font/fontello.1587147224637.woff2
new file mode 100644
index 000000000..6192c0f22
Binary files /dev/null and b/priv/static/static/font/fontello.1587147224637.woff2 differ
diff --git a/priv/static/static/fontello.1583594169021.css b/priv/static/static/fontello.1587147224637.css
similarity index 89%
rename from priv/static/static/fontello.1583594169021.css
rename to priv/static/static/fontello.1587147224637.css
index c096e6103..48e6a5b3c 100644
Binary files a/priv/static/static/fontello.1583594169021.css and b/priv/static/static/fontello.1587147224637.css differ
diff --git a/priv/static/static/js/app.5c94bdec79a7d0f3cfcb.js b/priv/static/static/js/app.5c94bdec79a7d0f3cfcb.js
deleted file mode 100644
index 7ef7a5f12..000000000
Binary files a/priv/static/static/js/app.5c94bdec79a7d0f3cfcb.js and /dev/null differ
diff --git a/priv/static/static/js/app.5c94bdec79a7d0f3cfcb.js.map b/priv/static/static/js/app.5c94bdec79a7d0f3cfcb.js.map
deleted file mode 100644
index 163f78149..000000000
Binary files a/priv/static/static/js/app.5c94bdec79a7d0f3cfcb.js.map and /dev/null differ
diff --git a/priv/static/static/js/app.def6476e8bc9b214218b.js b/priv/static/static/js/app.def6476e8bc9b214218b.js
new file mode 100644
index 000000000..1e6ced42d
Binary files /dev/null and b/priv/static/static/js/app.def6476e8bc9b214218b.js differ
diff --git a/priv/static/static/js/app.def6476e8bc9b214218b.js.map b/priv/static/static/js/app.def6476e8bc9b214218b.js.map
new file mode 100644
index 000000000..a03cad258
Binary files /dev/null and b/priv/static/static/js/app.def6476e8bc9b214218b.js.map differ
diff --git a/priv/static/sw-pleroma.js b/priv/static/sw-pleroma.js
index 88e8fcd5a..92361720e 100644
Binary files a/priv/static/sw-pleroma.js and b/priv/static/sw-pleroma.js differ
diff --git a/test/config/transfer_task_test.exs b/test/config/transfer_task_test.exs
index 0265a6156..473899d1d 100644
--- a/test/config/transfer_task_test.exs
+++ b/test/config/transfer_task_test.exs
@@ -16,6 +16,8 @@ test "transfer config values from db to env" do
refute Application.get_env(:pleroma, :test_key)
refute Application.get_env(:idna, :test_key)
refute Application.get_env(:quack, :test_key)
+ refute Application.get_env(:postgrex, :test_key)
+ initial = Application.get_env(:logger, :level)
ConfigDB.create(%{
group: ":pleroma",
@@ -35,16 +37,28 @@ test "transfer config values from db to env" do
value: [:test_value1, :test_value2]
})
+ ConfigDB.create(%{
+ group: ":postgrex",
+ key: ":test_key",
+ value: :value
+ })
+
+ ConfigDB.create(%{group: ":logger", key: ":level", value: :debug})
+
TransferTask.start_link([])
assert Application.get_env(:pleroma, :test_key) == [live: 2, com: 3]
assert Application.get_env(:idna, :test_key) == [live: 15, com: 35]
assert Application.get_env(:quack, :test_key) == [:test_value1, :test_value2]
+ assert Application.get_env(:logger, :level) == :debug
+ assert Application.get_env(:postgrex, :test_key) == :value
on_exit(fn ->
Application.delete_env(:pleroma, :test_key)
Application.delete_env(:idna, :test_key)
Application.delete_env(:quack, :test_key)
+ Application.delete_env(:postgrex, :test_key)
+ Application.put_env(:logger, :level, initial)
end)
end
@@ -78,8 +92,8 @@ test "transfer config values for 1 group and some keys" do
end
test "transfer config values with full subkey update" do
- emoji = Application.get_env(:pleroma, :emoji)
- assets = Application.get_env(:pleroma, :assets)
+ clear_config(:emoji)
+ clear_config(:assets)
ConfigDB.create(%{
group: ":pleroma",
@@ -99,11 +113,6 @@ test "transfer config values with full subkey update" do
assert emoji_env[:groups] == [a: 1, b: 2]
assets_env = Application.get_env(:pleroma, :assets)
assert assets_env[:mascots] == [a: 1, b: 2]
-
- on_exit(fn ->
- Application.put_env(:pleroma, :emoji, emoji)
- Application.put_env(:pleroma, :assets, assets)
- end)
end
describe "pleroma restart" do
@@ -112,8 +121,7 @@ test "transfer config values with full subkey update" do
end
test "don't restart if no reboot time settings were changed" do
- emoji = Application.get_env(:pleroma, :emoji)
- on_exit(fn -> Application.put_env(:pleroma, :emoji, emoji) end)
+ clear_config(:emoji)
ConfigDB.create(%{
group: ":pleroma",
@@ -128,8 +136,7 @@ test "don't restart if no reboot time settings were changed" do
end
test "on reboot time key" do
- chat = Application.get_env(:pleroma, :chat)
- on_exit(fn -> Application.put_env(:pleroma, :chat, chat) end)
+ clear_config(:chat)
ConfigDB.create(%{
group: ":pleroma",
@@ -141,8 +148,7 @@ test "on reboot time key" do
end
test "on reboot time subkey" do
- captcha = Application.get_env(:pleroma, Pleroma.Captcha)
- on_exit(fn -> Application.put_env(:pleroma, Pleroma.Captcha, captcha) end)
+ clear_config(Pleroma.Captcha)
ConfigDB.create(%{
group: ":pleroma",
@@ -154,13 +160,8 @@ test "on reboot time subkey" do
end
test "don't restart pleroma on reboot time key and subkey if there is false flag" do
- chat = Application.get_env(:pleroma, :chat)
- captcha = Application.get_env(:pleroma, Pleroma.Captcha)
-
- on_exit(fn ->
- Application.put_env(:pleroma, :chat, chat)
- Application.put_env(:pleroma, Pleroma.Captcha, captcha)
- end)
+ clear_config(:chat)
+ clear_config(Pleroma.Captcha)
ConfigDB.create(%{
group: ":pleroma",
diff --git a/test/emoji/formatter_test.exs b/test/emoji/formatter_test.exs
index 3bfee9420..12af6cd8b 100644
--- a/test/emoji/formatter_test.exs
+++ b/test/emoji/formatter_test.exs
@@ -3,7 +3,6 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Emoji.FormatterTest do
- alias Pleroma.Emoji
alias Pleroma.Emoji.Formatter
use Pleroma.DataCase
@@ -32,30 +31,19 @@ test "it does not add XSS emoji" do
end
end
- describe "get_emoji" do
+ describe "get_emoji_map" do
test "it returns the emoji used in the text" do
- text = "I love :firefox:"
-
- assert Formatter.get_emoji(text) == [
- {"firefox",
- %Emoji{
- code: "firefox",
- file: "/emoji/Firefox.gif",
- tags: ["Gif", "Fun"],
- safe_code: "firefox",
- safe_file: "/emoji/Firefox.gif"
- }}
- ]
+ assert Formatter.get_emoji_map("I love :firefox:") == %{
+ "firefox" => "http://localhost:4001/emoji/Firefox.gif"
+ }
end
test "it returns a nice empty result when no emojis are present" do
- text = "I love moominamma"
- assert Formatter.get_emoji(text) == []
+ assert Formatter.get_emoji_map("I love moominamma") == %{}
end
test "it doesn't die when text is absent" do
- text = nil
- assert Formatter.get_emoji(text) == []
+ assert Formatter.get_emoji_map(nil) == %{}
end
end
end
diff --git a/test/fixtures/config/temp.secret.exs b/test/fixtures/config/temp.secret.exs
index f4686c101..dc950ca30 100644
--- a/test/fixtures/config/temp.secret.exs
+++ b/test/fixtures/config/temp.secret.exs
@@ -7,3 +7,5 @@
config :quack, level: :info
config :pleroma, Pleroma.Repo, pool: Ecto.Adapters.SQL.Sandbox
+
+config :postgrex, :json_library, Poison
diff --git a/test/formatter_test.exs b/test/formatter_test.exs
index 93fd8eab7..bef5a2c28 100644
--- a/test/formatter_test.exs
+++ b/test/formatter_test.exs
@@ -140,7 +140,7 @@ test "gives a replacement for user links, using local nicknames in user links te
archaeme =
insert(:user,
nickname: "archa_eme_",
- source_data: %{"url" => "https://archeme/@archa_eme_"}
+ uri: "https://archeme/@archa_eme_"
)
archaeme_remote = insert(:user, %{nickname: "archaeme@archae.me"})
diff --git a/test/instance_static/add/shortcode.png b/test/instance_static/add/shortcode.png
new file mode 100644
index 000000000..8f50fa023
Binary files /dev/null and b/test/instance_static/add/shortcode.png differ
diff --git a/test/instance_static/emoji/pack_bad_sha/blank.png b/test/instance_static/emoji/pack_bad_sha/blank.png
new file mode 100644
index 000000000..8f50fa023
Binary files /dev/null and b/test/instance_static/emoji/pack_bad_sha/blank.png differ
diff --git a/test/instance_static/emoji/pack_bad_sha/pack.json b/test/instance_static/emoji/pack_bad_sha/pack.json
new file mode 100644
index 000000000..35caf4298
--- /dev/null
+++ b/test/instance_static/emoji/pack_bad_sha/pack.json
@@ -0,0 +1,13 @@
+{
+ "pack": {
+ "license": "Test license",
+ "homepage": "https://pleroma.social",
+ "description": "Test description",
+ "can-download": true,
+ "share-files": true,
+ "download-sha256": "57482F30674FD3DE821FF48C81C00DA4D4AF1F300209253684ABA7075E5FC238"
+ },
+ "files": {
+ "blank": "blank.png"
+ }
+}
\ No newline at end of file
diff --git a/test/instance_static/emoji/pack_bad_sha/pack_bad_sha.zip b/test/instance_static/emoji/pack_bad_sha/pack_bad_sha.zip
new file mode 100644
index 000000000..148446c64
Binary files /dev/null and b/test/instance_static/emoji/pack_bad_sha/pack_bad_sha.zip differ
diff --git a/test/instance_static/emoji/test_pack/pack.json b/test/instance_static/emoji/test_pack/pack.json
index 5a8ee75f9..481891b08 100644
--- a/test/instance_static/emoji/test_pack/pack.json
+++ b/test/instance_static/emoji/test_pack/pack.json
@@ -1,13 +1,11 @@
{
- "pack": {
- "license": "Test license",
- "homepage": "https://pleroma.social",
- "description": "Test description",
-
- "share-files": true
- },
-
"files": {
"blank": "blank.png"
+ },
+ "pack": {
+ "description": "Test description",
+ "homepage": "https://pleroma.social",
+ "license": "Test license",
+ "share-files": true
}
-}
+}
\ No newline at end of file
diff --git a/test/instance_static/emoji/test_pack_nonshared/pack.json b/test/instance_static/emoji/test_pack_nonshared/pack.json
index b96781f81..93d643a5f 100644
--- a/test/instance_static/emoji/test_pack_nonshared/pack.json
+++ b/test/instance_static/emoji/test_pack_nonshared/pack.json
@@ -3,14 +3,11 @@
"license": "Test license",
"homepage": "https://pleroma.social",
"description": "Test description",
-
"fallback-src": "https://nonshared-pack",
"fallback-src-sha256": "74409E2674DAA06C072729C6C8426C4CB3B7E0B85ED77792DB7A436E11D76DAF",
-
"share-files": false
},
-
"files": {
"blank": "blank.png"
}
-}
+}
\ No newline at end of file
diff --git a/test/notification_test.exs b/test/notification_test.exs
index f78a47af6..a24139609 100644
--- a/test/notification_test.exs
+++ b/test/notification_test.exs
@@ -8,11 +8,13 @@ defmodule Pleroma.NotificationTest do
import Pleroma.Factory
import Mock
+ alias Pleroma.FollowingRelationship
alias Pleroma.Notification
alias Pleroma.Tests.ObanHelpers
alias Pleroma.User
alias Pleroma.Web.ActivityPub.Transmogrifier
alias Pleroma.Web.CommonAPI
+ alias Pleroma.Web.MastodonAPI.NotificationView
alias Pleroma.Web.Push
alias Pleroma.Web.Streamer
@@ -275,16 +277,6 @@ test "it doesn't create a notification for user if he is the activity author" do
refute Notification.create_notification(activity, author)
end
- test "it doesn't create a notification for follow-unfollow-follow chains" do
- user = insert(:user)
- followed_user = insert(:user)
- {:ok, _, _, activity} = CommonAPI.follow(user, followed_user)
- Notification.create_notification(activity, followed_user)
- CommonAPI.unfollow(user, followed_user)
- {:ok, _, _, activity_dupe} = CommonAPI.follow(user, followed_user)
- refute Notification.create_notification(activity_dupe, followed_user)
- end
-
test "it doesn't create duplicate notifications for follow+subscribed users" do
user = insert(:user)
subscriber = insert(:user)
@@ -307,6 +299,84 @@ test "it doesn't create subscription notifications if the recipient cannot see t
end
end
+ describe "follow / follow_request notifications" do
+ test "it creates `follow` notification for approved Follow activity" do
+ user = insert(:user)
+ followed_user = insert(:user, locked: false)
+
+ {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
+ assert FollowingRelationship.following?(user, followed_user)
+ assert [notification] = Notification.for_user(followed_user)
+
+ assert %{type: "follow"} =
+ NotificationView.render("show.json", %{
+ notification: notification,
+ for: followed_user
+ })
+ end
+
+ test "if `follow_request` notifications are enabled, " <>
+ "it creates `follow_request` notification for pending Follow activity" do
+ clear_config([:notifications, :enable_follow_request_notifications], true)
+ user = insert(:user)
+ followed_user = insert(:user, locked: true)
+
+ {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
+ refute FollowingRelationship.following?(user, followed_user)
+ assert [notification] = Notification.for_user(followed_user)
+
+ render_opts = %{notification: notification, for: followed_user}
+ assert %{type: "follow_request"} = NotificationView.render("show.json", render_opts)
+
+ # After request is accepted, the same notification is rendered with type "follow":
+ assert {:ok, _} = CommonAPI.accept_follow_request(user, followed_user)
+
+ notification_id = notification.id
+ assert [%{id: ^notification_id}] = Notification.for_user(followed_user)
+ assert %{type: "follow"} = NotificationView.render("show.json", render_opts)
+ end
+
+ test "if `follow_request` notifications are disabled, " <>
+ "it does NOT create `follow*` notification for pending Follow activity" do
+ clear_config([:notifications, :enable_follow_request_notifications], false)
+ user = insert(:user)
+ followed_user = insert(:user, locked: true)
+
+ {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
+ refute FollowingRelationship.following?(user, followed_user)
+ assert [] = Notification.for_user(followed_user)
+
+ # After request is accepted, no new notifications are generated:
+ assert {:ok, _} = CommonAPI.accept_follow_request(user, followed_user)
+ assert [] = Notification.for_user(followed_user)
+ end
+
+ test "it doesn't create a notification for follow-unfollow-follow chains" do
+ user = insert(:user)
+ followed_user = insert(:user, locked: false)
+
+ {:ok, _, _, _activity} = CommonAPI.follow(user, followed_user)
+ assert FollowingRelationship.following?(user, followed_user)
+ assert [notification] = Notification.for_user(followed_user)
+
+ CommonAPI.unfollow(user, followed_user)
+ {:ok, _, _, _activity_dupe} = CommonAPI.follow(user, followed_user)
+
+ notification_id = notification.id
+ assert [%{id: ^notification_id}] = Notification.for_user(followed_user)
+ end
+
+ test "dismisses the notification on follow request rejection" do
+ clear_config([:notifications, :enable_follow_request_notifications], true)
+ user = insert(:user, locked: true)
+ follower = insert(:user)
+ {:ok, _, _, _follow_activity} = CommonAPI.follow(follower, user)
+ assert [notification] = Notification.for_user(user)
+ {:ok, _follower} = CommonAPI.reject_follow_request(follower, user)
+ assert [] = Notification.for_user(user)
+ end
+ end
+
describe "get notification" do
test "it gets a notification that belongs to the user" do
user = insert(:user)
@@ -622,6 +692,37 @@ test "it returns thread-muting recipient in disabled recipients list" do
assert [other_user] == disabled_receivers
refute other_user in enabled_receivers
end
+
+ test "it returns non-following domain-blocking recipient in disabled recipients list" do
+ blocked_domain = "blocked.domain"
+ user = insert(:user, %{ap_id: "https://#{blocked_domain}/@actor"})
+ other_user = insert(:user)
+
+ {:ok, other_user} = User.block_domain(other_user, blocked_domain)
+
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}!"})
+
+ {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
+
+ assert [] == enabled_receivers
+ assert [other_user] == disabled_receivers
+ end
+
+ test "it returns following domain-blocking recipient in enabled recipients list" do
+ blocked_domain = "blocked.domain"
+ user = insert(:user, %{ap_id: "https://#{blocked_domain}/@actor"})
+ other_user = insert(:user)
+
+ {:ok, other_user} = User.block_domain(other_user, blocked_domain)
+ {:ok, other_user} = User.follow(other_user, user)
+
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{other_user.nickname}!"})
+
+ {enabled_receivers, disabled_receivers} = Notification.get_notified_from_activity(activity)
+
+ assert [other_user] == enabled_receivers
+ assert [] == disabled_receivers
+ end
end
describe "notification lifecycle" do
@@ -884,7 +985,7 @@ test "it doesn't return notifications for blocked user" do
assert Notification.for_user(user) == []
end
- test "it doesn't return notifications for blocked domain" do
+ test "it doesn't return notifications for domain-blocked non-followed user" do
user = insert(:user)
blocked = insert(:user, ap_id: "http://some-domain.com")
{:ok, user} = User.block_domain(user, "some-domain.com")
@@ -894,6 +995,18 @@ test "it doesn't return notifications for blocked domain" do
assert Notification.for_user(user) == []
end
+ test "it returns notifications for domain-blocked but followed user" do
+ user = insert(:user)
+ blocked = insert(:user, ap_id: "http://some-domain.com")
+
+ {:ok, user} = User.block_domain(user, "some-domain.com")
+ {:ok, _} = User.follow(user, blocked)
+
+ {:ok, _activity} = CommonAPI.post(blocked, %{"status" => "hey @#{user.nickname}"})
+
+ assert length(Notification.for_user(user)) == 1
+ end
+
test "it doesn't return notifications for muted thread" do
user = insert(:user)
another_user = insert(:user)
@@ -924,7 +1037,8 @@ test "it doesn't return notifications from a blocked user when with_muted is set
assert Enum.empty?(Notification.for_user(user, %{with_muted: true}))
end
- test "it doesn't return notifications from a domain-blocked user when with_muted is set" do
+ test "when with_muted is set, " <>
+ "it doesn't return notifications from a domain-blocked non-followed user" do
user = insert(:user)
blocked = insert(:user, ap_id: "http://some-domain.com")
{:ok, user} = User.block_domain(user, "some-domain.com")
diff --git a/test/plugs/authentication_plug_test.exs b/test/plugs/authentication_plug_test.exs
index ae2f3f8ec..646bda9d3 100644
--- a/test/plugs/authentication_plug_test.exs
+++ b/test/plugs/authentication_plug_test.exs
@@ -6,6 +6,8 @@ defmodule Pleroma.Plugs.AuthenticationPlugTest do
use Pleroma.Web.ConnCase, async: true
alias Pleroma.Plugs.AuthenticationPlug
+ alias Pleroma.Plugs.OAuthScopesPlug
+ alias Pleroma.Plugs.PlugHelper
alias Pleroma.User
import ExUnit.CaptureLog
@@ -36,13 +38,16 @@ test "it does nothing if a user is assigned", %{conn: conn} do
assert ret_conn == conn
end
- test "with a correct password in the credentials, it assigns the auth_user", %{conn: conn} do
+ test "with a correct password in the credentials, " <>
+ "it assigns the auth_user and marks OAuthScopesPlug as skipped",
+ %{conn: conn} do
conn =
conn
|> assign(:auth_credentials, %{password: "guy"})
|> AuthenticationPlug.call(%{})
assert conn.assigns.user == conn.assigns.auth_user
+ assert PlugHelper.plug_skipped?(conn, OAuthScopesPlug)
end
test "with a wrong password in the credentials, it does nothing", %{conn: conn} do
diff --git a/test/plugs/ensure_authenticated_plug_test.exs b/test/plugs/ensure_authenticated_plug_test.exs
index 7f3559b83..689fe757f 100644
--- a/test/plugs/ensure_authenticated_plug_test.exs
+++ b/test/plugs/ensure_authenticated_plug_test.exs
@@ -20,7 +20,7 @@ test "it continues if a user is assigned", %{conn: conn} do
conn = assign(conn, :user, %User{})
ret_conn = EnsureAuthenticatedPlug.call(conn, %{})
- assert ret_conn == conn
+ refute ret_conn.halted
end
end
@@ -34,20 +34,22 @@ test "it continues if a user is assigned", %{conn: conn} do
test "it continues if a user is assigned", %{conn: conn, true_fn: true_fn, false_fn: false_fn} do
conn = assign(conn, :user, %User{})
- assert EnsureAuthenticatedPlug.call(conn, if_func: true_fn) == conn
- assert EnsureAuthenticatedPlug.call(conn, if_func: false_fn) == conn
- assert EnsureAuthenticatedPlug.call(conn, unless_func: true_fn) == conn
- assert EnsureAuthenticatedPlug.call(conn, unless_func: false_fn) == conn
+ refute EnsureAuthenticatedPlug.call(conn, if_func: true_fn).halted
+ refute EnsureAuthenticatedPlug.call(conn, if_func: false_fn).halted
+ refute EnsureAuthenticatedPlug.call(conn, unless_func: true_fn).halted
+ refute EnsureAuthenticatedPlug.call(conn, unless_func: false_fn).halted
end
test "it continues if a user is NOT assigned but :if_func evaluates to `false`",
%{conn: conn, false_fn: false_fn} do
- assert EnsureAuthenticatedPlug.call(conn, if_func: false_fn) == conn
+ ret_conn = EnsureAuthenticatedPlug.call(conn, if_func: false_fn)
+ refute ret_conn.halted
end
test "it continues if a user is NOT assigned but :unless_func evaluates to `true`",
%{conn: conn, true_fn: true_fn} do
- assert EnsureAuthenticatedPlug.call(conn, unless_func: true_fn) == conn
+ ret_conn = EnsureAuthenticatedPlug.call(conn, unless_func: true_fn)
+ refute ret_conn.halted
end
test "it halts if a user is NOT assigned and :if_func evaluates to `true`",
diff --git a/test/plugs/ensure_public_or_authenticated_plug_test.exs b/test/plugs/ensure_public_or_authenticated_plug_test.exs
index 411252274..fc2934369 100644
--- a/test/plugs/ensure_public_or_authenticated_plug_test.exs
+++ b/test/plugs/ensure_public_or_authenticated_plug_test.exs
@@ -29,7 +29,7 @@ test "it continues if public", %{conn: conn} do
conn
|> EnsurePublicOrAuthenticatedPlug.call(%{})
- assert ret_conn == conn
+ refute ret_conn.halted
end
test "it continues if a user is assigned, even if not public", %{conn: conn} do
@@ -43,6 +43,6 @@ test "it continues if a user is assigned, even if not public", %{conn: conn} do
conn
|> EnsurePublicOrAuthenticatedPlug.call(%{})
- assert ret_conn == conn
+ refute ret_conn.halted
end
end
diff --git a/test/plugs/legacy_authentication_plug_test.exs b/test/plugs/legacy_authentication_plug_test.exs
index 7559de7d3..3b8c07627 100644
--- a/test/plugs/legacy_authentication_plug_test.exs
+++ b/test/plugs/legacy_authentication_plug_test.exs
@@ -8,6 +8,8 @@ defmodule Pleroma.Plugs.LegacyAuthenticationPlugTest do
import Pleroma.Factory
alias Pleroma.Plugs.LegacyAuthenticationPlug
+ alias Pleroma.Plugs.OAuthScopesPlug
+ alias Pleroma.Plugs.PlugHelper
alias Pleroma.User
setup do
@@ -36,7 +38,8 @@ test "it does nothing if a user is assigned", %{conn: conn, user: user} do
end
@tag :skip_on_mac
- test "it authenticates the auth_user if present and password is correct and resets the password",
+ test "if `auth_user` is present and password is correct, " <>
+ "it authenticates the user, resets the password, marks OAuthScopesPlug as skipped",
%{
conn: conn,
user: user
@@ -49,6 +52,7 @@ test "it authenticates the auth_user if present and password is correct and rese
conn = LegacyAuthenticationPlug.call(conn, %{})
assert conn.assigns.user.id == user.id
+ assert PlugHelper.plug_skipped?(conn, OAuthScopesPlug)
end
@tag :skip_on_mac
diff --git a/test/plugs/oauth_scopes_plug_test.exs b/test/plugs/oauth_scopes_plug_test.exs
index e79ecf263..884de7b4d 100644
--- a/test/plugs/oauth_scopes_plug_test.exs
+++ b/test/plugs/oauth_scopes_plug_test.exs
@@ -5,15 +5,22 @@
defmodule Pleroma.Plugs.OAuthScopesPlugTest do
use Pleroma.Web.ConnCase, async: true
- alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
alias Pleroma.Plugs.OAuthScopesPlug
alias Pleroma.Repo
import Mock
import Pleroma.Factory
- setup_with_mocks([{EnsurePublicOrAuthenticatedPlug, [], [call: fn conn, _ -> conn end]}]) do
- :ok
+ test "is not performed if marked as skipped", %{conn: conn} do
+ with_mock OAuthScopesPlug, [:passthrough], perform: &passthrough([&1, &2]) do
+ conn =
+ conn
+ |> OAuthScopesPlug.skip_plug()
+ |> OAuthScopesPlug.call(%{scopes: ["random_scope"]})
+
+ refute called(OAuthScopesPlug.perform(:_, :_))
+ refute conn.halted
+ end
end
test "if `token.scopes` fulfills specified 'any of' conditions, " <>
@@ -48,7 +55,7 @@ test "if `token.scopes` fulfills specified 'all of' conditions, " <>
describe "with `fallback: :proceed_unauthenticated` option, " do
test "if `token.scopes` doesn't fulfill specified conditions, " <>
- "clears :user and :token assigns and calls EnsurePublicOrAuthenticatedPlug",
+ "clears :user and :token assigns",
%{conn: conn} do
user = insert(:user)
token1 = insert(:oauth_token, scopes: ["read", "write"], user: user)
@@ -67,35 +74,6 @@ test "if `token.scopes` doesn't fulfill specified conditions, " <>
refute ret_conn.halted
refute ret_conn.assigns[:user]
refute ret_conn.assigns[:token]
-
- assert called(EnsurePublicOrAuthenticatedPlug.call(ret_conn, :_))
- end
- end
-
- test "with :skip_instance_privacy_check option, " <>
- "if `token.scopes` doesn't fulfill specified conditions, " <>
- "clears :user and :token assigns and does NOT call EnsurePublicOrAuthenticatedPlug",
- %{conn: conn} do
- user = insert(:user)
- token1 = insert(:oauth_token, scopes: ["read:statuses", "write"], user: user)
-
- for token <- [token1, nil], op <- [:|, :&] do
- ret_conn =
- conn
- |> assign(:user, user)
- |> assign(:token, token)
- |> OAuthScopesPlug.call(%{
- scopes: ["read"],
- op: op,
- fallback: :proceed_unauthenticated,
- skip_instance_privacy_check: true
- })
-
- refute ret_conn.halted
- refute ret_conn.assigns[:user]
- refute ret_conn.assigns[:token]
-
- refute called(EnsurePublicOrAuthenticatedPlug.call(ret_conn, :_))
end
end
end
diff --git a/test/signature_test.exs b/test/signature_test.exs
index 04736d8b9..d5a2a62c4 100644
--- a/test/signature_test.exs
+++ b/test/signature_test.exs
@@ -19,12 +19,7 @@ defmodule Pleroma.SignatureTest do
@private_key "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEA48qb4v6kqigZutO9Ot0wkp27GIF2LiVaADgxQORZozZR63jH\nTaoOrS3Xhngbgc8SSOhfXET3omzeCLqaLNfXnZ8OXmuhJfJSU6mPUvmZ9QdT332j\nfN/g3iWGhYMf/M9ftCKh96nvFVO/tMruzS9xx7tkrfJjehdxh/3LlJMMImPtwcD7\nkFXwyt1qZTAU6Si4oQAJxRDQXHp1ttLl3Ob829VM7IKkrVmY8TD+JSlV0jtVJPj6\n1J19ytKTx/7UaucYvb9HIiBpkuiy5n/irDqKLVf5QEdZoNCdojOZlKJmTLqHhzKP\n3E9TxsUjhrf4/EqegNc/j982RvOxeu4i40zMQwIDAQABAoIBAQDH5DXjfh21i7b4\ncXJuw0cqget617CDUhemdakTDs9yH+rHPZd3mbGDWuT0hVVuFe4vuGpmJ8c+61X0\nRvugOlBlavxK8xvYlsqTzAmPgKUPljyNtEzQ+gz0I+3mH2jkin2rL3D+SksZZgKm\nfiYMPIQWB2WUF04gB46DDb2mRVuymGHyBOQjIx3WC0KW2mzfoFUFRlZEF+Nt8Ilw\nT+g/u0aZ1IWoszbsVFOEdghgZET0HEarum0B2Je/ozcPYtwmU10iBANGMKdLqaP/\nj954BPunrUf6gmlnLZKIKklJj0advx0NA+cL79+zeVB3zexRYSA5o9q0WPhiuTwR\n/aedWHnBAoGBAP0sDWBAM1Y4TRAf8ZI9PcztwLyHPzfEIqzbObJJnx1icUMt7BWi\n+/RMOnhrlPGE1kMhOqSxvXYN3u+eSmWTqai2sSH5Hdw2EqnrISSTnwNUPINX7fHH\njEkgmXQ6ixE48SuBZnb4w1EjdB/BA6/sjL+FNhggOc87tizLTkMXmMtTAoGBAOZV\n+wPuAMBDBXmbmxCuDIjoVmgSlgeRunB1SA8RCPAFAiUo3+/zEgzW2Oz8kgI+xVwM\n33XkLKrWG1Orhpp6Hm57MjIc5MG+zF4/YRDpE/KNG9qU1tiz0UD5hOpIU9pP4bR/\ngxgPxZzvbk4h5BfHWLpjlk8UUpgk6uxqfti48c1RAoGBALBOKDZ6HwYRCSGMjUcg\n3NPEUi84JD8qmFc2B7Tv7h2he2ykIz9iFAGpwCIyETQsJKX1Ewi0OlNnD3RhEEAy\nl7jFGQ+mkzPSeCbadmcpYlgIJmf1KN/x7fDTAepeBpCEzfZVE80QKbxsaybd3Dp8\nCfwpwWUFtBxr4c7J+gNhAGe/AoGAPn8ZyqkrPv9wXtyfqFjxQbx4pWhVmNwrkBPi\nZ2Qh3q4dNOPwTvTO8vjghvzIyR8rAZzkjOJKVFgftgYWUZfM5gE7T2mTkBYq8W+U\n8LetF+S9qAM2gDnaDx0kuUTCq7t87DKk6URuQ/SbI0wCzYjjRD99KxvChVGPBHKo\n1DjqMuECgYEAgJGNm7/lJCS2wk81whfy/ttKGsEIkyhPFYQmdGzSYC5aDc2gp1R3\nxtOkYEvdjfaLfDGEa4UX8CHHF+w3t9u8hBtcdhMH6GYb9iv6z0VBTt4A/11HUR49\n3Z7TQ18Iyh3jAUCzFV9IJlLIExq5Y7P4B3ojWFBN607sDCt8BMPbDYs=\n-----END RSA PRIVATE KEY-----"
- @public_key %{
- "id" => "https://mastodon.social/users/lambadalambda#main-key",
- "owner" => "https://mastodon.social/users/lambadalambda",
- "publicKeyPem" =>
- "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw0P/Tq4gb4G/QVuMGbJo\nC/AfMNcv+m7NfrlOwkVzcU47jgESuYI4UtJayissCdBycHUnfVUd9qol+eznSODz\nCJhfJloqEIC+aSnuEPGA0POtWad6DU0E6/Ho5zQn5WAWUwbRQqowbrsm/GHo2+3v\neR5jGenwA6sYhINg/c3QQbksyV0uJ20Umyx88w8+TJuv53twOfmyDWuYNoQ3y5cc\nHKOZcLHxYOhvwg3PFaGfFHMFiNmF40dTXt9K96r7sbzc44iLD+VphbMPJEjkMuf8\nPGEFOBzy8pm3wJZw2v32RNW2VESwMYyqDzwHXGSq1a73cS7hEnc79gXlELsK04L9\nQQIDAQAB\n-----END PUBLIC KEY-----\n"
- }
+ @public_key "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw0P/Tq4gb4G/QVuMGbJo\nC/AfMNcv+m7NfrlOwkVzcU47jgESuYI4UtJayissCdBycHUnfVUd9qol+eznSODz\nCJhfJloqEIC+aSnuEPGA0POtWad6DU0E6/Ho5zQn5WAWUwbRQqowbrsm/GHo2+3v\neR5jGenwA6sYhINg/c3QQbksyV0uJ20Umyx88w8+TJuv53twOfmyDWuYNoQ3y5cc\nHKOZcLHxYOhvwg3PFaGfFHMFiNmF40dTXt9K96r7sbzc44iLD+VphbMPJEjkMuf8\nPGEFOBzy8pm3wJZw2v32RNW2VESwMYyqDzwHXGSq1a73cS7hEnc79gXlELsK04L9\nQQIDAQAB\n-----END PUBLIC KEY-----\n"
@rsa_public_key {
:RSAPublicKey,
@@ -42,7 +37,7 @@ defp make_fake_conn(key_id),
test "it returns key" do
expected_result = {:ok, @rsa_public_key}
- user = insert(:user, source_data: %{"publicKey" => @public_key})
+ user = insert(:user, public_key: @public_key)
assert Signature.fetch_public_key(make_fake_conn(user.ap_id)) == expected_result
end
@@ -53,8 +48,8 @@ test "it returns error when not found user" do
end) =~ "[error] Could not decode user"
end
- test "it returns error if public key is empty" do
- user = insert(:user, source_data: %{"publicKey" => %{}})
+ test "it returns error if public key is nil" do
+ user = insert(:user, public_key: nil)
assert Signature.fetch_public_key(make_fake_conn(user.ap_id)) == {:error, :error}
end
diff --git a/test/stat_test.exs b/test/stats_test.exs
similarity index 86%
rename from test/stat_test.exs
rename to test/stats_test.exs
index bccc1c8d0..c1aeb2c7f 100644
--- a/test/stat_test.exs
+++ b/test/stats_test.exs
@@ -2,11 +2,21 @@
# Copyright © 2017-2020 Pleroma Authors
# SPDX-License-Identifier: AGPL-3.0-only
-defmodule Pleroma.StateTest do
+defmodule Pleroma.StatsTest do
use Pleroma.DataCase
import Pleroma.Factory
alias Pleroma.Web.CommonAPI
+ describe "user count" do
+ test "it ignores internal users" do
+ _user = insert(:user, local: true)
+ _internal = insert(:user, local: true, nickname: nil)
+ _internal = Pleroma.Web.ActivityPub.Relay.get_actor()
+
+ assert match?(%{stats: %{user_count: 1}}, Pleroma.Stats.calculate_stat_data())
+ end
+ end
+
describe "status visibility count" do
test "on new status" do
user = insert(:user)
diff --git a/test/support/api_spec_helpers.ex b/test/support/api_spec_helpers.ex
new file mode 100644
index 000000000..80c69c788
--- /dev/null
+++ b/test/support/api_spec_helpers.ex
@@ -0,0 +1,57 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Tests.ApiSpecHelpers do
+ @moduledoc """
+ OpenAPI spec test helpers
+ """
+
+ import ExUnit.Assertions
+
+ alias OpenApiSpex.Cast.Error
+ alias OpenApiSpex.Reference
+ alias OpenApiSpex.Schema
+
+ def assert_schema(value, schema) do
+ api_spec = Pleroma.Web.ApiSpec.spec()
+
+ case OpenApiSpex.cast_value(value, schema, api_spec) do
+ {:ok, data} ->
+ data
+
+ {:error, errors} ->
+ errors =
+ Enum.map(errors, fn error ->
+ message = Error.message(error)
+ path = Error.path_to_string(error)
+ "#{message} at #{path}"
+ end)
+
+ flunk(
+ "Value does not conform to schema #{schema.title}: #{Enum.join(errors, "\n")}\n#{
+ inspect(value)
+ }"
+ )
+ end
+ end
+
+ def resolve_schema(%Schema{} = schema), do: schema
+
+ def resolve_schema(%Reference{} = ref) do
+ schemas = Pleroma.Web.ApiSpec.spec().components.schemas
+ Reference.resolve_schema(ref, schemas)
+ end
+
+ def api_operations do
+ paths = Pleroma.Web.ApiSpec.spec().paths
+
+ Enum.flat_map(paths, fn {_, path_item} ->
+ path_item
+ |> Map.take([:delete, :get, :head, :options, :patch, :post, :put, :trace])
+ |> Map.values()
+ |> Enum.reject(&is_nil/1)
+ |> Enum.uniq()
+ end)
+ end
+end
diff --git a/test/support/conn_case.ex b/test/support/conn_case.ex
index 064874201..fa30a0c41 100644
--- a/test/support/conn_case.ex
+++ b/test/support/conn_case.ex
@@ -51,6 +51,60 @@ defp oauth_access(scopes, opts \\ []) do
%{user: user, token: token, conn: conn}
end
+ defp request_content_type(%{conn: conn}) do
+ conn = put_req_header(conn, "content-type", "multipart/form-data")
+ [conn: conn]
+ end
+
+ defp json_response_and_validate_schema(
+ %{
+ private: %{
+ open_api_spex: %{operation_id: op_id, operation_lookup: lookup, spec: spec}
+ }
+ } = conn,
+ status
+ ) do
+ content_type =
+ conn
+ |> Plug.Conn.get_resp_header("content-type")
+ |> List.first()
+ |> String.split(";")
+ |> List.first()
+
+ status = Plug.Conn.Status.code(status)
+
+ unless lookup[op_id].responses[status] do
+ err = "Response schema not found for #{conn.status} #{conn.method} #{conn.request_path}"
+ flunk(err)
+ end
+
+ schema = lookup[op_id].responses[status].content[content_type].schema
+ json = json_response(conn, status)
+
+ case OpenApiSpex.cast_value(json, schema, spec) do
+ {:ok, _data} ->
+ json
+
+ {:error, errors} ->
+ errors =
+ Enum.map(errors, fn error ->
+ message = OpenApiSpex.Cast.Error.message(error)
+ path = OpenApiSpex.Cast.Error.path_to_string(error)
+ "#{message} at #{path}"
+ end)
+
+ flunk(
+ "Response does not conform to schema of #{op_id} operation: #{
+ Enum.join(errors, "\n")
+ }\n#{inspect(json)}"
+ )
+ end
+ end
+
+ defp json_response_and_validate_schema(conn, _status) do
+ flunk("Response schema not found for #{conn.method} #{conn.request_path} #{conn.status}")
+ end
+
defp ensure_federating_or_authenticated(conn, url, user) do
initial_setting = Config.get([:instance, :federating])
on_exit(fn -> Config.put([:instance, :federating], initial_setting) end)
diff --git a/test/support/factory.ex b/test/support/factory.ex
index af639b6cd..f0b797fd4 100644
--- a/test/support/factory.ex
+++ b/test/support/factory.ex
@@ -294,7 +294,7 @@ def follow_activity_factory do
def oauth_app_factory do
%Pleroma.Web.OAuth.App{
- client_name: "Some client",
+ client_name: sequence(:client_name, &"Some client #{&1}"),
redirect_uris: "https://example.com/callback",
scopes: ["read", "write", "follow", "push", "admin"],
website: "https://example.com",
diff --git a/test/tasks/app_test.exs b/test/tasks/app_test.exs
new file mode 100644
index 000000000..b8f03566d
--- /dev/null
+++ b/test/tasks/app_test.exs
@@ -0,0 +1,65 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Mix.Tasks.Pleroma.AppTest do
+ use Pleroma.DataCase, async: true
+
+ setup_all do
+ Mix.shell(Mix.Shell.Process)
+
+ on_exit(fn ->
+ Mix.shell(Mix.Shell.IO)
+ end)
+ end
+
+ describe "creates new app" do
+ test "with default scopes" do
+ name = "Some name"
+ redirect = "https://example.com"
+ Mix.Tasks.Pleroma.App.run(["create", "-n", name, "-r", redirect])
+
+ assert_app(name, redirect, ["read", "write", "follow", "push"])
+ end
+
+ test "with custom scopes" do
+ name = "Another name"
+ redirect = "https://example.com"
+
+ Mix.Tasks.Pleroma.App.run([
+ "create",
+ "-n",
+ name,
+ "-r",
+ redirect,
+ "-s",
+ "read,write,follow,push,admin"
+ ])
+
+ assert_app(name, redirect, ["read", "write", "follow", "push", "admin"])
+ end
+ end
+
+ test "with errors" do
+ Mix.Tasks.Pleroma.App.run(["create"])
+ {:mix_shell, :error, ["Creating failed:"]}
+ {:mix_shell, :error, ["name: can't be blank"]}
+ {:mix_shell, :error, ["redirect_uris: can't be blank"]}
+ end
+
+ defp assert_app(name, redirect, scopes) do
+ app = Repo.get_by(Pleroma.Web.OAuth.App, client_name: name)
+
+ assert_received {:mix_shell, :info, [message]}
+ assert message == "#{name} successfully created:"
+
+ assert_received {:mix_shell, :info, [message]}
+ assert message == "App client_id: #{app.client_id}"
+
+ assert_received {:mix_shell, :info, [message]}
+ assert message == "App client_secret: #{app.client_secret}"
+
+ assert app.scopes == scopes
+ assert app.redirect_uris == redirect
+ end
+end
diff --git a/test/tasks/config_test.exs b/test/tasks/config_test.exs
index 3dee4f082..04bc947a9 100644
--- a/test/tasks/config_test.exs
+++ b/test/tasks/config_test.exs
@@ -38,7 +38,7 @@ test "error if file with custom settings doesn't exist" do
on_exit(fn -> Application.put_env(:quack, :level, initial) end)
end
- test "settings are migrated to db" do
+ test "filtered settings are migrated to db" do
assert Repo.all(ConfigDB) == []
Mix.Tasks.Pleroma.Config.migrate_to_db("test/fixtures/config/temp.secret.exs")
@@ -47,6 +47,7 @@ test "settings are migrated to db" do
config2 = ConfigDB.get_by_params(%{group: ":pleroma", key: ":second_setting"})
config3 = ConfigDB.get_by_params(%{group: ":quack", key: ":level"})
refute ConfigDB.get_by_params(%{group: ":pleroma", key: "Pleroma.Repo"})
+ refute ConfigDB.get_by_params(%{group: ":postgrex", key: ":json_library"})
assert ConfigDB.from_binary(config1.value) == [key: "value", key2: [Repo]]
assert ConfigDB.from_binary(config2.value) == [key: "value2", key2: ["Activity"]]
diff --git a/test/user_test.exs b/test/user_test.exs
index a00b1b5e2..347c5be72 100644
--- a/test/user_test.exs
+++ b/test/user_test.exs
@@ -582,7 +582,7 @@ test "updates an existing user, if stale" do
{:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin")
- assert user.source_data["endpoints"]
+ assert user.inbox
refute user.last_refreshed_at == orig_user.last_refreshed_at
end
@@ -610,7 +610,7 @@ test "returns an ap_followers link for a user" do
) <> "/followers"
end
- describe "remote user creation changeset" do
+ describe "remote user changeset" do
@valid_remote %{
bio: "hello",
name: "Someone",
@@ -622,28 +622,28 @@ test "returns an ap_followers link for a user" do
setup do: clear_config([:instance, :user_name_length])
test "it confirms validity" do
- cs = User.remote_user_creation(@valid_remote)
+ cs = User.remote_user_changeset(@valid_remote)
assert cs.valid?
end
test "it sets the follower_adress" do
- cs = User.remote_user_creation(@valid_remote)
+ cs = User.remote_user_changeset(@valid_remote)
# remote users get a fake local follower address
assert cs.changes.follower_address ==
User.ap_followers(%User{nickname: @valid_remote[:nickname]})
end
test "it enforces the fqn format for nicknames" do
- cs = User.remote_user_creation(%{@valid_remote | nickname: "bla"})
+ cs = User.remote_user_changeset(%{@valid_remote | nickname: "bla"})
assert Ecto.Changeset.get_field(cs, :local) == false
assert cs.changes.avatar
refute cs.valid?
end
test "it has required fields" do
- [:name, :ap_id]
+ [:ap_id]
|> Enum.each(fn field ->
- cs = User.remote_user_creation(Map.delete(@valid_remote, field))
+ cs = User.remote_user_changeset(Map.delete(@valid_remote, field))
refute cs.valid?
end)
end
@@ -756,8 +756,8 @@ test "it imports user followings from list" do
]
{:ok, job} = User.follow_import(user1, identifiers)
- result = ObanHelpers.perform(job)
+ assert {:ok, result} = ObanHelpers.perform(job)
assert is_list(result)
assert result == [user2, user3]
end
@@ -979,14 +979,26 @@ test "it imports user blocks from list" do
]
{:ok, job} = User.blocks_import(user1, identifiers)
- result = ObanHelpers.perform(job)
+ assert {:ok, result} = ObanHelpers.perform(job)
assert is_list(result)
assert result == [user2, user3]
end
end
describe "get_recipients_from_activity" do
+ test "works for announces" do
+ actor = insert(:user)
+ user = insert(:user, local: true)
+
+ {:ok, activity} = CommonAPI.post(actor, %{"status" => "hello"})
+ {:ok, announce, _} = CommonAPI.repeat(activity.id, user)
+
+ recipients = User.get_recipients_from_activity(announce)
+
+ assert user in recipients
+ end
+
test "get recipients" do
actor = insert(:user)
user = insert(:user, local: true)
@@ -1199,58 +1211,6 @@ test "get_public_key_for_ap_id fetches a user that's not in the db" do
assert {:ok, _key} = User.get_public_key_for_ap_id("http://mastodon.example.org/users/admin")
end
- describe "insert or update a user from given data" do
- test "with normal data" do
- user = insert(:user, %{nickname: "nick@name.de"})
- data = %{ap_id: user.ap_id <> "xxx", name: user.name, nickname: user.nickname}
-
- assert {:ok, %User{}} = User.insert_or_update_user(data)
- end
-
- test "with overly long fields" do
- current_max_length = Pleroma.Config.get([:instance, :account_field_value_length], 255)
- user = insert(:user, nickname: "nickname@supergood.domain")
-
- data = %{
- ap_id: user.ap_id,
- name: user.name,
- nickname: user.nickname,
- fields: [
- %{"name" => "myfield", "value" => String.duplicate("h", current_max_length + 1)}
- ]
- }
-
- assert {:ok, %User{}} = User.insert_or_update_user(data)
- end
-
- test "with an overly long bio" do
- current_max_length = Pleroma.Config.get([:instance, :user_bio_length], 5000)
- user = insert(:user, nickname: "nickname@supergood.domain")
-
- data = %{
- ap_id: user.ap_id,
- name: user.name,
- nickname: user.nickname,
- bio: String.duplicate("h", current_max_length + 1)
- }
-
- assert {:ok, %User{}} = User.insert_or_update_user(data)
- end
-
- test "with an overly long display name" do
- current_max_length = Pleroma.Config.get([:instance, :user_name_length], 100)
- user = insert(:user, nickname: "nickname@supergood.domain")
-
- data = %{
- ap_id: user.ap_id,
- name: String.duplicate("h", current_max_length + 1),
- nickname: user.nickname
- }
-
- assert {:ok, %User{}} = User.insert_or_update_user(data)
- end
- end
-
describe "per-user rich-text filtering" do
test "html_filter_policy returns default policies, when rich-text is enabled" do
user = insert(:user)
diff --git a/test/web/activity_pub/activity_pub_controller_test.exs b/test/web/activity_pub/activity_pub_controller_test.exs
index fbacb3993..6b5913f95 100644
--- a/test/web/activity_pub/activity_pub_controller_test.exs
+++ b/test/web/activity_pub/activity_pub_controller_test.exs
@@ -765,51 +765,87 @@ test "it requires authentication if instance is NOT federating", %{
end
end
- describe "POST /users/:nickname/outbox" do
- test "it rejects posts from other users / unauuthenticated users", %{conn: conn} do
- data = File.read!("test/fixtures/activitypub-client-post-activity.json") |> Poison.decode!()
+ describe "POST /users/:nickname/outbox (C2S)" do
+ setup do
+ [
+ activity: %{
+ "@context" => "https://www.w3.org/ns/activitystreams",
+ "type" => "Create",
+ "object" => %{"type" => "Note", "content" => "AP C2S test"},
+ "to" => "https://www.w3.org/ns/activitystreams#Public",
+ "cc" => []
+ }
+ ]
+ end
+
+ test "it rejects posts from other users / unauthenticated users", %{
+ conn: conn,
+ activity: activity
+ } do
user = insert(:user)
other_user = insert(:user)
conn = put_req_header(conn, "content-type", "application/activity+json")
conn
- |> post("/users/#{user.nickname}/outbox", data)
+ |> post("/users/#{user.nickname}/outbox", activity)
|> json_response(403)
conn
|> assign(:user, other_user)
- |> post("/users/#{user.nickname}/outbox", data)
+ |> post("/users/#{user.nickname}/outbox", activity)
|> json_response(403)
end
- test "it inserts an incoming create activity into the database", %{conn: conn} do
- data = File.read!("test/fixtures/activitypub-client-post-activity.json") |> Poison.decode!()
+ test "it inserts an incoming create activity into the database", %{
+ conn: conn,
+ activity: activity
+ } do
user = insert(:user)
- conn =
+ result =
conn
|> assign(:user, user)
|> put_req_header("content-type", "application/activity+json")
- |> post("/users/#{user.nickname}/outbox", data)
-
- result = json_response(conn, 201)
+ |> post("/users/#{user.nickname}/outbox", activity)
+ |> json_response(201)
assert Activity.get_by_ap_id(result["id"])
+ assert result["object"]
+ assert %Object{data: object} = Object.normalize(result["object"])
+ assert object["content"] == activity["object"]["content"]
end
- test "it rejects an incoming activity with bogus type", %{conn: conn} do
- data = File.read!("test/fixtures/activitypub-client-post-activity.json") |> Poison.decode!()
+ test "it inserts an incoming sensitive activity into the database", %{
+ conn: conn,
+ activity: activity
+ } do
user = insert(:user)
+ object = Map.put(activity["object"], "sensitive", true)
+ activity = Map.put(activity, "object", object)
- data =
- data
- |> Map.put("type", "BadType")
+ result =
+ conn
+ |> assign(:user, user)
+ |> put_req_header("content-type", "application/activity+json")
+ |> post("/users/#{user.nickname}/outbox", activity)
+ |> json_response(201)
+
+ assert Activity.get_by_ap_id(result["id"])
+ assert result["object"]
+ assert %Object{data: object} = Object.normalize(result["object"])
+ assert object["sensitive"] == activity["object"]["sensitive"]
+ assert object["content"] == activity["object"]["content"]
+ end
+
+ test "it rejects an incoming activity with bogus type", %{conn: conn, activity: activity} do
+ user = insert(:user)
+ activity = Map.put(activity, "type", "BadType")
conn =
conn
|> assign(:user, user)
|> put_req_header("content-type", "application/activity+json")
- |> post("/users/#{user.nickname}/outbox", data)
+ |> post("/users/#{user.nickname}/outbox", activity)
assert json_response(conn, 400)
end
diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs
index 17e7b97de..edd7dfb22 100644
--- a/test/web/activity_pub/activity_pub_test.exs
+++ b/test/web/activity_pub/activity_pub_test.exs
@@ -180,7 +180,6 @@ test "it returns a user" do
{:ok, user} = ActivityPub.make_user_from_ap_id(user_id)
assert user.ap_id == user_id
assert user.nickname == "admin@mastodon.example.org"
- assert user.source_data
assert user.ap_enabled
assert user.follower_address == "http://mastodon.example.org/users/admin/followers"
end
@@ -995,72 +994,6 @@ test "reverts emoji unreact on error" do
end
end
- describe "like an object" do
- test_with_mock "sends an activity to federation", Federator, [:passthrough], [] do
- Config.put([:instance, :federating], true)
- note_activity = insert(:note_activity)
- assert object_activity = Object.normalize(note_activity)
-
- user = insert(:user)
-
- {:ok, like_activity, _object} = ActivityPub.like(user, object_activity)
- assert called(Federator.publish(like_activity))
- end
-
- test "returns exist activity if object already liked" do
- note_activity = insert(:note_activity)
- assert object_activity = Object.normalize(note_activity)
-
- user = insert(:user)
-
- {:ok, like_activity, _object} = ActivityPub.like(user, object_activity)
-
- {:ok, like_activity_exist, _object} = ActivityPub.like(user, object_activity)
- assert like_activity == like_activity_exist
- end
-
- test "reverts like activity on error" do
- note_activity = insert(:note_activity)
- object = Object.normalize(note_activity)
- user = insert(:user)
-
- with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do
- assert {:error, :reverted} = ActivityPub.like(user, object)
- end
-
- assert Repo.aggregate(Activity, :count, :id) == 1
- assert Repo.get(Object, object.id) == object
- end
-
- test "adds a like activity to the db" do
- note_activity = insert(:note_activity)
- assert object = Object.normalize(note_activity)
-
- user = insert(:user)
- user_two = insert(:user)
-
- {:ok, like_activity, object} = ActivityPub.like(user, object)
-
- assert like_activity.data["actor"] == user.ap_id
- assert like_activity.data["type"] == "Like"
- assert like_activity.data["object"] == object.data["id"]
- assert like_activity.data["to"] == [User.ap_followers(user), note_activity.data["actor"]]
- assert like_activity.data["context"] == object.data["context"]
- assert object.data["like_count"] == 1
- assert object.data["likes"] == [user.ap_id]
-
- # Just return the original activity if the user already liked it.
- {:ok, same_like_activity, object} = ActivityPub.like(user, object)
-
- assert like_activity == same_like_activity
- assert object.data["likes"] == [user.ap_id]
- assert object.data["like_count"] == 1
-
- {:ok, _like_activity, object} = ActivityPub.like(user_two, object)
- assert object.data["like_count"] == 2
- end
- end
-
describe "unliking" do
test_with_mock "sends an activity to federation", Federator, [:passthrough], [] do
Config.put([:instance, :federating], true)
@@ -1072,7 +1005,8 @@ test "adds a like activity to the db" do
{:ok, object} = ActivityPub.unlike(user, object)
refute called(Federator.publish())
- {:ok, _like_activity, object} = ActivityPub.like(user, object)
+ {:ok, _like_activity} = CommonAPI.favorite(user, note_activity.id)
+ object = Object.get_by_id(object.id)
assert object.data["like_count"] == 1
{:ok, unlike_activity, _, object} = ActivityPub.unlike(user, object)
@@ -1083,10 +1017,10 @@ test "adds a like activity to the db" do
test "reverts unliking on error" do
note_activity = insert(:note_activity)
- object = Object.normalize(note_activity)
user = insert(:user)
- {:ok, like_activity, object} = ActivityPub.like(user, object)
+ {:ok, like_activity} = CommonAPI.favorite(user, note_activity.id)
+ object = Object.normalize(note_activity)
assert object.data["like_count"] == 1
with_mock(Utils, [:passthrough], maybe_federate: fn _ -> {:error, :reverted} end) do
@@ -1107,7 +1041,9 @@ test "unliking a previously liked object" do
{:ok, object} = ActivityPub.unlike(user, object)
assert object.data["like_count"] == 0
- {:ok, like_activity, object} = ActivityPub.like(user, object)
+ {:ok, like_activity} = CommonAPI.favorite(user, note_activity.id)
+
+ object = Object.get_by_id(object.id)
assert object.data["like_count"] == 1
{:ok, unlike_activity, _, object} = ActivityPub.unlike(user, object)
@@ -1974,4 +1910,497 @@ test "old user must be in the new user's `also_known_as` list" do
ActivityPub.move(old_user, new_user)
end
end
+
+ test "doesn't retrieve replies activities with exclude_replies" do
+ user = insert(:user)
+
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "yeah"})
+
+ {:ok, _reply} =
+ CommonAPI.post(user, %{"status" => "yeah", "in_reply_to_status_id" => activity.id})
+
+ [result] = ActivityPub.fetch_public_activities(%{"exclude_replies" => "true"})
+
+ assert result.id == activity.id
+
+ assert length(ActivityPub.fetch_public_activities()) == 2
+ end
+
+ describe "replies filtering with public messages" do
+ setup :public_messages
+
+ test "public timeline", %{users: %{u1: user}} do
+ activities_ids =
+ %{}
+ |> Map.put("type", ["Create", "Announce"])
+ |> Map.put("local_only", false)
+ |> Map.put("blocking_user", user)
+ |> Map.put("muting_user", user)
+ |> Map.put("reply_filtering_user", user)
+ |> ActivityPub.fetch_public_activities()
+ |> Enum.map(& &1.id)
+
+ assert length(activities_ids) == 16
+ end
+
+ test "public timeline with reply_visibility `following`", %{
+ users: %{u1: user},
+ u1: u1,
+ u2: u2,
+ u3: u3,
+ u4: u4,
+ activities: activities
+ } do
+ activities_ids =
+ %{}
+ |> Map.put("type", ["Create", "Announce"])
+ |> Map.put("local_only", false)
+ |> Map.put("blocking_user", user)
+ |> Map.put("muting_user", user)
+ |> Map.put("reply_visibility", "following")
+ |> Map.put("reply_filtering_user", user)
+ |> ActivityPub.fetch_public_activities()
+ |> Enum.map(& &1.id)
+
+ assert length(activities_ids) == 14
+
+ visible_ids =
+ Map.values(u1) ++ Map.values(u2) ++ Map.values(u4) ++ Map.values(activities) ++ [u3[:r1]]
+
+ assert Enum.all?(visible_ids, &(&1 in activities_ids))
+ end
+
+ test "public timeline with reply_visibility `self`", %{
+ users: %{u1: user},
+ u1: u1,
+ u2: u2,
+ u3: u3,
+ u4: u4,
+ activities: activities
+ } do
+ activities_ids =
+ %{}
+ |> Map.put("type", ["Create", "Announce"])
+ |> Map.put("local_only", false)
+ |> Map.put("blocking_user", user)
+ |> Map.put("muting_user", user)
+ |> Map.put("reply_visibility", "self")
+ |> Map.put("reply_filtering_user", user)
+ |> ActivityPub.fetch_public_activities()
+ |> Enum.map(& &1.id)
+
+ assert length(activities_ids) == 10
+ visible_ids = Map.values(u1) ++ [u2[:r1], u3[:r1], u4[:r1]] ++ Map.values(activities)
+ assert Enum.all?(visible_ids, &(&1 in activities_ids))
+ end
+
+ test "home timeline", %{
+ users: %{u1: user},
+ activities: activities,
+ u1: u1,
+ u2: u2,
+ u3: u3,
+ u4: u4
+ } do
+ params =
+ %{}
+ |> Map.put("type", ["Create", "Announce"])
+ |> Map.put("blocking_user", user)
+ |> Map.put("muting_user", user)
+ |> Map.put("user", user)
+ |> Map.put("reply_filtering_user", user)
+
+ activities_ids =
+ ActivityPub.fetch_activities([user.ap_id | User.following(user)], params)
+ |> Enum.map(& &1.id)
+
+ assert length(activities_ids) == 13
+
+ visible_ids =
+ Map.values(u1) ++
+ Map.values(u3) ++
+ [
+ activities[:a1],
+ activities[:a2],
+ activities[:a4],
+ u2[:r1],
+ u2[:r3],
+ u4[:r1],
+ u4[:r2]
+ ]
+
+ assert Enum.all?(visible_ids, &(&1 in activities_ids))
+ end
+
+ test "home timeline with reply_visibility `following`", %{
+ users: %{u1: user},
+ activities: activities,
+ u1: u1,
+ u2: u2,
+ u3: u3,
+ u4: u4
+ } do
+ params =
+ %{}
+ |> Map.put("type", ["Create", "Announce"])
+ |> Map.put("blocking_user", user)
+ |> Map.put("muting_user", user)
+ |> Map.put("user", user)
+ |> Map.put("reply_visibility", "following")
+ |> Map.put("reply_filtering_user", user)
+
+ activities_ids =
+ ActivityPub.fetch_activities([user.ap_id | User.following(user)], params)
+ |> Enum.map(& &1.id)
+
+ assert length(activities_ids) == 11
+
+ visible_ids =
+ Map.values(u1) ++
+ [
+ activities[:a1],
+ activities[:a2],
+ activities[:a4],
+ u2[:r1],
+ u2[:r3],
+ u3[:r1],
+ u4[:r1],
+ u4[:r2]
+ ]
+
+ assert Enum.all?(visible_ids, &(&1 in activities_ids))
+ end
+
+ test "home timeline with reply_visibility `self`", %{
+ users: %{u1: user},
+ activities: activities,
+ u1: u1,
+ u2: u2,
+ u3: u3,
+ u4: u4
+ } do
+ params =
+ %{}
+ |> Map.put("type", ["Create", "Announce"])
+ |> Map.put("blocking_user", user)
+ |> Map.put("muting_user", user)
+ |> Map.put("user", user)
+ |> Map.put("reply_visibility", "self")
+ |> Map.put("reply_filtering_user", user)
+
+ activities_ids =
+ ActivityPub.fetch_activities([user.ap_id | User.following(user)], params)
+ |> Enum.map(& &1.id)
+
+ assert length(activities_ids) == 9
+
+ visible_ids =
+ Map.values(u1) ++
+ [
+ activities[:a1],
+ activities[:a2],
+ activities[:a4],
+ u2[:r1],
+ u3[:r1],
+ u4[:r1]
+ ]
+
+ assert Enum.all?(visible_ids, &(&1 in activities_ids))
+ end
+ end
+
+ describe "replies filtering with private messages" do
+ setup :private_messages
+
+ test "public timeline", %{users: %{u1: user}} do
+ activities_ids =
+ %{}
+ |> Map.put("type", ["Create", "Announce"])
+ |> Map.put("local_only", false)
+ |> Map.put("blocking_user", user)
+ |> Map.put("muting_user", user)
+ |> Map.put("user", user)
+ |> ActivityPub.fetch_public_activities()
+ |> Enum.map(& &1.id)
+
+ assert activities_ids == []
+ end
+
+ test "public timeline with default reply_visibility `following`", %{users: %{u1: user}} do
+ activities_ids =
+ %{}
+ |> Map.put("type", ["Create", "Announce"])
+ |> Map.put("local_only", false)
+ |> Map.put("blocking_user", user)
+ |> Map.put("muting_user", user)
+ |> Map.put("reply_visibility", "following")
+ |> Map.put("reply_filtering_user", user)
+ |> Map.put("user", user)
+ |> ActivityPub.fetch_public_activities()
+ |> Enum.map(& &1.id)
+
+ assert activities_ids == []
+ end
+
+ test "public timeline with default reply_visibility `self`", %{users: %{u1: user}} do
+ activities_ids =
+ %{}
+ |> Map.put("type", ["Create", "Announce"])
+ |> Map.put("local_only", false)
+ |> Map.put("blocking_user", user)
+ |> Map.put("muting_user", user)
+ |> Map.put("reply_visibility", "self")
+ |> Map.put("reply_filtering_user", user)
+ |> Map.put("user", user)
+ |> ActivityPub.fetch_public_activities()
+ |> Enum.map(& &1.id)
+
+ assert activities_ids == []
+ end
+
+ test "home timeline", %{users: %{u1: user}} do
+ params =
+ %{}
+ |> Map.put("type", ["Create", "Announce"])
+ |> Map.put("blocking_user", user)
+ |> Map.put("muting_user", user)
+ |> Map.put("user", user)
+
+ activities_ids =
+ ActivityPub.fetch_activities([user.ap_id | User.following(user)], params)
+ |> Enum.map(& &1.id)
+
+ assert length(activities_ids) == 12
+ end
+
+ test "home timeline with default reply_visibility `following`", %{users: %{u1: user}} do
+ params =
+ %{}
+ |> Map.put("type", ["Create", "Announce"])
+ |> Map.put("blocking_user", user)
+ |> Map.put("muting_user", user)
+ |> Map.put("user", user)
+ |> Map.put("reply_visibility", "following")
+ |> Map.put("reply_filtering_user", user)
+
+ activities_ids =
+ ActivityPub.fetch_activities([user.ap_id | User.following(user)], params)
+ |> Enum.map(& &1.id)
+
+ assert length(activities_ids) == 12
+ end
+
+ test "home timeline with default reply_visibility `self`", %{
+ users: %{u1: user},
+ activities: activities,
+ u1: u1,
+ u2: u2,
+ u3: u3,
+ u4: u4
+ } do
+ params =
+ %{}
+ |> Map.put("type", ["Create", "Announce"])
+ |> Map.put("blocking_user", user)
+ |> Map.put("muting_user", user)
+ |> Map.put("user", user)
+ |> Map.put("reply_visibility", "self")
+ |> Map.put("reply_filtering_user", user)
+
+ activities_ids =
+ ActivityPub.fetch_activities([user.ap_id | User.following(user)], params)
+ |> Enum.map(& &1.id)
+
+ assert length(activities_ids) == 10
+
+ visible_ids =
+ Map.values(u1) ++ Map.values(u4) ++ [u2[:r1], u3[:r1]] ++ Map.values(activities)
+
+ assert Enum.all?(visible_ids, &(&1 in activities_ids))
+ end
+ end
+
+ defp public_messages(_) do
+ [u1, u2, u3, u4] = insert_list(4, :user)
+ {:ok, u1} = User.follow(u1, u2)
+ {:ok, u2} = User.follow(u2, u1)
+ {:ok, u1} = User.follow(u1, u4)
+ {:ok, u4} = User.follow(u4, u1)
+
+ {:ok, u2} = User.follow(u2, u3)
+ {:ok, u3} = User.follow(u3, u2)
+
+ {:ok, a1} = CommonAPI.post(u1, %{"status" => "Status"})
+
+ {:ok, r1_1} =
+ CommonAPI.post(u2, %{
+ "status" => "@#{u1.nickname} reply from u2 to u1",
+ "in_reply_to_status_id" => a1.id
+ })
+
+ {:ok, r1_2} =
+ CommonAPI.post(u3, %{
+ "status" => "@#{u1.nickname} reply from u3 to u1",
+ "in_reply_to_status_id" => a1.id
+ })
+
+ {:ok, r1_3} =
+ CommonAPI.post(u4, %{
+ "status" => "@#{u1.nickname} reply from u4 to u1",
+ "in_reply_to_status_id" => a1.id
+ })
+
+ {:ok, a2} = CommonAPI.post(u2, %{"status" => "Status"})
+
+ {:ok, r2_1} =
+ CommonAPI.post(u1, %{
+ "status" => "@#{u2.nickname} reply from u1 to u2",
+ "in_reply_to_status_id" => a2.id
+ })
+
+ {:ok, r2_2} =
+ CommonAPI.post(u3, %{
+ "status" => "@#{u2.nickname} reply from u3 to u2",
+ "in_reply_to_status_id" => a2.id
+ })
+
+ {:ok, r2_3} =
+ CommonAPI.post(u4, %{
+ "status" => "@#{u2.nickname} reply from u4 to u2",
+ "in_reply_to_status_id" => a2.id
+ })
+
+ {:ok, a3} = CommonAPI.post(u3, %{"status" => "Status"})
+
+ {:ok, r3_1} =
+ CommonAPI.post(u1, %{
+ "status" => "@#{u3.nickname} reply from u1 to u3",
+ "in_reply_to_status_id" => a3.id
+ })
+
+ {:ok, r3_2} =
+ CommonAPI.post(u2, %{
+ "status" => "@#{u3.nickname} reply from u2 to u3",
+ "in_reply_to_status_id" => a3.id
+ })
+
+ {:ok, r3_3} =
+ CommonAPI.post(u4, %{
+ "status" => "@#{u3.nickname} reply from u4 to u3",
+ "in_reply_to_status_id" => a3.id
+ })
+
+ {:ok, a4} = CommonAPI.post(u4, %{"status" => "Status"})
+
+ {:ok, r4_1} =
+ CommonAPI.post(u1, %{
+ "status" => "@#{u4.nickname} reply from u1 to u4",
+ "in_reply_to_status_id" => a4.id
+ })
+
+ {:ok, r4_2} =
+ CommonAPI.post(u2, %{
+ "status" => "@#{u4.nickname} reply from u2 to u4",
+ "in_reply_to_status_id" => a4.id
+ })
+
+ {:ok, r4_3} =
+ CommonAPI.post(u3, %{
+ "status" => "@#{u4.nickname} reply from u3 to u4",
+ "in_reply_to_status_id" => a4.id
+ })
+
+ {:ok,
+ users: %{u1: u1, u2: u2, u3: u3, u4: u4},
+ activities: %{a1: a1.id, a2: a2.id, a3: a3.id, a4: a4.id},
+ u1: %{r1: r1_1.id, r2: r1_2.id, r3: r1_3.id},
+ u2: %{r1: r2_1.id, r2: r2_2.id, r3: r2_3.id},
+ u3: %{r1: r3_1.id, r2: r3_2.id, r3: r3_3.id},
+ u4: %{r1: r4_1.id, r2: r4_2.id, r3: r4_3.id}}
+ end
+
+ defp private_messages(_) do
+ [u1, u2, u3, u4] = insert_list(4, :user)
+ {:ok, u1} = User.follow(u1, u2)
+ {:ok, u2} = User.follow(u2, u1)
+ {:ok, u1} = User.follow(u1, u3)
+ {:ok, u3} = User.follow(u3, u1)
+ {:ok, u1} = User.follow(u1, u4)
+ {:ok, u4} = User.follow(u4, u1)
+
+ {:ok, u2} = User.follow(u2, u3)
+ {:ok, u3} = User.follow(u3, u2)
+
+ {:ok, a1} = CommonAPI.post(u1, %{"status" => "Status", "visibility" => "private"})
+
+ {:ok, r1_1} =
+ CommonAPI.post(u2, %{
+ "status" => "@#{u1.nickname} reply from u2 to u1",
+ "in_reply_to_status_id" => a1.id,
+ "visibility" => "private"
+ })
+
+ {:ok, r1_2} =
+ CommonAPI.post(u3, %{
+ "status" => "@#{u1.nickname} reply from u3 to u1",
+ "in_reply_to_status_id" => a1.id,
+ "visibility" => "private"
+ })
+
+ {:ok, r1_3} =
+ CommonAPI.post(u4, %{
+ "status" => "@#{u1.nickname} reply from u4 to u1",
+ "in_reply_to_status_id" => a1.id,
+ "visibility" => "private"
+ })
+
+ {:ok, a2} = CommonAPI.post(u2, %{"status" => "Status", "visibility" => "private"})
+
+ {:ok, r2_1} =
+ CommonAPI.post(u1, %{
+ "status" => "@#{u2.nickname} reply from u1 to u2",
+ "in_reply_to_status_id" => a2.id,
+ "visibility" => "private"
+ })
+
+ {:ok, r2_2} =
+ CommonAPI.post(u3, %{
+ "status" => "@#{u2.nickname} reply from u3 to u2",
+ "in_reply_to_status_id" => a2.id,
+ "visibility" => "private"
+ })
+
+ {:ok, a3} = CommonAPI.post(u3, %{"status" => "Status", "visibility" => "private"})
+
+ {:ok, r3_1} =
+ CommonAPI.post(u1, %{
+ "status" => "@#{u3.nickname} reply from u1 to u3",
+ "in_reply_to_status_id" => a3.id,
+ "visibility" => "private"
+ })
+
+ {:ok, r3_2} =
+ CommonAPI.post(u2, %{
+ "status" => "@#{u3.nickname} reply from u2 to u3",
+ "in_reply_to_status_id" => a3.id,
+ "visibility" => "private"
+ })
+
+ {:ok, a4} = CommonAPI.post(u4, %{"status" => "Status", "visibility" => "private"})
+
+ {:ok, r4_1} =
+ CommonAPI.post(u1, %{
+ "status" => "@#{u4.nickname} reply from u1 to u4",
+ "in_reply_to_status_id" => a4.id,
+ "visibility" => "private"
+ })
+
+ {:ok,
+ users: %{u1: u1, u2: u2, u3: u3, u4: u4},
+ activities: %{a1: a1.id, a2: a2.id, a3: a3.id, a4: a4.id},
+ u1: %{r1: r1_1.id, r2: r1_2.id, r3: r1_3.id},
+ u2: %{r1: r2_1.id, r2: r2_2.id},
+ u3: %{r1: r3_1.id, r2: r3_2.id},
+ u4: %{r1: r4_1.id}}
+ end
end
diff --git a/test/web/activity_pub/mrf/object_age_policy_test.exs b/test/web/activity_pub/mrf/object_age_policy_test.exs
index 7ee195eeb..b0fb753bd 100644
--- a/test/web/activity_pub/mrf/object_age_policy_test.exs
+++ b/test/web/activity_pub/mrf/object_age_policy_test.exs
@@ -20,26 +20,38 @@ defmodule Pleroma.Web.ActivityPub.MRF.ObjectAgePolicyTest do
:ok
end
+ defp get_old_message do
+ File.read!("test/fixtures/mastodon-post-activity.json")
+ |> Poison.decode!()
+ end
+
+ defp get_new_message do
+ old_message = get_old_message()
+
+ new_object =
+ old_message
+ |> Map.get("object")
+ |> Map.put("published", DateTime.utc_now() |> DateTime.to_iso8601())
+
+ old_message
+ |> Map.put("object", new_object)
+ end
+
describe "with reject action" do
test "it rejects an old post" do
Config.put([:mrf_object_age, :actions], [:reject])
- data =
- File.read!("test/fixtures/mastodon-post-activity.json")
- |> Poison.decode!()
+ data = get_old_message()
- {:reject, _} = ObjectAgePolicy.filter(data)
+ assert match?({:reject, _}, ObjectAgePolicy.filter(data))
end
test "it allows a new post" do
Config.put([:mrf_object_age, :actions], [:reject])
- data =
- File.read!("test/fixtures/mastodon-post-activity.json")
- |> Poison.decode!()
- |> Map.put("published", DateTime.utc_now() |> DateTime.to_iso8601())
+ data = get_new_message()
- {:ok, _} = ObjectAgePolicy.filter(data)
+ assert match?({:ok, _}, ObjectAgePolicy.filter(data))
end
end
@@ -47,9 +59,7 @@ test "it allows a new post" do
test "it delists an old post" do
Config.put([:mrf_object_age, :actions], [:delist])
- data =
- File.read!("test/fixtures/mastodon-post-activity.json")
- |> Poison.decode!()
+ data = get_old_message()
{:ok, _u} = User.get_or_fetch_by_ap_id(data["actor"])
@@ -61,14 +71,11 @@ test "it delists an old post" do
test "it allows a new post" do
Config.put([:mrf_object_age, :actions], [:delist])
- data =
- File.read!("test/fixtures/mastodon-post-activity.json")
- |> Poison.decode!()
- |> Map.put("published", DateTime.utc_now() |> DateTime.to_iso8601())
+ data = get_new_message()
{:ok, _user} = User.get_or_fetch_by_ap_id(data["actor"])
- {:ok, ^data} = ObjectAgePolicy.filter(data)
+ assert match?({:ok, ^data}, ObjectAgePolicy.filter(data))
end
end
@@ -76,9 +83,7 @@ test "it allows a new post" do
test "it strips followers collections from an old post" do
Config.put([:mrf_object_age, :actions], [:strip_followers])
- data =
- File.read!("test/fixtures/mastodon-post-activity.json")
- |> Poison.decode!()
+ data = get_old_message()
{:ok, user} = User.get_or_fetch_by_ap_id(data["actor"])
@@ -91,14 +96,11 @@ test "it strips followers collections from an old post" do
test "it allows a new post" do
Config.put([:mrf_object_age, :actions], [:strip_followers])
- data =
- File.read!("test/fixtures/mastodon-post-activity.json")
- |> Poison.decode!()
- |> Map.put("published", DateTime.utc_now() |> DateTime.to_iso8601())
+ data = get_new_message()
{:ok, _u} = User.get_or_fetch_by_ap_id(data["actor"])
- {:ok, ^data} = ObjectAgePolicy.filter(data)
+ assert match?({:ok, ^data}, ObjectAgePolicy.filter(data))
end
end
end
diff --git a/test/web/activity_pub/mrf/simple_policy_test.exs b/test/web/activity_pub/mrf/simple_policy_test.exs
index 91c24c2d9..b7b9bc6a2 100644
--- a/test/web/activity_pub/mrf/simple_policy_test.exs
+++ b/test/web/activity_pub/mrf/simple_policy_test.exs
@@ -17,7 +17,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicyTest do
reject: [],
accept: [],
avatar_removal: [],
- banner_removal: []
+ banner_removal: [],
+ reject_deletes: []
)
describe "when :media_removal" do
@@ -382,6 +383,66 @@ test "match with wildcard domain" do
end
end
+ describe "when :reject_deletes is empty" do
+ setup do: Config.put([:mrf_simple, :reject_deletes], [])
+
+ test "it accepts deletions even from rejected servers" do
+ Config.put([:mrf_simple, :reject], ["remote.instance"])
+
+ deletion_message = build_remote_deletion_message()
+
+ assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
+ end
+
+ test "it accepts deletions even from non-whitelisted servers" do
+ Config.put([:mrf_simple, :accept], ["non.matching.remote"])
+
+ deletion_message = build_remote_deletion_message()
+
+ assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
+ end
+ end
+
+ describe "when :reject_deletes is not empty but it doesn't have a matching host" do
+ setup do: Config.put([:mrf_simple, :reject_deletes], ["non.matching.remote"])
+
+ test "it accepts deletions even from rejected servers" do
+ Config.put([:mrf_simple, :reject], ["remote.instance"])
+
+ deletion_message = build_remote_deletion_message()
+
+ assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
+ end
+
+ test "it accepts deletions even from non-whitelisted servers" do
+ Config.put([:mrf_simple, :accept], ["non.matching.remote"])
+
+ deletion_message = build_remote_deletion_message()
+
+ assert SimplePolicy.filter(deletion_message) == {:ok, deletion_message}
+ end
+ end
+
+ describe "when :reject_deletes has a matching host" do
+ setup do: Config.put([:mrf_simple, :reject_deletes], ["remote.instance"])
+
+ test "it rejects the deletion" do
+ deletion_message = build_remote_deletion_message()
+
+ assert SimplePolicy.filter(deletion_message) == {:reject, nil}
+ end
+ end
+
+ describe "when :reject_deletes match with wildcard domain" do
+ setup do: Config.put([:mrf_simple, :reject_deletes], ["*.remote.instance"])
+
+ test "it rejects the deletion" do
+ deletion_message = build_remote_deletion_message()
+
+ assert SimplePolicy.filter(deletion_message) == {:reject, nil}
+ end
+ end
+
defp build_local_message do
%{
"actor" => "#{Pleroma.Web.base_url()}/users/alice",
@@ -408,4 +469,11 @@ defp build_remote_user do
"type" => "Person"
}
end
+
+ defp build_remote_deletion_message do
+ %{
+ "type" => "Delete",
+ "actor" => "https://remote.instance/users/bob"
+ }
+ end
end
diff --git a/test/web/activity_pub/publisher_test.exs b/test/web/activity_pub/publisher_test.exs
index 801da03c1..c2bc38d52 100644
--- a/test/web/activity_pub/publisher_test.exs
+++ b/test/web/activity_pub/publisher_test.exs
@@ -48,10 +48,7 @@ test "it returns links" do
describe "determine_inbox/2" do
test "it returns sharedInbox for messages involving as:Public in to" do
- user =
- insert(:user, %{
- source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}}
- })
+ user = insert(:user, %{shared_inbox: "http://example.com/inbox"})
activity = %Activity{
data: %{"to" => [@as_public], "cc" => [user.follower_address]}
@@ -61,10 +58,7 @@ test "it returns sharedInbox for messages involving as:Public in to" do
end
test "it returns sharedInbox for messages involving as:Public in cc" do
- user =
- insert(:user, %{
- source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}}
- })
+ user = insert(:user, %{shared_inbox: "http://example.com/inbox"})
activity = %Activity{
data: %{"cc" => [@as_public], "to" => [user.follower_address]}
@@ -74,11 +68,7 @@ test "it returns sharedInbox for messages involving as:Public in cc" do
end
test "it returns sharedInbox for messages involving multiple recipients in to" do
- user =
- insert(:user, %{
- source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}}
- })
-
+ user = insert(:user, %{shared_inbox: "http://example.com/inbox"})
user_two = insert(:user)
user_three = insert(:user)
@@ -90,11 +80,7 @@ test "it returns sharedInbox for messages involving multiple recipients in to" d
end
test "it returns sharedInbox for messages involving multiple recipients in cc" do
- user =
- insert(:user, %{
- source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}}
- })
-
+ user = insert(:user, %{shared_inbox: "http://example.com/inbox"})
user_two = insert(:user)
user_three = insert(:user)
@@ -107,12 +93,10 @@ test "it returns sharedInbox for messages involving multiple recipients in cc" d
test "it returns sharedInbox for messages involving multiple recipients in total" do
user =
- insert(:user,
- source_data: %{
- "inbox" => "http://example.com/personal-inbox",
- "endpoints" => %{"sharedInbox" => "http://example.com/inbox"}
- }
- )
+ insert(:user, %{
+ shared_inbox: "http://example.com/inbox",
+ inbox: "http://example.com/personal-inbox"
+ })
user_two = insert(:user)
@@ -125,12 +109,10 @@ test "it returns sharedInbox for messages involving multiple recipients in total
test "it returns inbox for messages involving single recipients in total" do
user =
- insert(:user,
- source_data: %{
- "inbox" => "http://example.com/personal-inbox",
- "endpoints" => %{"sharedInbox" => "http://example.com/inbox"}
- }
- )
+ insert(:user, %{
+ shared_inbox: "http://example.com/inbox",
+ inbox: "http://example.com/personal-inbox"
+ })
activity = %Activity{
data: %{"to" => [user.ap_id], "cc" => []}
@@ -258,11 +240,11 @@ test "it returns inbox for messages involving single recipients in total" do
[:passthrough],
[] do
follower =
- insert(:user,
+ insert(:user, %{
local: false,
- source_data: %{"inbox" => "https://domain.com/users/nick1/inbox"},
+ inbox: "https://domain.com/users/nick1/inbox",
ap_enabled: true
- )
+ })
actor = insert(:user, follower_address: follower.ap_id)
user = insert(:user)
@@ -295,14 +277,14 @@ test "it returns inbox for messages involving single recipients in total" do
fetcher =
insert(:user,
local: false,
- source_data: %{"inbox" => "https://domain.com/users/nick1/inbox"},
+ inbox: "https://domain.com/users/nick1/inbox",
ap_enabled: true
)
another_fetcher =
insert(:user,
local: false,
- source_data: %{"inbox" => "https://domain2.com/users/nick1/inbox"},
+ inbox: "https://domain2.com/users/nick1/inbox",
ap_enabled: true
)
diff --git a/test/web/activity_pub/side_effects_test.exs b/test/web/activity_pub/side_effects_test.exs
index b67bd14b3..0b6b55156 100644
--- a/test/web/activity_pub/side_effects_test.exs
+++ b/test/web/activity_pub/side_effects_test.exs
@@ -5,7 +5,9 @@
defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
use Pleroma.DataCase
+ alias Pleroma.Notification
alias Pleroma.Object
+ alias Pleroma.Repo
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Builder
alias Pleroma.Web.ActivityPub.SideEffects
@@ -15,13 +17,14 @@ defmodule Pleroma.Web.ActivityPub.SideEffectsTest do
describe "like objects" do
setup do
+ poster = insert(:user)
user = insert(:user)
- {:ok, post} = CommonAPI.post(user, %{"status" => "hey"})
+ {:ok, post} = CommonAPI.post(poster, %{"status" => "hey"})
{:ok, like_data, _meta} = Builder.like(user, post.object)
{:ok, like, _meta} = ActivityPub.persist(like_data, local: true)
- %{like: like, user: user}
+ %{like: like, user: user, poster: poster}
end
test "add the like to the original object", %{like: like, user: user} do
@@ -30,5 +33,10 @@ test "add the like to the original object", %{like: like, user: user} do
assert object.data["like_count"] == 1
assert user.ap_id in object.data["likes"]
end
+
+ test "creates a notification", %{like: like, poster: poster} do
+ {:ok, like, _} = SideEffects.handle(like)
+ assert Repo.get_by(Notification, user_id: poster.id, activity_id: like.id)
+ end
end
end
diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs
index 2332029e5..6057e360a 100644
--- a/test/web/activity_pub/transmogrifier_test.exs
+++ b/test/web/activity_pub/transmogrifier_test.exs
@@ -746,7 +746,7 @@ test "it works with custom profile fields" do
user = User.get_cached_by_ap_id(activity.actor)
- assert User.fields(user) == [
+ assert user.fields == [
%{"name" => "foo", "value" => "bar"},
%{"name" => "foo1", "value" => "bar1"}
]
@@ -767,7 +767,7 @@ test "it works with custom profile fields" do
user = User.get_cached_by_ap_id(user.ap_id)
- assert User.fields(user) == [
+ assert user.fields == [
%{"name" => "foo", "value" => "updated"},
%{"name" => "foo1", "value" => "updated"}
]
@@ -785,7 +785,7 @@ test "it works with custom profile fields" do
user = User.get_cached_by_ap_id(user.ap_id)
- assert User.fields(user) == [
+ assert user.fields == [
%{"name" => "foo", "value" => "updated"},
%{"name" => "foo1", "value" => "updated"}
]
@@ -796,7 +796,7 @@ test "it works with custom profile fields" do
user = User.get_cached_by_ap_id(user.ap_id)
- assert User.fields(user) == []
+ assert user.fields == []
end
test "it works for incoming update activities which lock the account" do
@@ -2162,4 +2162,18 @@ test "sets `replies` collection with a limited number of self-replies" do
Transmogrifier.set_replies(object.data)["replies"]
end
end
+
+ test "take_emoji_tags/1" do
+ user = insert(:user, %{emoji: %{"firefox" => "https://example.org/firefox.png"}})
+
+ assert Transmogrifier.take_emoji_tags(user) == [
+ %{
+ "icon" => %{"type" => "Image", "url" => "https://example.org/firefox.png"},
+ "id" => "https://example.org/firefox.png",
+ "name" => ":firefox:",
+ "type" => "Emoji",
+ "updated" => "1970-01-01T00:00:00Z"
+ }
+ ]
+ end
end
diff --git a/test/web/activity_pub/utils_test.exs b/test/web/activity_pub/utils_test.exs
index e913a5148..b0bfed917 100644
--- a/test/web/activity_pub/utils_test.exs
+++ b/test/web/activity_pub/utils_test.exs
@@ -224,8 +224,7 @@ test "fetches only Create activities" do
object = Object.normalize(activity)
{:ok, [vote], object} = CommonAPI.vote(other_user, object, [0])
- vote_object = Object.normalize(vote)
- {:ok, _activity, _object} = ActivityPub.like(user, vote_object)
+ {:ok, _activity} = CommonAPI.favorite(user, activity.id)
[fetched_vote] = Utils.get_existing_votes(other_user.ap_id, object)
assert fetched_vote.id == vote.id
end
@@ -346,7 +345,7 @@ test "fetches existing like" do
user = insert(:user)
refute Utils.get_existing_like(user.ap_id, object)
- {:ok, like_activity, _object} = ActivityPub.like(user, object)
+ {:ok, like_activity} = CommonAPI.favorite(user, note_activity.id)
assert ^like_activity = Utils.get_existing_like(user.ap_id, object)
end
diff --git a/test/web/activity_pub/views/user_view_test.exs b/test/web/activity_pub/views/user_view_test.exs
index ecb2dc386..8d00893a5 100644
--- a/test/web/activity_pub/views/user_view_test.exs
+++ b/test/web/activity_pub/views/user_view_test.exs
@@ -29,7 +29,7 @@ test "Renders profile fields" do
{:ok, user} =
insert(:user)
- |> User.upgrade_changeset(%{fields: fields})
+ |> User.update_changeset(%{fields: fields})
|> User.update_and_set_cache()
assert %{
@@ -38,7 +38,7 @@ test "Renders profile fields" do
end
test "Renders with emoji tags" do
- user = insert(:user, emoji: [%{"bib" => "/test"}])
+ user = insert(:user, emoji: %{"bib" => "/test"})
assert %{
"tag" => [
diff --git a/test/web/admin_api/admin_api_controller_test.exs b/test/web/admin_api/admin_api_controller_test.exs
index 60ec895f5..f80dbf8dd 100644
--- a/test/web/admin_api/admin_api_controller_test.exs
+++ b/test/web/admin_api/admin_api_controller_test.exs
@@ -2110,7 +2110,7 @@ test "saving config which need pleroma reboot", %{conn: conn} do
|> get("/api/pleroma/admin/config")
|> json_response(200)
- refute Map.has_key?(configs, "need_reboot")
+ assert configs["need_reboot"] == false
end
test "update setting which need reboot, don't change reboot flag until reboot", %{conn: conn} do
@@ -2166,7 +2166,7 @@ test "update setting which need reboot, don't change reboot flag until reboot",
|> get("/api/pleroma/admin/config")
|> json_response(200)
- refute Map.has_key?(configs, "need_reboot")
+ assert configs["need_reboot"] == false
end
test "saving config with nested merge", %{conn: conn} do
@@ -2861,6 +2861,20 @@ test "pleroma restarts", %{conn: conn} do
end
end
+ test "need_reboot flag", %{conn: conn} do
+ assert conn
+ |> get("/api/pleroma/admin/need_reboot")
+ |> json_response(200) == %{"need_reboot" => false}
+
+ Restarter.Pleroma.need_reboot()
+
+ assert conn
+ |> get("/api/pleroma/admin/need_reboot")
+ |> json_response(200) == %{"need_reboot" => true}
+
+ on_exit(fn -> Restarter.Pleroma.refresh() end)
+ end
+
describe "GET /api/pleroma/admin/statuses" do
test "returns all public and unlisted statuses", %{conn: conn, admin: admin} do
blocked = insert(:user)
@@ -3503,6 +3517,191 @@ test "status visibility count", %{conn: conn} do
response["status_visibility"]
end
end
+
+ describe "POST /api/pleroma/admin/oauth_app" do
+ test "errors", %{conn: conn} do
+ response = conn |> post("/api/pleroma/admin/oauth_app", %{}) |> json_response(200)
+
+ assert response == %{"name" => "can't be blank", "redirect_uris" => "can't be blank"}
+ end
+
+ test "success", %{conn: conn} do
+ base_url = Pleroma.Web.base_url()
+ app_name = "Trusted app"
+
+ response =
+ conn
+ |> post("/api/pleroma/admin/oauth_app", %{
+ name: app_name,
+ redirect_uris: base_url
+ })
+ |> json_response(200)
+
+ assert %{
+ "client_id" => _,
+ "client_secret" => _,
+ "name" => ^app_name,
+ "redirect_uri" => ^base_url,
+ "trusted" => false
+ } = response
+ end
+
+ test "with trusted", %{conn: conn} do
+ base_url = Pleroma.Web.base_url()
+ app_name = "Trusted app"
+
+ response =
+ conn
+ |> post("/api/pleroma/admin/oauth_app", %{
+ name: app_name,
+ redirect_uris: base_url,
+ trusted: true
+ })
+ |> json_response(200)
+
+ assert %{
+ "client_id" => _,
+ "client_secret" => _,
+ "name" => ^app_name,
+ "redirect_uri" => ^base_url,
+ "trusted" => true
+ } = response
+ end
+ end
+
+ describe "GET /api/pleroma/admin/oauth_app" do
+ setup do
+ app = insert(:oauth_app)
+ {:ok, app: app}
+ end
+
+ test "list", %{conn: conn} do
+ response =
+ conn
+ |> get("/api/pleroma/admin/oauth_app")
+ |> json_response(200)
+
+ assert %{"apps" => apps, "count" => count, "page_size" => _} = response
+
+ assert length(apps) == count
+ end
+
+ test "with page size", %{conn: conn} do
+ insert(:oauth_app)
+ page_size = 1
+
+ response =
+ conn
+ |> get("/api/pleroma/admin/oauth_app", %{page_size: to_string(page_size)})
+ |> json_response(200)
+
+ assert %{"apps" => apps, "count" => _, "page_size" => ^page_size} = response
+
+ assert length(apps) == page_size
+ end
+
+ test "search by client name", %{conn: conn, app: app} do
+ response =
+ conn
+ |> get("/api/pleroma/admin/oauth_app", %{name: app.client_name})
+ |> json_response(200)
+
+ assert %{"apps" => [returned], "count" => _, "page_size" => _} = response
+
+ assert returned["client_id"] == app.client_id
+ assert returned["name"] == app.client_name
+ end
+
+ test "search by client id", %{conn: conn, app: app} do
+ response =
+ conn
+ |> get("/api/pleroma/admin/oauth_app", %{client_id: app.client_id})
+ |> json_response(200)
+
+ assert %{"apps" => [returned], "count" => _, "page_size" => _} = response
+
+ assert returned["client_id"] == app.client_id
+ assert returned["name"] == app.client_name
+ end
+
+ test "only trusted", %{conn: conn} do
+ app = insert(:oauth_app, trusted: true)
+
+ response =
+ conn
+ |> get("/api/pleroma/admin/oauth_app", %{trusted: true})
+ |> json_response(200)
+
+ assert %{"apps" => [returned], "count" => _, "page_size" => _} = response
+
+ assert returned["client_id"] == app.client_id
+ assert returned["name"] == app.client_name
+ end
+ end
+
+ describe "DELETE /api/pleroma/admin/oauth_app/:id" do
+ test "with id", %{conn: conn} do
+ app = insert(:oauth_app)
+
+ response =
+ conn
+ |> delete("/api/pleroma/admin/oauth_app/" <> to_string(app.id))
+ |> json_response(:no_content)
+
+ assert response == ""
+ end
+
+ test "with non existance id", %{conn: conn} do
+ response =
+ conn
+ |> delete("/api/pleroma/admin/oauth_app/0")
+ |> json_response(:bad_request)
+
+ assert response == ""
+ end
+ end
+
+ describe "PATCH /api/pleroma/admin/oauth_app/:id" do
+ test "with id", %{conn: conn} do
+ app = insert(:oauth_app)
+
+ name = "another name"
+ url = "https://example.com"
+ scopes = ["admin"]
+ id = app.id
+ website = "http://website.com"
+
+ response =
+ conn
+ |> patch("/api/pleroma/admin/oauth_app/" <> to_string(app.id), %{
+ name: name,
+ trusted: true,
+ redirect_uris: url,
+ scopes: scopes,
+ website: website
+ })
+ |> json_response(200)
+
+ assert %{
+ "client_id" => _,
+ "client_secret" => _,
+ "id" => ^id,
+ "name" => ^name,
+ "redirect_uri" => ^url,
+ "trusted" => true,
+ "website" => ^website
+ } = response
+ end
+
+ test "without id", %{conn: conn} do
+ response =
+ conn
+ |> patch("/api/pleroma/admin/oauth_app/0")
+ |> json_response(:bad_request)
+
+ assert response == ""
+ end
+ end
end
# Needed for testing
diff --git a/test/web/api_spec/app_operation_test.exs b/test/web/api_spec/app_operation_test.exs
deleted file mode 100644
index 5b96abb44..000000000
--- a/test/web/api_spec/app_operation_test.exs
+++ /dev/null
@@ -1,45 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.ApiSpec.AppOperationTest do
- use Pleroma.Web.ConnCase, async: true
-
- alias Pleroma.Web.ApiSpec
- alias Pleroma.Web.ApiSpec.Schemas.AppCreateRequest
- alias Pleroma.Web.ApiSpec.Schemas.AppCreateResponse
-
- import OpenApiSpex.TestAssertions
- import Pleroma.Factory
-
- test "AppCreateRequest example matches schema" do
- api_spec = ApiSpec.spec()
- schema = AppCreateRequest.schema()
- assert_schema(schema.example, "AppCreateRequest", api_spec)
- end
-
- test "AppCreateResponse example matches schema" do
- api_spec = ApiSpec.spec()
- schema = AppCreateResponse.schema()
- assert_schema(schema.example, "AppCreateResponse", api_spec)
- end
-
- test "AppController produces a AppCreateResponse", %{conn: conn} do
- api_spec = ApiSpec.spec()
- app_attrs = build(:oauth_app)
-
- json =
- conn
- |> put_req_header("content-type", "application/json")
- |> post(
- "/api/v1/apps",
- Jason.encode!(%{
- client_name: app_attrs.client_name,
- redirect_uris: app_attrs.redirect_uris
- })
- )
- |> json_response(200)
-
- assert_schema(json, "AppCreateResponse", api_spec)
- end
-end
diff --git a/test/web/api_spec/schema_examples_test.exs b/test/web/api_spec/schema_examples_test.exs
new file mode 100644
index 000000000..88b6f07cb
--- /dev/null
+++ b/test/web/api_spec/schema_examples_test.exs
@@ -0,0 +1,43 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ApiSpec.SchemaExamplesTest do
+ use ExUnit.Case, async: true
+ import Pleroma.Tests.ApiSpecHelpers
+
+ @content_type "application/json"
+
+ for operation <- api_operations() do
+ describe operation.operationId <> " Request Body" do
+ if operation.requestBody do
+ @media_type operation.requestBody.content[@content_type]
+ @schema resolve_schema(@media_type.schema)
+
+ if @media_type.example do
+ test "request body media type example matches schema" do
+ assert_schema(@media_type.example, @schema)
+ end
+ end
+
+ if @schema.example do
+ test "request body schema example matches schema" do
+ assert_schema(@schema.example, @schema)
+ end
+ end
+ end
+ end
+
+ for {status, response} <- operation.responses do
+ describe "#{operation.operationId} - #{status} Response" do
+ @schema resolve_schema(response.content[@content_type].schema)
+
+ if @schema.example do
+ test "example matches schema" do
+ assert_schema(@schema.example, @schema)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/test/web/auth/auth_test_controller_test.exs b/test/web/auth/auth_test_controller_test.exs
new file mode 100644
index 000000000..fed52b7f3
--- /dev/null
+++ b/test/web/auth/auth_test_controller_test.exs
@@ -0,0 +1,242 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Tests.AuthTestControllerTest do
+ use Pleroma.Web.ConnCase
+
+ import Pleroma.Factory
+
+ describe "do_oauth_check" do
+ test "serves with proper OAuth token (fulfilling requested scopes)" do
+ %{conn: good_token_conn, user: user} = oauth_access(["read"])
+
+ assert %{"user_id" => user.id} ==
+ good_token_conn
+ |> get("/test/authenticated_api/do_oauth_check")
+ |> json_response(200)
+
+ # Unintended usage (:api) — use with :authenticated_api instead
+ assert %{"user_id" => user.id} ==
+ good_token_conn
+ |> get("/test/api/do_oauth_check")
+ |> json_response(200)
+ end
+
+ test "fails on no token / missing scope(s)" do
+ %{conn: bad_token_conn} = oauth_access(["irrelevant_scope"])
+
+ bad_token_conn
+ |> get("/test/authenticated_api/do_oauth_check")
+ |> json_response(403)
+
+ bad_token_conn
+ |> assign(:token, nil)
+ |> get("/test/api/do_oauth_check")
+ |> json_response(403)
+ end
+ end
+
+ describe "fallback_oauth_check" do
+ test "serves with proper OAuth token (fulfilling requested scopes)" do
+ %{conn: good_token_conn, user: user} = oauth_access(["read"])
+
+ assert %{"user_id" => user.id} ==
+ good_token_conn
+ |> get("/test/api/fallback_oauth_check")
+ |> json_response(200)
+
+ # Unintended usage (:authenticated_api) — use with :api instead
+ assert %{"user_id" => user.id} ==
+ good_token_conn
+ |> get("/test/authenticated_api/fallback_oauth_check")
+ |> json_response(200)
+ end
+
+ test "for :api on public instance, drops :user and renders on no token / missing scope(s)" do
+ clear_config([:instance, :public], true)
+
+ %{conn: bad_token_conn} = oauth_access(["irrelevant_scope"])
+
+ assert %{"user_id" => nil} ==
+ bad_token_conn
+ |> get("/test/api/fallback_oauth_check")
+ |> json_response(200)
+
+ assert %{"user_id" => nil} ==
+ bad_token_conn
+ |> assign(:token, nil)
+ |> get("/test/api/fallback_oauth_check")
+ |> json_response(200)
+ end
+
+ test "for :api on private instance, fails on no token / missing scope(s)" do
+ clear_config([:instance, :public], false)
+
+ %{conn: bad_token_conn} = oauth_access(["irrelevant_scope"])
+
+ bad_token_conn
+ |> get("/test/api/fallback_oauth_check")
+ |> json_response(403)
+
+ bad_token_conn
+ |> assign(:token, nil)
+ |> get("/test/api/fallback_oauth_check")
+ |> json_response(403)
+ end
+ end
+
+ describe "skip_oauth_check" do
+ test "for :authenticated_api, serves if :user is set (regardless of token / token scopes)" do
+ user = insert(:user)
+
+ assert %{"user_id" => user.id} ==
+ build_conn()
+ |> assign(:user, user)
+ |> get("/test/authenticated_api/skip_oauth_check")
+ |> json_response(200)
+
+ %{conn: bad_token_conn, user: user} = oauth_access(["irrelevant_scope"])
+
+ assert %{"user_id" => user.id} ==
+ bad_token_conn
+ |> get("/test/authenticated_api/skip_oauth_check")
+ |> json_response(200)
+ end
+
+ test "serves via :api on public instance if :user is not set" do
+ clear_config([:instance, :public], true)
+
+ assert %{"user_id" => nil} ==
+ build_conn()
+ |> get("/test/api/skip_oauth_check")
+ |> json_response(200)
+
+ build_conn()
+ |> get("/test/authenticated_api/skip_oauth_check")
+ |> json_response(403)
+ end
+
+ test "fails on private instance if :user is not set" do
+ clear_config([:instance, :public], false)
+
+ build_conn()
+ |> get("/test/api/skip_oauth_check")
+ |> json_response(403)
+
+ build_conn()
+ |> get("/test/authenticated_api/skip_oauth_check")
+ |> json_response(403)
+ end
+ end
+
+ describe "fallback_oauth_skip_publicity_check" do
+ test "serves with proper OAuth token (fulfilling requested scopes)" do
+ %{conn: good_token_conn, user: user} = oauth_access(["read"])
+
+ assert %{"user_id" => user.id} ==
+ good_token_conn
+ |> get("/test/api/fallback_oauth_skip_publicity_check")
+ |> json_response(200)
+
+ # Unintended usage (:authenticated_api)
+ assert %{"user_id" => user.id} ==
+ good_token_conn
+ |> get("/test/authenticated_api/fallback_oauth_skip_publicity_check")
+ |> json_response(200)
+ end
+
+ test "for :api on private / public instance, drops :user and renders on token issue" do
+ %{conn: bad_token_conn} = oauth_access(["irrelevant_scope"])
+
+ for is_public <- [true, false] do
+ clear_config([:instance, :public], is_public)
+
+ assert %{"user_id" => nil} ==
+ bad_token_conn
+ |> get("/test/api/fallback_oauth_skip_publicity_check")
+ |> json_response(200)
+
+ assert %{"user_id" => nil} ==
+ bad_token_conn
+ |> assign(:token, nil)
+ |> get("/test/api/fallback_oauth_skip_publicity_check")
+ |> json_response(200)
+ end
+ end
+ end
+
+ describe "skip_oauth_skip_publicity_check" do
+ test "for :authenticated_api, serves if :user is set (regardless of token / token scopes)" do
+ user = insert(:user)
+
+ assert %{"user_id" => user.id} ==
+ build_conn()
+ |> assign(:user, user)
+ |> get("/test/authenticated_api/skip_oauth_skip_publicity_check")
+ |> json_response(200)
+
+ %{conn: bad_token_conn, user: user} = oauth_access(["irrelevant_scope"])
+
+ assert %{"user_id" => user.id} ==
+ bad_token_conn
+ |> get("/test/authenticated_api/skip_oauth_skip_publicity_check")
+ |> json_response(200)
+ end
+
+ test "for :api, serves on private and public instances regardless of whether :user is set" do
+ user = insert(:user)
+
+ for is_public <- [true, false] do
+ clear_config([:instance, :public], is_public)
+
+ assert %{"user_id" => nil} ==
+ build_conn()
+ |> get("/test/api/skip_oauth_skip_publicity_check")
+ |> json_response(200)
+
+ assert %{"user_id" => user.id} ==
+ build_conn()
+ |> assign(:user, user)
+ |> get("/test/api/skip_oauth_skip_publicity_check")
+ |> json_response(200)
+ end
+ end
+ end
+
+ describe "missing_oauth_check_definition" do
+ def test_missing_oauth_check_definition_failure(endpoint, expected_error) do
+ %{conn: conn} = oauth_access(["read", "write", "follow", "push", "admin"])
+
+ assert %{"error" => expected_error} ==
+ conn
+ |> get(endpoint)
+ |> json_response(403)
+ end
+
+ test "fails if served via :authenticated_api" do
+ test_missing_oauth_check_definition_failure(
+ "/test/authenticated_api/missing_oauth_check_definition",
+ "Security violation: OAuth scopes check was neither handled nor explicitly skipped."
+ )
+ end
+
+ test "fails if served via :api and the instance is private" do
+ clear_config([:instance, :public], false)
+
+ test_missing_oauth_check_definition_failure(
+ "/test/api/missing_oauth_check_definition",
+ "This resource requires authentication."
+ )
+ end
+
+ test "succeeds with dropped :user if served via :api on public instance" do
+ %{conn: conn} = oauth_access(["read", "write", "follow", "push", "admin"])
+
+ assert %{"user_id" => nil} ==
+ conn
+ |> get("/test/api/missing_oauth_check_definition")
+ |> json_response(200)
+ end
+ end
+end
diff --git a/test/web/auth/basic_auth_test.exs b/test/web/auth/basic_auth_test.exs
new file mode 100644
index 000000000..64f8a6863
--- /dev/null
+++ b/test/web/auth/basic_auth_test.exs
@@ -0,0 +1,46 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.Auth.BasicAuthTest do
+ use Pleroma.Web.ConnCase
+
+ import Pleroma.Factory
+
+ test "with HTTP Basic Auth used, grants access to OAuth scope-restricted endpoints", %{
+ conn: conn
+ } do
+ user = insert(:user)
+ assert Comeonin.Pbkdf2.checkpw("test", user.password_hash)
+
+ basic_auth_contents =
+ (URI.encode_www_form(user.nickname) <> ":" <> URI.encode_www_form("test"))
+ |> Base.encode64()
+
+ # Succeeds with HTTP Basic Auth
+ response =
+ conn
+ |> put_req_header("authorization", "Basic " <> basic_auth_contents)
+ |> get("/api/v1/accounts/verify_credentials")
+ |> json_response(200)
+
+ user_nickname = user.nickname
+ assert %{"username" => ^user_nickname} = response
+
+ # Succeeds with a properly scoped OAuth token
+ valid_token = insert(:oauth_token, scopes: ["read:accounts"])
+
+ conn
+ |> put_req_header("authorization", "Bearer #{valid_token.token}")
+ |> get("/api/v1/accounts/verify_credentials")
+ |> json_response(200)
+
+ # Fails with a wrong-scoped OAuth token (proof of restriction)
+ invalid_token = insert(:oauth_token, scopes: ["read:something"])
+
+ conn
+ |> put_req_header("authorization", "Bearer #{invalid_token.token}")
+ |> get("/api/v1/accounts/verify_credentials")
+ |> json_response(403)
+ end
+end
diff --git a/test/web/common_api/common_api_test.exs b/test/web/common_api/common_api_test.exs
index b12be973f..1758662b0 100644
--- a/test/web/common_api/common_api_test.exs
+++ b/test/web/common_api/common_api_test.exs
@@ -21,6 +21,60 @@ defmodule Pleroma.Web.CommonAPITest do
setup do: clear_config([:instance, :limit])
setup do: clear_config([:instance, :max_pinned_statuses])
+ test "favoriting race condition" do
+ user = insert(:user)
+ users_serial = insert_list(10, :user)
+ users = insert_list(10, :user)
+
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "."})
+
+ users_serial
+ |> Enum.map(fn user ->
+ CommonAPI.favorite(user, activity.id)
+ end)
+
+ object = Object.get_by_ap_id(activity.data["object"])
+ assert object.data["like_count"] == 10
+
+ users
+ |> Enum.map(fn user ->
+ Task.async(fn ->
+ CommonAPI.favorite(user, activity.id)
+ end)
+ end)
+ |> Enum.map(&Task.await/1)
+
+ object = Object.get_by_ap_id(activity.data["object"])
+ assert object.data["like_count"] == 20
+ end
+
+ test "repeating race condition" do
+ user = insert(:user)
+ users_serial = insert_list(10, :user)
+ users = insert_list(10, :user)
+
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "."})
+
+ users_serial
+ |> Enum.map(fn user ->
+ CommonAPI.repeat(activity.id, user)
+ end)
+
+ object = Object.get_by_ap_id(activity.data["object"])
+ assert object.data["announcement_count"] == 10
+
+ users
+ |> Enum.map(fn user ->
+ Task.async(fn ->
+ CommonAPI.repeat(activity.id, user)
+ end)
+ end)
+ |> Enum.map(&Task.await/1)
+
+ object = Object.get_by_ap_id(activity.data["object"])
+ assert object.data["announcement_count"] == 20
+ end
+
test "when replying to a conversation / participation, it will set the correct context id even if no explicit reply_to is given" do
user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"})
@@ -97,18 +151,6 @@ test "it adds emoji in the object" do
assert Object.normalize(activity).data["emoji"]["firefox"]
end
- test "it adds emoji when updating profiles" do
- user = insert(:user, %{name: ":firefox:"})
-
- {:ok, activity} = CommonAPI.update(user)
- user = User.get_cached_by_ap_id(user.ap_id)
- [firefox] = user.source_data["tag"]
-
- assert firefox["name"] == ":firefox:"
-
- assert Pleroma.Constants.as_public() in activity.recipients
- end
-
describe "posting" do
test "it supports explicit addressing" do
user = insert(:user)
@@ -268,6 +310,16 @@ test "repeating a status" do
{:ok, %Activity{}, _} = CommonAPI.repeat(activity.id, user)
end
+ test "can't repeat a repeat" do
+ user = insert(:user)
+ other_user = insert(:user)
+ {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"})
+
+ {:ok, %Activity{} = announce, _} = CommonAPI.repeat(activity.id, other_user)
+
+ refute match?({:ok, %Activity{}, _}, CommonAPI.repeat(announce.id, user))
+ end
+
test "repeating a status privately" do
user = insert(:user)
other_user = insert(:user)
@@ -297,8 +349,8 @@ test "retweeting a status twice returns the status" do
other_user = insert(:user)
{:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"})
- {:ok, %Activity{} = activity, object} = CommonAPI.repeat(activity.id, user)
- {:ok, ^activity, ^object} = CommonAPI.repeat(activity.id, user)
+ {:ok, %Activity{} = announce, object} = CommonAPI.repeat(activity.id, user)
+ {:ok, ^announce, ^object} = CommonAPI.repeat(activity.id, user)
end
test "favoriting a status twice returns ok, but without the like activity" do
@@ -372,7 +424,9 @@ test "unpin status", %{user: user, activity: activity} do
user = refresh_record(user)
- assert {:ok, ^activity} = CommonAPI.unpin(activity.id, user)
+ id = activity.id
+
+ assert match?({:ok, %{id: ^id}}, CommonAPI.unpin(activity.id, user))
user = refresh_record(user)
diff --git a/test/web/common_api/common_api_utils_test.exs b/test/web/common_api/common_api_utils_test.exs
index 98cf02d49..18a3b3b87 100644
--- a/test/web/common_api/common_api_utils_test.exs
+++ b/test/web/common_api/common_api_utils_test.exs
@@ -7,7 +7,6 @@ defmodule Pleroma.Web.CommonAPI.UtilsTest do
alias Pleroma.Object
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.CommonAPI.Utils
- alias Pleroma.Web.Endpoint
use Pleroma.DataCase
import ExUnit.CaptureLog
@@ -42,28 +41,6 @@ test "correct password given" do
end
end
- test "parses emoji from name and bio" do
- {:ok, user} = UserBuilder.insert(%{name: ":blank:", bio: ":firefox:"})
-
- expected = [
- %{
- "type" => "Emoji",
- "icon" => %{"type" => "Image", "url" => "#{Endpoint.url()}/emoji/Firefox.gif"},
- "name" => ":firefox:"
- },
- %{
- "type" => "Emoji",
- "icon" => %{
- "type" => "Image",
- "url" => "#{Endpoint.url()}/emoji/blank.png"
- },
- "name" => ":blank:"
- }
- ]
-
- assert expected == Utils.emoji_from_profile(user)
- end
-
describe "format_input/3" do
test "works for bare text/plain" do
text = "hello world!"
@@ -358,26 +335,6 @@ test "for direct posts, a reply" do
end
end
- describe "get_by_id_or_ap_id/1" do
- test "get activity by id" do
- activity = insert(:note_activity)
- %Pleroma.Activity{} = note = Utils.get_by_id_or_ap_id(activity.id)
- assert note.id == activity.id
- end
-
- test "get activity by ap_id" do
- activity = insert(:note_activity)
- %Pleroma.Activity{} = note = Utils.get_by_id_or_ap_id(activity.data["object"])
- assert note.id == activity.id
- end
-
- test "get activity by object when type isn't `Create` " do
- activity = insert(:like_activity)
- %Pleroma.Activity{} = like = Utils.get_by_id_or_ap_id(activity.id)
- assert like.data["object"] == activity.data["object"]
- end
- end
-
describe "to_master_date/1" do
test "removes microseconds from date (NaiveDateTime)" do
assert Utils.to_masto_date(~N[2015-01-23 23:50:07.123]) == "2015-01-23T23:50:07.000Z"
diff --git a/test/web/federator_test.exs b/test/web/federator_test.exs
index da844c24c..261518ef0 100644
--- a/test/web/federator_test.exs
+++ b/test/web/federator_test.exs
@@ -78,7 +78,7 @@ test "it federates only to reachable instances via AP" do
local: false,
nickname: "nick1@domain.com",
ap_id: "https://domain.com/users/nick1",
- source_data: %{"inbox" => inbox1},
+ inbox: inbox1,
ap_enabled: true
})
@@ -86,7 +86,7 @@ test "it federates only to reachable instances via AP" do
local: false,
nickname: "nick2@domain2.com",
ap_id: "https://domain2.com/users/nick2",
- source_data: %{"inbox" => inbox2},
+ inbox: inbox2,
ap_enabled: true
})
@@ -130,6 +130,9 @@ test "successfully processes incoming AP docs with correct origin" do
assert {:ok, job} = Federator.incoming_ap_doc(params)
assert {:ok, _activity} = ObanHelpers.perform(job)
+
+ assert {:ok, job} = Federator.incoming_ap_doc(params)
+ assert {:error, :already_present} = ObanHelpers.perform(job)
end
test "rejects incoming AP docs with incorrect origin" do
@@ -148,7 +151,7 @@ test "rejects incoming AP docs with incorrect origin" do
}
assert {:ok, job} = Federator.incoming_ap_doc(params)
- assert :error = ObanHelpers.perform(job)
+ assert {:error, :origin_containment_failed} = ObanHelpers.perform(job)
end
test "it does not crash if MRF rejects the post" do
@@ -164,7 +167,7 @@ test "it does not crash if MRF rejects the post" do
|> Poison.decode!()
assert {:ok, job} = Federator.incoming_ap_doc(params)
- assert :error = ObanHelpers.perform(job)
+ assert {:error, _} = ObanHelpers.perform(job)
end
end
end
diff --git a/test/web/feed/tag_controller_test.exs b/test/web/feed/tag_controller_test.exs
index e863df86b..d95aac108 100644
--- a/test/web/feed/tag_controller_test.exs
+++ b/test/web/feed/tag_controller_test.exs
@@ -150,8 +150,8 @@ test "gets a feed (RSS)", %{conn: conn} do
obj2 = Object.normalize(activity2)
assert xpath(xml, ~x"//channel/item/description/text()"sl) == [
- HtmlEntities.decode(FeedView.activity_content(obj2)),
- HtmlEntities.decode(FeedView.activity_content(obj1))
+ HtmlEntities.decode(FeedView.activity_content(obj2.data)),
+ HtmlEntities.decode(FeedView.activity_content(obj1.data))
]
response =
diff --git a/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs b/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs
index 2d256f63c..fdb6d4c5d 100644
--- a/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs
+++ b/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs
@@ -14,6 +14,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do
describe "updating credentials" do
setup do: oauth_access(["write:accounts"])
+ setup :request_content_type
test "sets user settings in a generic way", %{conn: conn} do
res_conn =
@@ -25,7 +26,7 @@ test "sets user settings in a generic way", %{conn: conn} do
}
})
- assert user_data = json_response(res_conn, 200)
+ assert user_data = json_response_and_validate_schema(res_conn, 200)
assert user_data["pleroma"]["settings_store"] == %{"pleroma_fe" => %{"theme" => "bla"}}
user = Repo.get(User, user_data["id"])
@@ -41,7 +42,7 @@ test "sets user settings in a generic way", %{conn: conn} do
}
})
- assert user_data = json_response(res_conn, 200)
+ assert user_data = json_response_and_validate_schema(res_conn, 200)
assert user_data["pleroma"]["settings_store"] ==
%{
@@ -62,7 +63,7 @@ test "sets user settings in a generic way", %{conn: conn} do
}
})
- assert user_data = json_response(res_conn, 200)
+ assert user_data = json_response_and_validate_schema(res_conn, 200)
assert user_data["pleroma"]["settings_store"] ==
%{
@@ -79,7 +80,7 @@ test "updates the user's bio", %{conn: conn} do
"note" => "I drink #cofe with @#{user2.nickname}\n\nsuya.."
})
- assert user_data = json_response(conn, 200)
+ assert user_data = json_response_and_validate_schema(conn, 200)
assert user_data["note"] ==
~s(I drink
#cofe with
%{"pleroma" => %{"discoverable" => true}}} =
conn
|> patch("/api/v1/accounts/update_credentials", %{discoverable: "true"})
- |> json_response(:ok)
+ |> json_response_and_validate_schema(:ok)
assert %{"source" => %{"pleroma" => %{"discoverable" => false}}} =
conn
|> patch("/api/v1/accounts/update_credentials", %{discoverable: "false"})
- |> json_response(:ok)
+ |> json_response_and_validate_schema(:ok)
end
test "updates the user's hide_followers_count and hide_follows_count", %{conn: conn} do
@@ -137,7 +138,7 @@ test "updates the user's hide_followers_count and hide_follows_count", %{conn: c
hide_follows_count: "true"
})
- assert user_data = json_response(conn, 200)
+ assert user_data = json_response_and_validate_schema(conn, 200)
assert user_data["pleroma"]["hide_followers_count"] == true
assert user_data["pleroma"]["hide_follows_count"] == true
end
@@ -146,7 +147,7 @@ test "updates the user's skip_thread_containment option", %{user: user, conn: co
response =
conn
|> patch("/api/v1/accounts/update_credentials", %{skip_thread_containment: "true"})
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
assert response["pleroma"]["skip_thread_containment"] == true
assert refresh_record(user).skip_thread_containment
@@ -155,28 +156,28 @@ test "updates the user's skip_thread_containment option", %{user: user, conn: co
test "updates the user's hide_follows status", %{conn: conn} do
conn = patch(conn, "/api/v1/accounts/update_credentials", %{hide_follows: "true"})
- assert user_data = json_response(conn, 200)
+ assert user_data = json_response_and_validate_schema(conn, 200)
assert user_data["pleroma"]["hide_follows"] == true
end
test "updates the user's hide_favorites status", %{conn: conn} do
conn = patch(conn, "/api/v1/accounts/update_credentials", %{hide_favorites: "true"})
- assert user_data = json_response(conn, 200)
+ assert user_data = json_response_and_validate_schema(conn, 200)
assert user_data["pleroma"]["hide_favorites"] == true
end
test "updates the user's show_role status", %{conn: conn} do
conn = patch(conn, "/api/v1/accounts/update_credentials", %{show_role: "false"})
- assert user_data = json_response(conn, 200)
+ assert user_data = json_response_and_validate_schema(conn, 200)
assert user_data["source"]["pleroma"]["show_role"] == false
end
test "updates the user's no_rich_text status", %{conn: conn} do
conn = patch(conn, "/api/v1/accounts/update_credentials", %{no_rich_text: "true"})
- assert user_data = json_response(conn, 200)
+ assert user_data = json_response_and_validate_schema(conn, 200)
assert user_data["source"]["pleroma"]["no_rich_text"] == true
end
@@ -184,7 +185,7 @@ test "updates the user's name", %{conn: conn} do
conn =
patch(conn, "/api/v1/accounts/update_credentials", %{"display_name" => "markorepairs"})
- assert user_data = json_response(conn, 200)
+ assert user_data = json_response_and_validate_schema(conn, 200)
assert user_data["display_name"] == "markorepairs"
end
@@ -197,7 +198,7 @@ test "updates the user's avatar", %{user: user, conn: conn} do
conn = patch(conn, "/api/v1/accounts/update_credentials", %{"avatar" => new_avatar})
- assert user_response = json_response(conn, 200)
+ assert user_response = json_response_and_validate_schema(conn, 200)
assert user_response["avatar"] != User.avatar_url(user)
end
@@ -210,7 +211,7 @@ test "updates the user's banner", %{user: user, conn: conn} do
conn = patch(conn, "/api/v1/accounts/update_credentials", %{"header" => new_header})
- assert user_response = json_response(conn, 200)
+ assert user_response = json_response_and_validate_schema(conn, 200)
assert user_response["header"] != User.banner_url(user)
end
@@ -226,7 +227,7 @@ test "updates the user's background", %{conn: conn} do
"pleroma_background_image" => new_header
})
- assert user_response = json_response(conn, 200)
+ assert user_response = json_response_and_validate_schema(conn, 200)
assert user_response["pleroma"]["background_image"]
end
@@ -237,14 +238,15 @@ test "requires 'write:accounts' permission" do
for token <- [token1, token2] do
conn =
build_conn()
+ |> put_req_header("content-type", "multipart/form-data")
|> put_req_header("authorization", "Bearer #{token.token}")
|> patch("/api/v1/accounts/update_credentials", %{})
if token == token1 do
assert %{"error" => "Insufficient permissions: write:accounts."} ==
- json_response(conn, 403)
+ json_response_and_validate_schema(conn, 403)
else
- assert json_response(conn, 200)
+ assert json_response_and_validate_schema(conn, 200)
end
end
end
@@ -259,11 +261,11 @@ test "updates profile emojos", %{user: user, conn: conn} do
"display_name" => name
})
- assert json_response(ret_conn, 200)
+ assert json_response_and_validate_schema(ret_conn, 200)
conn = get(conn, "/api/v1/accounts/#{user.id}")
- assert user_data = json_response(conn, 200)
+ assert user_data = json_response_and_validate_schema(conn, 200)
assert user_data["note"] == note
assert user_data["display_name"] == name
@@ -279,7 +281,7 @@ test "update fields", %{conn: conn} do
account_data =
conn
|> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
assert account_data["fields"] == [
%{"name" => "foo", "value" => "bar"},
@@ -312,7 +314,7 @@ test "update fields via x-www-form-urlencoded", %{conn: conn} do
conn
|> put_req_header("content-type", "application/x-www-form-urlencoded")
|> patch("/api/v1/accounts/update_credentials", fields)
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
assert account["fields"] == [
%{"name" => "foo", "value" => "bar"},
@@ -337,7 +339,7 @@ test "update fields with empty name", %{conn: conn} do
account =
conn
|> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
- |> json_response(200)
+ |> json_response_and_validate_schema(200)
assert account["fields"] == [
%{"name" => "foo", "value" => ""}
@@ -356,14 +358,14 @@ test "update fields when invalid request", %{conn: conn} do
assert %{"error" => "Invalid request"} ==
conn
|> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
- |> json_response(403)
+ |> json_response_and_validate_schema(403)
fields = [%{"name" => long_name, "value" => "bar"}]
assert %{"error" => "Invalid request"} ==
conn
|> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
- |> json_response(403)
+ |> json_response_and_validate_schema(403)
Pleroma.Config.put([:instance, :max_account_fields], 1)
@@ -375,7 +377,7 @@ test "update fields when invalid request", %{conn: conn} do
assert %{"error" => "Invalid request"} ==
conn
|> patch("/api/v1/accounts/update_credentials", %{"fields_attributes" => fields})
- |> json_response(403)
+ |> json_response_and_validate_schema(403)
end
end
end
diff --git a/test/web/mastodon_api/controllers/account_controller_test.exs b/test/web/mastodon_api/controllers/account_controller_test.exs
index a450a732c..ba70ba66c 100644
--- a/test/web/mastodon_api/controllers/account_controller_test.exs
+++ b/test/web/mastodon_api/controllers/account_controller_test.exs
@@ -19,43 +19,37 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
setup do: clear_config([:instance, :limit_to_local_content])
test "works by id" do
- user = insert(:user)
+ %User{id: user_id} = insert(:user)
- conn =
- build_conn()
- |> get("/api/v1/accounts/#{user.id}")
+ assert %{"id" => ^user_id} =
+ build_conn()
+ |> get("/api/v1/accounts/#{user_id}")
+ |> json_response_and_validate_schema(200)
- 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)
+ assert %{"error" => "Can't find user"} =
+ build_conn()
+ |> get("/api/v1/accounts/-1")
+ |> json_response_and_validate_schema(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
+ assert %{"id" => user_id} =
+ build_conn()
+ |> get("/api/v1/accounts/#{user.nickname}")
+ |> json_response_and_validate_schema(200)
end
test "works by nickname for remote users" do
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}")
-
- assert %{"id" => id} = json_response(conn, 200)
- assert id == user.id
+ assert %{"id" => user_id} =
+ build_conn()
+ |> get("/api/v1/accounts/#{user.nickname}")
+ |> json_response_and_validate_schema(200)
end
test "respects limit_to_local_content == :all for remote user nicknames" do
@@ -63,11 +57,9 @@ test "respects limit_to_local_content == :all for remote user nicknames" do
user = insert(:user, nickname: "user@example.com", local: false)
- conn =
- build_conn()
- |> get("/api/v1/accounts/#{user.nickname}")
-
- assert json_response(conn, 404)
+ assert build_conn()
+ |> get("/api/v1/accounts/#{user.nickname}")
+ |> json_response_and_validate_schema(404)
end
test "respects limit_to_local_content == :unauthenticated for remote user nicknames" do
@@ -80,7 +72,7 @@ test "respects limit_to_local_content == :unauthenticated for remote user nickna
build_conn()
|> get("/api/v1/accounts/#{user.nickname}")
- assert json_response(conn, 404)
+ assert json_response_and_validate_schema(conn, 404)
conn =
build_conn()
@@ -88,7 +80,7 @@ test "respects limit_to_local_content == :unauthenticated for remote user nickna
|> assign(:token, insert(:oauth_token, user: reading_user, scopes: ["read:accounts"]))
|> get("/api/v1/accounts/#{user.nickname}")
- assert %{"id" => id} = json_response(conn, 200)
+ assert %{"id" => id} = json_response_and_validate_schema(conn, 200)
assert id == user.id
end
@@ -99,21 +91,21 @@ test "accounts fetches correct account for nicknames beginning with numbers", %{
user_one = insert(:user, %{id: 1212})
user_two = insert(:user, %{nickname: "#{user_one.id}garbage"})
- resp_one =
+ acc_one =
conn
|> get("/api/v1/accounts/#{user_one.id}")
+ |> json_response_and_validate_schema(:ok)
- resp_two =
+ acc_two =
conn
|> get("/api/v1/accounts/#{user_two.nickname}")
+ |> json_response_and_validate_schema(:ok)
- resp_three =
+ acc_three =
conn
|> get("/api/v1/accounts/#{user_two.id}")
+ |> json_response_and_validate_schema(:ok)
- 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
@@ -121,23 +113,19 @@ test "accounts fetches correct account for nicknames beginning with numbers", %{
test "returns 404 when user is invisible", %{conn: conn} do
user = insert(:user, %{invisible: true})
- resp =
- conn
- |> get("/api/v1/accounts/#{user.nickname}")
- |> json_response(404)
-
- assert %{"error" => "Can't find user"} = resp
+ assert %{"error" => "Can't find user"} =
+ conn
+ |> get("/api/v1/accounts/#{user.nickname}")
+ |> json_response_and_validate_schema(404)
end
test "returns 404 for internal.fetch actor", %{conn: conn} do
%User{nickname: "internal.fetch"} = InternalFetchActor.get_actor()
- resp =
- conn
- |> get("/api/v1/accounts/internal.fetch")
- |> json_response(404)
-
- assert %{"error" => "Can't find user"} = resp
+ assert %{"error" => "Can't find user"} =
+ conn
+ |> get("/api/v1/accounts/internal.fetch")
+ |> json_response_and_validate_schema(404)
end
end
@@ -155,27 +143,25 @@ defp local_and_remote_users do
setup do: clear_config([:restrict_unauthenticated, :profiles, :remote], true)
test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
- res_conn = get(conn, "/api/v1/accounts/#{local.id}")
+ assert %{"error" => "Can't find user"} ==
+ conn
+ |> get("/api/v1/accounts/#{local.id}")
+ |> json_response_and_validate_schema(:not_found)
- assert json_response(res_conn, :not_found) == %{
- "error" => "Can't find user"
- }
-
- res_conn = get(conn, "/api/v1/accounts/#{remote.id}")
-
- assert json_response(res_conn, :not_found) == %{
- "error" => "Can't find user"
- }
+ assert %{"error" => "Can't find user"} ==
+ conn
+ |> get("/api/v1/accounts/#{remote.id}")
+ |> json_response_and_validate_schema(:not_found)
end
test "if user is authenticated", %{local: local, remote: remote} do
%{conn: conn} = oauth_access(["read"])
res_conn = get(conn, "/api/v1/accounts/#{local.id}")
- assert %{"id" => _} = json_response(res_conn, 200)
+ assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200)
res_conn = get(conn, "/api/v1/accounts/#{remote.id}")
- assert %{"id" => _} = json_response(res_conn, 200)
+ assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200)
end
end
@@ -187,22 +173,22 @@ test "if user is authenticated", %{local: local, remote: remote} do
test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
res_conn = get(conn, "/api/v1/accounts/#{local.id}")
- assert json_response(res_conn, :not_found) == %{
+ assert json_response_and_validate_schema(res_conn, :not_found) == %{
"error" => "Can't find user"
}
res_conn = get(conn, "/api/v1/accounts/#{remote.id}")
- assert %{"id" => _} = json_response(res_conn, 200)
+ assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200)
end
test "if user is authenticated", %{local: local, remote: remote} do
%{conn: conn} = oauth_access(["read"])
res_conn = get(conn, "/api/v1/accounts/#{local.id}")
- assert %{"id" => _} = json_response(res_conn, 200)
+ assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200)
res_conn = get(conn, "/api/v1/accounts/#{remote.id}")
- assert %{"id" => _} = json_response(res_conn, 200)
+ assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200)
end
end
@@ -213,11 +199,11 @@ test "if user is authenticated", %{local: local, remote: remote} do
test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
res_conn = get(conn, "/api/v1/accounts/#{local.id}")
- assert %{"id" => _} = json_response(res_conn, 200)
+ assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200)
res_conn = get(conn, "/api/v1/accounts/#{remote.id}")
- assert json_response(res_conn, :not_found) == %{
+ assert json_response_and_validate_schema(res_conn, :not_found) == %{
"error" => "Can't find user"
}
end
@@ -226,10 +212,10 @@ test "if user is authenticated", %{local: local, remote: remote} do
%{conn: conn} = oauth_access(["read"])
res_conn = get(conn, "/api/v1/accounts/#{local.id}")
- assert %{"id" => _} = json_response(res_conn, 200)
+ assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200)
res_conn = get(conn, "/api/v1/accounts/#{remote.id}")
- assert %{"id" => _} = json_response(res_conn, 200)
+ assert %{"id" => _} = json_response_and_validate_schema(res_conn, 200)
end
end
@@ -245,27 +231,37 @@ test "respects blocks", %{user: user_one, conn: conn} do
{:ok, activity} = CommonAPI.post(user_two, %{"status" => "User one sux0rz"})
{:ok, repeat, _} = CommonAPI.repeat(activity.id, user_three)
- resp = get(conn, "/api/v1/accounts/#{user_two.id}/statuses")
+ assert resp =
+ conn
+ |> get("/api/v1/accounts/#{user_two.id}/statuses")
+ |> json_response_and_validate_schema(200)
- assert [%{"id" => id}] = json_response(resp, 200)
+ assert [%{"id" => id}] = resp
assert id == activity.id
# Even a blocked user will deliver the full user timeline, there would be
# no point in looking at a blocked users timeline otherwise
- resp = get(conn, "/api/v1/accounts/#{user_two.id}/statuses")
+ assert resp =
+ conn
+ |> get("/api/v1/accounts/#{user_two.id}/statuses")
+ |> json_response_and_validate_schema(200)
- assert [%{"id" => id}] = json_response(resp, 200)
+ assert [%{"id" => id}] = resp
assert id == activity.id
# Third user's timeline includes the repeat when viewed by unauthenticated user
- resp = get(build_conn(), "/api/v1/accounts/#{user_three.id}/statuses")
- assert [%{"id" => id}] = json_response(resp, 200)
+ resp =
+ build_conn()
+ |> get("/api/v1/accounts/#{user_three.id}/statuses")
+ |> json_response_and_validate_schema(200)
+
+ assert [%{"id" => id}] = resp
assert id == repeat.id
# When viewing a third user's timeline, the blocked users' statuses will NOT be shown
resp = get(conn, "/api/v1/accounts/#{user_three.id}/statuses")
- assert [] = json_response(resp, 200)
+ assert [] == json_response_and_validate_schema(resp, 200)
end
test "gets users statuses", %{conn: conn} do
@@ -286,9 +282,13 @@ test "gets users statuses", %{conn: conn} do
{:ok, private_activity} =
CommonAPI.post(user_one, %{"status" => "private", "visibility" => "private"})
- resp = get(conn, "/api/v1/accounts/#{user_one.id}/statuses")
+ # TODO!!!
+ resp =
+ conn
+ |> get("/api/v1/accounts/#{user_one.id}/statuses")
+ |> json_response_and_validate_schema(200)
- assert [%{"id" => id}] = json_response(resp, 200)
+ assert [%{"id" => id}] = resp
assert id == to_string(activity.id)
resp =
@@ -296,8 +296,9 @@ test "gets users statuses", %{conn: conn} do
|> assign(:user, user_two)
|> assign(:token, insert(:oauth_token, user: user_two, scopes: ["read:statuses"]))
|> get("/api/v1/accounts/#{user_one.id}/statuses")
+ |> json_response_and_validate_schema(200)
- assert [%{"id" => id_one}, %{"id" => id_two}] = json_response(resp, 200)
+ assert [%{"id" => id_one}, %{"id" => id_two}] = resp
assert id_one == to_string(direct_activity.id)
assert id_two == to_string(activity.id)
@@ -306,8 +307,9 @@ test "gets users statuses", %{conn: conn} do
|> assign(:user, user_three)
|> assign(:token, insert(:oauth_token, user: user_three, scopes: ["read:statuses"]))
|> get("/api/v1/accounts/#{user_one.id}/statuses")
+ |> json_response_and_validate_schema(200)
- assert [%{"id" => id_one}, %{"id" => id_two}] = json_response(resp, 200)
+ assert [%{"id" => id_one}, %{"id" => id_two}] = resp
assert id_one == to_string(private_activity.id)
assert id_two == to_string(activity.id)
end
@@ -318,7 +320,7 @@ test "unimplemented pinned statuses feature", %{conn: conn} do
conn = get(conn, "/api/v1/accounts/#{user.id}/statuses?pinned=true")
- assert json_response(conn, 200) == []
+ assert json_response_and_validate_schema(conn, 200) == []
end
test "gets an users media", %{conn: conn} do
@@ -333,56 +335,48 @@ test "gets an users media", %{conn: conn} do
{:ok, %{id: media_id}} = ActivityPub.upload(file, actor: user.ap_id)
- {:ok, image_post} = CommonAPI.post(user, %{"status" => "cofe", "media_ids" => [media_id]})
+ {:ok, %{id: image_post_id}} =
+ CommonAPI.post(user, %{"status" => "cofe", "media_ids" => [media_id]})
- conn = get(conn, "/api/v1/accounts/#{user.id}/statuses", %{"only_media" => "true"})
+ conn = get(conn, "/api/v1/accounts/#{user.id}/statuses?only_media=true")
- assert [%{"id" => id}] = json_response(conn, 200)
- assert id == to_string(image_post.id)
+ assert [%{"id" => ^image_post_id}] = json_response_and_validate_schema(conn, 200)
- conn = get(build_conn(), "/api/v1/accounts/#{user.id}/statuses", %{"only_media" => "1"})
+ conn = get(build_conn(), "/api/v1/accounts/#{user.id}/statuses?only_media=1")
- assert [%{"id" => id}] = json_response(conn, 200)
- assert id == to_string(image_post.id)
+ assert [%{"id" => ^image_post_id}] = json_response_and_validate_schema(conn, 200)
end
test "gets a user's statuses without reblogs", %{user: user, conn: conn} do
- {:ok, post} = CommonAPI.post(user, %{"status" => "HI!!!"})
- {:ok, _, _} = CommonAPI.repeat(post.id, user)
+ {:ok, %{id: post_id}} = CommonAPI.post(user, %{"status" => "HI!!!"})
+ {:ok, _, _} = CommonAPI.repeat(post_id, user)
- conn = get(conn, "/api/v1/accounts/#{user.id}/statuses", %{"exclude_reblogs" => "true"})
+ conn = get(conn, "/api/v1/accounts/#{user.id}/statuses?exclude_reblogs=true")
+ assert [%{"id" => ^post_id}] = json_response_and_validate_schema(conn, 200)
- assert [%{"id" => id}] = json_response(conn, 200)
- assert id == to_string(post.id)
-
- conn = get(conn, "/api/v1/accounts/#{user.id}/statuses", %{"exclude_reblogs" => "1"})
-
- assert [%{"id" => id}] = json_response(conn, 200)
- assert id == to_string(post.id)
+ conn = get(conn, "/api/v1/accounts/#{user.id}/statuses?exclude_reblogs=1")
+ assert [%{"id" => ^post_id}] = json_response_and_validate_schema(conn, 200)
end
test "filters user's statuses by a hashtag", %{user: user, conn: conn} do
- {:ok, post} = CommonAPI.post(user, %{"status" => "#hashtag"})
+ {:ok, %{id: post_id}} = CommonAPI.post(user, %{"status" => "#hashtag"})
{:ok, _post} = CommonAPI.post(user, %{"status" => "hashtag"})
- conn = get(conn, "/api/v1/accounts/#{user.id}/statuses", %{"tagged" => "hashtag"})
-
- assert [%{"id" => id}] = json_response(conn, 200)
- assert id == to_string(post.id)
+ conn = get(conn, "/api/v1/accounts/#{user.id}/statuses?tagged=hashtag")
+ assert [%{"id" => ^post_id}] = json_response_and_validate_schema(conn, 200)
end
test "the user views their own timelines and excludes direct messages", %{
user: user,
conn: conn
} do
- {:ok, public_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "public"})
+ {:ok, %{id: public_activity_id}} =
+ CommonAPI.post(user, %{"status" => ".", "visibility" => "public"})
+
{:ok, _direct_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"})
- conn =
- get(conn, "/api/v1/accounts/#{user.id}/statuses", %{"exclude_visibilities" => ["direct"]})
-
- assert [%{"id" => id}] = json_response(conn, 200)
- assert id == to_string(public_activity.id)
+ conn = get(conn, "/api/v1/accounts/#{user.id}/statuses?exclude_visibilities[]=direct")
+ assert [%{"id" => ^public_activity_id}] = json_response_and_validate_schema(conn, 200)
end
end
@@ -402,27 +396,25 @@ defp local_and_remote_activities(%{local: local, remote: remote}) do
setup do: clear_config([:restrict_unauthenticated, :profiles, :remote], true)
test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
- res_conn = get(conn, "/api/v1/accounts/#{local.id}/statuses")
+ assert %{"error" => "Can't find user"} ==
+ conn
+ |> get("/api/v1/accounts/#{local.id}/statuses")
+ |> json_response_and_validate_schema(:not_found)
- assert json_response(res_conn, :not_found) == %{
- "error" => "Can't find user"
- }
-
- res_conn = get(conn, "/api/v1/accounts/#{remote.id}/statuses")
-
- assert json_response(res_conn, :not_found) == %{
- "error" => "Can't find user"
- }
+ assert %{"error" => "Can't find user"} ==
+ conn
+ |> get("/api/v1/accounts/#{remote.id}/statuses")
+ |> json_response_and_validate_schema(:not_found)
end
test "if user is authenticated", %{local: local, remote: remote} do
%{conn: conn} = oauth_access(["read"])
res_conn = get(conn, "/api/v1/accounts/#{local.id}/statuses")
- assert length(json_response(res_conn, 200)) == 1
+ assert length(json_response_and_validate_schema(res_conn, 200)) == 1
res_conn = get(conn, "/api/v1/accounts/#{remote.id}/statuses")
- assert length(json_response(res_conn, 200)) == 1
+ assert length(json_response_and_validate_schema(res_conn, 200)) == 1
end
end
@@ -433,24 +425,23 @@ test "if user is authenticated", %{local: local, remote: remote} do
setup do: clear_config([:restrict_unauthenticated, :profiles, :local], true)
test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
- res_conn = get(conn, "/api/v1/accounts/#{local.id}/statuses")
-
- assert json_response(res_conn, :not_found) == %{
- "error" => "Can't find user"
- }
+ assert %{"error" => "Can't find user"} ==
+ conn
+ |> get("/api/v1/accounts/#{local.id}/statuses")
+ |> json_response_and_validate_schema(:not_found)
res_conn = get(conn, "/api/v1/accounts/#{remote.id}/statuses")
- assert length(json_response(res_conn, 200)) == 1
+ assert length(json_response_and_validate_schema(res_conn, 200)) == 1
end
test "if user is authenticated", %{local: local, remote: remote} do
%{conn: conn} = oauth_access(["read"])
res_conn = get(conn, "/api/v1/accounts/#{local.id}/statuses")
- assert length(json_response(res_conn, 200)) == 1
+ assert length(json_response_and_validate_schema(res_conn, 200)) == 1
res_conn = get(conn, "/api/v1/accounts/#{remote.id}/statuses")
- assert length(json_response(res_conn, 200)) == 1
+ assert length(json_response_and_validate_schema(res_conn, 200)) == 1
end
end
@@ -462,23 +453,22 @@ test "if user is authenticated", %{local: local, remote: remote} do
test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
res_conn = get(conn, "/api/v1/accounts/#{local.id}/statuses")
- assert length(json_response(res_conn, 200)) == 1
+ assert length(json_response_and_validate_schema(res_conn, 200)) == 1
- res_conn = get(conn, "/api/v1/accounts/#{remote.id}/statuses")
-
- assert json_response(res_conn, :not_found) == %{
- "error" => "Can't find user"
- }
+ assert %{"error" => "Can't find user"} ==
+ conn
+ |> get("/api/v1/accounts/#{remote.id}/statuses")
+ |> json_response_and_validate_schema(:not_found)
end
test "if user is authenticated", %{local: local, remote: remote} do
%{conn: conn} = oauth_access(["read"])
res_conn = get(conn, "/api/v1/accounts/#{local.id}/statuses")
- assert length(json_response(res_conn, 200)) == 1
+ assert length(json_response_and_validate_schema(res_conn, 200)) == 1
res_conn = get(conn, "/api/v1/accounts/#{remote.id}/statuses")
- assert length(json_response(res_conn, 200)) == 1
+ assert length(json_response_and_validate_schema(res_conn, 200)) == 1
end
end
@@ -487,12 +477,11 @@ test "if user is authenticated", %{local: local, remote: remote} do
test "getting followers", %{user: user, conn: conn} do
other_user = insert(:user)
- {:ok, user} = User.follow(user, other_user)
+ {:ok, %{id: user_id}} = User.follow(user, other_user)
conn = get(conn, "/api/v1/accounts/#{other_user.id}/followers")
- assert [%{"id" => id}] = json_response(conn, 200)
- assert id == to_string(user.id)
+ assert [%{"id" => ^user_id}] = json_response_and_validate_schema(conn, 200)
end
test "getting followers, hide_followers", %{user: user, conn: conn} do
@@ -501,7 +490,7 @@ test "getting followers, hide_followers", %{user: user, conn: conn} do
conn = get(conn, "/api/v1/accounts/#{other_user.id}/followers")
- assert [] == json_response(conn, 200)
+ assert [] == json_response_and_validate_schema(conn, 200)
end
test "getting followers, hide_followers, same user requesting" do
@@ -515,37 +504,31 @@ test "getting followers, hide_followers, same user requesting" do
|> assign(:token, insert(:oauth_token, user: other_user, scopes: ["read:accounts"]))
|> get("/api/v1/accounts/#{other_user.id}/followers")
- refute [] == json_response(conn, 200)
+ refute [] == json_response_and_validate_schema(conn, 200)
end
test "getting followers, pagination", %{user: user, conn: conn} do
- follower1 = insert(:user)
- follower2 = insert(:user)
- follower3 = insert(:user)
- {:ok, _} = User.follow(follower1, user)
- {:ok, _} = User.follow(follower2, user)
- {:ok, _} = User.follow(follower3, user)
+ {:ok, %User{id: follower1_id}} = :user |> insert() |> User.follow(user)
+ {:ok, %User{id: follower2_id}} = :user |> insert() |> User.follow(user)
+ {:ok, %User{id: follower3_id}} = :user |> insert() |> User.follow(user)
- res_conn = get(conn, "/api/v1/accounts/#{user.id}/followers?since_id=#{follower1.id}")
+ assert [%{"id" => ^follower3_id}, %{"id" => ^follower2_id}] =
+ conn
+ |> get("/api/v1/accounts/#{user.id}/followers?since_id=#{follower1_id}")
+ |> json_response_and_validate_schema(200)
- assert [%{"id" => id3}, %{"id" => id2}] = json_response(res_conn, 200)
- assert id3 == follower3.id
- assert id2 == follower2.id
+ assert [%{"id" => ^follower2_id}, %{"id" => ^follower1_id}] =
+ conn
+ |> get("/api/v1/accounts/#{user.id}/followers?max_id=#{follower3_id}")
+ |> json_response_and_validate_schema(200)
- res_conn = get(conn, "/api/v1/accounts/#{user.id}/followers?max_id=#{follower3.id}")
+ res_conn = get(conn, "/api/v1/accounts/#{user.id}/followers?limit=1&max_id=#{follower3_id}")
- assert [%{"id" => id2}, %{"id" => id1}] = json_response(res_conn, 200)
- assert id2 == follower2.id
- assert id1 == follower1.id
-
- res_conn = get(conn, "/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 [%{"id" => ^follower2_id}] = json_response_and_validate_schema(res_conn, 200)
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}/
+ assert link_header =~ ~r/min_id=#{follower2_id}/
+ assert link_header =~ ~r/max_id=#{follower2_id}/
end
end
@@ -558,7 +541,7 @@ test "getting following", %{user: user, conn: conn} do
conn = get(conn, "/api/v1/accounts/#{user.id}/following")
- assert [%{"id" => id}] = json_response(conn, 200)
+ assert [%{"id" => id}] = json_response_and_validate_schema(conn, 200)
assert id == to_string(other_user.id)
end
@@ -573,7 +556,7 @@ test "getting following, hide_follows, other user requesting" do
|> assign(:token, insert(:oauth_token, user: other_user, scopes: ["read:accounts"]))
|> get("/api/v1/accounts/#{user.id}/following")
- assert [] == json_response(conn, 200)
+ assert [] == json_response_and_validate_schema(conn, 200)
end
test "getting following, hide_follows, same user requesting" do
@@ -587,7 +570,7 @@ test "getting following, hide_follows, same user requesting" do
|> assign(:token, insert(:oauth_token, user: user, scopes: ["read:accounts"]))
|> get("/api/v1/accounts/#{user.id}/following")
- refute [] == json_response(conn, 200)
+ refute [] == json_response_and_validate_schema(conn, 200)
end
test "getting following, pagination", %{user: user, conn: conn} do
@@ -600,20 +583,20 @@ test "getting following, pagination", %{user: user, conn: conn} do
res_conn = get(conn, "/api/v1/accounts/#{user.id}/following?since_id=#{following1.id}")
- assert [%{"id" => id3}, %{"id" => id2}] = json_response(res_conn, 200)
+ assert [%{"id" => id3}, %{"id" => id2}] = json_response_and_validate_schema(res_conn, 200)
assert id3 == following3.id
assert id2 == following2.id
res_conn = get(conn, "/api/v1/accounts/#{user.id}/following?max_id=#{following3.id}")
- assert [%{"id" => id2}, %{"id" => id1}] = json_response(res_conn, 200)
+ assert [%{"id" => id2}, %{"id" => id1}] = json_response_and_validate_schema(res_conn, 200)
assert id2 == following2.id
assert id1 == following1.id
res_conn =
get(conn, "/api/v1/accounts/#{user.id}/following?limit=1&max_id=#{following3.id}")
- assert [%{"id" => id2}] = json_response(res_conn, 200)
+ assert [%{"id" => id2}] = json_response_and_validate_schema(res_conn, 200)
assert id2 == following2.id
assert [link_header] = get_resp_header(res_conn, "link")
@@ -626,30 +609,37 @@ test "getting following, pagination", %{user: user, conn: conn} do
setup do: oauth_access(["follow"])
test "following / unfollowing a user", %{conn: conn} do
- other_user = insert(:user)
+ %{id: other_user_id, nickname: other_user_nickname} = insert(:user)
- ret_conn = post(conn, "/api/v1/accounts/#{other_user.id}/follow")
+ assert %{"id" => _id, "following" => true} =
+ conn
+ |> post("/api/v1/accounts/#{other_user_id}/follow")
+ |> json_response_and_validate_schema(200)
- assert %{"id" => _id, "following" => true} = json_response(ret_conn, 200)
+ assert %{"id" => _id, "following" => false} =
+ conn
+ |> post("/api/v1/accounts/#{other_user_id}/unfollow")
+ |> json_response_and_validate_schema(200)
- ret_conn = post(conn, "/api/v1/accounts/#{other_user.id}/unfollow")
-
- assert %{"id" => _id, "following" => false} = json_response(ret_conn, 200)
-
- conn = post(conn, "/api/v1/follows", %{"uri" => other_user.nickname})
-
- assert %{"id" => id} = json_response(conn, 200)
- assert id == to_string(other_user.id)
+ assert %{"id" => ^other_user_id} =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/follows", %{"uri" => other_user_nickname})
+ |> json_response_and_validate_schema(200)
end
test "cancelling follow request", %{conn: conn} do
%{id: other_user_id} = insert(:user, %{locked: true})
assert %{"id" => ^other_user_id, "following" => false, "requested" => true} =
- conn |> post("/api/v1/accounts/#{other_user_id}/follow") |> json_response(:ok)
+ conn
+ |> post("/api/v1/accounts/#{other_user_id}/follow")
+ |> json_response_and_validate_schema(:ok)
assert %{"id" => ^other_user_id, "following" => false, "requested" => false} =
- conn |> post("/api/v1/accounts/#{other_user_id}/unfollow") |> json_response(:ok)
+ conn
+ |> post("/api/v1/accounts/#{other_user_id}/unfollow")
+ |> json_response_and_validate_schema(:ok)
end
test "following without reblogs" do
@@ -659,51 +649,65 @@ test "following without reblogs" do
ret_conn = post(conn, "/api/v1/accounts/#{followed.id}/follow?reblogs=false")
- assert %{"showing_reblogs" => false} = json_response(ret_conn, 200)
+ assert %{"showing_reblogs" => false} = json_response_and_validate_schema(ret_conn, 200)
{:ok, activity} = CommonAPI.post(other_user, %{"status" => "hey"})
- {:ok, reblog, _} = CommonAPI.repeat(activity.id, followed)
+ {:ok, %{id: reblog_id}, _} = CommonAPI.repeat(activity.id, followed)
- ret_conn = get(conn, "/api/v1/timelines/home")
+ assert [] ==
+ conn
+ |> get("/api/v1/timelines/home")
+ |> json_response(200)
- assert [] == json_response(ret_conn, 200)
+ assert %{"showing_reblogs" => true} =
+ conn
+ |> post("/api/v1/accounts/#{followed.id}/follow?reblogs=true")
+ |> json_response_and_validate_schema(200)
- ret_conn = post(conn, "/api/v1/accounts/#{followed.id}/follow?reblogs=true")
-
- assert %{"showing_reblogs" => true} = json_response(ret_conn, 200)
-
- conn = get(conn, "/api/v1/timelines/home")
-
- expected_activity_id = reblog.id
- assert [%{"id" => ^expected_activity_id}] = json_response(conn, 200)
+ assert [%{"id" => ^reblog_id}] =
+ conn
+ |> get("/api/v1/timelines/home")
+ |> json_response(200)
end
test "following / unfollowing errors", %{user: user, conn: conn} do
# self follow
conn_res = post(conn, "/api/v1/accounts/#{user.id}/follow")
- assert %{"error" => "Record not found"} = json_response(conn_res, 404)
+
+ assert %{"error" => "Can not follow yourself"} =
+ json_response_and_validate_schema(conn_res, 400)
# 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)
+
+ assert %{"error" => "Can not unfollow yourself"} =
+ json_response_and_validate_schema(conn_res, 400)
# 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)
+
+ assert %{"error" => "Can not follow yourself"} =
+ conn
+ |> put_req_header("content-type", "multipart/form-data")
+ |> post("/api/v1/follows", %{"uri" => user.nickname})
+ |> json_response_and_validate_schema(400)
# follow non existing user
conn_res = post(conn, "/api/v1/accounts/doesntexist/follow")
- assert %{"error" => "Record not found"} = json_response(conn_res, 404)
+ assert %{"error" => "Record not found"} = json_response_and_validate_schema(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)
+ conn_res =
+ conn
+ |> put_req_header("content-type", "multipart/form-data")
+ |> post("/api/v1/follows", %{"uri" => "doesntexist"})
+
+ assert %{"error" => "Record not found"} = json_response_and_validate_schema(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)
+ assert %{"error" => "Record not found"} = json_response_and_validate_schema(conn_res, 404)
end
end
@@ -713,32 +717,33 @@ test "following / unfollowing errors", %{user: user, conn: conn} do
test "with notifications", %{conn: conn} do
other_user = insert(:user)
- ret_conn = post(conn, "/api/v1/accounts/#{other_user.id}/mute")
-
- response = json_response(ret_conn, 200)
-
- assert %{"id" => _id, "muting" => true, "muting_notifications" => true} = response
+ assert %{"id" => _id, "muting" => true, "muting_notifications" => true} =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/accounts/#{other_user.id}/mute")
+ |> json_response_and_validate_schema(200)
conn = post(conn, "/api/v1/accounts/#{other_user.id}/unmute")
- response = json_response(conn, 200)
- assert %{"id" => _id, "muting" => false, "muting_notifications" => false} = response
+ assert %{"id" => _id, "muting" => false, "muting_notifications" => false} =
+ json_response_and_validate_schema(conn, 200)
end
test "without notifications", %{conn: conn} do
other_user = insert(:user)
ret_conn =
- post(conn, "/api/v1/accounts/#{other_user.id}/mute", %{"notifications" => "false"})
+ conn
+ |> put_req_header("content-type", "multipart/form-data")
+ |> post("/api/v1/accounts/#{other_user.id}/mute", %{"notifications" => "false"})
- response = json_response(ret_conn, 200)
-
- assert %{"id" => _id, "muting" => true, "muting_notifications" => false} = response
+ assert %{"id" => _id, "muting" => true, "muting_notifications" => false} =
+ json_response_and_validate_schema(ret_conn, 200)
conn = post(conn, "/api/v1/accounts/#{other_user.id}/unmute")
- response = json_response(conn, 200)
- assert %{"id" => _id, "muting" => false, "muting_notifications" => false} = response
+ assert %{"id" => _id, "muting" => false, "muting_notifications" => false} =
+ json_response_and_validate_schema(conn, 200)
end
end
@@ -751,17 +756,13 @@ test "without notifications", %{conn: conn} do
[conn: conn, user: user, activity: activity]
end
- test "returns pinned statuses", %{conn: conn, user: user, activity: activity} do
- {:ok, _} = CommonAPI.pin(activity.id, user)
+ test "returns pinned statuses", %{conn: conn, user: user, activity: %{id: activity_id}} do
+ {:ok, _} = CommonAPI.pin(activity_id, user)
- result =
- conn
- |> 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
+ assert [%{"id" => ^activity_id, "pinned" => true}] =
+ conn
+ |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true")
+ |> json_response_and_validate_schema(200)
end
end
@@ -771,11 +772,11 @@ test "blocking / unblocking a user" do
ret_conn = post(conn, "/api/v1/accounts/#{other_user.id}/block")
- assert %{"id" => _id, "blocking" => true} = json_response(ret_conn, 200)
+ assert %{"id" => _id, "blocking" => true} = json_response_and_validate_schema(ret_conn, 200)
conn = post(conn, "/api/v1/accounts/#{other_user.id}/unblock")
- assert %{"id" => _id, "blocking" => false} = json_response(conn, 200)
+ assert %{"id" => _id, "blocking" => false} = json_response_and_validate_schema(conn, 200)
end
describe "create account by app" do
@@ -802,15 +803,15 @@ test "Account registration via Application", %{conn: conn} do
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)
+ assert %{
+ "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_and_validate_schema(conn, 200)
conn =
post(conn, "/oauth/token", %{
@@ -830,6 +831,7 @@ test "Account registration via Application", %{conn: conn} do
conn =
build_conn()
+ |> put_req_header("content-type", "multipart/form-data")
|> put_req_header("authorization", "Bearer " <> token)
|> post("/api/v1/accounts", %{
username: "lain",
@@ -844,7 +846,7 @@ test "Account registration via Application", %{conn: conn} do
"created_at" => _created_at,
"scope" => _scope,
"token_type" => "Bearer"
- } = json_response(conn, 200)
+ } = json_response_and_validate_schema(conn, 200)
token_from_db = Repo.get_by(Token, token: token)
assert token_from_db
@@ -858,12 +860,15 @@ test "returns error when user already registred", %{conn: conn, valid_params: va
_user = insert(:user, email: "lain@example.org")
app_token = insert(:oauth_token, user: nil)
- conn =
+ res =
conn
|> put_req_header("authorization", "Bearer " <> app_token.token)
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/v1/accounts", valid_params)
- res = post(conn, "/api/v1/accounts", valid_params)
- assert json_response(res, 400) == %{"error" => "{\"email\":[\"has already been taken\"]}"}
+ assert json_response_and_validate_schema(res, 400) == %{
+ "error" => "{\"email\":[\"has already been taken\"]}"
+ }
end
test "returns bad_request if missing required params", %{
@@ -872,10 +877,13 @@ test "returns bad_request if missing required params", %{
} do
app_token = insert(:oauth_token, user: nil)
- conn = put_req_header(conn, "authorization", "Bearer " <> app_token.token)
+ conn =
+ conn
+ |> put_req_header("authorization", "Bearer " <> app_token.token)
+ |> put_req_header("content-type", "application/json")
res = post(conn, "/api/v1/accounts", valid_params)
- assert json_response(res, 200)
+ assert json_response_and_validate_schema(res, 200)
[{127, 0, 0, 1}, {127, 0, 0, 2}, {127, 0, 0, 3}, {127, 0, 0, 4}]
|> Stream.zip(Map.delete(valid_params, :email))
@@ -884,9 +892,18 @@ test "returns bad_request if missing required params", %{
conn
|> Map.put(:remote_ip, ip)
|> post("/api/v1/accounts", Map.delete(valid_params, attr))
- |> json_response(400)
+ |> json_response_and_validate_schema(400)
- assert res == %{"error" => "Missing parameters"}
+ assert res == %{
+ "error" => "Missing field: #{attr}.",
+ "errors" => [
+ %{
+ "message" => "Missing field: #{attr}",
+ "source" => %{"pointer" => "/#{attr}"},
+ "title" => "Invalid value"
+ }
+ ]
+ }
end)
end
@@ -897,21 +914,27 @@ test "returns bad_request if missing email params when :account_activation_requi
Pleroma.Config.put([:instance, :account_activation_required], true)
app_token = insert(:oauth_token, user: nil)
- conn = put_req_header(conn, "authorization", "Bearer " <> app_token.token)
+
+ conn =
+ conn
+ |> put_req_header("authorization", "Bearer " <> app_token.token)
+ |> put_req_header("content-type", "application/json")
res =
conn
|> Map.put(:remote_ip, {127, 0, 0, 5})
|> post("/api/v1/accounts", Map.delete(valid_params, :email))
- assert json_response(res, 400) == %{"error" => "Missing parameters"}
+ assert json_response_and_validate_schema(res, 400) == %{"error" => "Missing parameters"}
res =
conn
|> Map.put(:remote_ip, {127, 0, 0, 6})
|> post("/api/v1/accounts", Map.put(valid_params, :email, ""))
- assert json_response(res, 400) == %{"error" => "{\"email\":[\"can't be blank\"]}"}
+ assert json_response_and_validate_schema(res, 400) == %{
+ "error" => "{\"email\":[\"can't be blank\"]}"
+ }
end
test "allow registration without an email", %{conn: conn, valid_params: valid_params} do
@@ -920,10 +943,11 @@ test "allow registration without an email", %{conn: conn, valid_params: valid_pa
res =
conn
+ |> put_req_header("content-type", "application/json")
|> Map.put(:remote_ip, {127, 0, 0, 7})
|> post("/api/v1/accounts", Map.delete(valid_params, :email))
- assert json_response(res, 200)
+ assert json_response_and_validate_schema(res, 200)
end
test "allow registration with an empty email", %{conn: conn, valid_params: valid_params} do
@@ -932,17 +956,89 @@ test "allow registration with an empty email", %{conn: conn, valid_params: valid
res =
conn
+ |> put_req_header("content-type", "application/json")
|> Map.put(:remote_ip, {127, 0, 0, 8})
|> post("/api/v1/accounts", Map.put(valid_params, :email, ""))
- assert json_response(res, 200)
+ assert json_response_and_validate_schema(res, 200)
end
test "returns forbidden if token is invalid", %{conn: conn, valid_params: valid_params} do
- conn = put_req_header(conn, "authorization", "Bearer " <> "invalid-token")
+ res =
+ conn
+ |> put_req_header("authorization", "Bearer " <> "invalid-token")
+ |> put_req_header("content-type", "multipart/form-data")
+ |> post("/api/v1/accounts", valid_params)
- res = post(conn, "/api/v1/accounts", valid_params)
- assert json_response(res, 403) == %{"error" => "Invalid credentials"}
+ assert json_response_and_validate_schema(res, 403) == %{"error" => "Invalid credentials"}
+ end
+
+ test "registration from trusted app" do
+ clear_config([Pleroma.Captcha, :enabled], true)
+ app = insert(:oauth_app, trusted: true, scopes: ["read", "write", "follow", "push"])
+
+ conn =
+ build_conn()
+ |> post("/oauth/token", %{
+ "grant_type" => "client_credentials",
+ "client_id" => app.client_id,
+ "client_secret" => app.client_secret
+ })
+
+ assert %{"access_token" => token, "token_type" => "Bearer"} = json_response(conn, 200)
+
+ response =
+ build_conn()
+ |> Plug.Conn.put_req_header("authorization", "Bearer " <> token)
+ |> put_req_header("content-type", "multipart/form-data")
+ |> post("/api/v1/accounts", %{
+ nickname: "nickanme",
+ agreement: true,
+ email: "email@example.com",
+ fullname: "Lain",
+ username: "Lain",
+ password: "some_password",
+ confirm: "some_password"
+ })
+ |> json_response_and_validate_schema(200)
+
+ assert %{
+ "access_token" => access_token,
+ "created_at" => _,
+ "scope" => ["read", "write", "follow", "push"],
+ "token_type" => "Bearer"
+ } = response
+
+ response =
+ build_conn()
+ |> Plug.Conn.put_req_header("authorization", "Bearer " <> access_token)
+ |> get("/api/v1/accounts/verify_credentials")
+ |> json_response_and_validate_schema(200)
+
+ assert %{
+ "acct" => "Lain",
+ "bot" => false,
+ "display_name" => "Lain",
+ "follow_requests_count" => 0,
+ "followers_count" => 0,
+ "following_count" => 0,
+ "locked" => false,
+ "note" => "",
+ "source" => %{
+ "fields" => [],
+ "note" => "",
+ "pleroma" => %{
+ "actor_type" => "Person",
+ "discoverable" => false,
+ "no_rich_text" => false,
+ "show_role" => true
+ },
+ "privacy" => "public",
+ "sensitive" => false
+ },
+ "statuses_count" => 0,
+ "username" => "Lain"
+ } = response
end
end
@@ -956,10 +1052,12 @@ test "respects rate limit setting", %{conn: conn} do
conn
|> put_req_header("authorization", "Bearer " <> app_token.token)
|> Map.put(:remote_ip, {15, 15, 15, 15})
+ |> put_req_header("content-type", "multipart/form-data")
for i <- 1..2 do
conn =
- post(conn, "/api/v1/accounts", %{
+ conn
+ |> post("/api/v1/accounts", %{
username: "#{i}lain",
email: "#{i}lain@example.org",
password: "PlzDontHackLain",
@@ -971,7 +1069,7 @@ test "respects rate limit setting", %{conn: conn} do
"created_at" => _created_at,
"scope" => _scope,
"token_type" => "Bearer"
- } = json_response(conn, 200)
+ } = json_response_and_validate_schema(conn, 200)
token_from_db = Repo.get_by(Token, token: token)
assert token_from_db
@@ -989,7 +1087,9 @@ test "respects rate limit setting", %{conn: conn} do
agreement: true
})
- assert json_response(conn, :too_many_requests) == %{"error" => "Throttled"}
+ assert json_response_and_validate_schema(conn, :too_many_requests) == %{
+ "error" => "Throttled"
+ }
end
end
@@ -997,15 +1097,13 @@ test "respects rate limit setting", %{conn: conn} do
test "returns lists to which the account belongs" do
%{user: user, conn: conn} = oauth_access(["read:lists"])
other_user = insert(:user)
- assert {:ok, %Pleroma.List{} = list} = Pleroma.List.create("Test List", user)
+ assert {:ok, %Pleroma.List{id: list_id} = list} = Pleroma.List.create("Test List", user)
{:ok, %{following: _following}} = Pleroma.List.follow(list, other_user)
- res =
- conn
- |> get("/api/v1/accounts/#{other_user.id}/lists")
- |> json_response(200)
-
- assert res == [%{"id" => to_string(list.id), "title" => "Test List"}]
+ assert [%{"id" => list_id, "title" => "Test List"}] =
+ conn
+ |> get("/api/v1/accounts/#{other_user.id}/lists")
+ |> json_response_and_validate_schema(200)
end
end
@@ -1014,7 +1112,7 @@ test "verify_credentials" do
%{user: user, conn: conn} = oauth_access(["read:accounts"])
conn = get(conn, "/api/v1/accounts/verify_credentials")
- response = json_response(conn, 200)
+ response = json_response_and_validate_schema(conn, 200)
assert %{"id" => id, "source" => %{"privacy" => "public"}} = response
assert response["pleroma"]["chat_token"]
@@ -1027,7 +1125,9 @@ test "verify_credentials default scope unlisted" do
conn = get(conn, "/api/v1/accounts/verify_credentials")
- assert %{"id" => id, "source" => %{"privacy" => "unlisted"}} = json_response(conn, 200)
+ assert %{"id" => id, "source" => %{"privacy" => "unlisted"}} =
+ json_response_and_validate_schema(conn, 200)
+
assert id == to_string(user.id)
end
@@ -1037,7 +1137,9 @@ test "locked accounts" do
conn = get(conn, "/api/v1/accounts/verify_credentials")
- assert %{"id" => id, "source" => %{"privacy" => "private"}} = json_response(conn, 200)
+ assert %{"id" => id, "source" => %{"privacy" => "private"}} =
+ json_response_and_validate_schema(conn, 200)
+
assert id == to_string(user.id)
end
end
@@ -1046,20 +1148,24 @@ test "locked accounts" do
setup do: oauth_access(["read:follows"])
test "returns the relationships for the current user", %{user: user, conn: conn} do
- other_user = insert(:user)
+ %{id: other_user_id} = other_user = insert(:user)
{:ok, _user} = User.follow(user, other_user)
- conn = get(conn, "/api/v1/accounts/relationships", %{"id" => [other_user.id]})
+ assert [%{"id" => ^other_user_id}] =
+ conn
+ |> get("/api/v1/accounts/relationships?id=#{other_user.id}")
+ |> json_response_and_validate_schema(200)
- assert [relationship] = json_response(conn, 200)
-
- assert to_string(other_user.id) == relationship["id"]
+ assert [%{"id" => ^other_user_id}] =
+ conn
+ |> get("/api/v1/accounts/relationships?id[]=#{other_user.id}")
+ |> json_response_and_validate_schema(200)
end
test "returns an empty list on a bad request", %{conn: conn} do
conn = get(conn, "/api/v1/accounts/relationships", %{})
- assert [] = json_response(conn, 200)
+ assert [] = json_response_and_validate_schema(conn, 200)
end
end
@@ -1072,7 +1178,7 @@ test "getting a list of mutes" do
conn = get(conn, "/api/v1/mutes")
other_user_id = to_string(other_user.id)
- assert [%{"id" => ^other_user_id}] = json_response(conn, 200)
+ assert [%{"id" => ^other_user_id}] = json_response_and_validate_schema(conn, 200)
end
test "getting a list of blocks" do
@@ -1087,6 +1193,6 @@ test "getting a list of blocks" do
|> get("/api/v1/blocks")
other_user_id = to_string(other_user.id)
- assert [%{"id" => ^other_user_id}] = json_response(conn, 200)
+ assert [%{"id" => ^other_user_id}] = json_response_and_validate_schema(conn, 200)
end
end
diff --git a/test/web/mastodon_api/controllers/app_controller_test.exs b/test/web/mastodon_api/controllers/app_controller_test.exs
index e7b11d14e..a0b8b126c 100644
--- a/test/web/mastodon_api/controllers/app_controller_test.exs
+++ b/test/web/mastodon_api/controllers/app_controller_test.exs
@@ -27,7 +27,7 @@ test "apps/verify_credentials", %{conn: conn} do
"vapid_key" => Push.vapid_config() |> Keyword.get(:public_key)
}
- assert expected == json_response(conn, 200)
+ assert expected == json_response_and_validate_schema(conn, 200)
end
test "creates an oauth app", %{conn: conn} do
@@ -55,6 +55,6 @@ test "creates an oauth app", %{conn: conn} do
"vapid_key" => Push.vapid_config() |> Keyword.get(:public_key)
}
- assert expected == json_response(conn, 200)
+ assert expected == json_response_and_validate_schema(conn, 200)
end
end
diff --git a/test/web/mastodon_api/controllers/custom_emoji_controller_test.exs b/test/web/mastodon_api/controllers/custom_emoji_controller_test.exs
index 6567a0667..ab0027f90 100644
--- a/test/web/mastodon_api/controllers/custom_emoji_controller_test.exs
+++ b/test/web/mastodon_api/controllers/custom_emoji_controller_test.exs
@@ -6,11 +6,12 @@ defmodule Pleroma.Web.MastodonAPI.CustomEmojiControllerTest do
use Pleroma.Web.ConnCase, async: true
test "with tags", %{conn: conn} do
- [emoji | _body] =
- conn
- |> get("/api/v1/custom_emojis")
- |> json_response(200)
+ assert resp =
+ conn
+ |> get("/api/v1/custom_emojis")
+ |> json_response_and_validate_schema(200)
+ assert [emoji | _body] = resp
assert Map.has_key?(emoji, "shortcode")
assert Map.has_key?(emoji, "static_url")
assert Map.has_key?(emoji, "tags")
diff --git a/test/web/mastodon_api/controllers/domain_block_controller_test.exs b/test/web/mastodon_api/controllers/domain_block_controller_test.exs
index d66190c90..01a24afcf 100644
--- a/test/web/mastodon_api/controllers/domain_block_controller_test.exs
+++ b/test/web/mastodon_api/controllers/domain_block_controller_test.exs
@@ -6,11 +6,8 @@ defmodule Pleroma.Web.MastodonAPI.DomainBlockControllerTest do
use Pleroma.Web.ConnCase
alias Pleroma.User
- alias Pleroma.Web.ApiSpec
- alias Pleroma.Web.ApiSpec.Schemas.DomainBlocksResponse
import Pleroma.Factory
- import OpenApiSpex.TestAssertions
test "blocking / unblocking a domain" do
%{user: user, conn: conn} = oauth_access(["write:blocks"])
@@ -21,7 +18,7 @@ test "blocking / unblocking a domain" do
|> put_req_header("content-type", "application/json")
|> post("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
- assert %{} = json_response(ret_conn, 200)
+ assert %{} == json_response_and_validate_schema(ret_conn, 200)
user = User.get_cached_by_ap_id(user.ap_id)
assert User.blocks?(user, other_user)
@@ -30,7 +27,7 @@ test "blocking / unblocking a domain" do
|> put_req_header("content-type", "application/json")
|> delete("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
- assert %{} = json_response(ret_conn, 200)
+ assert %{} == json_response_and_validate_schema(ret_conn, 200)
user = User.get_cached_by_ap_id(user.ap_id)
refute User.blocks?(user, other_user)
end
@@ -41,21 +38,10 @@ test "getting a list of domain blocks" do
{:ok, user} = User.block_domain(user, "bad.site")
{:ok, user} = User.block_domain(user, "even.worse.site")
- conn =
- conn
- |> assign(:user, user)
- |> get("/api/v1/domain_blocks")
-
- domain_blocks = json_response(conn, 200)
-
- assert "bad.site" in domain_blocks
- assert "even.worse.site" in domain_blocks
- assert_schema(domain_blocks, "DomainBlocksResponse", ApiSpec.spec())
- end
-
- test "DomainBlocksResponse example matches schema" do
- api_spec = ApiSpec.spec()
- schema = DomainBlocksResponse.schema()
- assert_schema(schema.example, "DomainBlocksResponse", api_spec)
+ assert ["even.worse.site", "bad.site"] ==
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/domain_blocks")
+ |> json_response_and_validate_schema(200)
end
end
diff --git a/test/web/mastodon_api/controllers/status_controller_test.exs b/test/web/mastodon_api/controllers/status_controller_test.exs
index 162f7b1b2..85068edd0 100644
--- a/test/web/mastodon_api/controllers/status_controller_test.exs
+++ b/test/web/mastodon_api/controllers/status_controller_test.exs
@@ -302,6 +302,17 @@ test "creates a scheduled activity", %{conn: conn} do
assert [] == Repo.all(Activity)
end
+ test "ignores nil values", %{conn: conn} do
+ conn =
+ post(conn, "/api/v1/statuses", %{
+ "status" => "not scheduled",
+ "scheduled_at" => nil
+ })
+
+ assert result = json_response(conn, 200)
+ assert Activity.get_by_id(result["id"])
+ end
+
test "creates a scheduled activity with a media attachment", %{user: user, conn: conn} do
scheduled_at = NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond)
diff --git a/test/web/mastodon_api/controllers/subscription_controller_test.exs b/test/web/mastodon_api/controllers/subscription_controller_test.exs
index 987158a74..5682498c0 100644
--- a/test/web/mastodon_api/controllers/subscription_controller_test.exs
+++ b/test/web/mastodon_api/controllers/subscription_controller_test.exs
@@ -35,7 +35,10 @@ defmacro assert_error_when_disable_push(do: yield) do
quote do
vapid_details = Application.get_env(:web_push_encryption, :vapid_details, [])
Application.put_env(:web_push_encryption, :vapid_details, [])
- assert "Something went wrong" == unquote(yield)
+
+ assert %{"error" => "Web push subscription is disabled on this Pleroma instance"} ==
+ unquote(yield)
+
Application.put_env(:web_push_encryption, :vapid_details, vapid_details)
end
end
@@ -45,7 +48,7 @@ test "returns error when push disabled ", %{conn: conn} do
assert_error_when_disable_push do
conn
|> post("/api/v1/push/subscription", %{})
- |> json_response(500)
+ |> json_response(403)
end
end
@@ -74,7 +77,7 @@ test "returns error when push disabled ", %{conn: conn} do
assert_error_when_disable_push do
conn
|> get("/api/v1/push/subscription", %{})
- |> json_response(500)
+ |> json_response(403)
end
end
@@ -127,7 +130,7 @@ test "returns error when push disabled ", %{conn: conn} do
assert_error_when_disable_push do
conn
|> put("/api/v1/push/subscription", %{data: %{"alerts" => %{"mention" => false}}})
- |> json_response(500)
+ |> json_response(403)
end
end
@@ -155,7 +158,7 @@ test "returns error when push disabled ", %{conn: conn} do
assert_error_when_disable_push do
conn
|> delete("/api/v1/push/subscription", %{})
- |> json_response(500)
+ |> json_response(403)
end
end
diff --git a/test/web/mastodon_api/controllers/suggestion_controller_test.exs b/test/web/mastodon_api/controllers/suggestion_controller_test.exs
index c697a39f8..8d0e70db8 100644
--- a/test/web/mastodon_api/controllers/suggestion_controller_test.exs
+++ b/test/web/mastodon_api/controllers/suggestion_controller_test.exs
@@ -7,34 +7,8 @@ defmodule Pleroma.Web.MastodonAPI.SuggestionControllerTest do
alias Pleroma.Config
- import Pleroma.Factory
- import Tesla.Mock
-
setup do: oauth_access(["read"])
- setup %{user: user} do
- other_user = insert(:user)
- host = Config.get([Pleroma.Web.Endpoint, :url, :host])
- url500 = "http://test500?#{host}{user.nickname}"
- url200 = "http://test200?#{host}{user.nickname}"
-
- mock(fn
- %{method: :get, url: ^url500} ->
- %Tesla.Env{status: 500, body: "bad request"}
-
- %{method: :get, url: ^url200} ->
- %Tesla.Env{
- status: 200,
- body:
- ~s([{"acct":"yj455","avatar":"https://social.heldscal.la/avatar/201.jpeg","avatar_static":"https://social.heldscal.la/avatar/s/201.jpeg"}, {"acct":"#{
- other_user.ap_id
- }","avatar":"https://social.heldscal.la/avatar/202.jpeg","avatar_static":"https://social.heldscal.la/avatar/s/202.jpeg"}])
- }
- end)
-
- [other_user: other_user]
- end
-
test "returns empty result", %{conn: conn} do
res =
conn
diff --git a/test/web/mastodon_api/mastodon_api_controller_test.exs b/test/web/mastodon_api/mastodon_api_controller_test.exs
index 75f184242..bb4bc4396 100644
--- a/test/web/mastodon_api/mastodon_api_controller_test.exs
+++ b/test/web/mastodon_api/mastodon_api_controller_test.exs
@@ -7,35 +7,28 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
describe "empty_array/2 (stubs)" do
test "GET /api/v1/accounts/:id/identity_proofs" do
- %{user: user, conn: conn} = oauth_access(["n/a"])
+ %{user: user, conn: conn} = oauth_access(["read:accounts"])
- res =
- conn
- |> assign(:user, user)
- |> get("/api/v1/accounts/#{user.id}/identity_proofs")
- |> json_response(200)
-
- assert res == []
+ assert [] ==
+ conn
+ |> get("/api/v1/accounts/#{user.id}/identity_proofs")
+ |> json_response(200)
end
test "GET /api/v1/endorsements" do
%{conn: conn} = oauth_access(["read:accounts"])
- res =
- conn
- |> get("/api/v1/endorsements")
- |> json_response(200)
-
- assert res == []
+ assert [] ==
+ conn
+ |> get("/api/v1/endorsements")
+ |> json_response(200)
end
test "GET /api/v1/trends", %{conn: conn} do
- res =
- conn
- |> get("/api/v1/trends")
- |> json_response(200)
-
- assert res == []
+ assert [] ==
+ conn
+ |> get("/api/v1/trends")
+ |> json_response(200)
end
end
end
diff --git a/test/web/mastodon_api/views/account_view_test.exs b/test/web/mastodon_api/views/account_view_test.exs
index 4435f69ff..85fa4f6a2 100644
--- a/test/web/mastodon_api/views/account_view_test.exs
+++ b/test/web/mastodon_api/views/account_view_test.exs
@@ -19,16 +19,6 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do
end
test "Represent a user account" do
- source_data = %{
- "tag" => [
- %{
- "type" => "Emoji",
- "icon" => %{"url" => "/file.png"},
- "name" => ":karjalanpiirakka:"
- }
- ]
- }
-
background_image = %{
"url" => [%{"href" => "https://example.com/images/asuka_hospital.png"}]
}
@@ -37,13 +27,13 @@ test "Represent a user account" do
insert(:user, %{
follower_count: 3,
note_count: 5,
- source_data: source_data,
background: background_image,
nickname: "shp@shitposter.club",
name: ":karjalanpiirakka: shp",
bio:
"valid html. a
b
c
d
f",
- inserted_at: ~N[2017-08-15 15:47:06.597036]
+ inserted_at: ~N[2017-08-15 15:47:06.597036],
+ emoji: %{"karjalanpiirakka" => "/file.png"}
})
expected = %{
@@ -117,7 +107,6 @@ test "Represent a Service(bot) account" do
insert(:user, %{
follower_count: 3,
note_count: 5,
- source_data: %{},
actor_type: "Service",
nickname: "shp@shitposter.club",
inserted_at: ~N[2017-08-15 15:47:06.597036]
@@ -311,7 +300,6 @@ test "represent an embedded relationship" do
insert(:user, %{
follower_count: 0,
note_count: 5,
- source_data: %{},
actor_type: "Service",
nickname: "shp@shitposter.club",
inserted_at: ~N[2017-08-15 15:47:06.597036]
diff --git a/test/web/mastodon_api/views/poll_view_test.exs b/test/web/mastodon_api/views/poll_view_test.exs
index 6211fa888..63b204387 100644
--- a/test/web/mastodon_api/views/poll_view_test.exs
+++ b/test/web/mastodon_api/views/poll_view_test.exs
@@ -43,7 +43,8 @@ test "renders a poll" do
%{title: "why are you even asking?", votes_count: 0}
],
voted: false,
- votes_count: 0
+ votes_count: 0,
+ voters_count: nil
}
result = PollView.render("show.json", %{object: object})
@@ -69,9 +70,20 @@ test "detects if it is multiple choice" do
}
})
+ voter = insert(:user)
+
object = Object.normalize(activity)
- assert %{multiple: true} = PollView.render("show.json", %{object: object})
+ {:ok, _votes, object} = CommonAPI.vote(voter, object, [0, 1])
+
+ assert match?(
+ %{
+ multiple: true,
+ voters_count: 1,
+ votes_count: 2
+ },
+ PollView.render("show.json", %{object: object})
+ )
end
test "detects emoji" do
diff --git a/test/web/mastodon_api/views/push_subscription_view_test.exs b/test/web/mastodon_api/views/subscription_view_test.exs
similarity index 72%
rename from test/web/mastodon_api/views/push_subscription_view_test.exs
rename to test/web/mastodon_api/views/subscription_view_test.exs
index 10c6082a5..981524c0e 100644
--- a/test/web/mastodon_api/views/push_subscription_view_test.exs
+++ b/test/web/mastodon_api/views/subscription_view_test.exs
@@ -2,10 +2,10 @@
# Copyright © 2017-2020 Pleroma Authors
# SPDX-License-Identifier: AGPL-3.0-only
-defmodule Pleroma.Web.MastodonAPI.PushSubscriptionViewTest do
+defmodule Pleroma.Web.MastodonAPI.SubscriptionViewTest do
use Pleroma.DataCase
import Pleroma.Factory
- alias Pleroma.Web.MastodonAPI.PushSubscriptionView, as: View
+ alias Pleroma.Web.MastodonAPI.SubscriptionView, as: View
alias Pleroma.Web.Push
test "Represent a subscription" do
@@ -18,6 +18,6 @@ test "Represent a subscription" do
server_key: Keyword.get(Push.vapid_config(), :public_key)
}
- assert expected == View.render("push_subscription.json", %{subscription: subscription})
+ assert expected == View.render("show.json", %{subscription: subscription})
end
end
diff --git a/test/web/mongooseim/mongoose_im_controller_test.exs b/test/web/mongooseim/mongoose_im_controller_test.exs
index 291ae54fc..1ac2f2c27 100644
--- a/test/web/mongooseim/mongoose_im_controller_test.exs
+++ b/test/web/mongooseim/mongoose_im_controller_test.exs
@@ -9,6 +9,7 @@ defmodule Pleroma.Web.MongooseIMController do
test "/user_exists", %{conn: conn} do
_user = insert(:user, nickname: "lain")
_remote_user = insert(:user, nickname: "alice", local: false)
+ _deactivated_user = insert(:user, nickname: "konata", deactivated: true)
res =
conn
@@ -30,11 +31,25 @@ test "/user_exists", %{conn: conn} do
|> json_response(404)
assert res == false
+
+ res =
+ conn
+ |> get(mongoose_im_path(conn, :user_exists), user: "konata")
+ |> json_response(404)
+
+ assert res == false
end
test "/check_password", %{conn: conn} do
user = insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt("cool"))
+ _deactivated_user =
+ insert(:user,
+ nickname: "konata",
+ deactivated: true,
+ password_hash: Comeonin.Pbkdf2.hashpwsalt("cool")
+ )
+
res =
conn
|> get(mongoose_im_path(conn, :check_password), user: user.nickname, pass: "cool")
@@ -49,6 +64,13 @@ test "/check_password", %{conn: conn} do
assert res == false
+ res =
+ conn
+ |> get(mongoose_im_path(conn, :check_password), user: "konata", pass: "cool")
+ |> json_response(404)
+
+ assert res == false
+
res =
conn
|> get(mongoose_im_path(conn, :check_password), user: "nobody", pass: "cool")
diff --git a/test/web/pleroma_api/controllers/account_controller_test.exs b/test/web/pleroma_api/controllers/account_controller_test.exs
index ae5334015..6b671a667 100644
--- a/test/web/pleroma_api/controllers/account_controller_test.exs
+++ b/test/web/pleroma_api/controllers/account_controller_test.exs
@@ -151,15 +151,18 @@ test "returns list of statuses favorited by specified user", %{
assert like["id"] == activity.id
end
- test "does not return favorites for specified user_id when user is not logged in", %{
+ test "returns favorites for specified user_id when requester is not logged in", %{
user: user
} do
activity = insert(:note_activity)
CommonAPI.favorite(user, activity.id)
- build_conn()
- |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
- |> json_response(403)
+ response =
+ build_conn()
+ |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
+ |> json_response(200)
+
+ assert length(response) == 1
end
test "returns favorited DM only when user is logged in and he is one of recipients", %{
@@ -185,9 +188,12 @@ test "returns favorited DM only when user is logged in and he is one of recipien
assert length(response) == 1
end
- build_conn()
- |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
- |> json_response(403)
+ response =
+ build_conn()
+ |> get("/api/v1/pleroma/accounts/#{user.id}/favourites")
+ |> json_response(200)
+
+ assert length(response) == 0
end
test "does not return others' favorited DM when user is not one of recipients", %{
diff --git a/test/web/pleroma_api/controllers/emoji_api_controller_test.exs b/test/web/pleroma_api/controllers/emoji_api_controller_test.exs
index 435fb6592..d343256fe 100644
--- a/test/web/pleroma_api/controllers/emoji_api_controller_test.exs
+++ b/test/web/pleroma_api/controllers/emoji_api_controller_test.exs
@@ -8,213 +8,298 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
import Tesla.Mock
import Pleroma.Factory
- @emoji_dir_path Path.join(
- Pleroma.Config.get!([:instance, :static_dir]),
- "emoji"
- )
+ @emoji_path Path.join(
+ Pleroma.Config.get!([:instance, :static_dir]),
+ "emoji"
+ )
setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], false)
- test "shared & non-shared pack information in list_packs is ok" do
- conn = build_conn()
- resp = conn |> get(emoji_api_path(conn, :list_packs)) |> json_response(200)
-
- assert Map.has_key?(resp, "test_pack")
-
- pack = resp["test_pack"]
-
- assert Map.has_key?(pack["pack"], "download-sha256")
- assert pack["pack"]["can-download"]
-
- assert pack["files"] == %{"blank" => "blank.png"}
-
- # Non-shared pack
-
- assert Map.has_key?(resp, "test_pack_nonshared")
-
- pack = resp["test_pack_nonshared"]
-
- refute pack["pack"]["shared"]
- refute pack["pack"]["can-download"]
- end
-
- test "listing remote packs" do
+ setup do
admin = insert(:user, is_admin: true)
- %{conn: conn} = oauth_access(["admin:write"], user: admin)
+ token = insert(:oauth_admin_token, user: admin)
- resp =
- build_conn()
- |> get(emoji_api_path(conn, :list_packs))
- |> json_response(200)
-
- mock(fn
- %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
- json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
-
- %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
- json(%{metadata: %{features: ["shareable_emoji_packs"]}})
-
- %{method: :get, url: "https://example.com/api/pleroma/emoji/packs"} ->
- json(resp)
- end)
-
- assert conn
- |> post(emoji_api_path(conn, :list_from), %{instance_address: "https://example.com"})
- |> json_response(200) == resp
- end
-
- test "downloading a shared pack from download_shared" do
- conn = build_conn()
-
- resp =
- conn
- |> get(emoji_api_path(conn, :download_shared, "test_pack"))
- |> response(200)
-
- {:ok, arch} = :zip.unzip(resp, [:memory])
-
- assert Enum.find(arch, fn {n, _} -> n == 'pack.json' end)
- assert Enum.find(arch, fn {n, _} -> n == 'blank.png' end)
- end
-
- test "downloading shared & unshared packs from another instance via download_from, deleting them" do
- on_exit(fn ->
- File.rm_rf!("#{@emoji_dir_path}/test_pack2")
- File.rm_rf!("#{@emoji_dir_path}/test_pack_nonshared2")
- end)
-
- mock(fn
- %{method: :get, url: "https://old-instance/.well-known/nodeinfo"} ->
- json(%{links: [%{href: "https://old-instance/nodeinfo/2.1.json"}]})
-
- %{method: :get, url: "https://old-instance/nodeinfo/2.1.json"} ->
- json(%{metadata: %{features: []}})
-
- %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
- json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
-
- %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
- json(%{metadata: %{features: ["shareable_emoji_packs"]}})
-
- %{
- method: :get,
- url: "https://example.com/api/pleroma/emoji/packs/list"
- } ->
- conn = build_conn()
-
- conn
- |> get(emoji_api_path(conn, :list_packs))
- |> json_response(200)
- |> json()
-
- %{
- method: :get,
- url: "https://example.com/api/pleroma/emoji/packs/download_shared/test_pack"
- } ->
- conn = build_conn()
-
- conn
- |> get(emoji_api_path(conn, :download_shared, "test_pack"))
- |> response(200)
- |> text()
-
- %{
- method: :get,
- url: "https://nonshared-pack"
- } ->
- text(File.read!("#{@emoji_dir_path}/test_pack_nonshared/nonshared.zip"))
- end)
-
- admin = insert(:user, is_admin: true)
-
- conn =
+ admin_conn =
build_conn()
|> assign(:user, admin)
- |> assign(:token, insert(:oauth_admin_token, user: admin, scopes: ["admin:write"]))
+ |> assign(:token, token)
- assert (conn
- |> put_req_header("content-type", "application/json")
- |> post(
- emoji_api_path(
- conn,
- :download_from
- ),
- %{
- instance_address: "https://old-instance",
- pack_name: "test_pack",
- as: "test_pack2"
- }
- |> Jason.encode!()
- )
- |> json_response(500))["error"] =~ "does not support"
-
- assert conn
- |> put_req_header("content-type", "application/json")
- |> post(
- emoji_api_path(
- conn,
- :download_from
- ),
- %{
- instance_address: "https://example.com",
- pack_name: "test_pack",
- as: "test_pack2"
- }
- |> Jason.encode!()
- )
- |> json_response(200) == "ok"
-
- assert File.exists?("#{@emoji_dir_path}/test_pack2/pack.json")
- assert File.exists?("#{@emoji_dir_path}/test_pack2/blank.png")
-
- assert conn
- |> delete(emoji_api_path(conn, :delete, "test_pack2"))
- |> json_response(200) == "ok"
-
- refute File.exists?("#{@emoji_dir_path}/test_pack2")
-
- # non-shared, downloaded from the fallback URL
-
- assert conn
- |> put_req_header("content-type", "application/json")
- |> post(
- emoji_api_path(
- conn,
- :download_from
- ),
- %{
- instance_address: "https://example.com",
- pack_name: "test_pack_nonshared",
- as: "test_pack_nonshared2"
- }
- |> Jason.encode!()
- )
- |> json_response(200) == "ok"
-
- assert File.exists?("#{@emoji_dir_path}/test_pack_nonshared2/pack.json")
- assert File.exists?("#{@emoji_dir_path}/test_pack_nonshared2/blank.png")
-
- assert conn
- |> delete(emoji_api_path(conn, :delete, "test_pack_nonshared2"))
- |> json_response(200) == "ok"
-
- refute File.exists?("#{@emoji_dir_path}/test_pack_nonshared2")
+ Pleroma.Emoji.reload()
+ {:ok, %{admin_conn: admin_conn}}
end
- describe "updating pack metadata" do
+ test "GET /api/pleroma/emoji/packs", %{conn: conn} do
+ resp = conn |> get("/api/pleroma/emoji/packs") |> json_response(200)
+
+ shared = resp["test_pack"]
+ assert shared["files"] == %{"blank" => "blank.png"}
+ assert Map.has_key?(shared["pack"], "download-sha256")
+ assert shared["pack"]["can-download"]
+ assert shared["pack"]["share-files"]
+
+ non_shared = resp["test_pack_nonshared"]
+ assert non_shared["pack"]["share-files"] == false
+ assert non_shared["pack"]["can-download"] == false
+ end
+
+ describe "GET /api/pleroma/emoji/packs/remote" do
+ test "shareable instance", %{admin_conn: admin_conn, conn: conn} do
+ resp =
+ conn
+ |> get("/api/pleroma/emoji/packs")
+ |> json_response(200)
+
+ mock(fn
+ %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
+ json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
+
+ %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
+ json(%{metadata: %{features: ["shareable_emoji_packs"]}})
+
+ %{method: :get, url: "https://example.com/api/pleroma/emoji/packs"} ->
+ json(resp)
+ end)
+
+ assert admin_conn
+ |> get("/api/pleroma/emoji/packs/remote", %{
+ url: "https://example.com"
+ })
+ |> json_response(200) == resp
+ end
+
+ test "non shareable instance", %{admin_conn: admin_conn} do
+ mock(fn
+ %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
+ json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
+
+ %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
+ json(%{metadata: %{features: []}})
+ end)
+
+ assert admin_conn
+ |> get("/api/pleroma/emoji/packs/remote", %{url: "https://example.com"})
+ |> json_response(500) == %{
+ "error" => "The requested instance does not support sharing emoji packs"
+ }
+ end
+ end
+
+ describe "GET /api/pleroma/emoji/packs/:name/archive" do
+ test "download shared pack", %{conn: conn} do
+ resp =
+ conn
+ |> get("/api/pleroma/emoji/packs/test_pack/archive")
+ |> response(200)
+
+ {:ok, arch} = :zip.unzip(resp, [:memory])
+
+ assert Enum.find(arch, fn {n, _} -> n == 'pack.json' end)
+ assert Enum.find(arch, fn {n, _} -> n == 'blank.png' end)
+ end
+
+ test "non existing pack", %{conn: conn} do
+ assert conn
+ |> get("/api/pleroma/emoji/packs/test_pack_for_import/archive")
+ |> json_response(:not_found) == %{
+ "error" => "Pack test_pack_for_import does not exist"
+ }
+ end
+
+ test "non downloadable pack", %{conn: conn} do
+ assert conn
+ |> get("/api/pleroma/emoji/packs/test_pack_nonshared/archive")
+ |> json_response(:forbidden) == %{
+ "error" =>
+ "Pack test_pack_nonshared cannot be downloaded from this instance, either pack sharing was disabled for this pack or some files are missing"
+ }
+ end
+ end
+
+ describe "POST /api/pleroma/emoji/packs/download" do
+ test "shared pack from remote and non shared from fallback-src", %{
+ admin_conn: admin_conn,
+ conn: conn
+ } do
+ mock(fn
+ %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
+ json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
+
+ %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
+ json(%{metadata: %{features: ["shareable_emoji_packs"]}})
+
+ %{
+ method: :get,
+ url: "https://example.com/api/pleroma/emoji/packs/test_pack"
+ } ->
+ conn
+ |> get("/api/pleroma/emoji/packs/test_pack")
+ |> json_response(200)
+ |> json()
+
+ %{
+ method: :get,
+ url: "https://example.com/api/pleroma/emoji/packs/test_pack/archive"
+ } ->
+ conn
+ |> get("/api/pleroma/emoji/packs/test_pack/archive")
+ |> response(200)
+ |> text()
+
+ %{
+ method: :get,
+ url: "https://example.com/api/pleroma/emoji/packs/test_pack_nonshared"
+ } ->
+ conn
+ |> get("/api/pleroma/emoji/packs/test_pack_nonshared")
+ |> json_response(200)
+ |> json()
+
+ %{
+ method: :get,
+ url: "https://nonshared-pack"
+ } ->
+ text(File.read!("#{@emoji_path}/test_pack_nonshared/nonshared.zip"))
+ end)
+
+ assert admin_conn
+ |> post("/api/pleroma/emoji/packs/download", %{
+ url: "https://example.com",
+ name: "test_pack",
+ as: "test_pack2"
+ })
+ |> json_response(200) == "ok"
+
+ assert File.exists?("#{@emoji_path}/test_pack2/pack.json")
+ assert File.exists?("#{@emoji_path}/test_pack2/blank.png")
+
+ assert admin_conn
+ |> delete("/api/pleroma/emoji/packs/test_pack2")
+ |> json_response(200) == "ok"
+
+ refute File.exists?("#{@emoji_path}/test_pack2")
+
+ assert admin_conn
+ |> post(
+ "/api/pleroma/emoji/packs/download",
+ %{
+ url: "https://example.com",
+ name: "test_pack_nonshared",
+ as: "test_pack_nonshared2"
+ }
+ )
+ |> json_response(200) == "ok"
+
+ assert File.exists?("#{@emoji_path}/test_pack_nonshared2/pack.json")
+ assert File.exists?("#{@emoji_path}/test_pack_nonshared2/blank.png")
+
+ assert admin_conn
+ |> delete("/api/pleroma/emoji/packs/test_pack_nonshared2")
+ |> json_response(200) == "ok"
+
+ refute File.exists?("#{@emoji_path}/test_pack_nonshared2")
+ end
+
+ test "nonshareable instance", %{admin_conn: admin_conn} do
+ mock(fn
+ %{method: :get, url: "https://old-instance/.well-known/nodeinfo"} ->
+ json(%{links: [%{href: "https://old-instance/nodeinfo/2.1.json"}]})
+
+ %{method: :get, url: "https://old-instance/nodeinfo/2.1.json"} ->
+ json(%{metadata: %{features: []}})
+ end)
+
+ assert admin_conn
+ |> post(
+ "/api/pleroma/emoji/packs/download",
+ %{
+ url: "https://old-instance",
+ name: "test_pack",
+ as: "test_pack2"
+ }
+ )
+ |> json_response(500) == %{
+ "error" => "The requested instance does not support sharing emoji packs"
+ }
+ end
+
+ test "checksum fail", %{admin_conn: admin_conn} do
+ mock(fn
+ %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
+ json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
+
+ %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
+ json(%{metadata: %{features: ["shareable_emoji_packs"]}})
+
+ %{
+ method: :get,
+ url: "https://example.com/api/pleroma/emoji/packs/pack_bad_sha"
+ } ->
+ %Tesla.Env{
+ status: 200,
+ body: Pleroma.Emoji.Pack.load_pack("pack_bad_sha") |> Jason.encode!()
+ }
+
+ %{
+ method: :get,
+ url: "https://example.com/api/pleroma/emoji/packs/pack_bad_sha/archive"
+ } ->
+ %Tesla.Env{
+ status: 200,
+ body: File.read!("test/instance_static/emoji/pack_bad_sha/pack_bad_sha.zip")
+ }
+ end)
+
+ assert admin_conn
+ |> post("/api/pleroma/emoji/packs/download", %{
+ url: "https://example.com",
+ name: "pack_bad_sha",
+ as: "pack_bad_sha2"
+ })
+ |> json_response(:internal_server_error) == %{
+ "error" => "SHA256 for the pack doesn't match the one sent by the server"
+ }
+ end
+
+ test "other error", %{admin_conn: admin_conn} do
+ mock(fn
+ %{method: :get, url: "https://example.com/.well-known/nodeinfo"} ->
+ json(%{links: [%{href: "https://example.com/nodeinfo/2.1.json"}]})
+
+ %{method: :get, url: "https://example.com/nodeinfo/2.1.json"} ->
+ json(%{metadata: %{features: ["shareable_emoji_packs"]}})
+
+ %{
+ method: :get,
+ url: "https://example.com/api/pleroma/emoji/packs/test_pack"
+ } ->
+ %Tesla.Env{
+ status: 200,
+ body: Pleroma.Emoji.Pack.load_pack("test_pack") |> Jason.encode!()
+ }
+ end)
+
+ assert admin_conn
+ |> post("/api/pleroma/emoji/packs/download", %{
+ url: "https://example.com",
+ name: "test_pack",
+ as: "test_pack2"
+ })
+ |> json_response(:internal_server_error) == %{
+ "error" =>
+ "The pack was not set as shared and there is no fallback src to download from"
+ }
+ end
+ end
+
+ describe "PATCH /api/pleroma/emoji/packs/:name" do
setup do
- pack_file = "#{@emoji_dir_path}/test_pack/pack.json"
+ pack_file = "#{@emoji_path}/test_pack/pack.json"
original_content = File.read!(pack_file)
on_exit(fn ->
File.write!(pack_file, original_content)
end)
- admin = insert(:user, is_admin: true)
- %{conn: conn} = oauth_access(["admin:write"], user: admin)
-
{:ok,
- admin: admin,
- conn: conn,
pack_file: pack_file,
new_data: %{
"license" => "Test license changed",
@@ -225,15 +310,8 @@ test "downloading shared & unshared packs from another instance via download_fro
end
test "for a pack without a fallback source", ctx do
- conn = ctx[:conn]
-
- assert conn
- |> post(
- emoji_api_path(conn, :update_metadata, "test_pack"),
- %{
- "new_data" => ctx[:new_data]
- }
- )
+ assert ctx[:admin_conn]
+ |> patch("/api/pleroma/emoji/packs/test_pack", %{"metadata" => ctx[:new_data]})
|> json_response(200) == ctx[:new_data]
assert Jason.decode!(File.read!(ctx[:pack_file]))["pack"] == ctx[:new_data]
@@ -245,7 +323,7 @@ test "for a pack with a fallback source", ctx do
method: :get,
url: "https://nonshared-pack"
} ->
- text(File.read!("#{@emoji_dir_path}/test_pack_nonshared/nonshared.zip"))
+ text(File.read!("#{@emoji_path}/test_pack_nonshared/nonshared.zip"))
end)
new_data = Map.put(ctx[:new_data], "fallback-src", "https://nonshared-pack")
@@ -257,15 +335,8 @@ test "for a pack with a fallback source", ctx do
"74409E2674DAA06C072729C6C8426C4CB3B7E0B85ED77792DB7A436E11D76DAF"
)
- conn = ctx[:conn]
-
- assert conn
- |> post(
- emoji_api_path(conn, :update_metadata, "test_pack"),
- %{
- "new_data" => new_data
- }
- )
+ assert ctx[:admin_conn]
+ |> patch("/api/pleroma/emoji/packs/test_pack", %{metadata: new_data})
|> json_response(200) == new_data_with_sha
assert Jason.decode!(File.read!(ctx[:pack_file]))["pack"] == new_data_with_sha
@@ -283,181 +354,377 @@ test "when the fallback source doesn't have all the files", ctx do
new_data = Map.put(ctx[:new_data], "fallback-src", "https://nonshared-pack")
- conn = ctx[:conn]
-
- assert (conn
- |> post(
- emoji_api_path(conn, :update_metadata, "test_pack"),
- %{
- "new_data" => new_data
- }
- )
- |> json_response(:bad_request))["error"] =~ "does not have all"
+ assert ctx[:admin_conn]
+ |> patch("/api/pleroma/emoji/packs/test_pack", %{metadata: new_data})
+ |> json_response(:bad_request) == %{
+ "error" => "The fallback archive does not have all files specified in pack.json"
+ }
end
end
- test "updating pack files" do
- pack_file = "#{@emoji_dir_path}/test_pack/pack.json"
- original_content = File.read!(pack_file)
+ describe "POST/PATCH/DELETE /api/pleroma/emoji/packs/:name/files" do
+ setup do
+ pack_file = "#{@emoji_path}/test_pack/pack.json"
+ original_content = File.read!(pack_file)
- on_exit(fn ->
- File.write!(pack_file, original_content)
+ on_exit(fn ->
+ File.write!(pack_file, original_content)
+ end)
- File.rm_rf!("#{@emoji_dir_path}/test_pack/blank_url.png")
- File.rm_rf!("#{@emoji_dir_path}/test_pack/dir")
- File.rm_rf!("#{@emoji_dir_path}/test_pack/dir_2")
- end)
+ :ok
+ end
- admin = insert(:user, is_admin: true)
- %{conn: conn} = oauth_access(["admin:write"], user: admin)
+ test "create shortcode exists", %{admin_conn: admin_conn} do
+ assert admin_conn
+ |> post("/api/pleroma/emoji/packs/test_pack/files", %{
+ shortcode: "blank",
+ filename: "dir/blank.png",
+ file: %Plug.Upload{
+ filename: "blank.png",
+ path: "#{@emoji_path}/test_pack/blank.png"
+ }
+ })
+ |> json_response(:conflict) == %{
+ "error" => "An emoji with the \"blank\" shortcode already exists"
+ }
+ end
- same_name = %{
- "action" => "add",
- "shortcode" => "blank",
- "filename" => "dir/blank.png",
- "file" => %Plug.Upload{
- filename: "blank.png",
- path: "#{@emoji_dir_path}/test_pack/blank.png"
- }
- }
+ test "don't rewrite old emoji", %{admin_conn: admin_conn} do
+ on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/dir/") end)
- different_name = %{same_name | "shortcode" => "blank_2"}
+ assert admin_conn
+ |> post("/api/pleroma/emoji/packs/test_pack/files", %{
+ shortcode: "blank2",
+ filename: "dir/blank.png",
+ file: %Plug.Upload{
+ filename: "blank.png",
+ path: "#{@emoji_path}/test_pack/blank.png"
+ }
+ })
+ |> json_response(200) == %{"blank" => "blank.png", "blank2" => "dir/blank.png"}
- assert (conn
- |> post(emoji_api_path(conn, :update_file, "test_pack"), same_name)
- |> json_response(:conflict))["error"] =~ "already exists"
+ assert File.exists?("#{@emoji_path}/test_pack/dir/blank.png")
- assert conn
- |> post(emoji_api_path(conn, :update_file, "test_pack"), different_name)
- |> json_response(200) == %{"blank" => "blank.png", "blank_2" => "dir/blank.png"}
+ assert admin_conn
+ |> patch("/api/pleroma/emoji/packs/test_pack/files", %{
+ shortcode: "blank",
+ new_shortcode: "blank2",
+ new_filename: "dir_2/blank_3.png"
+ })
+ |> json_response(:conflict) == %{
+ "error" =>
+ "New shortcode \"blank2\" is already used. If you want to override emoji use 'force' option"
+ }
+ end
- assert File.exists?("#{@emoji_dir_path}/test_pack/dir/blank.png")
+ test "rewrite old emoji with force option", %{admin_conn: admin_conn} do
+ on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/dir_2/") end)
- assert conn
- |> post(emoji_api_path(conn, :update_file, "test_pack"), %{
- "action" => "update",
- "shortcode" => "blank_2",
- "new_shortcode" => "blank_3",
- "new_filename" => "dir_2/blank_3.png"
- })
- |> json_response(200) == %{"blank" => "blank.png", "blank_3" => "dir_2/blank_3.png"}
+ assert admin_conn
+ |> post("/api/pleroma/emoji/packs/test_pack/files", %{
+ shortcode: "blank2",
+ filename: "dir/blank.png",
+ file: %Plug.Upload{
+ filename: "blank.png",
+ path: "#{@emoji_path}/test_pack/blank.png"
+ }
+ })
+ |> json_response(200) == %{"blank" => "blank.png", "blank2" => "dir/blank.png"}
- refute File.exists?("#{@emoji_dir_path}/test_pack/dir/")
- assert File.exists?("#{@emoji_dir_path}/test_pack/dir_2/blank_3.png")
+ assert File.exists?("#{@emoji_path}/test_pack/dir/blank.png")
- assert conn
- |> post(emoji_api_path(conn, :update_file, "test_pack"), %{
- "action" => "remove",
- "shortcode" => "blank_3"
- })
- |> json_response(200) == %{"blank" => "blank.png"}
+ assert admin_conn
+ |> patch("/api/pleroma/emoji/packs/test_pack/files", %{
+ shortcode: "blank2",
+ new_shortcode: "blank3",
+ new_filename: "dir_2/blank_3.png",
+ force: true
+ })
+ |> json_response(200) == %{
+ "blank" => "blank.png",
+ "blank3" => "dir_2/blank_3.png"
+ }
- refute File.exists?("#{@emoji_dir_path}/test_pack/dir_2/")
+ assert File.exists?("#{@emoji_path}/test_pack/dir_2/blank_3.png")
+ end
- mock(fn
- %{
- method: :get,
- url: "https://test-blank/blank_url.png"
- } ->
- text(File.read!("#{@emoji_dir_path}/test_pack/blank.png"))
- end)
+ test "with empty filename", %{admin_conn: admin_conn} do
+ assert admin_conn
+ |> post("/api/pleroma/emoji/packs/test_pack/files", %{
+ shortcode: "blank2",
+ filename: "",
+ file: %Plug.Upload{
+ filename: "blank.png",
+ path: "#{@emoji_path}/test_pack/blank.png"
+ }
+ })
+ |> json_response(:bad_request) == %{
+ "error" => "pack name, shortcode or filename cannot be empty"
+ }
+ end
- # The name should be inferred from the URL ending
- from_url = %{
- "action" => "add",
- "shortcode" => "blank_url",
- "file" => "https://test-blank/blank_url.png"
- }
+ test "add file with not loaded pack", %{admin_conn: admin_conn} do
+ assert admin_conn
+ |> post("/api/pleroma/emoji/packs/not_loaded/files", %{
+ shortcode: "blank2",
+ filename: "dir/blank.png",
+ file: %Plug.Upload{
+ filename: "blank.png",
+ path: "#{@emoji_path}/test_pack/blank.png"
+ }
+ })
+ |> json_response(:bad_request) == %{
+ "error" => "pack \"not_loaded\" is not found"
+ }
+ end
- assert conn
- |> post(emoji_api_path(conn, :update_file, "test_pack"), from_url)
- |> json_response(200) == %{
- "blank" => "blank.png",
- "blank_url" => "blank_url.png"
- }
+ test "remove file with not loaded pack", %{admin_conn: admin_conn} do
+ assert admin_conn
+ |> delete("/api/pleroma/emoji/packs/not_loaded/files", %{shortcode: "blank3"})
+ |> json_response(:bad_request) == %{"error" => "pack \"not_loaded\" is not found"}
+ end
- assert File.exists?("#{@emoji_dir_path}/test_pack/blank_url.png")
+ test "remove file with empty shortcode", %{admin_conn: admin_conn} do
+ assert admin_conn
+ |> delete("/api/pleroma/emoji/packs/not_loaded/files", %{shortcode: ""})
+ |> json_response(:bad_request) == %{
+ "error" => "pack name or shortcode cannot be empty"
+ }
+ end
- assert conn
- |> post(emoji_api_path(conn, :update_file, "test_pack"), %{
- "action" => "remove",
- "shortcode" => "blank_url"
- })
- |> json_response(200) == %{"blank" => "blank.png"}
+ test "update file with not loaded pack", %{admin_conn: admin_conn} do
+ assert admin_conn
+ |> patch("/api/pleroma/emoji/packs/not_loaded/files", %{
+ shortcode: "blank4",
+ new_shortcode: "blank3",
+ new_filename: "dir_2/blank_3.png"
+ })
+ |> json_response(:bad_request) == %{"error" => "pack \"not_loaded\" is not found"}
+ end
- refute File.exists?("#{@emoji_dir_path}/test_pack/blank_url.png")
+ test "new with shortcode as file with update", %{admin_conn: admin_conn} do
+ assert admin_conn
+ |> post("/api/pleroma/emoji/packs/test_pack/files", %{
+ shortcode: "blank4",
+ filename: "dir/blank.png",
+ file: %Plug.Upload{
+ filename: "blank.png",
+ path: "#{@emoji_path}/test_pack/blank.png"
+ }
+ })
+ |> json_response(200) == %{"blank" => "blank.png", "blank4" => "dir/blank.png"}
+
+ assert File.exists?("#{@emoji_path}/test_pack/dir/blank.png")
+
+ assert admin_conn
+ |> patch("/api/pleroma/emoji/packs/test_pack/files", %{
+ shortcode: "blank4",
+ new_shortcode: "blank3",
+ new_filename: "dir_2/blank_3.png"
+ })
+ |> json_response(200) == %{"blank3" => "dir_2/blank_3.png", "blank" => "blank.png"}
+
+ refute File.exists?("#{@emoji_path}/test_pack/dir/")
+ assert File.exists?("#{@emoji_path}/test_pack/dir_2/blank_3.png")
+
+ assert admin_conn
+ |> delete("/api/pleroma/emoji/packs/test_pack/files", %{shortcode: "blank3"})
+ |> json_response(200) == %{"blank" => "blank.png"}
+
+ refute File.exists?("#{@emoji_path}/test_pack/dir_2/")
+
+ on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/dir") end)
+ end
+
+ test "new with shortcode from url", %{admin_conn: admin_conn} do
+ mock(fn
+ %{
+ method: :get,
+ url: "https://test-blank/blank_url.png"
+ } ->
+ text(File.read!("#{@emoji_path}/test_pack/blank.png"))
+ end)
+
+ assert admin_conn
+ |> post("/api/pleroma/emoji/packs/test_pack/files", %{
+ shortcode: "blank_url",
+ file: "https://test-blank/blank_url.png"
+ })
+ |> json_response(200) == %{
+ "blank_url" => "blank_url.png",
+ "blank" => "blank.png"
+ }
+
+ assert File.exists?("#{@emoji_path}/test_pack/blank_url.png")
+
+ on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/blank_url.png") end)
+ end
+
+ test "new without shortcode", %{admin_conn: admin_conn} do
+ on_exit(fn -> File.rm_rf!("#{@emoji_path}/test_pack/shortcode.png") end)
+
+ assert admin_conn
+ |> post("/api/pleroma/emoji/packs/test_pack/files", %{
+ file: %Plug.Upload{
+ filename: "shortcode.png",
+ path: "#{Pleroma.Config.get([:instance, :static_dir])}/add/shortcode.png"
+ }
+ })
+ |> json_response(200) == %{"shortcode" => "shortcode.png", "blank" => "blank.png"}
+ end
+
+ test "remove non existing shortcode in pack.json", %{admin_conn: admin_conn} do
+ assert admin_conn
+ |> delete("/api/pleroma/emoji/packs/test_pack/files", %{shortcode: "blank2"})
+ |> json_response(:bad_request) == %{"error" => "Emoji \"blank2\" does not exist"}
+ end
+
+ test "update non existing emoji", %{admin_conn: admin_conn} do
+ assert admin_conn
+ |> patch("/api/pleroma/emoji/packs/test_pack/files", %{
+ shortcode: "blank2",
+ new_shortcode: "blank3",
+ new_filename: "dir_2/blank_3.png"
+ })
+ |> json_response(:bad_request) == %{"error" => "Emoji \"blank2\" does not exist"}
+ end
+
+ test "update with empty shortcode", %{admin_conn: admin_conn} do
+ assert admin_conn
+ |> patch("/api/pleroma/emoji/packs/test_pack/files", %{
+ shortcode: "blank",
+ new_filename: "dir_2/blank_3.png"
+ })
+ |> json_response(:bad_request) == %{
+ "error" => "new_shortcode or new_filename cannot be empty"
+ }
+ end
end
- test "creating and deleting a pack" do
- on_exit(fn ->
- File.rm_rf!("#{@emoji_dir_path}/test_created")
- end)
+ describe "POST/DELETE /api/pleroma/emoji/packs/:name" do
+ test "creating and deleting a pack", %{admin_conn: admin_conn} do
+ assert admin_conn
+ |> post("/api/pleroma/emoji/packs/test_created")
+ |> json_response(200) == "ok"
- admin = insert(:user, is_admin: true)
- %{conn: conn} = oauth_access(["admin:write"], user: admin)
+ assert File.exists?("#{@emoji_path}/test_created/pack.json")
- assert conn
- |> put_req_header("content-type", "application/json")
- |> put(
- emoji_api_path(
- conn,
- :create,
- "test_created"
- )
- )
- |> json_response(200) == "ok"
+ assert Jason.decode!(File.read!("#{@emoji_path}/test_created/pack.json")) == %{
+ "pack" => %{},
+ "files" => %{}
+ }
- assert File.exists?("#{@emoji_dir_path}/test_created/pack.json")
+ assert admin_conn
+ |> delete("/api/pleroma/emoji/packs/test_created")
+ |> json_response(200) == "ok"
- assert Jason.decode!(File.read!("#{@emoji_dir_path}/test_created/pack.json")) == %{
- "pack" => %{},
- "files" => %{}
- }
+ refute File.exists?("#{@emoji_path}/test_created/pack.json")
+ end
- assert conn
- |> delete(emoji_api_path(conn, :delete, "test_created"))
- |> json_response(200) == "ok"
+ test "if pack exists", %{admin_conn: admin_conn} do
+ path = Path.join(@emoji_path, "test_created")
+ File.mkdir(path)
+ pack_file = Jason.encode!(%{files: %{}, pack: %{}})
+ File.write!(Path.join(path, "pack.json"), pack_file)
- refute File.exists?("#{@emoji_dir_path}/test_created/pack.json")
+ assert admin_conn
+ |> post("/api/pleroma/emoji/packs/test_created")
+ |> json_response(:conflict) == %{
+ "error" => "A pack named \"test_created\" already exists"
+ }
+
+ on_exit(fn -> File.rm_rf(path) end)
+ end
+
+ test "with empty name", %{admin_conn: admin_conn} do
+ assert admin_conn
+ |> post("/api/pleroma/emoji/packs/ ")
+ |> json_response(:bad_request) == %{"error" => "pack name cannot be empty"}
+ end
end
- test "filesystem import" do
+ test "deleting nonexisting pack", %{admin_conn: admin_conn} do
+ assert admin_conn
+ |> delete("/api/pleroma/emoji/packs/non_existing")
+ |> json_response(:not_found) == %{"error" => "Pack non_existing does not exist"}
+ end
+
+ test "deleting with empty name", %{admin_conn: admin_conn} do
+ assert admin_conn
+ |> delete("/api/pleroma/emoji/packs/ ")
+ |> json_response(:bad_request) == %{"error" => "pack name cannot be empty"}
+ end
+
+ test "filesystem import", %{admin_conn: admin_conn, conn: conn} do
on_exit(fn ->
- File.rm!("#{@emoji_dir_path}/test_pack_for_import/emoji.txt")
- File.rm!("#{@emoji_dir_path}/test_pack_for_import/pack.json")
+ File.rm!("#{@emoji_path}/test_pack_for_import/emoji.txt")
+ File.rm!("#{@emoji_path}/test_pack_for_import/pack.json")
end)
- conn = build_conn()
- resp = conn |> get(emoji_api_path(conn, :list_packs)) |> json_response(200)
+ resp = conn |> get("/api/pleroma/emoji/packs") |> json_response(200)
refute Map.has_key?(resp, "test_pack_for_import")
- admin = insert(:user, is_admin: true)
- %{conn: conn} = oauth_access(["admin:write"], user: admin)
-
- assert conn
- |> post(emoji_api_path(conn, :import_from_fs))
+ assert admin_conn
+ |> get("/api/pleroma/emoji/packs/import")
|> json_response(200) == ["test_pack_for_import"]
- resp = conn |> get(emoji_api_path(conn, :list_packs)) |> json_response(200)
+ resp = conn |> get("/api/pleroma/emoji/packs") |> json_response(200)
assert resp["test_pack_for_import"]["files"] == %{"blank" => "blank.png"}
- File.rm!("#{@emoji_dir_path}/test_pack_for_import/pack.json")
- refute File.exists?("#{@emoji_dir_path}/test_pack_for_import/pack.json")
+ File.rm!("#{@emoji_path}/test_pack_for_import/pack.json")
+ refute File.exists?("#{@emoji_path}/test_pack_for_import/pack.json")
- emoji_txt_content = "blank, blank.png, Fun\n\nblank2, blank.png"
+ emoji_txt_content = """
+ blank, blank.png, Fun
+ blank2, blank.png
+ foo, /emoji/test_pack_for_import/blank.png
+ bar
+ """
- File.write!("#{@emoji_dir_path}/test_pack_for_import/emoji.txt", emoji_txt_content)
+ File.write!("#{@emoji_path}/test_pack_for_import/emoji.txt", emoji_txt_content)
- assert conn
- |> post(emoji_api_path(conn, :import_from_fs))
+ assert admin_conn
+ |> get("/api/pleroma/emoji/packs/import")
|> json_response(200) == ["test_pack_for_import"]
- resp = build_conn() |> get(emoji_api_path(conn, :list_packs)) |> json_response(200)
+ resp = conn |> get("/api/pleroma/emoji/packs") |> json_response(200)
assert resp["test_pack_for_import"]["files"] == %{
"blank" => "blank.png",
- "blank2" => "blank.png"
+ "blank2" => "blank.png",
+ "foo" => "blank.png"
}
end
+
+ describe "GET /api/pleroma/emoji/packs/:name" do
+ test "shows pack.json", %{conn: conn} do
+ assert %{
+ "files" => %{"blank" => "blank.png"},
+ "pack" => %{
+ "can-download" => true,
+ "description" => "Test description",
+ "download-sha256" => _,
+ "homepage" => "https://pleroma.social",
+ "license" => "Test license",
+ "share-files" => true
+ }
+ } =
+ conn
+ |> get("/api/pleroma/emoji/packs/test_pack")
+ |> json_response(200)
+ end
+
+ test "non existing pack", %{conn: conn} do
+ assert conn
+ |> get("/api/pleroma/emoji/packs/non_existing")
+ |> json_response(:not_found) == %{"error" => "Pack non_existing does not exist"}
+ end
+
+ test "error name", %{conn: conn} do
+ assert conn
+ |> get("/api/pleroma/emoji/packs/ ")
+ |> json_response(:bad_request) == %{"error" => "pack name cannot be empty"}
+ end
+ end
end
diff --git a/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs b/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs
index 8bf7eb3be..61a1689b9 100644
--- a/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs
+++ b/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs
@@ -220,7 +220,7 @@ test "PATCH /api/v1/pleroma/conversations/:id" do
test "POST /api/v1/pleroma/conversations/read" do
user = insert(:user)
- %{user: other_user, conn: conn} = oauth_access(["write:notifications"])
+ %{user: other_user, conn: conn} = oauth_access(["write:conversations"])
{:ok, _activity} =
CommonAPI.post(user, %{"status" => "Hi @#{other_user.nickname}", "visibility" => "direct"})
diff --git a/test/web/push/impl_test.exs b/test/web/push/impl_test.exs
index 9121d90e7..b2664bf28 100644
--- a/test/web/push/impl_test.exs
+++ b/test/web/push/impl_test.exs
@@ -63,12 +63,12 @@ test "performs sending notifications" do
activity: activity
)
- assert Impl.perform(notif) == [:ok, :ok]
+ assert Impl.perform(notif) == {:ok, [:ok, :ok]}
end
@tag capture_log: true
test "returns error if notif does not match " do
- assert Impl.perform(%{}) == :error
+ assert Impl.perform(%{}) == {:error, :unknown_type}
end
test "successful message sending" do
diff --git a/test/web/streamer/streamer_test.exs b/test/web/streamer/streamer_test.exs
index eb082b79f..8b8d8af6c 100644
--- a/test/web/streamer/streamer_test.exs
+++ b/test/web/streamer/streamer_test.exs
@@ -28,6 +28,42 @@ defmodule Pleroma.Web.StreamerTest do
{:ok, %{user: user, notify: notify}}
end
+ test "it streams the user's post in the 'user' stream", %{user: user} do
+ task =
+ Task.async(fn ->
+ assert_receive {:text, _}, @streamer_timeout
+ end)
+
+ Streamer.add_socket(
+ "user",
+ %{transport_pid: task.pid, assigns: %{user: user}}
+ )
+
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "hey"})
+
+ Streamer.stream("user", activity)
+ Task.await(task)
+ end
+
+ test "it streams boosts of the user in the 'user' stream", %{user: user} do
+ task =
+ Task.async(fn ->
+ assert_receive {:text, _}, @streamer_timeout
+ end)
+
+ Streamer.add_socket(
+ "user",
+ %{transport_pid: task.pid, assigns: %{user: user}}
+ )
+
+ other_user = insert(:user)
+ {:ok, activity} = CommonAPI.post(other_user, %{"status" => "hey"})
+ {:ok, announce, _} = CommonAPI.repeat(activity.id, user)
+
+ Streamer.stream("user", announce)
+ Task.await(task)
+ end
+
test "it sends notify to in the 'user' stream", %{user: user, notify: notify} do
task =
Task.async(fn ->
diff --git a/test/web/twitter_api/twitter_api_controller_test.exs b/test/web/twitter_api/twitter_api_controller_test.exs
index ab0a2c3df..464d0ea2e 100644
--- a/test/web/twitter_api/twitter_api_controller_test.exs
+++ b/test/web/twitter_api/twitter_api_controller_test.exs
@@ -19,13 +19,9 @@ test "without valid credentials", %{conn: conn} do
end
test "with credentials, without any params" do
- %{user: current_user, conn: conn} =
- oauth_access(["read:notifications", "write:notifications"])
+ %{conn: conn} = oauth_access(["write:notifications"])
- conn =
- conn
- |> assign(:user, current_user)
- |> post("/api/qvitter/statuses/notifications/read")
+ conn = post(conn, "/api/qvitter/statuses/notifications/read")
assert json_response(conn, 400) == %{
"error" => "You need to specify latest_id",
diff --git a/test/web/twitter_api/twitter_api_test.exs b/test/web/twitter_api/twitter_api_test.exs
index f6e13b661..7926a0757 100644
--- a/test/web/twitter_api/twitter_api_test.exs
+++ b/test/web/twitter_api/twitter_api_test.exs
@@ -18,11 +18,11 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
test "it registers a new user and returns the user." do
data = %{
- "nickname" => "lain",
- "email" => "lain@wired.jp",
- "fullname" => "lain iwakura",
- "password" => "bear",
- "confirm" => "bear"
+ :nickname => "lain",
+ :email => "lain@wired.jp",
+ :fullname => "lain iwakura",
+ :password => "bear",
+ :confirm => "bear"
}
{:ok, user} = TwitterAPI.register_user(data)
@@ -35,12 +35,12 @@ test "it registers a new user and returns the user." do
test "it registers a new user with empty string in bio and returns the user." do
data = %{
- "nickname" => "lain",
- "email" => "lain@wired.jp",
- "fullname" => "lain iwakura",
- "bio" => "",
- "password" => "bear",
- "confirm" => "bear"
+ :nickname => "lain",
+ :email => "lain@wired.jp",
+ :fullname => "lain iwakura",
+ :bio => "",
+ :password => "bear",
+ :confirm => "bear"
}
{:ok, user} = TwitterAPI.register_user(data)
@@ -60,12 +60,12 @@ test "it sends confirmation email if :account_activation_required is specified i
end
data = %{
- "nickname" => "lain",
- "email" => "lain@wired.jp",
- "fullname" => "lain iwakura",
- "bio" => "",
- "password" => "bear",
- "confirm" => "bear"
+ :nickname => "lain",
+ :email => "lain@wired.jp",
+ :fullname => "lain iwakura",
+ :bio => "",
+ :password => "bear",
+ :confirm => "bear"
}
{:ok, user} = TwitterAPI.register_user(data)
@@ -87,23 +87,23 @@ test "it sends confirmation email if :account_activation_required is specified i
test "it registers a new user and parses mentions in the bio" do
data1 = %{
- "nickname" => "john",
- "email" => "john@gmail.com",
- "fullname" => "John Doe",
- "bio" => "test",
- "password" => "bear",
- "confirm" => "bear"
+ :nickname => "john",
+ :email => "john@gmail.com",
+ :fullname => "John Doe",
+ :bio => "test",
+ :password => "bear",
+ :confirm => "bear"
}
{:ok, user1} = TwitterAPI.register_user(data1)
data2 = %{
- "nickname" => "lain",
- "email" => "lain@wired.jp",
- "fullname" => "lain iwakura",
- "bio" => "@john test",
- "password" => "bear",
- "confirm" => "bear"
+ :nickname => "lain",
+ :email => "lain@wired.jp",
+ :fullname => "lain iwakura",
+ :bio => "@john test",
+ :password => "bear",
+ :confirm => "bear"
}
{:ok, user2} = TwitterAPI.register_user(data2)
@@ -123,13 +123,13 @@ test "returns user on success" do
{:ok, invite} = UserInviteToken.create_invite()
data = %{
- "nickname" => "vinny",
- "email" => "pasta@pizza.vs",
- "fullname" => "Vinny Vinesauce",
- "bio" => "streamer",
- "password" => "hiptofbees",
- "confirm" => "hiptofbees",
- "token" => invite.token
+ :nickname => "vinny",
+ :email => "pasta@pizza.vs",
+ :fullname => "Vinny Vinesauce",
+ :bio => "streamer",
+ :password => "hiptofbees",
+ :confirm => "hiptofbees",
+ :token => invite.token
}
{:ok, user} = TwitterAPI.register_user(data)
@@ -145,13 +145,13 @@ test "returns user on success" do
test "returns error on invalid token" do
data = %{
- "nickname" => "GrimReaper",
- "email" => "death@reapers.afterlife",
- "fullname" => "Reaper Grim",
- "bio" => "Your time has come",
- "password" => "scythe",
- "confirm" => "scythe",
- "token" => "DudeLetMeInImAFairy"
+ :nickname => "GrimReaper",
+ :email => "death@reapers.afterlife",
+ :fullname => "Reaper Grim",
+ :bio => "Your time has come",
+ :password => "scythe",
+ :confirm => "scythe",
+ :token => "DudeLetMeInImAFairy"
}
{:error, msg} = TwitterAPI.register_user(data)
@@ -165,13 +165,13 @@ test "returns error on expired token" do
UserInviteToken.update_invite!(invite, used: true)
data = %{
- "nickname" => "GrimReaper",
- "email" => "death@reapers.afterlife",
- "fullname" => "Reaper Grim",
- "bio" => "Your time has come",
- "password" => "scythe",
- "confirm" => "scythe",
- "token" => invite.token
+ :nickname => "GrimReaper",
+ :email => "death@reapers.afterlife",
+ :fullname => "Reaper Grim",
+ :bio => "Your time has come",
+ :password => "scythe",
+ :confirm => "scythe",
+ :token => invite.token
}
{:error, msg} = TwitterAPI.register_user(data)
@@ -186,16 +186,16 @@ test "returns error on expired token" do
setup do
data = %{
- "nickname" => "vinny",
- "email" => "pasta@pizza.vs",
- "fullname" => "Vinny Vinesauce",
- "bio" => "streamer",
- "password" => "hiptofbees",
- "confirm" => "hiptofbees"
+ :nickname => "vinny",
+ :email => "pasta@pizza.vs",
+ :fullname => "Vinny Vinesauce",
+ :bio => "streamer",
+ :password => "hiptofbees",
+ :confirm => "hiptofbees"
}
check_fn = fn invite ->
- data = Map.put(data, "token", invite.token)
+ data = Map.put(data, :token, invite.token)
{:ok, user} = TwitterAPI.register_user(data)
fetched_user = User.get_cached_by_nickname("vinny")
@@ -250,13 +250,13 @@ test "returns user on success, after him registration fails" do
UserInviteToken.update_invite!(invite, uses: 99)
data = %{
- "nickname" => "vinny",
- "email" => "pasta@pizza.vs",
- "fullname" => "Vinny Vinesauce",
- "bio" => "streamer",
- "password" => "hiptofbees",
- "confirm" => "hiptofbees",
- "token" => invite.token
+ :nickname => "vinny",
+ :email => "pasta@pizza.vs",
+ :fullname => "Vinny Vinesauce",
+ :bio => "streamer",
+ :password => "hiptofbees",
+ :confirm => "hiptofbees",
+ :token => invite.token
}
{:ok, user} = TwitterAPI.register_user(data)
@@ -269,13 +269,13 @@ test "returns user on success, after him registration fails" do
AccountView.render("show.json", %{user: fetched_user})
data = %{
- "nickname" => "GrimReaper",
- "email" => "death@reapers.afterlife",
- "fullname" => "Reaper Grim",
- "bio" => "Your time has come",
- "password" => "scythe",
- "confirm" => "scythe",
- "token" => invite.token
+ :nickname => "GrimReaper",
+ :email => "death@reapers.afterlife",
+ :fullname => "Reaper Grim",
+ :bio => "Your time has come",
+ :password => "scythe",
+ :confirm => "scythe",
+ :token => invite.token
}
{:error, msg} = TwitterAPI.register_user(data)
@@ -292,13 +292,13 @@ test "returns user on success" do
{:ok, invite} = UserInviteToken.create_invite(%{expires_at: Date.utc_today(), max_use: 100})
data = %{
- "nickname" => "vinny",
- "email" => "pasta@pizza.vs",
- "fullname" => "Vinny Vinesauce",
- "bio" => "streamer",
- "password" => "hiptofbees",
- "confirm" => "hiptofbees",
- "token" => invite.token
+ :nickname => "vinny",
+ :email => "pasta@pizza.vs",
+ :fullname => "Vinny Vinesauce",
+ :bio => "streamer",
+ :password => "hiptofbees",
+ :confirm => "hiptofbees",
+ :token => invite.token
}
{:ok, user} = TwitterAPI.register_user(data)
@@ -317,13 +317,13 @@ test "error after max uses" do
UserInviteToken.update_invite!(invite, uses: 99)
data = %{
- "nickname" => "vinny",
- "email" => "pasta@pizza.vs",
- "fullname" => "Vinny Vinesauce",
- "bio" => "streamer",
- "password" => "hiptofbees",
- "confirm" => "hiptofbees",
- "token" => invite.token
+ :nickname => "vinny",
+ :email => "pasta@pizza.vs",
+ :fullname => "Vinny Vinesauce",
+ :bio => "streamer",
+ :password => "hiptofbees",
+ :confirm => "hiptofbees",
+ :token => invite.token
}
{:ok, user} = TwitterAPI.register_user(data)
@@ -335,13 +335,13 @@ test "error after max uses" do
AccountView.render("show.json", %{user: fetched_user})
data = %{
- "nickname" => "GrimReaper",
- "email" => "death@reapers.afterlife",
- "fullname" => "Reaper Grim",
- "bio" => "Your time has come",
- "password" => "scythe",
- "confirm" => "scythe",
- "token" => invite.token
+ :nickname => "GrimReaper",
+ :email => "death@reapers.afterlife",
+ :fullname => "Reaper Grim",
+ :bio => "Your time has come",
+ :password => "scythe",
+ :confirm => "scythe",
+ :token => invite.token
}
{:error, msg} = TwitterAPI.register_user(data)
@@ -355,13 +355,13 @@ test "returns error on overdue date" do
UserInviteToken.create_invite(%{expires_at: Date.add(Date.utc_today(), -1), max_use: 100})
data = %{
- "nickname" => "GrimReaper",
- "email" => "death@reapers.afterlife",
- "fullname" => "Reaper Grim",
- "bio" => "Your time has come",
- "password" => "scythe",
- "confirm" => "scythe",
- "token" => invite.token
+ :nickname => "GrimReaper",
+ :email => "death@reapers.afterlife",
+ :fullname => "Reaper Grim",
+ :bio => "Your time has come",
+ :password => "scythe",
+ :confirm => "scythe",
+ :token => invite.token
}
{:error, msg} = TwitterAPI.register_user(data)
@@ -377,13 +377,13 @@ test "returns error on with overdue date and after max" do
UserInviteToken.update_invite!(invite, uses: 100)
data = %{
- "nickname" => "GrimReaper",
- "email" => "death@reapers.afterlife",
- "fullname" => "Reaper Grim",
- "bio" => "Your time has come",
- "password" => "scythe",
- "confirm" => "scythe",
- "token" => invite.token
+ :nickname => "GrimReaper",
+ :email => "death@reapers.afterlife",
+ :fullname => "Reaper Grim",
+ :bio => "Your time has come",
+ :password => "scythe",
+ :confirm => "scythe",
+ :token => invite.token
}
{:error, msg} = TwitterAPI.register_user(data)
@@ -395,11 +395,11 @@ test "returns error on with overdue date and after max" do
test "it returns the error on registration problems" do
data = %{
- "nickname" => "lain",
- "email" => "lain@wired.jp",
- "fullname" => "lain iwakura",
- "bio" => "close the world.",
- "password" => "bear"
+ :nickname => "lain",
+ :email => "lain@wired.jp",
+ :fullname => "lain iwakura",
+ :bio => "close the world.",
+ :password => "bear"
}
{:error, error_object} = TwitterAPI.register_user(data)
diff --git a/test/web/twitter_api/util_controller_test.exs b/test/web/twitter_api/util_controller_test.exs
index 30e54bebd..b701239a0 100644
--- a/test/web/twitter_api/util_controller_test.exs
+++ b/test/web/twitter_api/util_controller_test.exs
@@ -95,6 +95,30 @@ test "requires 'follow' or 'write:follows' permissions" do
end
end
end
+
+ test "it imports follows with different nickname variations", %{conn: conn} do
+ [user2, user3, user4, user5, user6] = insert_list(5, :user)
+
+ identifiers =
+ [
+ user2.ap_id,
+ user3.nickname,
+ " ",
+ "@" <> user4.nickname,
+ user5.nickname <> "@localhost",
+ "@" <> user6.nickname <> "@localhost"
+ ]
+ |> Enum.join("\n")
+
+ response =
+ conn
+ |> post("/api/pleroma/follow_import", %{"list" => identifiers})
+ |> json_response(:ok)
+
+ assert response == "job started"
+ assert [{:ok, job_result}] = ObanHelpers.perform_all()
+ assert job_result == [user2, user3, user4, user5, user6]
+ end
end
describe "POST /api/pleroma/blocks_import" do
@@ -136,6 +160,29 @@ test "it imports blocks users from file", %{user: user1, conn: conn} do
)
end
end
+
+ test "it imports blocks with different nickname variations", %{conn: conn} do
+ [user2, user3, user4, user5, user6] = insert_list(5, :user)
+
+ identifiers =
+ [
+ user2.ap_id,
+ user3.nickname,
+ "@" <> user4.nickname,
+ user5.nickname <> "@localhost",
+ "@" <> user6.nickname <> "@localhost"
+ ]
+ |> Enum.join(" ")
+
+ response =
+ conn
+ |> post("/api/pleroma/blocks_import", %{"list" => identifiers})
+ |> json_response(:ok)
+
+ assert response == "job started"
+ assert [{:ok, job_result}] = ObanHelpers.perform_all()
+ assert job_result == [user2, user3, user4, user5, user6]
+ end
end
describe "PUT /api/pleroma/notification_settings" do