aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxim Filippov <colixer@gmail.com>2019-10-15 17:33:29 +0200
committerMaxim Filippov <colixer@gmail.com>2019-10-15 17:33:29 +0200
commitda0e4879bcd12849182a39445174384420fcf064 (patch)
treebf54d1b4ee868b187a66948993babe86350840c2
parentc0aca32dd0aed522cfc537cc88b77f7ff254946b (diff)
parent3b1bc079af8fb6e467a9114de0d32e2de59a7fab (diff)
downloadpleroma-da0e4879bcd12849182a39445174384420fcf064.tar.gz
DELETE /api/pleroma/admin/users now accepts nicknames array
-rw-r--r--.gitlab-ci.yml5
-rw-r--r--CHANGELOG.md4
-rw-r--r--docs/API/admin_api.md11
-rw-r--r--docs/API/differences_in_mastoapi_responses.md7
-rw-r--r--docs/installation/alpine_linux_en.md2
-rw-r--r--docs/installation/arch_linux_en.md2
-rw-r--r--docs/installation/centos7_en.md2
-rw-r--r--docs/installation/debian_based_en.md2
-rw-r--r--docs/installation/debian_based_jp.md2
-rw-r--r--docs/installation/gentoo_en.md2
-rw-r--r--docs/installation/migrating_from_source_otp_en.md4
-rw-r--r--docs/installation/netbsd_en.md2
-rw-r--r--docs/installation/openbsd_en.md2
-rw-r--r--docs/installation/openbsd_fi.md2
-rw-r--r--docs/installation/otp_en.md2
-rw-r--r--lib/pleroma/moderation_log.ex4
-rw-r--r--lib/pleroma/notification.ex104
-rw-r--r--lib/pleroma/reverse_proxy/reverse_proxy.ex6
-rw-r--r--lib/pleroma/user.ex4
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub.ex89
-rw-r--r--lib/pleroma/web/activity_pub/transmogrifier.ex15
-rw-r--r--lib/pleroma/web/admin_api/admin_api_controller.ex16
-rw-r--r--lib/pleroma/web/mastodon_api/mastodon_api.ex1
-rw-r--r--lib/pleroma/web/ostatus/handlers/delete_handler.ex2
-rw-r--r--mix.exs5
-rwxr-xr-xrel/files/bin/pleroma_ctl4
-rw-r--r--test/moderation_log_test.exs4
-rw-r--r--test/web/activity_pub/activity_pub_test.exs60
-rw-r--r--test/web/activity_pub/transmogrifier_test.exs11
-rw-r--r--test/web/admin_api/admin_api_controller_test.exs33
-rw-r--r--test/web/mastodon_api/controllers/account_controller_test.exs14
-rw-r--r--test/web/mastodon_api/controllers/notification_controller_test.exs51
-rw-r--r--test/web/mastodon_api/controllers/search_controller_test.exs8
-rw-r--r--test/web/mastodon_api/controllers/timeline_controller_test.exs55
34 files changed, 428 insertions, 109 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 748bec74a..36137b38e 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -70,7 +70,7 @@ docs-deploy:
stage: deploy
image: alpine:latest
only:
- - master@pleroma/pleroma
+ - stable@pleroma/pleroma
- develop@pleroma/pleroma
before_script:
- apk add curl
@@ -127,9 +127,10 @@ amd64:
# TODO: Replace with upstream image when 1.9.0 comes out
image: rinpatch/elixir:1.9.0-rc.0
only: &release-only
- - master@pleroma/pleroma
+ - stable@pleroma/pleroma
- develop@pleroma/pleroma
- /^maint/.*$/@pleroma/pleroma
+ - /^release/.*$/@pleroma/pleroma
artifacts: &release-artifacts
name: "pleroma-$CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA-$CI_JOB_NAME"
paths:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 30b765251..24876d3f2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,8 +17,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Authentication: Added rate limit for password-authorized actions / login existence checks
- Metadata Link: Atom syndication Feed
- Mix task to re-count statuses for all users (`mix pleroma.count_statuses`)
+- Mastodon API: Add `exclude_visibilities` parameter to the timeline and notification endpoints
- Admin API: `/users/:nickname/toggle_activation` endpoint is now deprecated in favor of: `/users/activate`, `/users/deactivate`, both accept `nicknames` array
-- Admin API: `POST /api/pleroma/admin/users/:nickname/permission_group/:permission_group` / `DELETE /api/pleroma/admin/users/:nickname/permission_group/:permission_group` are deprecated in favor of: `POST /api/pleroma/admin/users/permission_group/:permission_group` / `DELETE /api/pleroma/admin/users/permission_group/:permission_group` (both accept `nicknames` array)
+- Admin API: `POST/DELETE /api/pleroma/admin/users/:nickname/permission_group/:permission_group` are deprecated in favor of: `POST/DELETE /api/pleroma/admin/users/permission_group/:permission_group` (both accept `nicknames` array), `DELETE /api/pleroma/admin/users` (`nickname` query param or `nickname` sent in JSON body) is deprecated in favor of: `DELETE /api/pleroma/admin/users` (`nicknames` query array param or `nicknames` sent in JSON body).
### Changed
- **Breaking:** Elixir >=1.8 is now required (was >= 1.7)
@@ -39,6 +40,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Report emails now include functional links to profiles of remote user accounts
## [1.1.0] - 2019-??-??
+**Breaking:** The stable branch has been changed from `master` to `stable`, `master` now points to `release/1.0`
### Security
- Mastodon API: respect post privacy in `/api/v1/statuses/:id/{favourited,reblogged}_by`
diff --git a/docs/API/admin_api.md b/docs/API/admin_api.md
index 2c8237b57..60755e40a 100644
--- a/docs/API/admin_api.md
+++ b/docs/API/admin_api.md
@@ -47,7 +47,7 @@ Authentication is required and the user must be an admin.
}
```
-## `/api/pleroma/admin/users`
+## DEPRECATED `DELETE /api/pleroma/admin/users`
### Remove a user
@@ -56,6 +56,15 @@ Authentication is required and the user must be an admin.
- `nickname`
- Response: User’s nickname
+## `DELETE /api/pleroma/admin/users`
+
+### Remove a user
+
+- Method `DELETE`
+- Params:
+ - `nicknames`
+- Response: Array of user nicknames
+
### Create a user
- Method: `POST`
diff --git a/docs/API/differences_in_mastoapi_responses.md b/docs/API/differences_in_mastoapi_responses.md
index 21b297529..aca0f5e0e 100644
--- a/docs/API/differences_in_mastoapi_responses.md
+++ b/docs/API/differences_in_mastoapi_responses.md
@@ -13,6 +13,7 @@ Some apps operate under the assumption that no more than 4 attachments can be re
## Timelines
Adding the parameter `with_muted=true` to the timeline queries will also return activities by muted (not by blocked!) users.
+Adding the parameter `exclude_visibilities` to the timeline queries will exclude the statuses with the given visibilities. The parameter accepts an array of visibility types (`public`, `unlisted`, `private`, `direct`), e.g., `exclude_visibilities[]=direct&exclude_visibilities[]=private`.
## Statuses
@@ -84,6 +85,12 @@ Has these additional fields under the `pleroma` object:
- `is_seen`: true if the notification was read by the user
+## GET `/api/v1/notifications`
+
+Accepts additional parameters:
+
+- `exclude_visibilities`: will exclude the notifications for activities with the given visibilities. The parameter accepts an array of visibility types (`public`, `unlisted`, `private`, `direct`). Usage example: `GET /api/v1/notifications?exclude_visibilities[]=direct&exclude_visibilities[]=private`.
+
## POST `/api/v1/statuses`
Additional parameters can be added to the JSON body/Form data:
diff --git a/docs/installation/alpine_linux_en.md b/docs/installation/alpine_linux_en.md
index f5d1fade1..2a9b8f6ff 100644
--- a/docs/installation/alpine_linux_en.md
+++ b/docs/installation/alpine_linux_en.md
@@ -91,7 +91,7 @@ sudo adduser -S -s /bin/false -h /opt/pleroma -H -G pleroma pleroma
```shell
sudo mkdir -p /opt/pleroma
sudo chown -R pleroma:pleroma /opt/pleroma
-sudo -Hu pleroma git clone -b master https://git.pleroma.social/pleroma/pleroma /opt/pleroma
+sudo -Hu pleroma git clone -b stable https://git.pleroma.social/pleroma/pleroma /opt/pleroma
```
* Change to the new directory:
diff --git a/docs/installation/arch_linux_en.md b/docs/installation/arch_linux_en.md
index 58a8d023f..8370986ad 100644
--- a/docs/installation/arch_linux_en.md
+++ b/docs/installation/arch_linux_en.md
@@ -66,7 +66,7 @@ sudo useradd -r -s /bin/false -m -d /var/lib/pleroma -U pleroma
```shell
sudo mkdir -p /opt/pleroma
sudo chown -R pleroma:pleroma /opt/pleroma
-sudo -Hu pleroma git clone -b master https://git.pleroma.social/pleroma/pleroma /opt/pleroma
+sudo -Hu pleroma git clone -b stable https://git.pleroma.social/pleroma/pleroma /opt/pleroma
```
* Change to the new directory:
diff --git a/docs/installation/centos7_en.md b/docs/installation/centos7_en.md
index fe26339b5..ad4f58dc1 100644
--- a/docs/installation/centos7_en.md
+++ b/docs/installation/centos7_en.md
@@ -143,7 +143,7 @@ sudo useradd -r -s /bin/false -m -d /var/lib/pleroma -U pleroma
```shell
sudo mkdir -p /opt/pleroma
sudo chown -R pleroma:pleroma /opt/pleroma
-sudo -Hu pleroma git clone -b master https://git.pleroma.social/pleroma/pleroma /opt/pleroma
+sudo -Hu pleroma git clone -b stable https://git.pleroma.social/pleroma/pleroma /opt/pleroma
```
* Change to the new directory:
diff --git a/docs/installation/debian_based_en.md b/docs/installation/debian_based_en.md
index e5f8dd670..fe2dbb92d 100644
--- a/docs/installation/debian_based_en.md
+++ b/docs/installation/debian_based_en.md
@@ -68,7 +68,7 @@ sudo useradd -r -s /bin/false -m -d /var/lib/pleroma -U pleroma
```shell
sudo mkdir -p /opt/pleroma
sudo chown -R pleroma:pleroma /opt/pleroma
-sudo -Hu pleroma git clone -b master https://git.pleroma.social/pleroma/pleroma /opt/pleroma
+sudo -Hu pleroma git clone -b stable https://git.pleroma.social/pleroma/pleroma /opt/pleroma
```
* Change to the new directory:
diff --git a/docs/installation/debian_based_jp.md b/docs/installation/debian_based_jp.md
index e7d834b17..7aa0bcc24 100644
--- a/docs/installation/debian_based_jp.md
+++ b/docs/installation/debian_based_jp.md
@@ -68,7 +68,7 @@ sudo useradd -r -s /bin/false -m -d /var/lib/pleroma -U pleroma
```
sudo mkdir -p /opt/pleroma
sudo chown -R pleroma:pleroma /opt/pleroma
-sudo -Hu pleroma git clone -b master https://git.pleroma.social/pleroma/pleroma /opt/pleroma
+sudo -Hu pleroma git clone -b stable https://git.pleroma.social/pleroma/pleroma /opt/pleroma
```
* 新しいディレクトリに移動します。
diff --git a/docs/installation/gentoo_en.md b/docs/installation/gentoo_en.md
index 55d677acf..1e61373cc 100644
--- a/docs/installation/gentoo_en.md
+++ b/docs/installation/gentoo_en.md
@@ -106,7 +106,7 @@ It is highly recommended you use your own fork for the `https://path/to/repo` pa
```shell
pleroma$ cd ~
- pleroma$ git clone -b master https://path/to/repo
+ pleroma$ git clone -b stable https://path/to/repo
```
* Change to the new directory:
diff --git a/docs/installation/migrating_from_source_otp_en.md b/docs/installation/migrating_from_source_otp_en.md
index e204cb3ee..87568faad 100644
--- a/docs/installation/migrating_from_source_otp_en.md
+++ b/docs/installation/migrating_from_source_otp_en.md
@@ -96,9 +96,9 @@ rm -r ~pleroma/*
export FLAVOUR="arm64-musl"
# Clone the release build into a temporary directory and unpack it
-# Replace `master` with `develop` if you want to run the develop branch
+# Replace `stable` with `unstable` if you want to run the unstable branch
su pleroma -s $SHELL -lc "
-curl 'https://git.pleroma.social/api/v4/projects/2/jobs/artifacts/master/download?job=$FLAVOUR' -o /tmp/pleroma.zip
+curl 'https://git.pleroma.social/api/v4/projects/2/jobs/artifacts/stable/download?job=$FLAVOUR' -o /tmp/pleroma.zip
unzip /tmp/pleroma.zip -d /tmp/
"
diff --git a/docs/installation/netbsd_en.md b/docs/installation/netbsd_en.md
index a096d5354..6a922a27e 100644
--- a/docs/installation/netbsd_en.md
+++ b/docs/installation/netbsd_en.md
@@ -58,7 +58,7 @@ Clone the repository:
```
$ cd /home/pleroma
-$ git clone -b master https://git.pleroma.social/pleroma/pleroma.git
+$ git clone -b stable https://git.pleroma.social/pleroma/pleroma.git
```
Configure Pleroma. Note that you need a domain name at this point:
diff --git a/docs/installation/openbsd_en.md b/docs/installation/openbsd_en.md
index fcba38b2c..3585a326b 100644
--- a/docs/installation/openbsd_en.md
+++ b/docs/installation/openbsd_en.md
@@ -29,7 +29,7 @@ This creates a "pleroma" login class and sets higher values than default for dat
Create the \_pleroma user, assign it the pleroma login class and create its home directory (/home/\_pleroma/): `useradd -m -L pleroma _pleroma`
#### Clone pleroma's directory
-Enter a shell as the \_pleroma user. As root, run `su _pleroma -;cd`. Then clone the repository with `git clone -b master https://git.pleroma.social/pleroma/pleroma.git`. Pleroma is now installed in /home/\_pleroma/pleroma/, it will be configured and started at the end of this guide.
+Enter a shell as the \_pleroma user. As root, run `su _pleroma -;cd`. Then clone the repository with `git clone -b stable https://git.pleroma.social/pleroma/pleroma.git`. Pleroma is now installed in /home/\_pleroma/pleroma/, it will be configured and started at the end of this guide.
#### Postgresql
Start a shell as the \_postgresql user (as root run `su _postgresql -` then run the `initdb` command to initialize postgresql:
diff --git a/docs/installation/openbsd_fi.md b/docs/installation/openbsd_fi.md
index 39819a8c8..272273cff 100644
--- a/docs/installation/openbsd_fi.md
+++ b/docs/installation/openbsd_fi.md
@@ -44,7 +44,7 @@ Vaihda pleroma-käyttäjään ja mene kotihakemistoosi:
Lataa pleroman lähdekoodi:
-`$ git clone -b master https://git.pleroma.social/pleroma/pleroma.git`
+`$ git clone -b stable https://git.pleroma.social/pleroma/pleroma.git`
`$ cd pleroma`
diff --git a/docs/installation/otp_en.md b/docs/installation/otp_en.md
index b4e5254cd..c028f4229 100644
--- a/docs/installation/otp_en.md
+++ b/docs/installation/otp_en.md
@@ -80,7 +80,7 @@ export FLAVOUR="arm64-musl"
# Clone the release build into a temporary directory and unpack it
su pleroma -s $SHELL -lc "
-curl 'https://git.pleroma.social/api/v4/projects/2/jobs/artifacts/master/download?job=$FLAVOUR' -o /tmp/pleroma.zip
+curl 'https://git.pleroma.social/api/v4/projects/2/jobs/artifacts/stable/download?job=$FLAVOUR' -o /tmp/pleroma.zip
unzip /tmp/pleroma.zip -d /tmp/
"
diff --git a/lib/pleroma/moderation_log.ex b/lib/pleroma/moderation_log.ex
index 42649ff02..e8884e6e8 100644
--- a/lib/pleroma/moderation_log.ex
+++ b/lib/pleroma/moderation_log.ex
@@ -352,10 +352,10 @@ defmodule Pleroma.ModerationLog do
data: %{
"actor" => %{"nickname" => actor_nickname},
"action" => "delete",
- "subject" => %{"nickname" => subject_nickname, "type" => "user"}
+ "subject" => subjects
}
}) do
- "@#{actor_nickname} deleted user @#{subject_nickname}"
+ "@#{actor_nickname} deleted users: #{users_to_nicknames_string(subjects)}"
end
@spec get_log_entry_message(ModerationLog) :: String.t()
diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex
index d94ae5971..d145f8d5b 100644
--- a/lib/pleroma/notification.ex
+++ b/lib/pleroma/notification.ex
@@ -17,6 +17,7 @@ defmodule Pleroma.Notification do
import Ecto.Query
import Ecto.Changeset
+ require Logger
@type t :: %__MODULE__{}
@@ -34,43 +35,92 @@ defmodule Pleroma.Notification do
end
def for_user_query(user, opts \\ []) do
- query =
- Notification
- |> where(user_id: ^user.id)
- |> where(
- [n, a],
+ Notification
+ |> where(user_id: ^user.id)
+ |> where(
+ [n, a],
+ fragment(
+ "? not in (SELECT ap_id FROM users WHERE info->'deactivated' @> 'true')",
+ a.actor
+ )
+ )
+ |> join(:inner, [n], activity in assoc(n, :activity))
+ |> join(:left, [n, a], object in Object,
+ on:
fragment(
- "? not in (SELECT ap_id FROM users WHERE info->'deactivated' @> 'true')",
- a.actor
+ "(?->>'id') = COALESCE((? -> 'object'::text) ->> 'id'::text)",
+ object.data,
+ a.data
)
- )
- |> join(:inner, [n], activity in assoc(n, :activity))
- |> join(:left, [n, a], object in Object,
- on:
- fragment(
- "(?->>'id') = COALESCE((? -> 'object'::text) ->> 'id'::text)",
- object.data,
- a.data
- )
- )
- |> preload([n, a, o], activity: {a, object: o})
+ )
+ |> preload([n, a, o], activity: {a, object: o})
+ |> exclude_muted(user, opts)
+ |> exclude_visibility(opts)
+ end
+
+ defp exclude_muted(query, _, %{with_muted: true}) do
+ query
+ end
+
+ defp exclude_muted(query, user, _opts) do
+ query
+ |> where([n, a], a.actor not in ^user.info.muted_notifications)
+ |> where([n, a], a.actor not in ^user.info.blocks)
+ |> where(
+ [n, a],
+ fragment("substring(? from '.*://([^/]*)')", a.actor) not in ^user.info.domain_blocks
+ )
+ |> join(:left, [n, a], tm in Pleroma.ThreadMute,
+ on: tm.user_id == ^user.id and tm.context == fragment("?->>'context'", a.data)
+ )
+ |> where([n, a, o, tm], is_nil(tm.user_id))
+ end
- if opts[:with_muted] do
+ @valid_visibilities ~w[direct unlisted public private]
+
+ defp exclude_visibility(query, %{exclude_visibilities: visibility})
+ when is_list(visibility) do
+ if Enum.all?(visibility, &(&1 in @valid_visibilities)) do
query
- else
- where(query, [n, a], a.actor not in ^user.info.muted_notifications)
- |> where([n, a], a.actor not in ^user.info.blocks)
|> where(
[n, a],
- fragment("substring(? from '.*://([^/]*)')", a.actor) not in ^user.info.domain_blocks
- )
- |> join(:left, [n, a], tm in Pleroma.ThreadMute,
- on: tm.user_id == ^user.id and tm.context == fragment("?->>'context'", a.data)
+ not fragment(
+ "activity_visibility(?, ?, ?) = ANY (?)",
+ a.actor,
+ a.recipients,
+ a.data,
+ ^visibility
+ )
)
- |> where([n, a, o, tm], is_nil(tm.user_id))
+ else
+ Logger.error("Could not exclude visibility to #{visibility}")
+ query
end
end
+ defp exclude_visibility(query, %{exclude_visibilities: visibility})
+ when visibility in @valid_visibilities do
+ query
+ |> where(
+ [n, a],
+ not fragment(
+ "activity_visibility(?, ?, ?) = (?)",
+ a.actor,
+ a.recipients,
+ a.data,
+ ^visibility
+ )
+ )
+ end
+
+ defp exclude_visibility(query, %{exclude_visibilities: visibility})
+ when visibility not in @valid_visibilities do
+ Logger.error("Could not exclude visibility to #{visibility}")
+ query
+ end
+
+ defp exclude_visibility(query, _visibility), do: query
+
def for_user(user, opts \\ %{}) do
user
|> for_user_query(opts)
diff --git a/lib/pleroma/reverse_proxy/reverse_proxy.ex b/lib/pleroma/reverse_proxy/reverse_proxy.ex
index 78144cae3..2ed719315 100644
--- a/lib/pleroma/reverse_proxy/reverse_proxy.ex
+++ b/lib/pleroma/reverse_proxy/reverse_proxy.ex
@@ -401,11 +401,9 @@ defmodule Pleroma.ReverseProxy do
defp client, do: Pleroma.ReverseProxy.Client
- defp track_failed_url(url, code, opts) do
- code = to_string(code)
-
+ defp track_failed_url(url, error, opts) do
ttl =
- if code in ["403", "404"] or String.starts_with?(code, "5") do
+ unless error in [:body_too_large, 400, 204] do
Keyword.get(opts, :failed_request_ttl, @failed_request_ttl)
else
nil
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index a76a5ad70..596584062 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -1080,6 +1080,10 @@ defmodule Pleroma.User do
update_info(user, &User.Info.update_notification_settings(&1, settings))
end
+ def delete(users) when is_list(users) do
+ for user <- users, do: delete(user)
+ end
+
def delete(%User{} = user) do
BackgroundWorker.enqueue("delete_user", %{"user_id" => user.id})
end
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index 9f29087df..1d34c4d7e 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -269,22 +269,21 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
end
end
- def accept(%{to: to, actor: actor, object: object} = params) do
- # only accept false as false value
- local = !(params[:local] == false)
+ def accept(params) do
+ accept_or_reject("Accept", params)
+ end
- with data <- %{"to" => to, "type" => "Accept", "actor" => actor.ap_id, "object" => object},
- {:ok, activity} <- insert(data, local),
- :ok <- maybe_federate(activity) do
- {:ok, activity}
- end
+ def reject(params) do
+ accept_or_reject("Reject", params)
end
- def reject(%{to: to, actor: actor, object: object} = params) do
- # only accept false as false value
- local = !(params[:local] == false)
+ def accept_or_reject(type, %{to: to, actor: actor, object: object} = params) do
+ local = Map.get(params, :local, true)
+ activity_id = Map.get(params, :activity_id, nil)
- with data <- %{"to" => to, "type" => "Reject", "actor" => actor.ap_id, "object" => object},
+ with data <-
+ %{"to" => to, "type" => type, "actor" => actor.ap_id, "object" => object}
+ |> Utils.maybe_put("id", activity_id),
{:ok, activity} <- insert(data, local),
:ok <- maybe_federate(activity) do
{:ok, activity}
@@ -409,18 +408,24 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
end
end
- def delete(%Object{data: %{"id" => id, "actor" => actor}} = object, local \\ true) do
+ def delete(%Object{data: %{"id" => id, "actor" => actor}} = object, options \\ []) do
+ local = Keyword.get(options, :local, true)
+ activity_id = Keyword.get(options, :activity_id, nil)
+ actor = Keyword.get(options, :actor, actor)
+
user = User.get_cached_by_ap_id(actor)
to = (object.data["to"] || []) ++ (object.data["cc"] || [])
with {:ok, object, activity} <- Object.delete(object),
- data <- %{
- "type" => "Delete",
- "actor" => actor,
- "object" => id,
- "to" => to,
- "deleted_activity_id" => activity && activity.id
- },
+ data <-
+ %{
+ "type" => "Delete",
+ "actor" => actor,
+ "object" => id,
+ "to" => to,
+ "deleted_activity_id" => activity && activity.id
+ }
+ |> maybe_put("id", activity_id),
{:ok, activity} <- insert(data, local, false),
stream_out_participations(object, user),
_ <- decrease_replies_count_if_reply(object),
@@ -591,6 +596,49 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
defp restrict_visibility(query, _visibility), do: query
+ defp exclude_visibility(query, %{"exclude_visibilities" => visibility})
+ when is_list(visibility) do
+ if Enum.all?(visibility, &(&1 in @valid_visibilities)) do
+ from(
+ a in query,
+ where:
+ not fragment(
+ "activity_visibility(?, ?, ?) = ANY (?)",
+ a.actor,
+ a.recipients,
+ a.data,
+ ^visibility
+ )
+ )
+ else
+ Logger.error("Could not exclude visibility to #{visibility}")
+ query
+ end
+ end
+
+ defp exclude_visibility(query, %{"exclude_visibilities" => visibility})
+ when visibility in @valid_visibilities do
+ from(
+ a in query,
+ where:
+ not fragment(
+ "activity_visibility(?, ?, ?) = ?",
+ a.actor,
+ a.recipients,
+ a.data,
+ ^visibility
+ )
+ )
+ end
+
+ defp exclude_visibility(query, %{"exclude_visibilities" => visibility})
+ when visibility not in @valid_visibilities do
+ Logger.error("Could not exclude visibility to #{visibility}")
+ query
+ end
+
+ defp exclude_visibility(query, _visibility), do: query
+
defp restrict_thread_visibility(query, _, %{skip_thread_containment: true} = _),
do: query
@@ -955,6 +1003,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|> restrict_muted_reblogs(opts)
|> Activity.restrict_deactivated_users()
|> exclude_poll_votes(opts)
+ |> exclude_visibility(opts)
end
def fetch_activities(recipients, opts \\ %{}, pagination \\ :keyset) do
diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
index 872ed0eb2..b56343beb 100644
--- a/lib/pleroma/web/activity_pub/transmogrifier.ex
+++ b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -514,7 +514,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end
def handle_incoming(
- %{"type" => "Accept", "object" => follow_object, "actor" => _actor, "id" => _id} = data,
+ %{"type" => "Accept", "object" => follow_object, "actor" => _actor, "id" => id} = data,
_options
) do
with actor <- Containment.get_actor(data),
@@ -528,7 +528,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
type: "Accept",
actor: followed,
object: follow_activity.data["id"],
- local: false
+ local: false,
+ activity_id: id
})
else
_e -> :error
@@ -536,7 +537,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end
def handle_incoming(
- %{"type" => "Reject", "object" => follow_object, "actor" => _actor, "id" => _id} = data,
+ %{"type" => "Reject", "object" => follow_object, "actor" => _actor, "id" => id} = data,
_options
) do
with actor <- Containment.get_actor(data),
@@ -550,7 +551,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
type: "Reject",
actor: followed,
object: follow_activity.data["id"],
- local: false
+ local: false,
+ activity_id: id
}) do
User.unfollow(follower, followed)
@@ -637,7 +639,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
# an error or a tombstone. This would allow us to verify that a deletion actually took
# place.
def handle_incoming(
- %{"type" => "Delete", "object" => object_id, "actor" => actor, "id" => _id} = data,
+ %{"type" => "Delete", "object" => object_id, "actor" => actor, "id" => id} = data,
_options
) do
object_id = Utils.get_ap_id(object_id)
@@ -646,7 +648,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
{:ok, %User{} = actor} <- User.get_or_fetch_by_ap_id(actor),
{:ok, object} <- get_obj_helper(object_id),
:ok <- Containment.contain_origin(actor.ap_id, object.data),
- {:ok, activity} <- ActivityPub.delete(object, false) do
+ {:ok, activity} <-
+ ActivityPub.delete(object, local: false, activity_id: id, actor: actor.ap_id) do
{:ok, activity}
else
nil ->
diff --git a/lib/pleroma/web/admin_api/admin_api_controller.ex b/lib/pleroma/web/admin_api/admin_api_controller.ex
index 33e2180ec..ab0d0fe0a 100644
--- a/lib/pleroma/web/admin_api/admin_api_controller.ex
+++ b/lib/pleroma/web/admin_api/admin_api_controller.ex
@@ -100,7 +100,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
ModerationLog.insert_log(%{
actor: admin,
- subject: user,
+ subject: [user],
action: "delete"
})
@@ -108,6 +108,20 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
|> json(nickname)
end
+ def user_delete(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
+ users = nicknames |> Enum.map(&User.get_cached_by_nickname/1)
+ User.delete(users)
+
+ ModerationLog.insert_log(%{
+ actor: admin,
+ subject: users,
+ action: "delete"
+ })
+
+ conn
+ |> json(nicknames)
+ end
+
def user_follow(%{assigns: %{user: admin}} = conn, %{
"follower" => follower_nick,
"followed" => followed_nick
diff --git a/lib/pleroma/web/mastodon_api/mastodon_api.ex b/lib/pleroma/web/mastodon_api/mastodon_api.ex
index ac01d1ff3..d875a5788 100644
--- a/lib/pleroma/web/mastodon_api/mastodon_api.ex
+++ b/lib/pleroma/web/mastodon_api/mastodon_api.ex
@@ -71,6 +71,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do
defp cast_params(params) do
param_types = %{
exclude_types: {:array, :string},
+ exclude_visibilities: {:array, :string},
reblogs: :boolean,
with_muted: :boolean
}
diff --git a/lib/pleroma/web/ostatus/handlers/delete_handler.ex b/lib/pleroma/web/ostatus/handlers/delete_handler.ex
index b2f9f3946..ac2dc115c 100644
--- a/lib/pleroma/web/ostatus/handlers/delete_handler.ex
+++ b/lib/pleroma/web/ostatus/handlers/delete_handler.ex
@@ -11,7 +11,7 @@ defmodule Pleroma.Web.OStatus.DeleteHandler do
def handle_delete(entry, _doc \\ nil) do
with id <- XML.string_from_xpath("//id", entry),
%Object{} = object <- Object.normalize(id),
- {:ok, delete} <- ActivityPub.delete(object, false) do
+ {:ok, delete} <- ActivityPub.delete(object, local: false) do
delete
end
end
diff --git a/mix.exs b/mix.exs
index 3a605b455..6cf766c52 100644
--- a/mix.exs
+++ b/mix.exs
@@ -220,7 +220,10 @@ defmodule Pleroma.Mixfile do
with {branch_name, 0} <- System.cmd("git", ["rev-parse", "--abbrev-ref", "HEAD"]),
branch_name <- String.trim(branch_name),
branch_name <- System.get_env("PLEROMA_BUILD_BRANCH") || branch_name,
- true <- branch_name not in ["master", "HEAD"] do
+ true <-
+ !Enum.any?(["master", "HEAD", "release/", "stable"], fn name ->
+ String.starts_with?(name, branch_name)
+ end) do
branch_name =
branch_name
|> String.trim()
diff --git a/rel/files/bin/pleroma_ctl b/rel/files/bin/pleroma_ctl
index f767fe134..90f87a990 100755
--- a/rel/files/bin/pleroma_ctl
+++ b/rel/files/bin/pleroma_ctl
@@ -35,11 +35,11 @@ detect_branch() {
if [ "$branch" = "develop" ]; then
echo "develop"
elif [ "$branch" = "" ]; then
- echo "master"
+ echo "stable"
else
# Note: branch name in version is of SemVer format and may only contain [0-9a-zA-Z-] symbols —
# if supporting releases for more branches, need to ensure they contain only these symbols.
- echo "Releases are built only for master and develop branches" >&2
+ echo "Can't detect the branch automatically, please specify it by using the --branch option." >&2
exit 1
fi
}
diff --git a/test/moderation_log_test.exs b/test/moderation_log_test.exs
index ead97e948..81c0fef12 100644
--- a/test/moderation_log_test.exs
+++ b/test/moderation_log_test.exs
@@ -24,13 +24,13 @@ defmodule Pleroma.ModerationLogTest do
{:ok, _} =
ModerationLog.insert_log(%{
actor: moderator,
- subject: subject1,
+ subject: [subject1],
action: "delete"
})
log = Repo.one(ModerationLog)
- assert log.data["message"] == "@#{moderator.nickname} deleted user @#{subject1.nickname}"
+ assert log.data["message"] == "@#{moderator.nickname} deleted users: @#{subject1.nickname}"
end
test "logging user creation by moderator", %{
diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs
index c9f2a92e7..3a5a2f984 100644
--- a/test/web/activity_pub/activity_pub_test.exs
+++ b/test/web/activity_pub/activity_pub_test.exs
@@ -87,6 +87,66 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
end
end
+ describe "fetching excluded by visibility" do
+ test "it excludes by the appropriate visibility" do
+ user = insert(:user)
+
+ {:ok, public_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "public"})
+
+ {:ok, direct_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"})
+
+ {:ok, unlisted_activity} =
+ CommonAPI.post(user, %{"status" => ".", "visibility" => "unlisted"})
+
+ {:ok, private_activity} =
+ CommonAPI.post(user, %{"status" => ".", "visibility" => "private"})
+
+ activities =
+ ActivityPub.fetch_activities([], %{
+ "exclude_visibilities" => "direct",
+ "actor_id" => user.ap_id
+ })
+
+ assert public_activity in activities
+ assert unlisted_activity in activities
+ assert private_activity in activities
+ refute direct_activity in activities
+
+ activities =
+ ActivityPub.fetch_activities([], %{
+ "exclude_visibilities" => "unlisted",
+ "actor_id" => user.ap_id
+ })
+
+ assert public_activity in activities
+ refute unlisted_activity in activities
+ assert private_activity in activities
+ assert direct_activity in activities
+
+ activities =
+ ActivityPub.fetch_activities([], %{
+ "exclude_visibilities" => "private",
+ "actor_id" => user.ap_id
+ })
+
+ assert public_activity in activities
+ assert unlisted_activity in activities
+ refute private_activity in activities
+ assert direct_activity in activities
+
+ activities =
+ ActivityPub.fetch_activities([], %{
+ "exclude_visibilities" => "public",
+ "actor_id" => user.ap_id
+ })
+
+ refute public_activity in activities
+ assert unlisted_activity in activities
+ assert private_activity in activities
+ assert direct_activity in activities
+ end
+ end
+
describe "building a user from his ap id" do
test "it returns a user" do
user_id = "http://mastodon.example.org/users/admin"
diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs
index 50c0bfb84..6c35a6f4d 100644
--- a/test/web/activity_pub/transmogrifier_test.exs
+++ b/test/web/activity_pub/transmogrifier_test.exs
@@ -682,6 +682,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
test "it works for incoming deletes" do
activity = insert(:note_activity)
+ deleting_user = insert(:user)
data =
File.read!("test/fixtures/mastodon-delete.json")
@@ -694,11 +695,14 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
data =
data
|> Map.put("object", object)
- |> Map.put("actor", activity.data["actor"])
+ |> Map.put("actor", deleting_user.ap_id)
- {:ok, %Activity{local: false}} = Transmogrifier.handle_incoming(data)
+ {:ok, %Activity{actor: actor, local: false, data: %{"id" => id}}} =
+ Transmogrifier.handle_incoming(data)
+ assert id == data["id"]
refute Activity.get_by_id(activity.id)
+ assert actor == deleting_user.ap_id
end
test "it fails for incoming deletes with spoofed origin" do
@@ -905,6 +909,8 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert activity.data["object"] == follow_activity.data["id"]
+ assert activity.data["id"] == accept_data["id"]
+
follower = User.get_cached_by_id(follower.id)
assert User.following?(follower, followed) == true
@@ -1009,6 +1015,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
{:ok, activity} = Transmogrifier.handle_incoming(reject_data)
refute activity.local
+ assert activity.data["id"] == reject_data["id"]
follower = User.get_cached_by_id(follower.id)
diff --git a/test/web/admin_api/admin_api_controller_test.exs b/test/web/admin_api/admin_api_controller_test.exs
index 81dc5d101..645b79f57 100644
--- a/test/web/admin_api/admin_api_controller_test.exs
+++ b/test/web/admin_api/admin_api_controller_test.exs
@@ -17,8 +17,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
alias Pleroma.Web.MediaProxy
import Pleroma.Factory
- describe "/api/pleroma/admin/users" do
- test "Delete" do
+ describe "DELETE /api/pleroma/admin/users" do
+ test "single user" do
admin = insert(:user, info: %{is_admin: true})
user = insert(:user)
@@ -30,15 +30,36 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
log_entry = Repo.one(ModerationLog)
- assert log_entry.data["subject"]["nickname"] == user.nickname
- assert log_entry.data["action"] == "delete"
-
assert ModerationLog.get_log_entry_message(log_entry) ==
- "@#{admin.nickname} deleted user @#{user.nickname}"
+ "@#{admin.nickname} deleted users: @#{user.nickname}"
assert json_response(conn, 200) == user.nickname
end
+ test "multiple users" do
+ admin = insert(:user, info: %{is_admin: true})
+ user_one = insert(:user)
+ user_two = insert(:user)
+
+ conn =
+ build_conn()
+ |> assign(:user, admin)
+ |> put_req_header("accept", "application/json")
+ |> delete("/api/pleroma/admin/users", %{
+ nicknames: [user_one.nickname, user_two.nickname]
+ })
+
+ log_entry = Repo.one(ModerationLog)
+
+ assert ModerationLog.get_log_entry_message(log_entry) ==
+ "@#{admin.nickname} deleted users: @#{user_one.nickname}, @#{user_two.nickname}"
+
+ response = json_response(conn, 200)
+ assert response -- [user_one.nickname, user_two.nickname] == []
+ end
+ end
+
+ describe "/api/pleroma/admin/users" do
test "Create" do
admin = insert(:user, info: %{is_admin: true})
diff --git a/test/web/mastodon_api/controllers/account_controller_test.exs b/test/web/mastodon_api/controllers/account_controller_test.exs
index 6a59c3d94..745383757 100644
--- a/test/web/mastodon_api/controllers/account_controller_test.exs
+++ b/test/web/mastodon_api/controllers/account_controller_test.exs
@@ -237,6 +237,20 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
assert [%{"id" => id}] = json_response(conn, 200)
assert id == to_string(post.id)
end
+
+ test "the user views their own timelines and excludes direct messages", %{conn: conn} do
+ user = insert(:user)
+ {:ok, public_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "public"})
+ {:ok, _direct_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"})
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/accounts/#{user.id}/statuses", %{"exclude_visibilities" => ["direct"]})
+
+ assert [%{"id" => id}] = json_response(conn, 200)
+ assert id == to_string(public_activity.id)
+ end
end
describe "followers" do
diff --git a/test/web/mastodon_api/controllers/notification_controller_test.exs b/test/web/mastodon_api/controllers/notification_controller_test.exs
index e4137e92c..fa55a7cf9 100644
--- a/test/web/mastodon_api/controllers/notification_controller_test.exs
+++ b/test/web/mastodon_api/controllers/notification_controller_test.exs
@@ -137,6 +137,57 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
assert [%{"id" => ^notification3_id}, %{"id" => ^notification2_id}] = result
end
+ test "filters notifications using exclude_visibilities", %{conn: conn} do
+ user = insert(:user)
+ other_user = insert(:user)
+
+ {:ok, public_activity} =
+ CommonAPI.post(other_user, %{"status" => "@#{user.nickname}", "visibility" => "public"})
+
+ {:ok, direct_activity} =
+ CommonAPI.post(other_user, %{"status" => "@#{user.nickname}", "visibility" => "direct"})
+
+ {:ok, unlisted_activity} =
+ CommonAPI.post(other_user, %{"status" => "@#{user.nickname}", "visibility" => "unlisted"})
+
+ {:ok, private_activity} =
+ CommonAPI.post(other_user, %{"status" => "@#{user.nickname}", "visibility" => "private"})
+
+ conn = assign(conn, :user, user)
+
+ conn_res =
+ get(conn, "/api/v1/notifications", %{
+ exclude_visibilities: ["public", "unlisted", "private"]
+ })
+
+ assert [%{"status" => %{"id" => id}}] = json_response(conn_res, 200)
+ assert id == direct_activity.id
+
+ conn_res =
+ get(conn, "/api/v1/notifications", %{
+ exclude_visibilities: ["public", "unlisted", "direct"]
+ })
+
+ assert [%{"status" => %{"id" => id}}] = json_response(conn_res, 200)
+ assert id == private_activity.id
+
+ conn_res =
+ get(conn, "/api/v1/notifications", %{
+ exclude_visibilities: ["public", "private", "direct"]
+ })
+
+ assert [%{"status" => %{"id" => id}}] = json_response(conn_res, 200)
+ assert id == unlisted_activity.id
+
+ conn_res =
+ get(conn, "/api/v1/notifications", %{
+ exclude_visibilities: ["unlisted", "private", "direct"]
+ })
+
+ assert [%{"status" => %{"id" => id}}] = json_response(conn_res, 200)
+ assert id == public_activity.id
+ end
+
test "filters notifications using exclude_types", %{conn: conn} do
user = insert(:user)
other_user = insert(:user)
diff --git a/test/web/mastodon_api/controllers/search_controller_test.exs b/test/web/mastodon_api/controllers/search_controller_test.exs
index 0ca896e01..ee413eef7 100644
--- a/test/web/mastodon_api/controllers/search_controller_test.exs
+++ b/test/web/mastodon_api/controllers/search_controller_test.exs
@@ -40,9 +40,9 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do
test "search", %{conn: conn} do
user = insert(:user)
user_two = insert(:user, %{nickname: "shp@shitposter.club"})
- user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu 天子"})
+ user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
- {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about 2hu private"})
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about 2hu private 天子"})
{:ok, _activity} =
CommonAPI.post(user, %{
@@ -70,8 +70,8 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do
get(conn, "/api/v2/search", %{"q" => "天子"})
|> json_response(200)
- [account] == results["accounts"]
- assert account["id"] == to_string(user_three.id)
+ [status] = results["statuses"]
+ assert status["id"] == to_string(activity.id)
end
end
diff --git a/test/web/mastodon_api/controllers/timeline_controller_test.exs b/test/web/mastodon_api/controllers/timeline_controller_test.exs
index d3652d964..fc45c25de 100644
--- a/test/web/mastodon_api/controllers/timeline_controller_test.exs
+++ b/test/web/mastodon_api/controllers/timeline_controller_test.exs
@@ -20,27 +20,52 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
:ok
end
- test "the home timeline", %{conn: conn} do
- user = insert(:user)
- following = insert(:user)
+ describe "home" do
+ test "the home timeline", %{conn: conn} do
+ user = insert(:user)
+ following = insert(:user)
- {:ok, _activity} = CommonAPI.post(following, %{"status" => "test"})
+ {:ok, _activity} = CommonAPI.post(following, %{"status" => "test"})
- conn =
- conn
- |> assign(:user, user)
- |> get("/api/v1/timelines/home")
+ conn =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/timelines/home")
- assert Enum.empty?(json_response(conn, :ok))
+ assert Enum.empty?(json_response(conn, :ok))
- {:ok, user} = User.follow(user, following)
+ {:ok, user} = User.follow(user, following)
- conn =
- build_conn()
- |> assign(:user, user)
- |> get("/api/v1/timelines/home")
+ conn =
+ build_conn()
+ |> assign(:user, user)
+ |> get("/api/v1/timelines/home")
- assert [%{"content" => "test"}] = json_response(conn, :ok)
+ assert [%{"content" => "test"}] = json_response(conn, :ok)
+ end
+
+ test "the home timeline when the direct messages are excluded", %{conn: conn} do
+ user = insert(:user)
+ {:ok, public_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "public"})
+ {:ok, direct_activity} = CommonAPI.post(user, %{"status" => ".", "visibility" => "direct"})
+
+ {:ok, unlisted_activity} =
+ CommonAPI.post(user, %{"status" => ".", "visibility" => "unlisted"})
+
+ {:ok, private_activity} =
+ CommonAPI.post(user, %{"status" => ".", "visibility" => "private"})
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/timelines/home", %{"exclude_visibilities" => ["direct"]})
+
+ assert status_ids = json_response(conn, :ok) |> Enum.map(& &1["id"])
+ assert public_activity.id in status_ids
+ assert unlisted_activity.id in status_ids
+ assert private_activity.id in status_ids
+ refute direct_activity.id in status_ids
+ end
end
describe "public" do