Merge branch 'instance_rules' into 'develop'

Instance rules

See merge request pleroma/pleroma!3669
This commit is contained in:
feld 2024-05-15 20:29:04 +00:00
commit 53ef576739
27 changed files with 758 additions and 14 deletions

View File

@ -0,0 +1 @@
Add instance rules

View File

@ -1751,3 +1751,53 @@ Note that this differs from the Mastodon API variant: Mastodon API only returns
```json ```json
{} {}
``` ```
## `GET /api/v1/pleroma/admin/rules`
### List rules
- Response: JSON, list of rules
```json
[
{
"id": "1",
"priority": 1,
"text": "There are no rules",
"hint": null
}
]
```
## `POST /api/v1/pleroma/admin/rules`
### Create a rule
- Params:
- `text`: string, required, rule content
- `hint`: string, optional, rule description
- `priority`: integer, optional, rule ordering priority
- Response: JSON, a single rule
## `PATCH /api/v1/pleroma/admin/rules/:id`
### Update a rule
- Params:
- `text`: string, optional, rule content
- `hint`: string, optional, rule description
- `priority`: integer, optional, rule ordering priority
- Response: JSON, a single rule
## `DELETE /api/v1/pleroma/admin/rules/:id`
### Delete a rule
- Response: JSON, empty object
```json
{}
```

View File

@ -19,7 +19,8 @@ defmodule Pleroma.Constants do
"context_id", "context_id",
"deleted_activity_id", "deleted_activity_id",
"pleroma_internal", "pleroma_internal",
"generator" "generator",
"rules"
] ]
) )

68
lib/pleroma/rule.ex Normal file
View File

@ -0,0 +1,68 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Rule do
use Ecto.Schema
import Ecto.Changeset
import Ecto.Query
alias Pleroma.Repo
alias Pleroma.Rule
schema "rules" do
field(:priority, :integer, default: 0)
field(:text, :string)
field(:hint, :string)
timestamps()
end
def changeset(%Rule{} = rule, params \\ %{}) do
rule
|> cast(params, [:priority, :text, :hint])
|> validate_required([:text])
end
def query do
Rule
|> order_by(asc: :priority)
|> order_by(asc: :id)
end
def get(ids) when is_list(ids) do
from(r in __MODULE__, where: r.id in ^ids)
|> Repo.all()
end
def get(id), do: Repo.get(__MODULE__, id)
def exists?(id) do
from(r in __MODULE__, where: r.id == ^id)
|> Repo.exists?()
end
def create(params) do
{:ok, rule} =
%Rule{}
|> changeset(params)
|> Repo.insert()
rule
end
def update(params, id) do
{:ok, rule} =
get(id)
|> changeset(params)
|> Repo.update()
rule
end
def delete(id) do
get(id)
|> Repo.delete()
end
end

View File

@ -1260,6 +1260,15 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
defp restrict_quote_url(query, _), do: query defp restrict_quote_url(query, _), do: query
defp restrict_rule(query, %{rule_id: rule_id}) do
from(
activity in query,
where: fragment("(?)->'rules' \\? (?)", activity.data, ^rule_id)
)
end
defp restrict_rule(query, _), do: query
defp exclude_poll_votes(query, %{include_poll_votes: true}), do: query defp exclude_poll_votes(query, %{include_poll_votes: true}), do: query
defp exclude_poll_votes(query, _) do defp exclude_poll_votes(query, _) do
@ -1422,6 +1431,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|> restrict_instance(opts) |> restrict_instance(opts)
|> restrict_announce_object_actor(opts) |> restrict_announce_object_actor(opts)
|> restrict_filtered(opts) |> restrict_filtered(opts)
|> restrict_rule(opts)
|> restrict_quote_url(opts) |> restrict_quote_url(opts)
|> maybe_restrict_deactivated_users(opts) |> maybe_restrict_deactivated_users(opts)
|> exclude_poll_votes(opts) |> exclude_poll_votes(opts)

View File

