Merge branch 'feature/reports' into 'develop'
Reports Closes #83 See merge request pleroma/pleroma!701
This commit is contained in:
commit
54f9e3d382
|
@ -164,7 +164,8 @@
|
||||||
max_pinned_statuses: 1,
|
max_pinned_statuses: 1,
|
||||||
no_attachment_links: false,
|
no_attachment_links: false,
|
||||||
welcome_user_nickname: nil,
|
welcome_user_nickname: nil,
|
||||||
welcome_message: nil
|
welcome_message: nil,
|
||||||
|
max_report_comment_size: 1000
|
||||||
|
|
||||||
config :pleroma, :markup,
|
config :pleroma, :markup,
|
||||||
# XXX - unfortunately, inline images must be enabled by default right now, because
|
# XXX - unfortunately, inline images must be enabled by default right now, because
|
||||||
|
@ -340,7 +341,8 @@
|
||||||
|
|
||||||
config :pleroma, Pleroma.Jobs,
|
config :pleroma, Pleroma.Jobs,
|
||||||
federator_incoming: [max_jobs: 50],
|
federator_incoming: [max_jobs: 50],
|
||||||
federator_outgoing: [max_jobs: 50]
|
federator_outgoing: [max_jobs: 50],
|
||||||
|
mailer: [max_jobs: 10]
|
||||||
|
|
||||||
# Import environment specific config. This must remain at the bottom
|
# Import environment specific config. This must remain at the bottom
|
||||||
# of this file so it overrides the configuration defined above.
|
# of this file so it overrides the configuration defined above.
|
||||||
|
|
|
@ -100,6 +100,7 @@ config :pleroma, Pleroma.Mailer,
|
||||||
* `no_attachment_links`: Set to true to disable automatically adding attachment link text to statuses
|
* `no_attachment_links`: Set to true to disable automatically adding attachment link text to statuses
|
||||||
* `welcome_message`: A message that will be send to a newly registered users as a direct message.
|
* `welcome_message`: A message that will be send to a newly registered users as a direct message.
|
||||||
* `welcome_user_nickname`: The nickname of the local user that sends the welcome message.
|
* `welcome_user_nickname`: The nickname of the local user that sends the welcome message.
|
||||||
|
* `max_report_size`: The maximum size of the report comment (Default: `1000`)
|
||||||
|
|
||||||
## :logger
|
## :logger
|
||||||
* `backends`: `:console` is used to send logs to stdout, `{ExSyslogger, :ex_syslogger}` to log to syslog
|
* `backends`: `:console` is used to send logs to stdout, `{ExSyslogger, :ex_syslogger}` to log to syslog
|
||||||
|
|
|
@ -113,4 +113,14 @@ def mastodon_notification_type(%Activity{data: %{"type" => unquote(ap_type)}}),
|
||||||
end
|
end
|
||||||
|
|
||||||
def mastodon_notification_type(%Activity{}), do: nil
|
def mastodon_notification_type(%Activity{}), do: nil
|
||||||
|
|
||||||
|
def all_by_actor_and_id(actor, status_ids \\ [])
|
||||||
|
def all_by_actor_and_id(_actor, []), do: []
|
||||||
|
|
||||||
|
def all_by_actor_and_id(actor, status_ids) do
|
||||||
|
Activity
|
||||||
|
|> where([s], s.id in ^status_ids)
|
||||||
|
|> where([s], s.actor == ^actor)
|
||||||
|
|> Repo.all()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.AdminEmail do
|
||||||
|
@moduledoc "Admin emails"
|
||||||
|
|
||||||
|
import Swoosh.Email
|
||||||
|
|
||||||
|
alias Pleroma.Web.Router.Helpers
|
||||||
|
|
||||||
|
defp instance_config, do: Pleroma.Config.get(:instance)
|
||||||
|
defp instance_name, do: instance_config()[:name]
|
||||||
|
defp instance_email, do: instance_config()[:email]
|
||||||
|
|
||||||
|
defp user_url(user) do
|
||||||
|
Helpers.o_status_url(Pleroma.Web.Endpoint, :feed_redirect, user.nickname)
|
||||||
|
end
|
||||||
|
|
||||||
|
def report(to, reporter, account, statuses, comment) do
|
||||||
|
comment_html =
|
||||||
|
if comment do
|
||||||
|
"<p>Comment: #{comment}"
|
||||||
|
else
|
||||||
|
""
|
||||||
|
end
|
||||||
|
|
||||||
|
statuses_html =
|
||||||
|
if length(statuses) > 0 do
|
||||||
|
statuses_list_html =
|
||||||
|
statuses
|
||||||
|
|> Enum.map(fn %{id: id} ->
|
||||||
|
status_url = Helpers.o_status_url(Pleroma.Web.Endpoint, :notice, id)
|
||||||
|
"<li><a href=\"#{status_url}\">#{status_url}</li>"
|
||||||
|
end)
|
||||||
|
|> Enum.join("\n")
|
||||||
|
|
||||||
|
"""
|
||||||
|
<p> Statuses:
|
||||||
|
<ul>
|
||||||
|
#{statuses_list_html}
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
"""
|
||||||
|
else
|
||||||
|
""
|
||||||
|
end
|
||||||
|
|
||||||
|
html_body = """
|
||||||
|
<p>Reported by: <a href="#{user_url(reporter)}">#{reporter.nickname}</a></p>
|
||||||
|
<p>Reported Account: <a href="#{user_url(account)}">#{account.nickname}</a></p>
|
||||||
|
#{comment_html}
|
||||||
|
#{statuses_html}
|
||||||
|
"""
|
||||||
|
|
||||||
|
new()
|
||||||
|
|> to({to.name, to.email})
|
||||||
|
|> from({instance_name(), instance_email()})
|
||||||
|
|> reply_to({reporter.name, reporter.email})
|
||||||
|
|> subject("#{instance_name()} Report")
|
||||||
|
|> html_body(html_body)
|
||||||
|
end
|
||||||
|
end
|
|
@ -4,4 +4,10 @@
|
||||||
|
|
||||||
defmodule Pleroma.Mailer do
|
defmodule Pleroma.Mailer do
|
||||||
use Swoosh.Mailer, otp_app: :pleroma
|
use Swoosh.Mailer, otp_app: :pleroma
|
||||||
|
|
||||||
|
def deliver_async(email, config \\ []) do
|
||||||
|
Pleroma.Jobs.enqueue(:mailer, __MODULE__, [:deliver_async, email, config])
|
||||||
|
end
|
||||||
|
|
||||||
|
def perform(:deliver_async, email, config), do: deliver(email, config)
|
||||||
end
|
end
|
||||||
|
|
|
@ -273,7 +273,7 @@ def try_send_confirmation_email(%User{} = user) do
|
||||||
Pleroma.Config.get([:instance, :account_activation_required]) do
|
Pleroma.Config.get([:instance, :account_activation_required]) do
|
||||||
user
|
user
|
||||||
|> Pleroma.UserEmail.account_confirmation_email()
|
|> Pleroma.UserEmail.account_confirmation_email()
|
||||||
|> Pleroma.Mailer.deliver()
|
|> Pleroma.Mailer.deliver_async()
|
||||||
else
|
else
|
||||||
{:ok, :noop}
|
{:ok, :noop}
|
||||||
end
|
end
|
||||||
|
@ -1284,4 +1284,13 @@ def error_user(ap_id) do
|
||||||
inserted_at: NaiveDateTime.utc_now()
|
inserted_at: NaiveDateTime.utc_now()
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def all_superusers do
|
||||||
|
from(
|
||||||
|
u in User,
|
||||||
|
where: u.local == true,
|
||||||
|
where: fragment("?->'is_admin' @> 'true' OR ?->'is_moderator' @> 'true'", u.info, u.info)
|
||||||
|
)
|
||||||
|
|> Repo.all()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -353,6 +353,31 @@ def unblock(blocker, blocked, activity_id \\ nil, local \\ true) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def flag(
|
||||||
|
%{
|
||||||
|
actor: actor,
|
||||||
|
context: context,
|
||||||
|
account: account,
|
||||||
|
statuses: statuses,
|
||||||
|
content: content
|
||||||
|
} = params
|
||||||
|
) do
|
||||||
|
additional = params[:additional] || %{}
|
||||||
|
|
||||||
|
# only accept false as false value
|
||||||
|
local = !(params[:local] == false)
|
||||||
|
|
||||||
|
%{
|
||||||
|
actor: actor,
|
||||||
|
context: context,
|
||||||
|
account: account,
|
||||||
|
statuses: statuses,
|
||||||
|
content: content
|
||||||
|
}
|
||||||
|
|> make_flag_data(additional)
|
||||||
|
|> insert(local)
|
||||||
|
end
|
||||||
|
|
||||||
def fetch_activities_for_context(context, opts \\ %{}) do
|
def fetch_activities_for_context(context, opts \\ %{}) do
|
||||||
public = ["https://www.w3.org/ns/activitystreams#Public"]
|
public = ["https://www.w3.org/ns/activitystreams#Public"]
|
||||||
|
|
||||||
|
|
|
@ -598,4 +598,20 @@ def make_create_data(params, additional) do
|
||||||
}
|
}
|
||||||
|> Map.merge(additional)
|
|> Map.merge(additional)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#### Flag-related helpers
|
||||||
|
|
||||||
|
def make_flag_data(params, additional) do
|
||||||
|
status_ap_ids = Enum.map(params.statuses || [], & &1.data["id"])
|
||||||
|
object = [params.account.ap_id] ++ status_ap_ids
|
||||||
|
|
||||||
|
%{
|
||||||
|
"type" => "Flag",
|
||||||
|
"actor" => params.actor.ap_id,
|
||||||
|
"content" => params.content,
|
||||||
|
"object" => object,
|
||||||
|
"context" => params.context
|
||||||
|
}
|
||||||
|
|> Map.merge(additional)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -243,4 +243,31 @@ def thread_muted?(user, activity) do
|
||||||
_ -> true
|
_ -> true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def report(user, data) do
|
||||||
|
with {:account_id, %{"account_id" => account_id}} <- {:account_id, data},
|
||||||
|
{:account, %User{} = account} <- {:account, User.get_by_id(account_id)},
|
||||||
|
{:ok, content_html} <- make_report_content_html(data["comment"]),
|
||||||
|
{:ok, statuses} <- get_report_statuses(account, data),
|
||||||
|
{:ok, activity} <-
|
||||||
|
ActivityPub.flag(%{
|
||||||
|
context: Utils.generate_context_id(),
|
||||||
|
actor: user,
|
||||||
|
account: account,
|
||||||
|
statuses: statuses,
|
||||||
|
content: content_html
|
||||||
|
}) do
|
||||||
|
Enum.each(User.all_superusers(), fn superuser ->
|
||||||
|
superuser
|
||||||
|
|> Pleroma.AdminEmail.report(user, account, statuses, content_html)
|
||||||
|
|> Pleroma.Mailer.deliver_async()
|
||||||
|
end)
|
||||||
|
|
||||||
|
{:ok, activity}
|
||||||
|
else
|
||||||
|
{:error, err} -> {:error, err}
|
||||||
|
{:account_id, %{}} -> {:error, "Valid `account_id` required"}
|
||||||
|
{:account, nil} -> {:error, "Account not found"}
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -322,4 +322,22 @@ def maybe_extract_mentions(%{"tag" => tag}) do
|
||||||
end
|
end
|
||||||
|
|
||||||
def maybe_extract_mentions(_), do: []
|
def maybe_extract_mentions(_), do: []
|
||||||
|
|
||||||
|
def make_report_content_html(nil), do: {:ok, nil}
|
||||||
|
|
||||||
|
def make_report_content_html(comment) do
|
||||||
|
max_size = Pleroma.Config.get([:instance, :max_report_comment_size], 1000)
|
||||||
|
|
||||||
|
if String.length(comment) <= max_size do
|
||||||
|
{:ok, format_input(comment, [], [], "text/plain")}
|
||||||
|
else
|
||||||
|
{:error, "Comment must be up to #{max_size} characters"}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_report_statuses(%User{ap_id: actor}, %{"status_ids" => status_ids}) do
|
||||||
|
{:ok, Activity.all_by_actor_and_id(actor, status_ids)}
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_report_statuses(_, _), do: {:ok, nil}
|
||||||
end
|
end
|
||||||
|
|
|
@ -24,6 +24,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
||||||
alias Pleroma.Web.MastodonAPI.MastodonView
|
alias Pleroma.Web.MastodonAPI.MastodonView
|
||||||
alias Pleroma.Web.MastodonAPI.PushSubscriptionView
|
alias Pleroma.Web.MastodonAPI.PushSubscriptionView
|
||||||
alias Pleroma.Web.MastodonAPI.StatusView
|
alias Pleroma.Web.MastodonAPI.StatusView
|
||||||
|
alias Pleroma.Web.MastodonAPI.ReportView
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
alias Pleroma.Web.ActivityPub.Utils
|
alias Pleroma.Web.ActivityPub.Utils
|
||||||
alias Pleroma.Web.OAuth.App
|
alias Pleroma.Web.OAuth.App
|
||||||
|
@ -1533,6 +1534,20 @@ def status_card(conn, %{"id" => status_id}) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def reports(%{assigns: %{user: user}} = conn, params) do
|
||||||
|
case CommonAPI.report(user, params) do
|
||||||
|
{:ok, activity} ->
|
||||||
|
conn
|
||||||
|
|> put_view(ReportView)
|
||||||
|
|> try_render("report.json", %{activity: activity})
|
||||||
|
|
||||||
|
{:error, err} ->
|
||||||
|
conn
|
||||||
|
|> put_status(:bad_request)
|
||||||
|
|> json(%{error: err})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def try_render(conn, target, params)
|
def try_render(conn, target, params)
|
||||||
when is_binary(target) do
|
when is_binary(target) do
|
||||||
res = render(conn, target, params)
|
res = render(conn, target, params)
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.MastodonAPI.ReportView do
|
||||||
|
use Pleroma.Web, :view
|
||||||
|
|
||||||
|
def render("report.json", %{activity: activity}) do
|
||||||
|
%{
|
||||||
|
id: to_string(activity.id),
|
||||||
|
action_taken: false
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
|
@ -275,6 +275,8 @@ defmodule Pleroma.Web.Router do
|
||||||
delete("/filters/:id", MastodonAPIController, :delete_filter)
|
delete("/filters/:id", MastodonAPIController, :delete_filter)
|
||||||
|
|
||||||
post("/pleroma/flavour/:flavour", MastodonAPIController, :set_flavour)
|
post("/pleroma/flavour/:flavour", MastodonAPIController, :set_flavour)
|
||||||
|
|
||||||
|
post("/reports", MastodonAPIController, :reports)
|
||||||
end
|
end
|
||||||
|
|
||||||
scope [] do
|
scope [] do
|
||||||
|
|
|
@ -216,7 +216,7 @@ def password_reset(nickname_or_email) do
|
||||||
{: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)
|
||||||
|> Mailer.deliver()
|
|> Mailer.deliver_async()
|
||||||
else
|
else
|
||||||
false ->
|
false ->
|
||||||
{:error, "bad user identifier"}
|
{:error, "bad user identifier"}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
defmodule Pleroma.Repo.Migrations.UsersAddIsAdminIndex do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def change do
|
||||||
|
create(index(:users, ["(info->'is_admin')"], name: :users_is_admin_index, using: :gin))
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,5 +1,5 @@
|
||||||
# Pleroma: A lightweight social networking server
|
# Pleroma: A lightweight social networking server
|
||||||
# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
|
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
||||||
|
@ -742,6 +742,37 @@ test "returned pinned statuses" do
|
||||||
assert 3 = length(activities)
|
assert 3 = length(activities)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "it can create a Flag activity" do
|
||||||
|
reporter = insert(:user)
|
||||||
|
target_account = insert(:user)
|
||||||
|
{:ok, activity} = CommonAPI.post(target_account, %{"status" => "foobar"})
|
||||||
|
context = Utils.generate_context_id()
|
||||||
|
content = "foobar"
|
||||||
|
|
||||||
|
reporter_ap_id = reporter.ap_id
|
||||||
|
target_ap_id = target_account.ap_id
|
||||||
|
activity_ap_id = activity.data["id"]
|
||||||
|
|
||||||
|
assert {:ok, activity} =
|
||||||
|
ActivityPub.flag(%{
|
||||||
|
actor: reporter,
|
||||||
|
context: context,
|
||||||
|
account: target_account,
|
||||||
|
statuses: [activity],
|
||||||
|
content: content
|
||||||
|
})
|
||||||
|
|
||||||
|
assert %Activity{
|
||||||
|
actor: ^reporter_ap_id,
|
||||||
|
data: %{
|
||||||
|
"type" => "Flag",
|
||||||
|
"content" => ^content,
|
||||||
|
"context" => ^context,
|
||||||
|
"object" => [^target_ap_id, ^activity_ap_id]
|
||||||
|
}
|
||||||
|
} = activity
|
||||||
|
end
|
||||||
|
|
||||||
describe "publish_one/1" do
|
describe "publish_one/1" do
|
||||||
test_with_mock "calls `Instances.set_reachable` on successful federation if `unreachable_since` is not specified",
|
test_with_mock "calls `Instances.set_reachable` on successful federation if `unreachable_since` is not specified",
|
||||||
Instances,
|
Instances,
|
||||||
|
|
|
@ -190,4 +190,35 @@ test "check that mutes can't be duplicate", %{user: user, activity: activity} do
|
||||||
{:error, _} = CommonAPI.add_mute(user, activity)
|
{:error, _} = CommonAPI.add_mute(user, activity)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "reports" do
|
||||||
|
test "creates a report" do
|
||||||
|
reporter = insert(:user)
|
||||||
|
target_user = insert(:user)
|
||||||
|
|
||||||
|
{:ok, activity} = CommonAPI.post(target_user, %{"status" => "foobar"})
|
||||||
|
|
||||||
|
reporter_ap_id = reporter.ap_id
|
||||||
|
target_ap_id = target_user.ap_id
|
||||||
|
activity_ap_id = activity.data["id"]
|
||||||
|
comment = "foobar"
|
||||||
|
|
||||||
|
report_data = %{
|
||||||
|
"account_id" => target_user.id,
|
||||||
|
"comment" => comment,
|
||||||
|
"status_ids" => [activity.id]
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {:ok, flag_activity} = CommonAPI.report(reporter, report_data)
|
||||||
|
|
||||||
|
assert %Activity{
|
||||||
|
actor: ^reporter_ap_id,
|
||||||
|
data: %{
|
||||||
|
"type" => "Flag",
|
||||||
|
"content" => ^comment,
|
||||||
|
"object" => [^target_ap_id, ^activity_ap_id]
|
||||||
|
}
|
||||||
|
} = flag_activity
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1855,4 +1855,69 @@ test "flavours switching (Pleroma Extension)", %{conn: conn} do
|
||||||
|
|
||||||
assert json_response(set_flavour, 200) == json_response(get_new_flavour, 200)
|
assert json_response(set_flavour, 200) == json_response(get_new_flavour, 200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "reports" do
|
||||||
|
setup do
|
||||||
|
reporter = insert(:user)
|
||||||
|
target_user = insert(:user)
|
||||||
|
|
||||||
|
{:ok, activity} = CommonAPI.post(target_user, %{"status" => "foobar"})
|
||||||
|
|
||||||
|
[reporter: reporter, target_user: target_user, activity: activity]
|
||||||
|
end
|
||||||
|
|
||||||
|
test "submit a basic report", %{conn: conn, reporter: reporter, target_user: target_user} do
|
||||||
|
assert %{"action_taken" => false, "id" => _} =
|
||||||
|
conn
|
||||||
|
|> assign(:user, reporter)
|
||||||
|
|> post("/api/v1/reports", %{"account_id" => target_user.id})
|
||||||
|
|> json_response(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "submit a report with statuses and comment", %{
|
||||||
|
conn: conn,
|
||||||
|
reporter: reporter,
|
||||||
|
target_user: target_user,
|
||||||
|
activity: activity
|
||||||
|
} do
|
||||||
|
assert %{"action_taken" => false, "id" => _} =
|
||||||
|
conn
|
||||||
|
|> assign(:user, reporter)
|
||||||
|
|> post("/api/v1/reports", %{
|
||||||
|
"account_id" => target_user.id,
|
||||||
|
"status_ids" => [activity.id],
|
||||||
|
"comment" => "bad status!"
|
||||||
|
})
|
||||||
|
|> json_response(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "accound_id is required", %{
|
||||||
|
conn: conn,
|
||||||
|
reporter: reporter,
|
||||||
|
activity: activity
|
||||||
|
} do
|
||||||
|
assert %{"error" => "Valid `account_id` required"} =
|
||||||
|
conn
|
||||||
|
|> assign(:user, reporter)
|
||||||
|
|> post("/api/v1/reports", %{"status_ids" => [activity.id]})
|
||||||
|
|> json_response(400)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "comment must be up to the size specified in the config", %{
|
||||||
|
conn: conn,
|
||||||
|
reporter: reporter,
|
||||||
|
target_user: target_user
|
||||||
|
} do
|
||||||
|
max_size = Pleroma.Config.get([:instance, :max_report_comment_size], 1000)
|
||||||
|
comment = String.pad_trailing("a", max_size + 1, "a")
|
||||||
|
|
||||||
|
error = %{"error" => "Comment must be up to #{max_size} characters"}
|
||||||
|
|
||||||
|
assert ^error =
|
||||||
|
conn
|
||||||
|
|> assign(:user, reporter)
|
||||||
|
|> post("/api/v1/reports", %{"account_id" => target_user.id, "comment" => comment})
|
||||||
|
|> json_response(400)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue