@@ -39,6 +39,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). | |||||
- Logger: default log level changed from `warn` to `info`. | - Logger: default log level changed from `warn` to `info`. | ||||
- Config mix task `migrate_to_db` truncates `config` table before migrating the config file. | - Config mix task `migrate_to_db` truncates `config` table before migrating the config file. | ||||
- Default to `prepare: :unnamed` in the database configuration. | - Default to `prepare: :unnamed` in the database configuration. | ||||
- Instance stats are now loaded on startup instead of being empty until next hourly job. | |||||
<details> | <details> | ||||
<summary>API Changes</summary> | <summary>API Changes</summary> | ||||
@@ -278,6 +278,19 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret | |||||
- On failure: `Not found` | - On failure: `Not found` | ||||
- On success: JSON array of instance's latest statuses | - On success: JSON array of instance's latest statuses | ||||
## `GET /api/pleroma/admin/statuses` | |||||
### Retrives all latest statuses | |||||
- Params: | |||||
- *optional* `page_size`: number of statuses to return (default is `20`) | |||||
- *optional* `local_only`: excludes remote statuses | |||||
- *optional* `godmode`: `true`/`false` – allows to see private statuses | |||||
- *optional* `with_reblogs`: `true`/`false` – allows to see reblogs (default is false) | |||||
- Response: | |||||
- On failure: `Not found` | |||||
- On success: JSON array of user's latest statuses | |||||
## `POST /api/pleroma/admin/relay` | ## `POST /api/pleroma/admin/relay` | ||||
### Follow a Relay | ### Follow a Relay | ||||
@@ -12,6 +12,19 @@ defmodule Mix.Pleroma do | |||||
end | end | ||||
{:ok, _} = Application.ensure_all_started(:pleroma) | {:ok, _} = Application.ensure_all_started(:pleroma) | ||||
if Pleroma.Config.get(:env) not in [:test, :benchmark] do | |||||
pleroma_rebooted?() | |||||
end | |||||
end | |||||
defp pleroma_rebooted? do | |||||
if Restarter.Pleroma.rebooted?() do | |||||
:ok | |||||
else | |||||
Process.sleep(10) | |||||
pleroma_rebooted?() | |||||
end | |||||
end | end | ||||
def load_pleroma do | def load_pleroma do | ||||
@@ -45,7 +45,8 @@ defmodule Pleroma.Config.TransferTask do | |||||
@spec load_and_update_env([ConfigDB.t()]) :: :ok | false | @spec load_and_update_env([ConfigDB.t()]) :: :ok | false | ||||
def load_and_update_env(deleted \\ [], restart_pleroma? \\ true) do | def load_and_update_env(deleted \\ [], restart_pleroma? \\ true) do | ||||
with true <- Pleroma.Config.get(:configurable_from_database), | |||||
with {:configurable, true} <- | |||||
{:configurable, Pleroma.Config.get(:configurable_from_database)}, | |||||
true <- Ecto.Adapters.SQL.table_exists?(Repo, "config"), | true <- Ecto.Adapters.SQL.table_exists?(Repo, "config"), | ||||
started_applications <- Application.started_applications() do | started_applications <- Application.started_applications() do | ||||
# We need to restart applications for loaded settings take effect | # We need to restart applications for loaded settings take effect | ||||
@@ -68,12 +69,15 @@ defmodule Pleroma.Config.TransferTask do | |||||
if :pleroma in applications do | if :pleroma in applications do | ||||
List.delete(applications, :pleroma) ++ [:pleroma] | List.delete(applications, :pleroma) ++ [:pleroma] | ||||
else | else | ||||
Restarter.Pleroma.rebooted() | |||||
applications | applications | ||||
end | end | ||||
Enum.each(applications, &restart(started_applications, &1, Pleroma.Config.get(:env))) | Enum.each(applications, &restart(started_applications, &1, Pleroma.Config.get(:env))) | ||||
:ok | :ok | ||||
else | |||||
{:configurable, false} -> Restarter.Pleroma.rebooted() | |||||
end | end | ||||
end | end | ||||
@@ -10,19 +10,10 @@ defmodule Pleroma.Stats do | |||||
use GenServer | use GenServer | ||||
@init_state %{ | |||||
peers: [], | |||||
stats: %{ | |||||
domain_count: 0, | |||||
status_count: 0, | |||||
user_count: 0 | |||||
} | |||||
} | |||||
def start_link(_) do | def start_link(_) do | ||||
GenServer.start_link( | GenServer.start_link( | ||||
__MODULE__, | __MODULE__, | ||||
@init_state, | |||||
nil, | |||||
name: __MODULE__ | name: __MODULE__ | ||||
) | ) | ||||
end | end | ||||
@@ -53,8 +44,8 @@ defmodule Pleroma.Stats do | |||||
peers | peers | ||||
end | end | ||||
def init(args) do | |||||
{:ok, args} | |||||
def init(_args) do | |||||
{:ok, get_stat_data()} | |||||
end | end | ||||
def handle_call(:force_update, _from, _state) do | def handle_call(:force_update, _from, _state) do | ||||
@@ -660,7 +660,9 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do | |||||
{:ok, activity} <- insert(flag_data, local), | {:ok, activity} <- insert(flag_data, local), | ||||
{:ok, stripped_activity} <- strip_report_status_data(activity), | {:ok, stripped_activity} <- strip_report_status_data(activity), | ||||
:ok <- maybe_federate(stripped_activity) do | :ok <- maybe_federate(stripped_activity) do | ||||
Enum.each(User.all_superusers(), fn superuser -> | |||||
User.all_superusers() | |||||
|> Enum.filter(fn user -> not is_nil(user.email) end) | |||||
|> Enum.each(fn superuser -> | |||||
superuser | superuser | ||||
|> Pleroma.Emails.AdminEmail.report(actor, account, statuses, content) | |> Pleroma.Emails.AdminEmail.report(actor, account, statuses, content) | ||||
|> Pleroma.Emails.Mailer.deliver_async() | |> Pleroma.Emails.Mailer.deliver_async() | ||||
@@ -748,6 +748,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do | |||||
def list_statuses(%{assigns: %{user: admin}} = conn, params) do | def list_statuses(%{assigns: %{user: admin}} = conn, params) do | ||||
godmode = params["godmode"] == "true" || params["godmode"] == true | godmode = params["godmode"] == "true" || params["godmode"] == true | ||||
local_only = params["local_only"] == "true" || params["local_only"] == true | local_only = params["local_only"] == "true" || params["local_only"] == true | ||||
with_reblogs = params["with_reblogs"] == "true" || params["with_reblogs"] == true | |||||
{page, page_size} = page_params(params) | {page, page_size} = page_params(params) | ||||
activities = | activities = | ||||
@@ -755,7 +756,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do | |||||
"godmode" => godmode, | "godmode" => godmode, | ||||
"local_only" => local_only, | "local_only" => local_only, | ||||
"limit" => page_size, | "limit" => page_size, | ||||
"offset" => (page - 1) * page_size | |||||
"offset" => (page - 1) * page_size, | |||||
"exclude_reblogs" => !with_reblogs && "true" | |||||
}) | }) | ||||
conn | conn | ||||
@@ -70,20 +70,21 @@ defmodule Pleroma.Web.CommonAPI do | |||||
end | end | ||||
def delete(activity_id, user) do | def delete(activity_id, user) do | ||||
with %Activity{data: %{"object" => _}} = activity <- | |||||
Activity.get_by_id_with_object(activity_id), | |||||
with {_, %Activity{data: %{"object" => _}} = activity} <- | |||||
{:find_activity, Activity.get_by_id_with_object(activity_id)}, | |||||
%Object{} = object <- Object.normalize(activity), | %Object{} = object <- Object.normalize(activity), | ||||
true <- User.superuser?(user) || user.ap_id == object.data["actor"], | true <- User.superuser?(user) || user.ap_id == object.data["actor"], | ||||
{:ok, _} <- unpin(activity_id, user), | {:ok, _} <- unpin(activity_id, user), | ||||
{:ok, delete} <- ActivityPub.delete(object) do | {:ok, delete} <- ActivityPub.delete(object) do | ||||
{:ok, delete} | {:ok, delete} | ||||
else | else | ||||
{:find_activity, _} -> {:error, :not_found} | |||||
_ -> {:error, dgettext("errors", "Could not delete")} | _ -> {:error, dgettext("errors", "Could not delete")} | ||||
end | end | ||||
end | end | ||||
def repeat(id_or_ap_id, user, params \\ %{}) do | def repeat(id_or_ap_id, user, params \\ %{}) do | ||||
with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id), | |||||
with {_, %Activity{} = activity} <- {:find_activity, get_by_id_or_ap_id(id_or_ap_id)}, | |||||
object <- Object.normalize(activity), | object <- Object.normalize(activity), | ||||
announce_activity <- Utils.get_existing_announce(user.ap_id, object), | announce_activity <- Utils.get_existing_announce(user.ap_id, object), | ||||
public <- public_announce?(object, params) do | public <- public_announce?(object, params) do | ||||
@@ -93,21 +94,23 @@ defmodule Pleroma.Web.CommonAPI do | |||||
ActivityPub.announce(user, object, nil, true, public) | ActivityPub.announce(user, object, nil, true, public) | ||||
end | end | ||||
else | else | ||||
{:find_activity, _} -> {:error, :not_found} | |||||
_ -> {:error, dgettext("errors", "Could not repeat")} | _ -> {:error, dgettext("errors", "Could not repeat")} | ||||
end | end | ||||
end | end | ||||
def unrepeat(id_or_ap_id, user) do | def unrepeat(id_or_ap_id, user) do | ||||
with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id) do | |||||
with {_, %Activity{} = activity} <- {:find_activity, get_by_id_or_ap_id(id_or_ap_id)} do | |||||
object = Object.normalize(activity) | object = Object.normalize(activity) | ||||
ActivityPub.unannounce(user, object) | ActivityPub.unannounce(user, object) | ||||
else | else | ||||
{:find_activity, _} -> {:error, :not_found} | |||||
_ -> {:error, dgettext("errors", "Could not unrepeat")} | _ -> {:error, dgettext("errors", "Could not unrepeat")} | ||||
end | end | ||||
end | end | ||||
def favorite(id_or_ap_id, user) do | def favorite(id_or_ap_id, user) do | ||||
with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id), | |||||
with {_, %Activity{} = activity} <- {:find_activity, get_by_id_or_ap_id(id_or_ap_id)}, | |||||
object <- Object.normalize(activity), | object <- Object.normalize(activity), | ||||
like_activity <- Utils.get_existing_like(user.ap_id, object) do | like_activity <- Utils.get_existing_like(user.ap_id, object) do | ||||
if like_activity do | if like_activity do | ||||
@@ -116,15 +119,17 @@ defmodule Pleroma.Web.CommonAPI do | |||||
ActivityPub.like(user, object) | ActivityPub.like(user, object) | ||||
end | end | ||||
else | else | ||||
{:find_activity, _} -> {:error, :not_found} | |||||
_ -> {:error, dgettext("errors", "Could not favorite")} | _ -> {:error, dgettext("errors", "Could not favorite")} | ||||
end | end | ||||
end | end | ||||
def unfavorite(id_or_ap_id, user) do | def unfavorite(id_or_ap_id, user) do | ||||
with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id) do | |||||
with {_, %Activity{} = activity} <- {:find_activity, get_by_id_or_ap_id(id_or_ap_id)} do | |||||
object = Object.normalize(activity) | object = Object.normalize(activity) | ||||
ActivityPub.unlike(user, object) | ActivityPub.unlike(user, object) | ||||
else | else | ||||
{:find_activity, _} -> {:error, :not_found} | |||||
_ -> {:error, dgettext("errors", "Could not unfavorite")} | _ -> {:error, dgettext("errors", "Could not unfavorite")} | ||||
end | end | ||||
end | end | ||||
@@ -175,6 +175,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do | |||||
for: user, | for: user, | ||||
with_direct_conversation_id: true | with_direct_conversation_id: true | ||||
) | ) | ||||
else | |||||
_ -> {:error, :not_found} | |||||
end | end | ||||
end | end | ||||
@@ -183,6 +185,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do | |||||
with {:ok, %Activity{}} <- CommonAPI.delete(id, user) do | with {:ok, %Activity{}} <- CommonAPI.delete(id, user) do | ||||
json(conn, %{}) | json(conn, %{}) | ||||
else | else | ||||
{:error, :not_found} = e -> e | |||||
_e -> render_error(conn, :forbidden, "Can't delete this post") | _e -> render_error(conn, :forbidden, "Can't delete this post") | ||||
end | end | ||||
end | end | ||||
@@ -99,7 +99,8 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do | |||||
def password_reset(nickname_or_email) do | def password_reset(nickname_or_email) do | ||||
with true <- is_binary(nickname_or_email), | with true <- is_binary(nickname_or_email), | ||||
%User{local: true} = user <- User.get_by_nickname_or_email(nickname_or_email), | |||||
%User{local: true, email: email} = user when not is_nil(email) <- | |||||
User.get_by_nickname_or_email(nickname_or_email), | |||||
{:ok, token_record} <- Pleroma.PasswordResetToken.create_token(user) do | {:ok, token_record} <- Pleroma.PasswordResetToken.create_token(user) do | ||||
user | user | ||||
|> UserEmail.password_reset_email(token_record.token) | |> UserEmail.password_reset_email(token_record.token) | ||||
@@ -110,6 +111,9 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do | |||||
false -> | false -> | ||||
{:error, "bad user identifier"} | {:error, "bad user identifier"} | ||||
%User{local: true, email: nil} -> | |||||
{:ok, :noop} | |||||
%User{local: false} -> | %User{local: false} -> | ||||
{:error, "remote user"} | {:error, "remote user"} | ||||
@@ -31,6 +31,7 @@ defmodule Pleroma.Workers.Cron.DigestEmailsWorker do | |||||
from(u in inactive_users_query, | from(u in inactive_users_query, | ||||
where: fragment(~s(? ->'digest' @> 'true'), u.email_notifications), | where: fragment(~s(? ->'digest' @> 'true'), u.email_notifications), | ||||
where: not is_nil(u.email), | |||||
where: u.last_digest_emailed_at < datetime_add(^now, ^negative_interval, "day"), | where: u.last_digest_emailed_at < datetime_add(^now, ^negative_interval, "day"), | ||||
select: u | select: u | ||||
) | ) | ||||
@@ -51,6 +51,7 @@ defmodule Pleroma.Workers.Cron.NewUsersDigestWorker do | |||||
if users_and_statuses != [] do | if users_and_statuses != [] do | ||||
%{is_admin: true} | %{is_admin: true} | ||||
|> User.Query.build() | |> User.Query.build() | ||||
|> where([u], not is_nil(u.email)) | |||||
|> Repo.all() | |> Repo.all() | ||||
|> Enum.map(&Pleroma.Emails.NewUsersDigestEmail.new_users(&1, users_and_statuses)) | |> Enum.map(&Pleroma.Emails.NewUsersDigestEmail.new_users(&1, users_and_statuses)) | ||||
|> Enum.each(&Pleroma.Emails.Mailer.deliver/1) | |> Enum.each(&Pleroma.Emails.Mailer.deliver/1) | ||||
@@ -3,11 +3,21 @@ defmodule Restarter.Pleroma do | |||||
require Logger | require Logger | ||||
@init_state %{need_reboot: false, rebooted: false, after_boot: false} | |||||
def start_link(_) do | def start_link(_) do | ||||
GenServer.start_link(__MODULE__, [], name: __MODULE__) | GenServer.start_link(__MODULE__, [], name: __MODULE__) | ||||
end | end | ||||
def init(_), do: {:ok, %{need_reboot?: false}} | |||||
def init(_), do: {:ok, @init_state} | |||||
def rebooted? do | |||||
GenServer.call(__MODULE__, :rebooted?) | |||||
end | |||||
def rebooted do | |||||
GenServer.cast(__MODULE__, :rebooted) | |||||
end | |||||
def need_reboot? do | def need_reboot? do | ||||
GenServer.call(__MODULE__, :need_reboot?) | GenServer.call(__MODULE__, :need_reboot?) | ||||
@@ -29,41 +39,51 @@ defmodule Restarter.Pleroma do | |||||
GenServer.cast(__MODULE__, {:after_boot, env}) | GenServer.cast(__MODULE__, {:after_boot, env}) | ||||
end | end | ||||
def handle_call(:rebooted?, _from, state) do | |||||
{:reply, state[:rebooted], state} | |||||
end | |||||
def handle_call(:need_reboot?, _from, state) do | def handle_call(:need_reboot?, _from, state) do | ||||
{:reply, state[:need_reboot?], state} | |||||
{:reply, state[:need_reboot], state} | |||||
end | end | ||||
def handle_cast(:refresh, _state) do | |||||
{:noreply, %{need_reboot?: false}} | |||||
def handle_cast(:rebooted, state) do | |||||
{:noreply, Map.put(state, :rebooted, true)} | |||||
end | end | ||||
def handle_cast(:need_reboot, %{need_reboot?: true} = state), do: {:noreply, state} | |||||
def handle_cast(:need_reboot, %{need_reboot: true} = state), do: {:noreply, state} | |||||
def handle_cast(:need_reboot, state) do | def handle_cast(:need_reboot, state) do | ||||
{:noreply, Map.put(state, :need_reboot?, true)} | |||||
{:noreply, Map.put(state, :need_reboot, true)} | |||||
end | |||||
def handle_cast(:refresh, _state) do | |||||
{:noreply, @init_state} | |||||
end | end | ||||
def handle_cast({:restart, :test, _}, state) do | def handle_cast({:restart, :test, _}, state) do | ||||
Logger.debug("pleroma manually restarted") | Logger.debug("pleroma manually restarted") | ||||
{:noreply, Map.put(state, :need_reboot?, false)} | |||||
{:noreply, Map.put(state, :need_reboot, false)} | |||||
end | end | ||||
def handle_cast({:restart, _, delay}, state) do | def handle_cast({:restart, _, delay}, state) do | ||||
Process.sleep(delay) | Process.sleep(delay) | ||||
do_restart(:pleroma) | do_restart(:pleroma) | ||||
{:noreply, Map.put(state, :need_reboot?, false)} | |||||
{:noreply, Map.put(state, :need_reboot, false)} | |||||
end | end | ||||
def handle_cast({:after_boot, _}, %{after_boot: true} = state), do: {:noreply, state} | def handle_cast({:after_boot, _}, %{after_boot: true} = state), do: {:noreply, state} | ||||
def handle_cast({:after_boot, :test}, state) do | def handle_cast({:after_boot, :test}, state) do | ||||
Logger.debug("pleroma restarted after boot") | Logger.debug("pleroma restarted after boot") | ||||
{:noreply, Map.put(state, :after_boot, true)} | |||||
state = %{state | after_boot: true, rebooted: true} | |||||
{:noreply, state} | |||||
end | end | ||||
def handle_cast({:after_boot, _}, state) do | def handle_cast({:after_boot, _}, state) do | ||||
do_restart(:pleroma) | do_restart(:pleroma) | ||||
{:noreply, Map.put(state, :after_boot, true)} | |||||
state = %{state | after_boot: true, rebooted: true} | |||||
{:noreply, state} | |||||
end | end | ||||
defp do_restart(app) do | defp do_restart(app) do | ||||
@@ -1880,10 +1880,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do | |||||
"@#{admin.nickname} deleted status ##{id}" | "@#{admin.nickname} deleted status ##{id}" | ||||
end | end | ||||
test "returns error when status is not exist", %{conn: conn} do | |||||
test "returns 404 when the status does not exist", %{conn: conn} do | |||||
conn = delete(conn, "/api/pleroma/admin/statuses/test") | conn = delete(conn, "/api/pleroma/admin/statuses/test") | ||||
assert json_response(conn, :bad_request) == "Could not delete" | |||||
assert json_response(conn, :not_found) == "Not found" | |||||
end | end | ||||
end | end | ||||
@@ -85,6 +85,37 @@ defmodule Pleroma.Web.MastodonAPI.AuthControllerTest do | |||||
end | end | ||||
end | end | ||||
describe "POST /auth/password, with nickname" do | |||||
test "it returns 204", %{conn: conn} do | |||||
user = insert(:user) | |||||
assert conn | |||||
|> post("/auth/password?nickname=#{user.nickname}") | |||||
|> json_response(:no_content) | |||||
ObanHelpers.perform_all() | |||||
token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id) | |||||
email = Pleroma.Emails.UserEmail.password_reset_email(user, token_record.token) | |||||
notify_email = Config.get([:instance, :notify_email]) | |||||
instance_name = Config.get([:instance, :name]) | |||||
assert_email_sent( | |||||
from: {instance_name, notify_email}, | |||||
to: {user.name, user.email}, | |||||
html_body: email.html_body | |||||
) | |||||
end | |||||
test "it doesn't fail when a user has no email", %{conn: conn} do | |||||
user = insert(:user, %{email: nil}) | |||||
assert conn | |||||
|> post("/auth/password?nickname=#{user.nickname}") | |||||
|> json_response(:no_content) | |||||
end | |||||
end | |||||
describe "POST /auth/password, with invalid parameters" do | describe "POST /auth/password, with invalid parameters" do | ||||
setup do | setup do | ||||
user = insert(:user) | user = insert(:user) | ||||
@@ -75,4 +75,13 @@ defmodule Pleroma.Web.MastodonAPI.ReportControllerTest do | |||||
assert json_response(conn, 400) == %{"error" => "Account not found"} | assert json_response(conn, 400) == %{"error" => "Account not found"} | ||||
end | end | ||||
test "doesn't fail if an admin has no email", %{conn: conn, target_user: target_user} do | |||||
insert(:user, %{is_admin: true, email: nil}) | |||||
assert %{"action_taken" => false, "id" => _} = | |||||
conn | |||||
|> post("/api/v1/reports", %{"account_id" => target_user.id}) | |||||
|> json_response(200) | |||||
end | |||||
end | end |
@@ -476,6 +476,15 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do | |||||
assert id == to_string(activity.id) | assert id == to_string(activity.id) | ||||
end | end | ||||
test "getting a status that doesn't exist returns 404" do | |||||
%{conn: conn} = oauth_access(["read:statuses"]) | |||||
activity = insert(:note_activity) | |||||
conn = get(conn, "/api/v1/statuses/#{String.downcase(activity.id)}") | |||||
assert json_response(conn, 404) == %{"error" => "Record not found"} | |||||
end | |||||
test "get a direct status" do | test "get a direct status" do | ||||
%{user: user, conn: conn} = oauth_access(["read:statuses"]) | %{user: user, conn: conn} = oauth_access(["read:statuses"]) | ||||
other_user = insert(:user) | other_user = insert(:user) | ||||
@@ -520,6 +529,18 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do | |||||
refute Activity.get_by_id(activity.id) | refute Activity.get_by_id(activity.id) | ||||
end | end | ||||
test "when it doesn't exist" do | |||||
%{user: author, conn: conn} = oauth_access(["write:statuses"]) | |||||
activity = insert(:note_activity, user: author) | |||||
conn = | |||||
conn | |||||
|> assign(:user, author) | |||||
|> delete("/api/v1/statuses/#{String.downcase(activity.id)}") | |||||
assert %{"error" => "Record not found"} == json_response(conn, 404) | |||||
end | |||||
test "when you didn't create it" do | test "when you didn't create it" do | ||||
%{conn: conn} = oauth_access(["write:statuses"]) | %{conn: conn} = oauth_access(["write:statuses"]) | ||||
activity = insert(:note_activity) | activity = insert(:note_activity) | ||||
@@ -574,6 +595,14 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do | |||||
assert to_string(activity.id) == id | assert to_string(activity.id) == id | ||||
end | end | ||||
test "returns 404 if the reblogged status doesn't exist", %{conn: conn} do | |||||
activity = insert(:note_activity) | |||||
conn = post(conn, "/api/v1/statuses/#{String.downcase(activity.id)}/reblog") | |||||
assert %{"error" => "Record not found"} = json_response(conn, 404) | |||||
end | |||||
test "reblogs privately and returns the reblogged status", %{conn: conn} do | test "reblogs privately and returns the reblogged status", %{conn: conn} do | ||||
activity = insert(:note_activity) | activity = insert(:note_activity) | ||||
@@ -626,12 +655,6 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do | |||||
assert to_string(activity.id) == id | assert to_string(activity.id) == id | ||||
end | end | ||||
test "returns 400 error when activity is not exist", %{conn: conn} do | |||||
conn = post(conn, "/api/v1/statuses/foo/reblog") | |||||
assert json_response(conn, 400) == %{"error" => "Could not repeat"} | |||||
end | |||||
end | end | ||||
describe "unreblogging" do | describe "unreblogging" do | ||||
@@ -649,10 +672,10 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do | |||||
assert to_string(activity.id) == id | assert to_string(activity.id) == id | ||||
end | end | ||||
test "returns 400 error when activity is not exist", %{conn: conn} do | |||||
test "returns 404 error when activity does not exist", %{conn: conn} do | |||||
conn = post(conn, "/api/v1/statuses/foo/unreblog") | conn = post(conn, "/api/v1/statuses/foo/unreblog") | ||||
assert json_response(conn, 400) == %{"error" => "Could not unrepeat"} | |||||
assert json_response(conn, 404) == %{"error" => "Record not found"} | |||||
end | end | ||||
end | end | ||||
@@ -677,10 +700,10 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do | |||||
assert post(conn, "/api/v1/statuses/#{activity.id}/favourite") |> json_response(200) | assert post(conn, "/api/v1/statuses/#{activity.id}/favourite") |> json_response(200) | ||||
end | end | ||||
test "returns 400 error for a wrong id", %{conn: conn} do | |||||
test "returns 404 error for a wrong id", %{conn: conn} do | |||||
conn = post(conn, "/api/v1/statuses/1/favourite") | conn = post(conn, "/api/v1/statuses/1/favourite") | ||||
assert json_response(conn, 400) == %{"error" => "Could not favorite"} | |||||
assert json_response(conn, 404) == %{"error" => "Record not found"} | |||||
end | end | ||||
end | end | ||||
@@ -700,10 +723,10 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do | |||||
assert to_string(activity.id) == id | assert to_string(activity.id) == id | ||||
end | end | ||||
test "returns 400 error for a wrong id", %{conn: conn} do | |||||
test "returns 404 error for a wrong id", %{conn: conn} do | |||||
conn = post(conn, "/api/v1/statuses/1/unfavourite") | conn = post(conn, "/api/v1/statuses/1/unfavourite") | ||||
assert json_response(conn, 400) == %{"error" => "Could not unfavorite"} | |||||
assert json_response(conn, 404) == %{"error" => "Record not found"} | |||||
end | end | ||||
end | end | ||||
@@ -13,7 +13,7 @@ defmodule Pleroma.Workers.Cron.DigestEmailsWorkerTest do | |||||
clear_config([:email_notifications, :digest]) | clear_config([:email_notifications, :digest]) | ||||
test "it sends digest emails" do | |||||
setup do | |||||
Pleroma.Config.put([:email_notifications, :digest], %{ | Pleroma.Config.put([:email_notifications, :digest], %{ | ||||
active: true, | active: true, | ||||
inactivity_threshold: 7, | inactivity_threshold: 7, | ||||
@@ -31,6 +31,10 @@ defmodule Pleroma.Workers.Cron.DigestEmailsWorkerTest do | |||||
{:ok, _} = User.switch_email_notifications(user2, "digest", true) | {:ok, _} = User.switch_email_notifications(user2, "digest", true) | ||||
CommonAPI.post(user, %{"status" => "hey @#{user2.nickname}!"}) | CommonAPI.post(user, %{"status" => "hey @#{user2.nickname}!"}) | ||||
{:ok, user2: user2} | |||||
end | |||||
test "it sends digest emails", %{user2: user2} do | |||||
Pleroma.Workers.Cron.DigestEmailsWorker.perform(:opts, :pid) | Pleroma.Workers.Cron.DigestEmailsWorker.perform(:opts, :pid) | ||||
# Performing job(s) enqueued at previous step | # Performing job(s) enqueued at previous step | ||||
ObanHelpers.perform_all() | ObanHelpers.perform_all() | ||||
@@ -39,4 +43,12 @@ defmodule Pleroma.Workers.Cron.DigestEmailsWorkerTest do | |||||
assert email.to == [{user2.name, user2.email}] | assert email.to == [{user2.name, user2.email}] | ||||
assert email.subject == "Your digest from #{Pleroma.Config.get(:instance)[:name]}" | assert email.subject == "Your digest from #{Pleroma.Config.get(:instance)[:name]}" | ||||
end | end | ||||
test "it doesn't fail when a user has no email", %{user2: user2} do | |||||
{:ok, _} = user2 |> Ecto.Changeset.change(%{email: nil}) |> Pleroma.Repo.update() | |||||
Pleroma.Workers.Cron.DigestEmailsWorker.perform(:opts, :pid) | |||||
# Performing job(s) enqueued at previous step | |||||
ObanHelpers.perform_all() | |||||
end | |||||
end | end |
@@ -29,4 +29,16 @@ defmodule Pleroma.Workers.Cron.NewUsersDigestWorkerTest do | |||||
assert email.html_body =~ user2.nickname | assert email.html_body =~ user2.nickname | ||||
assert email.html_body =~ "cofe" | assert email.html_body =~ "cofe" | ||||
end | end | ||||
test "it doesn't fail when admin has no email" do | |||||
yesterday = NaiveDateTime.utc_now() |> Timex.shift(days: -1) | |||||
insert(:user, %{is_admin: true, email: nil}) | |||||
insert(:user, %{inserted_at: yesterday}) | |||||
user = insert(:user, %{inserted_at: yesterday}) | |||||
CommonAPI.post(user, %{"status" => "cofe"}) | |||||
NewUsersDigestWorker.perform(nil, nil) | |||||
ObanHelpers.perform_all() | |||||
end | |||||
end | end |