@ -721,14 +721,18 @@ defmodule Pleroma.Web.ActivityPub.Utils do
#### Flag-related helpers #### Flag-related helpers
@spec make_flag_data(map(), map()) :: map() @spec make_flag_data(map(), map()) :: map()
def make_flag_data(%{actor: actor, context: context, content: content} = params, additional) do def make_flag_data(
%{actor: actor, context: context, content: content} = params,
additional
) do
%{ %{
"type" => "Flag", "type" => "Flag",
"actor" => actor.ap_id, "actor" => actor.ap_id,
"content" => content, "content" => content,
"object" => build_flag_object(params), "object" => build_flag_object(params),
"context" => context, "context" => context,
"state" => "open" "state" => "open",
"rules" => Map.get(params, :rules, nil)
} }
|> Map.merge(additional) |> Map.merge(additional)
end end

View File

@ -0,0 +1,62 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.AdminAPI.RuleController do
use Pleroma.Web, :controller
alias Pleroma.Repo
alias Pleroma.Rule
alias Pleroma.Web.Plugs.OAuthScopesPlug
import Pleroma.Web.ControllerHelper,
only: [
json_response: 3
]
plug(Pleroma.Web.ApiSpec.CastAndValidate)
plug(
OAuthScopesPlug,
%{scopes: ["admin:write"]}
when action in [:create, :update, :delete]
)
plug(OAuthScopesPlug, %{scopes: ["admin:read"]} when action == :index)
action_fallback(AdminAPI.FallbackController)
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.Admin.RuleOperation
def index(conn, _) do
rules =
Rule.query()
|> Repo.all()
render(conn, "index.json", rules: rules)
end
def create(%{body_params: params} = conn, _) do
rule =
params
|> Rule.create()
render(conn, "show.json", rule: rule)
end
def update(%{body_params: params} = conn, %{id: id}) do
rule =
params
|> Rule.update(id)
render(conn, "show.json", rule: rule)
end
def delete(conn, %{id: id}) do
with {:ok, _} <- Rule.delete(id) do
json(conn, %{})
else
_ -> json_response(conn, :bad_request, "")
end
end
end

View File

@ -6,9 +6,11 @@ defmodule Pleroma.Web.AdminAPI.ReportView do
use Pleroma.Web, :view use Pleroma.Web, :view
alias Pleroma.HTML alias Pleroma.HTML
alias Pleroma.Rule
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.AdminAPI alias Pleroma.Web.AdminAPI
alias Pleroma.Web.AdminAPI.Report alias Pleroma.Web.AdminAPI.Report
alias Pleroma.Web.AdminAPI.RuleView
alias Pleroma.Web.CommonAPI.Utils alias Pleroma.Web.CommonAPI.Utils
alias Pleroma.Web.MastodonAPI.StatusView alias Pleroma.Web.MastodonAPI.StatusView
@ -46,7 +48,8 @@ defmodule Pleroma.Web.AdminAPI.ReportView do
as: :activity as: :activity
}), }),
state: report.data["state"], state: report.data["state"],
notes: render(__MODULE__, "index_notes.json", %{notes: report.report_notes}) notes: render(__MODULE__, "index_notes.json", %{notes: report.report_notes}),
rules: rules(Map.get(report.data, "rules", nil))
} }
end end
@ -71,4 +74,16 @@ defmodule Pleroma.Web.AdminAPI.ReportView do
created_at: Utils.to_masto_date(inserted_at) created_at: Utils.to_masto_date(inserted_at)
} }
end end
defp rules(nil) do
[]
end
defp rules(rule_ids) do
rules =
rule_ids
|> Rule.get()
render(RuleView, "index.json", rules: rules)
end
end end

View File

@ -0,0 +1,22 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.AdminAPI.RuleView do
use Pleroma.Web, :view
require Pleroma.Constants
def render("index.json", %{rules: rules} = _opts) do
render_many(rules, __MODULE__, "show.json")
end
def render("show.json", %{rule: rule} = _opts) do
%{
id: to_string(rule.id),
priority: rule.priority,
text: rule.text,
hint: rule.hint
}
end
end

View File

@ -97,6 +97,7 @@ defmodule Pleroma.Web.ApiSpec do
"Frontend management", "Frontend management",
"Instance configuration", "Instance configuration",
"Instance documents", "Instance documents",
"Instance rule managment",
"Invites", "Invites",
"MediaProxy cache", "MediaProxy cache",
"OAuth application management", "OAuth application management",

View File

@ -30,6 +30,12 @@ defmodule Pleroma.Web.ApiSpec.Admin.ReportOperation do
report_state(), report_state(),
"Filter by report state" "Filter by report state"
), ),
Operation.parameter(
:rule_id,
:query,
%Schema{type: :string},
"Filter by selected rule id"
),
Operation.parameter( Operation.parameter(
:limit, :limit,
:query, :query,
@ -169,6 +175,17 @@ defmodule Pleroma.Web.ApiSpec.Admin.ReportOperation do
inserted_at: %Schema{type: :string, format: :"date-time"} inserted_at: %Schema{type: :string, format: :"date-time"}
} }
} }
},
rules: %Schema{
type: :array,
items: %Schema{
type: :object,
properties: %{
id: %Schema{type: :string},
text: %Schema{type: :string},
hint: %Schema{type: :string, nullable: true}
}
}
} }
} }
} }

View File

@ -0,0 +1,115 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ApiSpec.Admin.RuleOperation do
alias OpenApiSpex.Operation
alias OpenApiSpex.Schema
alias Pleroma.Web.ApiSpec.Schemas.ApiError
import Pleroma.Web.ApiSpec.Helpers
def open_api_operation(action) do
operation = String.to_existing_atom("#{action}_operation")
apply(__MODULE__, operation, [])
end
def index_operation do
%Operation{
tags: ["Instance rule managment"],
summary: "Retrieve list of instance rules",
operationId: "AdminAPI.RuleController.index",
security: [%{"oAuth" => ["admin:read"]}],
responses: %{
200 =>
Operation.response("Response", "application/json", %Schema{
type: :array,
items: rule()
}),
403 => Operation.response("Forbidden", "application/json", ApiError)
}
}
end
def create_operation do
%Operation{
tags: ["Instance rule managment"],
summary: "Create new rule",
operationId: "AdminAPI.RuleController.create",
security: [%{"oAuth" => ["admin:write"]}],
parameters: admin_api_params(),
requestBody: request_body("Parameters", create_request(), required: true),
responses: %{
200 => Operation.response("Response", "application/json", rule()),
400 => Operation.response("Bad Request", "application/json", ApiError),
403 => Operation.response("Forbidden", "application/json", ApiError)
}
}
end
def update_operation do
%Operation{
tags: ["Instance rule managment"],
summary: "Modify existing rule",
operationId: "AdminAPI.RuleController.update",
security: [%{"oAuth" => ["admin:write"]}],
parameters: [Operation.parameter(:id, :path, :string, "Rule ID")],
requestBody: request_body("Parameters", update_request(), required: true),
responses: %{
200 => Operation.response("Response", "application/json", rule()),
400 => Operation.response("Bad Request", "application/json", ApiError),
403 => Operation.response("Forbidden", "application/json", ApiError)
}
}
end
def delete_operation do
%Operation{
tags: ["Instance rule managment"],
summary: "Delete rule",
operationId: "AdminAPI.RuleController.delete",
parameters: [Operation.parameter(:id, :path, :string, "Rule ID")],
security: [%{"oAuth" => ["admin:write"]}],
responses: %{
200 => empty_object_response(),
404 => Operation.response("Not Found", "application/json", ApiError),
403 => Operation.response("Forbidden", "application/json", ApiError)
}
}
end
defp create_request do
%Schema{
type: :object,
required: [:text],
properties: %{
priority: %Schema{type: :integer},
text: %Schema{type: :string},
hint: %Schema{type: :string}
}
}
end
defp update_request do
%Schema{
type: :object,
properties: %{
priority: %Schema{type: :integer},
text: %Schema{type: :string},
hint: %Schema{type: :string}
}
}
end
defp rule do
%Schema{
type: :object,
properties: %{
id: %Schema{type: :string},
priority: %Schema{type: :integer},
text: %Schema{type: :string},
hint: %Schema{type: :string, nullable: true}
}
}
end
end

View File

@ -46,6 +46,17 @@ defmodule Pleroma.Web.ApiSpec.InstanceOperation do
} }
end end
def rules_operation do
%Operation{
tags: ["Instance misc"],
summary: "Retrieve list of instance rules",
operationId: "InstanceController.rules",
responses: %{
200 => Operation.response("Array of domains", "application/json", array_of_rules())
}
}
end
defp instance do defp instance do
%Schema{ %Schema{
type: :object, type: :object,
@ -181,7 +192,8 @@ defmodule Pleroma.Web.ApiSpec.InstanceOperation do
"urls" => %{ "urls" => %{
"streaming_api" => "wss://lain.com" "streaming_api" => "wss://lain.com"
}, },
"version" => "2.7.2 (compatible; Pleroma 2.0.50-536-g25eec6d7-develop)" "version" => "2.7.2 (compatible; Pleroma 2.0.50-536-g25eec6d7-develop)",
"rules" => array_of_rules()
} }
} }
end end
@ -371,4 +383,18 @@ defmodule Pleroma.Web.ApiSpec.InstanceOperation do
example: ["pleroma.site", "lain.com", "bikeshed.party"] example: ["pleroma.site", "lain.com", "bikeshed.party"]
} }
end end
defp array_of_rules do
%Schema{
type: :array,
items: %Schema{
type: :object,
properties: %{
id: %Schema{type: :string},
text: %Schema{type: :string},
hint: %Schema{type: :string}
}
}
}
end
end end

View File

@ -53,6 +53,12 @@ defmodule Pleroma.Web.ApiSpec.ReportOperation do
default: false, default: false,
description: description:
"If the account is remote, should the report be forwarded to the remote admin?" "If the account is remote, should the report be forwarded to the remote admin?"
},
rule_ids: %Schema{
type: :array,
nullable: true,
items: %Schema{type: :string},
description: "Array of rules"
} }
}, },
required: [:account_id], required: [:account_id],
@ -60,7 +66,8 @@ defmodule Pleroma.Web.ApiSpec.ReportOperation do
"account_id" => "123", "account_id" => "123",
"status_ids" => ["1337"], "status_ids" => ["1337"],
"comment" => "bad status!", "comment" => "bad status!",
"forward" => "false" "forward" => "false",
"rule_ids" => ["3"]
} }
} }
end end

View File

@ -8,6 +8,7 @@ defmodule Pleroma.Web.CommonAPI do
alias Pleroma.Formatter alias Pleroma.Formatter
alias Pleroma.ModerationLog alias Pleroma.ModerationLog
alias Pleroma.Object alias Pleroma.Object
alias Pleroma.Rule
alias Pleroma.ThreadMute alias Pleroma.ThreadMute
alias Pleroma.User alias Pleroma.User
alias Pleroma.UserRelationship alias Pleroma.UserRelationship
@ -568,14 +569,16 @@ defmodule Pleroma.Web.CommonAPI do
def report(user, data) do def report(user, data) do
with {:ok, account} <- get_reported_account(data.account_id), with {:ok, account} <- get_reported_account(data.account_id),
{:ok, {content_html, _, _}} <- make_report_content_html(data[:comment]), {:ok, {content_html, _, _}} <- make_report_content_html(data[:comment]),
{:ok, statuses} <- get_report_statuses(account, data) do {:ok, statuses} <- get_report_statuses(account, data),
rules <- get_report_rules(Map.get(data, :rule_ids, nil)) do
ActivityPub.flag(%{ ActivityPub.flag(%{
context: Utils.generate_context_id(), context: Utils.generate_context_id(),
actor: user, actor: user,
account: account, account: account,
statuses: statuses, statuses: statuses,
content: content_html, content: content_html,
forward: Map.get(data, :forward, false) forward: Map.get(data, :forward, false),
rules: rules
}) })
end end
end end
@ -587,6 +590,15 @@ defmodule Pleroma.Web.CommonAPI do
end end
end end
defp get_report_rules(nil) do
nil
end
defp get_report_rules(rule_ids) do
rule_ids
|> Enum.filter(&Rule.exists?/1)
end
def update_report_state(activity_ids, state) when is_list(activity_ids) do def update_report_state(activity_ids, state) when is_list(activity_ids) do
case Utils.update_report_state(activity_ids, state) do case Utils.update_report_state(activity_ids, state) do
:ok -> {:ok, activity_ids} :ok -> {:ok, activity_ids}

View File

@ -25,4 +25,9 @@ defmodule Pleroma.Web.MastodonAPI.InstanceController do
def peers(conn, _params) do def peers(conn, _params) do
json(conn, Pleroma.Stats.get_peers()) json(conn, Pleroma.Stats.get_peers())
end end
@doc "GET /api/v1/instance/rules"
def rules(conn, _params) do
render(conn, "rules.json")
end
end end

View File

@ -76,12 +76,26 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do
}) })
end end
def render("rules.json", _) do
Pleroma.Rule.query()
|> Pleroma.Repo.all()
|> render_many(__MODULE__, "rule.json", as: :rule)
end
def render("rule.json", %{rule: rule}) do
%{
id: to_string(rule.id),
text: rule.text,
hint: rule.hint || ""
}
end
defp common_information(instance) do defp common_information(instance) do
%{ %{
title: Keyword.get(instance, :name),
version: "#{@mastodon_api_level} (compatible; #{Pleroma.Application.named_version()})",
languages: Keyword.get(instance, :languages, ["en"]), languages: Keyword.get(instance, :languages, ["en"]),
rules: [] rules: render(__MODULE__, "rules.json"),
title: Keyword.get(instance, :name),
version: "#{@mastodon_api_level} (compatible; #{Pleroma.Application.named_version()})"
} }
end end

View File

@ -292,6 +292,11 @@ defmodule Pleroma.Web.Router do
post("/frontends/install", FrontendController, :install) post("/frontends/install", FrontendController, :install)
post("/backups", AdminAPIController, :create_backup) post("/backups", AdminAPIController, :create_backup)
get("/rules", RuleController, :index)
post("/rules", RuleController, :create)
patch("/rules/:id", RuleController, :update)
delete("/rules/:id", RuleController, :delete)
end end
# AdminAPI: admins and mods (staff) can perform these actions (if privileged by role) # AdminAPI: admins and mods (staff) can perform these actions (if privileged by role)
@ -764,6 +769,7 @@ defmodule Pleroma.Web.Router do
get("/instance", InstanceController, :show) get("/instance", InstanceController, :show)
get("/instance/peers", InstanceController, :peers) get("/instance/peers", InstanceController, :peers)
get("/instance/rules", InstanceController, :rules)
get("/statuses", StatusController, :index) get("/statuses", StatusController, :index)
get("/statuses/:id", StatusController, :show) get("/statuses/:id", StatusController, :show)

View File

@ -0,0 +1,12 @@
defmodule Pleroma.Repo.Migrations.CreateRules do
use Ecto.Migration
def change do
create_if_not_exists table(:rules) do
add(:priority, :integer, default: 0, null: false)
add(:text, :text, null: false)
timestamps()
end
end
end

View File

@ -0,0 +1,13 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2024 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Repo.Migrations.AddHintToRules do
use Ecto.Migration
def change do
alter table(:rules) do
add_if_not_exists(:hint, :text)
end
end
end

View File

@ -0,0 +1,57 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.RuleTest do
use Pleroma.DataCase, async: true
alias Pleroma.Repo
alias Pleroma.Rule
test "getting a list of rules sorted by priority" do
%{id: id1} = Rule.create(%{text: "Example rule"})
%{id: id2} = Rule.create(%{text: "Second rule", priority: 2})
%{id: id3} = Rule.create(%{text: "Third rule", priority: 1})
rules =
Rule.query()
|> Repo.all()
assert [%{id: ^id1}, %{id: ^id3}, %{id: ^id2}] = rules
end
test "creating rules" do
%{id: id} = Rule.create(%{text: "Example rule"})
assert %{text: "Example rule"} = Rule.get(id)
end
test "editing rules" do
%{id: id} = Rule.create(%{text: "Example rule"})
Rule.update(%{text: "There are no rules", priority: 2}, id)
assert %{text: "There are no rules", priority: 2} = Rule.get(id)
end
test "deleting rules" do
%{id: id} = Rule.create(%{text: "Example rule"})
Rule.delete(id)
assert [] =
Rule.query()
|> Pleroma.Repo.all()
end
test "getting rules by ids" do
%{id: id1} = Rule.create(%{text: "Example rule"})
%{id: id2} = Rule.create(%{text: "Second rule"})
%{id: _id3} = Rule.create(%{text: "Third rule"})
rules = Rule.get([id1, id2])
assert Enum.all?(rules, &(&1.id in [id1, id2]))
assert length(rules) == 2
end
end

View File

@ -11,6 +11,7 @@ defmodule Pleroma.Web.AdminAPI.ReportControllerTest do
alias Pleroma.ModerationLog alias Pleroma.ModerationLog
alias Pleroma.Repo alias Pleroma.Repo
alias Pleroma.ReportNote alias Pleroma.ReportNote
alias Pleroma.Rule
alias Pleroma.Web.CommonAPI alias Pleroma.Web.CommonAPI
setup do setup do
@ -436,6 +437,34 @@ defmodule Pleroma.Web.AdminAPI.ReportControllerTest do
"error" => "Invalid credentials." "error" => "Invalid credentials."
} }
end end
test "returns reports with specified role_id", %{conn: conn} do
[reporter, target_user] = insert_pair(:user)
%{id: rule_id} = Rule.create(%{text: "Example rule"})
rule_id = to_string(rule_id)
{:ok, %{id: report_id}} =
CommonAPI.report(reporter, %{
account_id: target_user.id,
comment: "",
rule_ids: [rule_id]
})
{:ok, _report} =
CommonAPI.report(reporter, %{
account_id: target_user.id,
comment: ""
})
response =
conn
|> get("/api/pleroma/admin/reports?rule_id=#{rule_id}")
|> json_response_and_validate_schema(:ok)
assert %{"reports" => [%{"id" => ^report_id}]} = response
end
end end
describe "POST /api/pleroma/admin/reports/:id/notes" do describe "POST /api/pleroma/admin/reports/:id/notes" do

View File

@ -0,0 +1,82 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.AdminAPI.RuleControllerTest do
use Pleroma.Web.ConnCase, async: true
import Pleroma.Factory
alias Pleroma.Rule
setup do
admin = insert(:user, is_admin: true)
token = insert(:oauth_admin_token, user: admin)
conn =
build_conn()
|> assign(:user, admin)
|> assign(:token, token)
{:ok, %{admin: admin, token: token, conn: conn}}
end
describe "GET /api/pleroma/admin/rules" do
test "sorts rules by priority", %{conn: conn} do
%{id: id1} = Rule.create(%{text: "Example rule"})
%{id: id2} = Rule.create(%{text: "Second rule", priority: 2})
%{id: id3} = Rule.create(%{text: "Third rule", priority: 1})
id1 = to_string(id1)
id2 = to_string(id2)
id3 = to_string(id3)
response =
conn
|> get("/api/pleroma/admin/rules")
|> json_response_and_validate_schema(:ok)
assert [%{"id" => ^id1}, %{"id" => ^id3}, %{"id" => ^id2}] = response
end
end
describe "POST /api/pleroma/admin/rules" do
test "creates a rule", %{conn: conn} do
%{"id" => id} =
conn
|> put_req_header("content-type", "application/json")
|> post("/api/pleroma/admin/rules", %{text: "Example rule"})
|> json_response_and_validate_schema(:ok)
assert %{text: "Example rule"} = Rule.get(id)
end
end
describe "PATCH /api/pleroma/admin/rules" do
test "edits a rule", %{conn: conn} do
%{id: id} = Rule.create(%{text: "Example rule"})
conn
|> put_req_header("content-type", "application/json")
|> patch("/api/pleroma/admin/rules/#{id}", %{text: "There are no rules", priority: 2})
|> json_response_and_validate_schema(:ok)
assert %{text: "There are no rules", priority: 2} = Rule.get(id)
end
end
describe "DELETE /api/pleroma/admin/rules" do
test "deletes a rule", %{conn: conn} do
%{id: id} = Rule.create(%{text: "Example rule"})
conn
|> put_req_header("content-type", "application/json")
|> delete("/api/pleroma/admin/rules/#{id}")
|> json_response_and_validate_schema(:ok)
assert [] =
Rule.query()
|> Pleroma.Repo.all()
end
end
end

View File

@ -7,6 +7,7 @@ defmodule Pleroma.Web.AdminAPI.ReportViewTest do
import Pleroma.Factory import Pleroma.Factory
alias Pleroma.Rule
alias Pleroma.Web.AdminAPI alias Pleroma.Web.AdminAPI
alias Pleroma.Web.AdminAPI.Report alias Pleroma.Web.AdminAPI.Report
alias Pleroma.Web.AdminAPI.ReportView alias Pleroma.Web.AdminAPI.ReportView
@ -38,7 +39,8 @@ defmodule Pleroma.Web.AdminAPI.ReportViewTest do
statuses: [], statuses: [],
notes: [], notes: [],
state: "open", state: "open",
id: activity.id id: activity.id,
rules: []
} }
result = result =
@ -76,7 +78,8 @@ defmodule Pleroma.Web.AdminAPI.ReportViewTest do
statuses: [StatusView.render("show.json", %{activity: activity})], statuses: [StatusView.render("show.json", %{activity: activity})],
state: "open", state: "open",
notes: [], notes: [],
id: report_activity.id id: report_activity.id,
rules: []
} }
result = result =
@ -168,4 +171,22 @@ defmodule Pleroma.Web.AdminAPI.ReportViewTest do
assert report2.id == rendered |> Enum.at(0) |> Map.get(:id) assert report2.id == rendered |> Enum.at(0) |> Map.get(:id)
assert report1.id == rendered |> Enum.at(1) |> Map.get(:id) assert report1.id == rendered |> Enum.at(1) |> Map.get(:id)
end end
test "renders included rules" do
user = insert(:user)
other_user = insert(:user)
%{id: rule_id, text: text} = Rule.create(%{text: "Example rule"})
rule_id = to_string(rule_id)
{:ok, activity} =
CommonAPI.report(user, %{
account_id: other_user.id,
rule_ids: [rule_id]
})
assert %{rules: [%{id: ^rule_id, text: ^text}]} =
ReportView.render("show.json", Report.extract_report_info(activity))
end
end end

View File

@ -12,6 +12,7 @@ defmodule Pleroma.Web.CommonAPITest do
alias Pleroma.Notification alias Pleroma.Notification
alias Pleroma.Object alias Pleroma.Object
alias Pleroma.Repo alias Pleroma.Repo
alias Pleroma.Rule
alias Pleroma.UnstubbedConfigMock, as: ConfigMock alias Pleroma.UnstubbedConfigMock, as: ConfigMock
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.ActivityPub
@ -1363,6 +1364,33 @@ defmodule Pleroma.Web.CommonAPITest do
assert first_report.data["state"] == "resolved" assert first_report.data["state"] == "resolved"
assert second_report.data["state"] == "resolved" assert second_report.data["state"] == "resolved"
end end
test "creates a report with provided rules" do
reporter = insert(:user)
target_user = insert(:user)
%{id: rule_id} = Rule.create(%{text: "There are no rules"})
reporter_ap_id = reporter.ap_id
target_ap_id = target_user.ap_id
report_data = %{
account_id: target_user.id,
rule_ids: [rule_id]
}
assert {:ok, flag_activity} = CommonAPI.report(reporter, report_data)
assert %Activity{
actor: ^reporter_ap_id,
data: %{
"type" => "Flag",
"object" => [^target_ap_id],
"state" => "open",
"rules" => [^rule_id]
}
} = flag_activity
end
end end
describe "reblog muting" do describe "reblog muting" do

View File

@ -6,6 +6,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceControllerTest do
# TODO: Should not need Cachex # TODO: Should not need Cachex
use Pleroma.Web.ConnCase use Pleroma.Web.ConnCase
alias Pleroma.Rule
alias Pleroma.User alias Pleroma.User
import Pleroma.Factory import Pleroma.Factory
@ -40,7 +41,8 @@ defmodule Pleroma.Web.MastodonAPI.InstanceControllerTest do
"banner_upload_limit" => _, "banner_upload_limit" => _,
"background_image" => from_config_background, "background_image" => from_config_background,
"shout_limit" => _, "shout_limit" => _,
"description_limit" => _ "description_limit" => _,
"rules" => _
} = result } = result
assert result["pleroma"]["metadata"]["account_activation_required"] != nil assert result["pleroma"]["metadata"]["account_activation_required"] != nil
@ -125,4 +127,29 @@ defmodule Pleroma.Web.MastodonAPI.InstanceControllerTest do
assert get(conn, "/api/v2/instance") assert get(conn, "/api/v2/instance")
|> json_response_and_validate_schema(200) |> json_response_and_validate_schema(200)
end end
test "get instance rules", %{conn: conn} do
Rule.create(%{text: "Example rule", hint: "Rule description", priority: 1})
Rule.create(%{text: "Third rule", priority: 2})
Rule.create(%{text: "Second rule", priority: 1})
conn = get(conn, "/api/v1/instance")
assert result = json_response_and_validate_schema(conn, 200)
assert [
%{
"text" => "Example rule",
"hint" => "Rule description"
},
%{
"text" => "Second rule",
"hint" => ""
},
%{
"text" => "Third rule",
"hint" => ""
}
] = result["rules"]
end
end end

View File

@ -7,6 +7,7 @@ defmodule Pleroma.Web.MastodonAPI.ReportControllerTest do
alias Pleroma.Activity alias Pleroma.Activity
alias Pleroma.Repo alias Pleroma.Repo
alias Pleroma.Rule
alias Pleroma.Web.CommonAPI alias Pleroma.Web.CommonAPI
import Pleroma.Factory import Pleroma.Factory
@ -81,6 +82,44 @@ defmodule Pleroma.Web.MastodonAPI.ReportControllerTest do
|> json_response_and_validate_schema(200) |> json_response_and_validate_schema(200)
end end
test "submit a report with rule_ids", %{
conn: conn,
target_user: target_user
} do
%{id: rule_id} = Rule.create(%{text: "There are no rules"})
rule_id = to_string(rule_id)
assert %{"action_taken" => false, "id" => id} =
conn
|> put_req_header("content-type", "application/json")
|> post("/api/v1/reports", %{
"account_id" => target_user.id,
"forward" => "false",
"rule_ids" => [rule_id]
})
|> json_response_and_validate_schema(200)
assert %Activity{data: %{"rules" => [^rule_id]}} = Activity.get_report(id)
end
test "rules field is empty if provided wrong rule id", %{
conn: conn,
target_user: target_user
} do
assert %{"id" => id} =
conn
|> put_req_header("content-type", "application/json")
|> post("/api/v1/reports", %{
"account_id" => target_user.id,
"forward" => "false",
"rule_ids" => ["-1"]
})
|> json_response_and_validate_schema(200)
assert %Activity{data: %{"rules" => []}} = Activity.get_report(id)
end
test "account_id is required", %{ test "account_id is required", %{
conn: conn, conn: conn,
activity: activity activity: activity