aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.credo.exs2
-rw-r--r--.gitlab-ci.yml5
-rw-r--r--config/config.exs8
-rw-r--r--config/dev.exs3
-rw-r--r--docs/Clients.md13
-rw-r--r--docs/Differences-in-MastodonAPI-Responses.md11
-rw-r--r--docs/Pleroma-API.md14
-rw-r--r--docs/config.md2
-rw-r--r--lib/pleroma/notification.ex3
-rw-r--r--lib/pleroma/object.ex22
-rw-r--r--lib/pleroma/plugs/http_security_plug.ex23
-rw-r--r--lib/pleroma/thread_mute.ex45
-rw-r--r--lib/pleroma/uploaders/mdii.ex2
-rw-r--r--lib/pleroma/user.ex33
-rw-r--r--lib/pleroma/user/info.ex10
-rw-r--r--lib/pleroma/user/welcome_message.ex30
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub.ex20
-rw-r--r--lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex82
-rw-r--r--lib/pleroma/web/activity_pub/mrf/keyword_policy.ex28
-rw-r--r--lib/pleroma/web/activity_pub/transmogrifier.ex26
-rw-r--r--lib/pleroma/web/activity_pub/utils.ex10
-rw-r--r--lib/pleroma/web/activity_pub/views/user_view.ex75
-rw-r--r--lib/pleroma/web/common_api/common_api.ex26
-rw-r--r--lib/pleroma/web/common_api/utils.ex18
-rw-r--r--lib/pleroma/web/mastodon_api/mastodon_api_controller.ex70
-rw-r--r--lib/pleroma/web/mastodon_api/views/status_view.ex5
-rw-r--r--lib/pleroma/web/media_proxy/media_proxy.ex13
-rw-r--r--lib/pleroma/web/oauth/app.ex10
-rw-r--r--lib/pleroma/web/oauth/authorization.ex2
-rw-r--r--lib/pleroma/web/oauth/oauth_controller.ex2
-rw-r--r--lib/pleroma/web/oauth/token.ex24
-rw-r--r--lib/pleroma/web/rich_media/parser.ex9
-rw-r--r--lib/pleroma/web/router.ex10
-rw-r--r--lib/pleroma/web/templates/layout/app.html.eex26
-rw-r--r--lib/pleroma/web/templates/mastodon_api/mastodon/index.html.eex8
-rw-r--r--lib/pleroma/web/templates/o_auth/o_auth/show.html.eex4
-rw-r--r--lib/pleroma/web/twitter_api/twitter_api.ex12
-rw-r--r--lib/pleroma/web/twitter_api/twitter_api_controller.ex25
-rw-r--r--lib/pleroma/web/twitter_api/views/token_view.ex21
-rw-r--r--lib/pleroma/web/twitter_api/views/user_view.ex18
-rw-r--r--mix.exs9
-rw-r--r--priv/repo/migrations/20190205114625_create_thread_mutes.exs12
-rw-r--r--priv/static/schemas/litepub-0.1.jsonld6
-rw-r--r--test/formatter_test.exs2
-rw-r--r--test/media_proxy_test.exs9
-rw-r--r--test/notification_test.exs33
-rw-r--r--test/object_test.exs31
-rw-r--r--test/support/builders/user_builder.ex3
-rw-r--r--test/support/factory.ex13
-rw-r--r--test/tasks/relay_test.exs4
-rw-r--r--test/tasks/user_test.exs2
-rw-r--r--test/user_test.exs39
-rw-r--r--test/web/activity_pub/activity_pub_controller_test.exs13
-rw-r--r--test/web/activity_pub/activity_pub_test.exs5
-rw-r--r--test/web/activity_pub/mrf/hellthread_policy_test.exs73
-rw-r--r--test/web/activity_pub/mrf/keyword_policy_test.exs132
-rw-r--r--test/web/activity_pub/transmogrifier_test.exs54
-rw-r--r--test/web/activity_pub/views/user_view_test.exs39
-rw-r--r--test/web/admin_api/admin_api_controller_test.exs3
-rw-r--r--test/web/common_api/common_api_test.exs28
-rw-r--r--test/web/common_api/common_api_utils_test.exs2
-rw-r--r--test/web/federator_test.exs3
-rw-r--r--test/web/mastodon_api/mastodon_api_controller_test.exs76
-rw-r--r--test/web/mastodon_api/status_view_test.exs3
-rw-r--r--test/web/oauth/authorization_test.exs3
-rw-r--r--test/web/oauth/oauth_controller_test.exs3
-rw-r--r--test/web/oauth/token_test.exs4
-rw-r--r--test/web/ostatus/activity_representer_test.exs4
-rw-r--r--test/web/ostatus/feed_representer_test.exs4
-rw-r--r--test/web/ostatus/incoming_documents/delete_handling_test.exs4
-rw-r--r--test/web/ostatus/ostatus_controller_test.exs4
-rw-r--r--test/web/ostatus/ostatus_test.exs6
-rw-r--r--test/web/salmon/salmon_test.exs4
-rw-r--r--test/web/twitter_api/representers/activity_representer_test.exs7
-rw-r--r--test/web/twitter_api/twitter_api_controller_test.exs80
-rw-r--r--test/web/twitter_api/twitter_api_test.exs9
-rw-r--r--test/web/twitter_api/views/notification_view_test.exs3
-rw-r--r--test/web/websub/websub_controller_test.exs5
-rw-r--r--test/web/websub/websub_test.exs3
79 files changed, 1273 insertions, 234 deletions
diff --git a/.credo.exs b/.credo.exs
index 94e19c4b5..580cb2705 100644
--- a/.credo.exs
+++ b/.credo.exs
@@ -19,7 +19,7 @@
#
# You can give explicit globs or simply directories.
# In the latter case `**/*.{ex,exs}` will be used.
- included: ["lib/", "src/", "web/", "apps/"],
+ included: ["lib/", "src/", "web/", "apps/", "test/"],
excluded: [~r"/_build/", ~r"/deps/"]
},
#
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index b59445895..6deb0a1de 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,7 +1,8 @@
image: elixir:1.7.2
services:
- - postgres:9.6.2
+ - name: postgres:9.6.2
+ command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
variables:
POSTGRES_DB: pleroma_test
@@ -35,4 +36,4 @@ lint:
unit-testing:
stage: test
script:
- - mix test --trace
+ - mix test --trace --preload-modules
diff --git a/config/config.exs b/config/config.exs
index 9e4ee8d02..317299bf1 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -162,7 +162,9 @@ config :pleroma, :instance,
mrf_transparency: true,
autofollowed_nicknames: [],
max_pinned_statuses: 1,
- no_attachment_links: false
+ no_attachment_links: false,
+ welcome_user_nickname: nil,
+ welcome_message: nil
config :pleroma, :markup,
# XXX - unfortunately, inline images must be enabled by default right now, because
@@ -228,8 +230,8 @@ config :pleroma, :mrf_rejectnonpublic,
allow_direct: false
config :pleroma, :mrf_hellthread,
- delist_threshold: 5,
- reject_threshold: 10
+ delist_threshold: 10,
+ reject_threshold: 20
config :pleroma, :mrf_simple,
media_removal: [],
diff --git a/config/dev.exs b/config/dev.exs
index 8f89aa03c..f77bb9976 100644
--- a/config/dev.exs
+++ b/config/dev.exs
@@ -16,7 +16,8 @@ config :pleroma, Pleroma.Web.Endpoint,
debug_errors: true,
code_reloader: true,
check_origin: false,
- watchers: []
+ watchers: [],
+ secure_cookie_flag: false
config :pleroma, Pleroma.Mailer, adapter: Swoosh.Adapters.Local
diff --git a/docs/Clients.md b/docs/Clients.md
index 057f12392..c3d776488 100644
--- a/docs/Clients.md
+++ b/docs/Clients.md
@@ -7,6 +7,7 @@ Feel free to contact us to be added to this list!
- Homepage: <http://www.pleroma.com/desktop-app/>
- Source Code: ???
- Platforms: Windows, Mac, (Linux?)
+- Features: Streaming Ready
### Social
- Source Code: <https://gitlab.gnome.org/BrainBlasted/Social>
@@ -19,6 +20,7 @@ Feel free to contact us to be added to this list!
- Source Code: <https://github.com/h3poteto/whalebird-desktop>
- Contact: [@h3poteto@pleroma.io](https://pleroma.io/users/h3poteto)
- Platforms: Windows, Mac, Linux
+- Features: Streaming Ready
## Handheld
### Amaroq
@@ -26,60 +28,71 @@ Feel free to contact us to be added to this list!
- Source Code: <https://github.com/ReticentJohn/Amaroq>
- Contact: [@eurasierboy@mastodon.social](https://mastodon.social/users/eurasierboy)
- Platforms: iOS
+- Features: No Streaming
### Nekonium
- Homepage: [F-Droid Repository](https://repo.gdgd.jp.net/), [Google Play](https://play.google.com/store/apps/details?id=com.apps.nekonium), [Amazon](https://www.amazon.co.jp/dp/B076FXPRBC/)
- Source: <https://git.gdgd.jp.net/lin/nekonium/>
- Contact: [@lin@pleroma.gdgd.jp.net](https://pleroma.gdgd.jp.net/users/lin)
- Platforms: Android
+- Features: Streaming Ready
### Mastalab
- Source Code: <https://gitlab.com/tom79/mastalab/>
- Contact: [@tom79@mastodon.social](https://mastodon.social/users/tom79)
- Platforms: Android
+- Features: Streaming Ready
### Roma
- Homepage: <http://www.pleroma.com/>
- Source Code: ???
- Platforms: iOS, Android
+- Features: No Streaming
### Tootdon
- Homepage: <http://tootdon.club/>, <http://blog.mastodon-tootdon.com/>
- Source Code: ???
- Contact: [@tootdon@mstdn.jp](https://mstdn.jp/users/tootdon)
- Platforms: Android, iOS
+- Features: No Streaming
### Tusky
- Homepage: <https://tuskyapp.github.io/>
- Source Code: <https://github.com/tuskyapp/Tusky>
- Contact: [@ConnyDuck@mastodon.social](https://mastodon.social/users/ConnyDuck)
- Platforms: Android
+- Features: No Streaming
### Twidere
- Homepage: <https://twidere.mariotaku.org/>
- Source Code: <https://github.com/TwidereProject/Twidere-Android/>, <https://github.com/TwidereProject/Twidere-iOS/>
- Contact: <me@mariotaku.org>
- Platform: Android, iOS
+- Features: No Streaming
## Alternative Web Interfaces
### Brutaldon
- Homepage: <https://jfm.carcosa.net/projects/software/brutaldon/>
- Source Code: <https://github.com/jfmcbrayer/brutaldon>
- Contact: [@gcupc@glitch.social](https://glitch.social/users/gcupc)
+- Features: No Streaming
### Feather
- Source Code: <https://github.com/kaniini/feather>
- Contact: [@kaniini@pleroma.site](https://pleroma.site/kaniini)
+- Features: No Streaming
### Halcyon
- Source Code: <https://notabug.org/halcyon-suite/halcyon>
- Contact: [@halcyon@social.csswg.org](https://social.csswg.org/users/halcyon)
+- Features: Streaming Ready
### Pinafore
- Homepage: <https://pinafore.social/>
- Source Code: <https://github.com/nolanlawson/pinafore>
- Contact: [@pinafore@mastodon.technology](https://mastodon.technology/users/pinafore)
- Note: Pleroma support is a secondary goal
+- Features: No Streaming
### Sengi
- Source Code: <https://github.com/NicolasConstant/sengi>
diff --git a/docs/Differences-in-MastodonAPI-Responses.md b/docs/Differences-in-MastodonAPI-Responses.md
new file mode 100644
index 000000000..f6a5b6461
--- /dev/null
+++ b/docs/Differences-in-MastodonAPI-Responses.md
@@ -0,0 +1,11 @@
+# Differences in Mastodon API responses from vanilla Mastodon
+
+A Pleroma instance can be identified by "<Mastodon version> (compatible; Pleroma <version>)" present in `version` field in response from `/api/v1/instance`
+
+## Flake IDs
+
+Pleroma uses 128-bit ids as opposed to Mastodon's 64 bits. However just like Mastodon's ids they are sortable strings
+
+## Attachment cap
+
+Some apps operate under the assumption that no more than 4 attachments can be returned or uploaded. Pleroma however does not enforce any limits on attachment count neither when returning the status object nor when posting.
diff --git a/docs/Pleroma-API.md b/docs/Pleroma-API.md
index e1448d3f0..379d3dbed 100644
--- a/docs/Pleroma-API.md
+++ b/docs/Pleroma-API.md
@@ -94,3 +94,17 @@ Request parameters can be passed via [query strings](https://en.wikipedia.org/wi
## `/api/pleroma/admin/`…
See [Admin-API](Admin-API.md)
+
+## `/api/v1/pleroma/flavour/:flavour`
+* Method `POST`
+* Authentication: required
+* Response: JSON string. Returns the user flavour or the default one on success, otherwise returns `{"error": "error_msg"}`
+* Example response: "glitch"
+* Note: This is intended to be used only by mastofe
+
+## `/api/v1/pleroma/flavour`
+* Method `GET`
+* Authentication: required
+* Response: JSON string. Returns the user flavour or the default one.
+* Example response: "glitch"
+* Note: This is intended to be used only by mastofe
diff --git a/docs/config.md b/docs/config.md
index eb5f88e12..6647549a2 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -98,6 +98,8 @@ config :pleroma, Pleroma.Mailer,
* `max_pinned_statuses`: The maximum number of pinned statuses. `0` will disable the feature.
* `autofollowed_nicknames`: Set to nicknames of (local) users that every new user should automatically follow.
* `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_user_nickname`: The nickname of the local user that sends the welcome message.
## :logger
* `backends`: `:console` is used to send logs to stdout, `{ExSyslogger, :ex_syslogger}` to log to syslog
diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex
index c7c925c89..c88512567 100644
--- a/lib/pleroma/notification.ex
+++ b/lib/pleroma/notification.ex
@@ -10,6 +10,7 @@ defmodule Pleroma.Notification do
alias Pleroma.Notification
alias Pleroma.Repo
alias Pleroma.Web.CommonAPI.Utils
+ alias Pleroma.Web.CommonAPI
import Ecto.Query
@@ -117,7 +118,7 @@ defmodule Pleroma.Notification do
# TODO move to sql, too.
def create_notification(%Activity{} = activity, %User{} = user) do
unless User.blocks?(user, %{ap_id: activity.data["actor"]}) or
- user.ap_id == activity.data["actor"] or
+ CommonAPI.thread_muted?(user, activity) or user.ap_id == activity.data["actor"] or
(activity.data["type"] == "Follow" and
Enum.any?(Notification.for_user(user), fn notif ->
notif.activity.data["type"] == "Follow" and
diff --git a/lib/pleroma/object.ex b/lib/pleroma/object.ex
index dabb49536..5f1fc801b 100644
--- a/lib/pleroma/object.ex
+++ b/lib/pleroma/object.ex
@@ -20,29 +20,9 @@ defmodule Pleroma.Object do
timestamps()
end
- def insert_or_get(cng) do
- {_, data} = fetch_field(cng, :data)
- id = data["id"] || data[:id]
- key = "object:#{id}"
-
- fetcher = fn _ ->
- with nil <- get_by_ap_id(id),
- {:ok, object} <- Repo.insert(cng) do
- {:commit, object}
- else
- %Object{} = object -> {:commit, object}
- e -> {:ignore, e}
- end
- end
-
- with {state, object} when state in [:commit, :ok] <- Cachex.fetch(:object_cache, key, fetcher) do
- {:ok, object}
- end
- end
-
def create(data) do
Object.change(%Object{}, %{data: data})
- |> insert_or_get()
+ |> Repo.insert()
end
def change(struct, params \\ %{}) do
diff --git a/lib/pleroma/plugs/http_security_plug.ex b/lib/pleroma/plugs/http_security_plug.ex
index 2a266c407..057553e24 100644
--- a/lib/pleroma/plugs/http_security_plug.ex
+++ b/lib/pleroma/plugs/http_security_plug.ex
@@ -33,7 +33,22 @@ defmodule Pleroma.Plugs.HTTPSecurityPlug do
end
defp csp_string do
- protocol = Config.get([Pleroma.Web.Endpoint, :protocol])
+ scheme = Config.get([Pleroma.Web.Endpoint, :url])[:scheme]
+ websocket_url = String.replace(Pleroma.Web.Endpoint.static_url(), "http", "ws")
+
+ connect_src =
+ if Mix.env() == :dev do
+ "connect-src 'self' http://localhost:3035/ " <> websocket_url
+ else
+ "connect-src 'self' " <> websocket_url
+ end
+
+ script_src =
+ if Mix.env() == :dev do
+ "script-src 'self' 'unsafe-eval'"
+ else
+ "script-src 'self'"
+ end
[
"default-src 'none'",
@@ -43,10 +58,10 @@ defmodule Pleroma.Plugs.HTTPSecurityPlug do
"media-src 'self' https:",
"style-src 'self' 'unsafe-inline'",
"font-src 'self'",
- "script-src 'self'",
- "connect-src 'self' " <> String.replace(Pleroma.Web.Endpoint.static_url(), "http", "ws"),
"manifest-src 'self'",
- if protocol == "https" do
+ connect_src,
+ script_src,
+ if scheme == "https" do
"upgrade-insecure-requests"
end
]
diff --git a/lib/pleroma/thread_mute.ex b/lib/pleroma/thread_mute.ex
new file mode 100644
index 000000000..0b577113d
--- /dev/null
+++ b/lib/pleroma/thread_mute.ex
@@ -0,0 +1,45 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.ThreadMute do
+ use Ecto.Schema
+ alias Pleroma.{Repo, User, ThreadMute}
+ require Ecto.Query
+
+ schema "thread_mutes" do
+ belongs_to(:user, User, type: Pleroma.FlakeId)
+ field(:context, :string)
+ end
+
+ def changeset(mute, params \\ %{}) do
+ mute
+ |> Ecto.Changeset.cast(params, [:user_id, :context])
+ |> Ecto.Changeset.foreign_key_constraint(:user_id)
+ |> Ecto.Changeset.unique_constraint(:user_id, name: :unique_index)
+ end
+
+ def query(user_id, context) do
+ user_id = Pleroma.FlakeId.from_string(user_id)
+
+ ThreadMute
+ |> Ecto.Query.where(user_id: ^user_id)
+ |> Ecto.Query.where(context: ^context)
+ end
+
+ def add_mute(user_id, context) do
+ %ThreadMute{}
+ |> changeset(%{user_id: user_id, context: context})
+ |> Repo.insert()
+ end
+
+ def remove_mute(user_id, context) do
+ query(user_id, context)
+ |> Repo.delete_all()
+ end
+
+ def check_muted(user_id, context) do
+ query(user_id, context)
+ |> Repo.all()
+ end
+end
diff --git a/lib/pleroma/uploaders/mdii.ex b/lib/pleroma/uploaders/mdii.ex
index 320b07abd..190ed9f3a 100644
--- a/lib/pleroma/uploaders/mdii.ex
+++ b/lib/pleroma/uploaders/mdii.ex
@@ -25,7 +25,7 @@ defmodule Pleroma.Uploaders.MDII do
query = "#{cgi}?#{extension}"
with {:ok, %{status: 200, body: body}} <-
- @httpoison.post(query, file_data, adapter: [pool: :default]) do
+ @httpoison.post(query, file_data, [], adapter: [pool: :default]) do
remote_file_name = String.split(body) |> List.first()
public_url = "#{files}/#{remote_file_name}.#{extension}"
{:ok, {:url, public_url}}
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 0060d966b..ff84e7b0a 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -261,6 +261,7 @@ defmodule Pleroma.User do
def register(%Ecto.Changeset{} = changeset) do
with {:ok, user} <- Repo.insert(changeset),
{:ok, user} <- autofollow_users(user),
+ {:ok, _} <- Pleroma.User.WelcomeMessage.post_welcome_message_to_user(user),
{:ok, _} <- try_send_confirmation_email(user) do
{:ok, user}
end
@@ -311,12 +312,12 @@ defmodule Pleroma.User do
end
end
- @doc "A mass follow for local users. Respects blocks but does not create activities."
+ @doc "A mass follow for local users. Respects blocks in both directions but does not create activities."
@spec follow_all(User.t(), list(User.t())) :: {atom(), User.t()}
def follow_all(follower, followeds) do
followed_addresses =
followeds
- |> Enum.reject(fn %{ap_id: ap_id} -> ap_id in follower.info.blocks end)
+ |> Enum.reject(fn followed -> blocks?(follower, followed) || blocks?(followed, follower) end)
|> Enum.map(fn %{follower_address: fa} -> fa end)
q =
@@ -618,6 +619,32 @@ defmodule Pleroma.User do
)
end
+ def update_follow_request_count(%User{} = user) do
+ subquery =
+ user
+ |> User.get_follow_requests_query()
+ |> select([a], %{count: count(a.id)})
+
+ User
+ |> where(id: ^user.id)
+ |> join(:inner, [u], s in subquery(subquery))
+ |> update([u, s],
+ set: [
+ info:
+ fragment(
+ "jsonb_set(?, '{follow_request_count}', ?::varchar::jsonb, true)",
+ u.info,
+ s.count
+ )
+ ]
+ )
+ |> Repo.update_all([], returning: true)
+ |> case do
+ {1, [user]} -> {:ok, user}
+ _ -> {:error, user}
+ end
+ end
+
def get_follow_requests(%User{} = user) do
q = get_follow_requests_query(user)
reqs = Repo.all(q)
@@ -731,7 +758,7 @@ defmodule Pleroma.User do
# Strip the beginning @ off if there is a query
query = String.trim_leading(query, "@")
- if resolve, do: User.get_or_fetch_by_nickname(query)
+ if resolve, do: get_or_fetch(query)
fts_results = do_search(fts_search_subquery(query), for_user)
diff --git a/lib/pleroma/user/info.ex b/lib/pleroma/user/info.ex
index 9d8779fab..9099d7fbb 100644
--- a/lib/pleroma/user/info.ex
+++ b/lib/pleroma/user/info.ex
@@ -12,6 +12,7 @@ defmodule Pleroma.User.Info do
field(:source_data, :map, default: %{})
field(:note_count, :integer, default: 0)
field(:follower_count, :integer, default: 0)
+ field(:follow_request_count, :integer, default: 0)
field(:locked, :boolean, default: false)
field(:confirmation_pending, :boolean, default: false)
field(:confirmation_token, :string, default: nil)
@@ -34,6 +35,7 @@ defmodule Pleroma.User.Info do
field(:hide_followers, :boolean, default: false)
field(:hide_follows, :boolean, default: false)
field(:pinned_activities, {:array, :string}, default: [])
+ field(:flavour, :string, default: nil)
# Found in the wild
# ap_id -> Where is this used?
@@ -186,6 +188,14 @@ defmodule Pleroma.User.Info do
|> validate_required([:settings])
end
+ def mastodon_flavour_update(info, flavour) do
+ params = %{flavour: flavour}
+
+ info
+ |> cast(params, [:flavour])
+ |> validate_required([:flavour])
+ end
+
def set_source_data(info, source_data) do
params = %{source_data: source_data}
diff --git a/lib/pleroma/user/welcome_message.ex b/lib/pleroma/user/welcome_message.ex
new file mode 100644
index 000000000..8018ac22f
--- /dev/null
+++ b/lib/pleroma/user/welcome_message.ex
@@ -0,0 +1,30 @@
+defmodule Pleroma.User.WelcomeMessage do
+ alias Pleroma.User
+ alias Pleroma.Web.CommonAPI
+
+ def post_welcome_message_to_user(user) do
+ with %User{} = sender_user <- welcome_user(),
+ message when is_binary(message) <- welcome_message() do
+ CommonAPI.post(sender_user, %{
+ "visibility" => "direct",
+ "status" => "@#{user.nickname}\n#{message}"
+ })
+ else
+ _ -> {:ok, nil}
+ end
+ end
+
+ defp welcome_user() do
+ with nickname when is_binary(nickname) <-
+ Pleroma.Config.get([:instance, :welcome_user_nickname]),
+ %User{local: true} = user <- User.get_cached_by_nickname(nickname) do
+ user
+ else
+ _ -> nil
+ end
+ end
+
+ defp welcome_message() do
+ Pleroma.Config.get([:instance, :welcome_message])
+ end
+end
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index 501c8b845..8fd4c9899 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -172,9 +172,10 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
# only accept false as false value
local = !(params[:local] == false)
- with data <- %{"to" => to, "type" => "Accept", "actor" => actor, "object" => object},
+ with data <- %{"to" => to, "type" => "Accept", "actor" => actor.ap_id, "object" => object},
{:ok, activity} <- insert(data, local),
- :ok <- maybe_federate(activity) do
+ :ok <- maybe_federate(activity),
+ _ <- User.update_follow_request_count(actor) do
{:ok, activity}
end
end
@@ -183,9 +184,10 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
# only accept false as false value
local = !(params[:local] == false)
- with data <- %{"to" => to, "type" => "Reject", "actor" => actor, "object" => object},
+ with data <- %{"to" => to, "type" => "Reject", "actor" => actor.ap_id, "object" => object},
{:ok, activity} <- insert(data, local),
- :ok <- maybe_federate(activity) do
+ :ok <- maybe_federate(activity),
+ _ <- User.update_follow_request_count(actor) do
{:ok, activity}
end
end
@@ -283,7 +285,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
def follow(follower, followed, activity_id \\ nil, local \\ true) do
with data <- make_follow_data(follower, followed, activity_id),
{:ok, activity} <- insert(data, local),
- :ok <- maybe_federate(activity) do
+ :ok <- maybe_federate(activity),
+ _ <- User.update_follow_request_count(followed) do
{:ok, activity}
end
end
@@ -293,7 +296,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
{:ok, follow_activity} <- update_follow_state(follow_activity, "cancelled"),
unfollow_data <- make_unfollow_data(follower, followed, follow_activity, activity_id),
{:ok, activity} <- insert(unfollow_data, local),
- :ok <- maybe_federate(activity) do
+ :ok <- maybe_federate(activity),
+ _ <- User.update_follow_request_count(followed) do
{:ok, activity}
end
end
@@ -816,8 +820,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
if object = Object.get_cached_by_ap_id(id) do
{:ok, object}
else
- Logger.info("Fetching #{id} via AP")
-
with {:ok, data} <- fetch_and_contain_remote_object_from_id(id),
nil <- Object.normalize(data),
params <- %{
@@ -849,7 +851,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
end
def fetch_and_contain_remote_object_from_id(id) do
- Logger.info("Fetching #{id} via AP")
+ Logger.info("Fetching object #{id} via AP")
with true <- String.starts_with?(id, "http"),
{:ok, %{body: body, status: code}} when code in 200..299 <-
diff --git a/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex b/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex
index 4c6e612b2..6736f3cb9 100644
--- a/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/hellthread_policy.ex
@@ -6,40 +6,80 @@ defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicy do
alias Pleroma.User
@behaviour Pleroma.Web.ActivityPub.MRF
- defp delist_message(message) do
+ defp delist_message(message, threshold) when threshold > 0 do
follower_collection = User.get_cached_by_ap_id(message["actor"]).follower_address
- message
- |> Map.put("to", [follower_collection])
- |> Map.put("cc", ["https://www.w3.org/ns/activitystreams#Public"])
+ follower_collection? = Enum.member?(message["to"] ++ message["cc"], follower_collection)
+
+ message =
+ case get_recipient_count(message) do
+ {:public, recipients}
+ when follower_collection? and recipients > threshold ->
+ message
+ |> Map.put("to", [follower_collection])
+ |> Map.put("cc", ["https://www.w3.org/ns/activitystreams#Public"])
+
+ {:public, recipients} when recipients > threshold ->
+ message
+ |> Map.put("to", [])
+ |> Map.put("cc", ["https://www.w3.org/ns/activitystreams#Public"])
+
+ _ ->
+ message
+ end
+
+ {:ok, message}
+ end
+
+ defp delist_message(message, _threshold), do: {:ok, message}
+
+ defp reject_message(message, threshold) when threshold > 0 do
+ with {_, recipients} <- get_recipient_count(message) do
+ if recipients > threshold do
+ {:reject, nil}
+ else
+ {:ok, message}
+ end
+ end
+ end
+
+ defp reject_message(message, _threshold), do: {:ok, message}
+
+ defp get_recipient_count(message) do
+ recipients = (message["to"] || []) ++ (message["cc"] || [])
+ follower_collection = User.get_cached_by_ap_id(message["actor"]).follower_address
+
+ if Enum.member?(recipients, "https://www.w3.org/ns/activitystreams#Public") do
+ recipients =
+ recipients
+ |> List.delete("https://www.w3.org/ns/activitystreams#Public")
+ |> List.delete(follower_collection)
+
+ {:public, length(recipients)}
+ else
+ recipients =
+ recipients
+ |> List.delete(follower_collection)
+
+ {:not_public, length(recipients)}
+ end
end
@impl true
def filter(%{"type" => "Create"} = message) do
- delist_threshold = Pleroma.Config.get([:mrf_hellthread, :delist_threshold])
-
reject_threshold =
Pleroma.Config.get(
[:mrf_hellthread, :reject_threshold],
Pleroma.Config.get([:mrf_hellthread, :threshold])
)
- recipients = (message["to"] || []) ++ (message["cc"] || [])
-
- cond do
- length(recipients) > reject_threshold and reject_threshold > 0 ->
- {:reject, nil}
-
- length(recipients) > delist_threshold and delist_threshold > 0 ->
- if Enum.member?(message["to"], "https://www.w3.org/ns/activitystreams#Public") or
- Enum.member?(message["cc"], "https://www.w3.org/ns/activitystreams#Public") do
- {:ok, delist_message(message)}
- else
- {:ok, message}
- end
+ delist_threshold = Pleroma.Config.get([:mrf_hellthread, :delist_threshold])
- true ->
- {:ok, message}
+ with {:ok, message} <- reject_message(message, reject_threshold),
+ {:ok, message} <- delist_message(message, delist_threshold) do
+ {:ok, message}
+ else
+ _e -> {:reject, nil}
end
end
diff --git a/lib/pleroma/web/activity_pub/mrf/keyword_policy.ex b/lib/pleroma/web/activity_pub/mrf/keyword_policy.ex
index ce6d2e529..5fdc03414 100644
--- a/lib/pleroma/web/activity_pub/mrf/keyword_policy.ex
+++ b/lib/pleroma/web/activity_pub/mrf/keyword_policy.ex
@@ -12,9 +12,9 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
String.match?(string, pattern)
end
- defp check_reject(%{"object" => %{"content" => content}} = message) do
+ defp check_reject(%{"object" => %{"content" => content, "summary" => summary}} = message) do
if Enum.any?(Pleroma.Config.get([:mrf_keyword, :reject]), fn pattern ->
- string_matches?(content, pattern)
+ string_matches?(content, pattern) or string_matches?(summary, pattern)
end) do
{:reject, nil}
else
@@ -22,10 +22,12 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
end
end
- defp check_ftl_removal(%{"to" => to, "object" => %{"content" => content}} = message) do
+ defp check_ftl_removal(
+ %{"to" => to, "object" => %{"content" => content, "summary" => summary}} = message
+ ) do
if "https://www.w3.org/ns/activitystreams#Public" in to and
Enum.any?(Pleroma.Config.get([:mrf_keyword, :federated_timeline_removal]), fn pattern ->
- string_matches?(content, pattern)
+ string_matches?(content, pattern) or string_matches?(summary, pattern)
end) do
to = List.delete(to, "https://www.w3.org/ns/activitystreams#Public")
cc = ["https://www.w3.org/ns/activitystreams#Public" | message["cc"] || []]
@@ -41,14 +43,20 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
end
end
- defp check_replace(%{"object" => %{"content" => content}} = message) do
- content =
- Enum.reduce(Pleroma.Config.get([:mrf_keyword, :replace]), content, fn {pattern, replacement},
- acc ->
- String.replace(acc, pattern, replacement)
+ defp check_replace(%{"object" => %{"content" => content, "summary" => summary}} = message) do
+ {content, summary} =
+ Enum.reduce(Pleroma.Config.get([:mrf_keyword, :replace]), {content, summary}, fn {pattern,
+ replacement},
+ {content_acc,
+ summary_acc} ->
+ {String.replace(content_acc, pattern, replacement),
+ String.replace(summary_acc, pattern, replacement)}
end)
- {:ok, put_in(message["object"]["content"], content)}
+ {:ok,
+ message
+ |> put_in(["object", "content"], content)
+ |> put_in(["object", "summary"], summary)}
end
@impl true
diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
index 98a2af819..41d89a02b 100644
--- a/lib/pleroma/web/activity_pub/transmogrifier.ex
+++ b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -406,7 +406,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
if not User.locked?(followed) do
ActivityPub.accept(%{
to: [follower.ap_id],
- actor: followed.ap_id,
+ actor: followed,
object: data,
local: true
})
@@ -432,7 +432,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
ActivityPub.accept(%{
to: follow_activity.data["to"],
type: "Accept",
- actor: followed.ap_id,
+ actor: followed,
object: follow_activity.data["id"],
local: false
}) do
@@ -458,7 +458,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
ActivityPub.reject(%{
to: follow_activity.data["to"],
type: "Reject",
- actor: followed.ap_id,
+ actor: followed,
object: follow_activity.data["id"],
local: false
}) do
@@ -649,7 +649,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
if object = Object.normalize(id), do: {:ok, object}, else: nil
end
- def set_reply_to_uri(%{"inReplyTo" => inReplyTo} = object) do
+ def set_reply_to_uri(%{"inReplyTo" => inReplyTo} = object) when is_binary(inReplyTo) do
with false <- String.starts_with?(inReplyTo, "http"),
{:ok, %{data: replied_to_object}} <- get_obj_helper(inReplyTo) do
Map.put(object, "inReplyTo", replied_to_object["external_url"] || inReplyTo)
@@ -765,12 +765,18 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
def add_hashtags(object) do
tags =
(object["tag"] || [])
- |> Enum.map(fn tag ->
- %{
- "href" => Pleroma.Web.Endpoint.url() <> "/tags/#{tag}",
- "name" => "##{tag}",
- "type" => "Hashtag"
- }
+ |> Enum.map(fn
+ # Expand internal representation tags into AS2 tags.
+ tag when is_binary(tag) ->
+ %{
+ "href" => Pleroma.Web.Endpoint.url() <> "/tags/#{tag}",
+ "name" => "##{tag}",
+ "type" => "Hashtag"
+ }
+
+ # Do not process tags which are already AS2 tag objects.
+ tag when is_map(tag) ->
+ tag
end)
object
diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex
index e34dd1d41..6a89374d0 100644
--- a/lib/pleroma/web/activity_pub/utils.ex
+++ b/lib/pleroma/web/activity_pub/utils.ex
@@ -142,8 +142,14 @@ defmodule Pleroma.Web.ActivityPub.Utils do
context = context || generate_id("contexts")
changeset = Object.context_mapping(context)
- with {:ok, object} <- Object.insert_or_get(changeset) do
- object
+ case Repo.insert(changeset) do
+ {:ok, object} ->
+ object
+
+ # This should be solved by an upsert, but it seems ecto
+ # has problems accessing the constraint inside the jsonb.
+ {:error, _} ->
+ Object.get_cached_by_ap_id(context)
end
end
diff --git a/lib/pleroma/web/activity_pub/views/user_view.ex b/lib/pleroma/web/activity_pub/views/user_view.ex
index 15e6c1f68..c8e154989 100644
--- a/lib/pleroma/web/activity_pub/views/user_view.ex
+++ b/lib/pleroma/web/activity_pub/views/user_view.ex
@@ -12,9 +12,26 @@ defmodule Pleroma.Web.ActivityPub.UserView do
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Transmogrifier
alias Pleroma.Web.ActivityPub.Utils
+ alias Pleroma.Web.Router.Helpers
+ alias Pleroma.Web.Endpoint
import Ecto.Query
+ def render("endpoints.json", %{user: %User{nickname: nil, local: true} = _user}) do
+ %{"sharedInbox" => Helpers.activity_pub_url(Endpoint, :inbox)}
+ end
+
+ def render("endpoints.json", %{user: %User{local: true} = _user}) do
+ %{
+ "oauthAuthorizationEndpoint" => Helpers.o_auth_url(Endpoint, :authorize),
+ "oauthRegistrationEndpoint" => Helpers.mastodon_api_url(Endpoint, :create_app),
+ "oauthTokenEndpoint" => Helpers.o_auth_url(Endpoint, :token_exchange),
+ "sharedInbox" => Helpers.activity_pub_url(Endpoint, :inbox)
+ }
+ end
+
+ def render("endpoints.json", _), do: %{}
+
# the instance itself is not a Person, but instead an Application
def render("user.json", %{user: %{nickname: nil} = user}) do
{:ok, user} = WebFinger.ensure_keys_present(user)
@@ -22,6 +39,8 @@ defmodule Pleroma.Web.ActivityPub.UserView do
public_key = :public_key.pem_entry_encode(:SubjectPublicKeyInfo, public_key)
public_key = :public_key.pem_encode([public_key])
+ endpoints = render("endpoints.json", %{user: user})
+
%{
"id" => user.ap_id,
"type" => "Application",
@@ -37,9 +56,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
"owner" => user.ap_id,
"publicKeyPem" => public_key
},
- "endpoints" => %{
- "sharedInbox" => "#{Pleroma.Web.Endpoint.url()}/inbox"
- }
+ "endpoints" => endpoints
}
|> Map.merge(Utils.make_json_ld_header())
end
@@ -50,6 +67,8 @@ defmodule Pleroma.Web.ActivityPub.UserView do
public_key = :public_key.pem_entry_encode(:SubjectPublicKeyInfo, public_key)
public_key = :public_key.pem_encode([public_key])
+ endpoints = render("endpoints.json", %{user: user})
+
%{
"id" => user.ap_id,
"type" => "Person",
@@ -67,9 +86,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
"owner" => user.ap_id,
"publicKeyPem" => public_key
},
- "endpoints" => %{
- "sharedInbox" => "#{Pleroma.Web.Endpoint.url()}/inbox"
- },
+ "endpoints" => endpoints,
"icon" => %{
"type" => "Image",
"url" => User.avatar_url(user)
@@ -88,7 +105,14 @@ defmodule Pleroma.Web.ActivityPub.UserView do
query = from(user in query, select: [:ap_id])
following = Repo.all(query)
- collection(following, "#{user.ap_id}/following", page, !user.info.hide_follows)
+ total =
+ if !user.info.hide_follows do
+ length(following)
+ else
+ 0
+ end
+
+ collection(following, "#{user.ap_id}/following", page, !user.info.hide_follows, total)
|> Map.merge(Utils.make_json_ld_header())
end
@@ -97,10 +121,17 @@ defmodule Pleroma.Web.ActivityPub.UserView do
query = from(user in query, select: [:ap_id])
following = Repo.all(query)
+ total =
+ if !user.info.hide_follows do
+ length(following)
+ else
+ 0
+ end
+
%{
"id" => "#{user.ap_id}/following",
"type" => "OrderedCollection",
- "totalItems" => length(following),
+ "totalItems" => total,
"first" => collection(following, "#{user.ap_id}/following", 1, !user.info.hide_follows)
}
|> Map.merge(Utils.make_json_ld_header())
@@ -111,7 +142,14 @@ defmodule Pleroma.Web.ActivityPub.UserView do
query = from(user in query, select: [:ap_id])
followers = Repo.all(query)
- collection(followers, "#{user.ap_id}/followers", page, !user.info.hide_followers)
+ total =
+ if !user.info.hide_followers do
+ length(followers)
+ else
+ 0
+ end
+
+ collection(followers, "#{user.ap_id}/followers", page, !user.info.hide_followers, total)
|> Map.merge(Utils.make_json_ld_header())
end
@@ -120,19 +158,24 @@ defmodule Pleroma.Web.ActivityPub.UserView do
query = from(user in query, select: [:ap_id])
followers = Repo.all(query)
+ total =
+ if !user.info.hide_followers do
+ length(followers)
+ else
+ 0
+ end
+
%{
"id" => "#{user.ap_id}/followers",
"type" => "OrderedCollection",
- "totalItems" => length(followers),
- "first" => collection(followers, "#{user.ap_id}/followers", 1, !user.info.hide_followers)
+ "totalItems" => total,
+ "first" =>
+ collection(followers, "#{user.ap_id}/followers", 1, !user.info.hide_followers, total)
}
|> Map.merge(Utils.make_json_ld_header())
end
def render("outbox.json", %{user: user, max_id: max_qid}) do
- # XXX: technically note_count is wrong for this, but it's better than nothing
- info = User.user_info(user)
-
params = %{
"limit" => "10"
}
@@ -160,7 +203,6 @@ defmodule Pleroma.Web.ActivityPub.UserView do
"id" => "#{iri}?max_id=#{max_id}",
"type" => "OrderedCollectionPage",
"partOf" => iri,
- "totalItems" => info.note_count,
"orderedItems" => collection,
"next" => "#{iri}?max_id=#{min_id}"
}
@@ -169,7 +211,6 @@ defmodule Pleroma.Web.ActivityPub.UserView do
%{
"id" => iri,
"type" => "OrderedCollection",
- "totalItems" => info.note_count,
"first" => page
}
|> Map.merge(Utils.make_json_ld_header())
@@ -207,7 +248,6 @@ defmodule Pleroma.Web.ActivityPub.UserView do
"id" => "#{iri}?max_id=#{max_id}",
"type" => "OrderedCollectionPage",
"partOf" => iri,
- "totalItems" => -1,
"orderedItems" => collection,
"next" => "#{iri}?max_id=#{min_id}"
}
@@ -216,7 +256,6 @@ defmodule Pleroma.Web.ActivityPub.UserView do
%{
"id" => iri,
"type" => "OrderedCollection",
- "totalItems" => -1,
"first" => page
}
|> Map.merge(Utils.make_json_ld_header())
diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex
index c0d6fb5c4..90b208e54 100644
--- a/lib/pleroma/web/common_api/common_api.ex
+++ b/lib/pleroma/web/common_api/common_api.ex
@@ -7,6 +7,7 @@ defmodule Pleroma.Web.CommonAPI do
alias Pleroma.Repo
alias Pleroma.Activity
alias Pleroma.Object
+ alias Pleroma.ThreadMute
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Formatter
@@ -94,7 +95,7 @@ defmodule Pleroma.Web.CommonAPI do
limit = Pleroma.Config.get([:instance, :limit])
with status <- String.trim(status),
- attachments <- attachments_from_ids(data["media_ids"]),
+ attachments <- attachments_from_ids(data),
mentions <- Formatter.parse_mentions(status),
inReplyTo <- get_replied_to_activity(data["in_reply_to_status_id"]),
{to, cc} <- to_for_user_and_mentions(user, mentions, inReplyTo, visibility),
@@ -219,4 +220,27 @@ defmodule Pleroma.Web.CommonAPI do
{:error, "Could not unpin"}
end
end
+
+ def add_mute(user, activity) do
+ with {:ok, _} <- ThreadMute.add_mute(user.id, activity.data["context"]) do
+ {:ok, activity}
+ else
+ {:error, _} -> {:error, "conversation is already muted"}
+ end
+ end
+
+ def remove_mute(user, activity) do
+ ThreadMute.remove_mute(user.id, activity.data["context"])
+ {:ok, activity}
+ end
+
+ def thread_muted?(%{id: nil} = _user, _activity), do: false
+
+ def thread_muted?(user, activity) do
+ with [] <- ThreadMute.check_muted(user.id, activity.data["context"]) do
+ false
+ else
+ _ -> true
+ end
+ end
end
diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex
index 123107b56..abdeee947 100644
--- a/lib/pleroma/web/common_api/utils.ex
+++ b/lib/pleroma/web/common_api/utils.ex
@@ -35,12 +35,28 @@ defmodule Pleroma.Web.CommonAPI.Utils do
def get_replied_to_activity(_), do: nil
- def attachments_from_ids(ids) do
+ def attachments_from_ids(data) do
+ if Map.has_key?(data, "descriptions") do
+ attachments_from_ids_descs(data["media_ids"], data["descriptions"])
+ else
+ attachments_from_ids_no_descs(data["media_ids"])
+ end
+ end
+
+ def attachments_from_ids_no_descs(ids) do
Enum.map(ids || [], fn media_id ->
Repo.get(Object, media_id).data
end)
end
+ def attachments_from_ids_descs(ids, descs_str) do
+ {_, descs} = Jason.decode(descs_str)
+
+ Enum.map(ids || [], fn media_id ->
+ Map.put(Repo.get(Object, media_id).data, "name", descs[media_id])
+ end)
+ end
+
def to_for_user_and_mentions(user, mentions, inReplyTo, "public") do
mentioned_users = Enum.map(mentions, fn {_, %{ap_id: ap_id}} -> ap_id end)
diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
index 06f870393..e2715bd08 100644
--- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
+++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
@@ -456,6 +456,31 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
end
end
+ def mute_conversation(%{assigns: %{user: user}} = conn, %{"id" => id}) do
+ activity = Activity.get_by_id(id)
+
+ with {:ok, activity} <- CommonAPI.add_mute(user, activity) do
+ conn
+ |> put_view(StatusView)
+ |> try_render("status.json", %{activity: activity, for: user, as: :activity})
+ else
+ {:error, reason} ->
+ conn
+ |> put_resp_content_type("application/json")
+ |> send_resp(:bad_request, Jason.encode!(%{"error" => reason}))
+ end
+ end
+
+ def unmute_conversation(%{assigns: %{user: user}} = conn, %{"id" => id}) do
+ activity = Activity.get_by_id(id)
+
+ with {:ok, activity} <- CommonAPI.remove_mute(user, activity) do
+ conn
+ |> put_view(StatusView)
+ |> try_render("status.json", %{activity: activity, for: user, as: :activity})
+ end
+ end
+
def notifications(%{assigns: %{user: user}} = conn, params) do
notifications = Notification.for_user(user, params)
@@ -655,7 +680,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
{:ok, _activity} <-
ActivityPub.accept(%{
to: [follower.ap_id],
- actor: followed.ap_id,
+ actor: followed,
object: follow_activity.data["id"],
type: "Accept"
}) do
@@ -677,7 +702,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
{:ok, _activity} <-
ActivityPub.reject(%{
to: [follower.ap_id],
- actor: followed.ap_id,
+ actor: followed,
object: follow_activity.data["id"],
type: "Reject"
}) do
@@ -1026,6 +1051,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
accounts =
Map.put(%{}, user.id, AccountView.render("account.json", %{user: user, for: user}))
+ flavour = get_user_flavour(user)
+
initial_state =
%{
meta: %{
@@ -1110,7 +1137,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
conn
|> put_layout(false)
|> put_view(MastodonView)
- |> render("index.html", %{initial_state: initial_state})
+ |> render("index.html", %{initial_state: initial_state, flavour: flavour})
else
conn
|> redirect(to: "/web/login")
@@ -1132,6 +1159,43 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
end
end
+ @supported_flavours ["glitch", "vanilla"]
+
+ def set_flavour(%{assigns: %{user: user}} = conn, %{"flavour" => flavour} = _params)
+ when flavour in @supported_flavours do
+ flavour_cng = User.Info.mastodon_flavour_update(user.info, flavour)
+
+ with changeset <- Ecto.Changeset.change(user),
+ changeset <- Ecto.Changeset.put_embed(changeset, :info, flavour_cng),
+ {:ok, user} <- User.update_and_set_cache(changeset),
+ flavour <- user.info.flavour do
+ json(conn, flavour)
+ else
+ e ->
+ conn
+ |> put_resp_content_type("application/json")
+ |> send_resp(500, Jason.encode!(%{"error" => inspect(e)}))
+ end
+ end
+
+ def set_flavour(conn, _params) do
+ conn
+ |> put_status(400)
+ |> json(%{error: "Unsupported flavour"})
+ end
+
+ def get_flavour(%{assigns: %{user: user}} = conn, _params) do
+ json(conn, get_user_flavour(user))
+ end
+
+ defp get_user_flavour(%User{info: %{flavour: flavour}}) when flavour in @supported_flavours do
+ flavour
+ end
+
+ defp get_user_flavour(_) do
+ "glitch"
+ end
+
def login(conn, %{"code" => code}) do
with {:ok, app} <- get_or_make_app(),
%Authorization{} = auth <- Repo.get_by(Authorization, token: code, app_id: app.id),
diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex
index f51a2ebb0..a49b381c9 100644
--- a/lib/pleroma/web/mastodon_api/views/status_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/status_view.ex
@@ -9,6 +9,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
alias Pleroma.HTML
alias Pleroma.Repo
alias Pleroma.User
+ alias Pleroma.Web.CommonAPI
alias Pleroma.Web.CommonAPI.Utils
alias Pleroma.Web.MastodonAPI.AccountView
alias Pleroma.Web.MastodonAPI.StatusView
@@ -160,12 +161,12 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
reblogged: present?(repeated),
favourited: present?(favorited),
bookmarked: present?(bookmarked),
- muted: false,
+ muted: CommonAPI.thread_muted?(user, activity),
pinned: pinned?(activity, user),
sensitive: sensitive,
spoiler_text: object["summary"] || "",
visibility: get_visibility(object),
- media_attachments: attachments |> Enum.take(4),
+ media_attachments: attachments,
mentions: mentions,
tags: build_tags(tags),
application: %{
diff --git a/lib/pleroma/web/media_proxy/media_proxy.ex b/lib/pleroma/web/media_proxy/media_proxy.ex
index 1e9da7283..39a725a69 100644
--- a/lib/pleroma/web/media_proxy/media_proxy.ex
+++ b/lib/pleroma/web/media_proxy/media_proxy.ex
@@ -19,11 +19,16 @@ defmodule Pleroma.Web.MediaProxy do
else
secret = Application.get_env(:pleroma, Pleroma.Web.Endpoint)[:secret_key_base]
+ # Must preserve `%2F` for compatibility with S3 (https://git.pleroma.social/pleroma/pleroma/issues/580)
+ replacement = get_replacement(url, ":2F:")
+
# The URL is url-decoded and encoded again to ensure it is correctly encoded and not twice.
base64 =
url
+ |> String.replace("%2F", replacement)
|> URI.decode()
|> URI.encode()
+ |> String.replace(replacement, "%2F")
|> Base.url_encode64(@base64_opts)
sig = :crypto.hmac(:sha, secret, base64)
@@ -60,4 +65,12 @@ defmodule Pleroma.Web.MediaProxy do
|> Enum.filter(fn value -> value end)
|> Path.join()
end
+
+ defp get_replacement(url, replacement) do
+ if String.contains?(url, replacement) do
+ get_replacement(url, replacement <> replacement)
+ else
+ replacement
+ end
+ end
end
diff --git a/lib/pleroma/web/oauth/app.ex b/lib/pleroma/web/oauth/app.ex
index 3e8acde31..8b61bf3a4 100644
--- a/lib/pleroma/web/oauth/app.ex
+++ b/lib/pleroma/web/oauth/app.ex
@@ -25,8 +25,14 @@ defmodule Pleroma.Web.OAuth.App do
if changeset.valid? do
changeset
- |> put_change(:client_id, :crypto.strong_rand_bytes(32) |> Base.url_encode64())
- |> put_change(:client_secret, :crypto.strong_rand_bytes(32) |> Base.url_encode64())
+ |> put_change(
+ :client_id,
+ :crypto.strong_rand_bytes(32) |> Base.url_encode64(padding: false)
+ )
+ |> put_change(
+ :client_secret,
+ :crypto.strong_rand_bytes(32) |> Base.url_encode64(padding: false)
+ )
else
changeset
end
diff --git a/lib/pleroma/web/oauth/authorization.ex b/lib/pleroma/web/oauth/authorization.ex
index 75c9ab9aa..9039b8b45 100644
--- a/lib/pleroma/web/oauth/authorization.ex
+++ b/lib/pleroma/web/oauth/authorization.ex
@@ -24,7 +24,7 @@ defmodule Pleroma.Web.OAuth.Authorization do
end
def create_authorization(%App{} = app, %User{} = user) do
- token = :crypto.strong_rand_bytes(32) |> Base.url_encode64()
+ token = :crypto.strong_rand_bytes(32) |> Base.url_encode64(padding: false)
authorization = %Authorization{
token: token,
diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex
index e4d0601f8..dddfcf299 100644
--- a/lib/pleroma/web/oauth/oauth_controller.ex
+++ b/lib/pleroma/web/oauth/oauth_controller.ex
@@ -173,7 +173,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do
token
|> URI.decode()
|> Base.url_decode64!(padding: false)
- |> Base.url_encode64()
+ |> Base.url_encode64(padding: false)
end
defp get_app_from_request(conn, params) do
diff --git a/lib/pleroma/web/oauth/token.ex b/lib/pleroma/web/oauth/token.ex
index b0bbeeb69..71fd1b874 100644
--- a/lib/pleroma/web/oauth/token.ex
+++ b/lib/pleroma/web/oauth/token.ex
@@ -31,8 +31,8 @@ defmodule Pleroma.Web.OAuth.Token do
end
def create_token(%App{} = app, %User{} = user) do
- token = :crypto.strong_rand_bytes(32) |> Base.url_encode64()
- refresh_token = :crypto.strong_rand_bytes(32) |> Base.url_encode64()
+ token = :crypto.strong_rand_bytes(32) |> Base.url_encode64(padding: false)
+ refresh_token = :crypto.strong_rand_bytes(32) |> Base.url_encode64(padding: false)
token = %Token{
token: token,
@@ -47,9 +47,27 @@ defmodule Pleroma.Web.OAuth.Token do
def delete_user_tokens(%User{id: user_id}) do
from(
- t in Pleroma.Web.OAuth.Token,
+ t in Token,
where: t.user_id == ^user_id
)
|> Repo.delete_all()
end
+
+ def delete_user_token(%User{id: user_id}, token_id) do
+ from(
+ t in Token,
+ where: t.user_id == ^user_id,
+ where: t.id == ^token_id
+ )
+ |> Repo.delete_all()
+ end
+
+ def get_user_tokens(%User{id: user_id}) do
+ from(
+ t in Token,
+ where: t.user_id == ^user_id
+ )
+ |> Repo.all()
+ |> Repo.preload(:app)
+ end
end
diff --git a/lib/pleroma/web/rich_media/parser.ex b/lib/pleroma/web/rich_media/parser.ex
index 38f1cdeec..4341141df 100644
--- a/lib/pleroma/web/rich_media/parser.ex
+++ b/lib/pleroma/web/rich_media/parser.ex
@@ -9,6 +9,13 @@ defmodule Pleroma.Web.RichMedia.Parser do
Pleroma.Web.RichMedia.Parsers.OEmbed
]
+ @hackney_options [
+ pool: :media,
+ timeout: 2_000,
+ recv_timeout: 2_000,
+ max_body: 2_000_000
+ ]
+
def parse(nil), do: {:error, "No URL provided"}
if Mix.env() == :test do
@@ -28,7 +35,7 @@ defmodule Pleroma.Web.RichMedia.Parser do
defp parse_url(url) do
try do
- {:ok, %Tesla.Env{body: html}} = Pleroma.HTTP.get(url, [], adapter: [pool: :media])
+ {:ok, %Tesla.Env{body: html}} = Pleroma.HTTP.get(url, [], adapter: @hackney_options)
html |> maybe_parse() |> clean_parsed_data() |> check_parsed_data()
rescue
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index 7f606ac40..9a6cf2232 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -198,6 +198,8 @@ defmodule Pleroma.Web.Router do
post("/statuses/:id/unpin", MastodonAPIController, :unpin_status)
post("/statuses/:id/bookmark", MastodonAPIController, :bookmark_status)
post("/statuses/:id/unbookmark", MastodonAPIController, :unbookmark_status)
+ post("/statuses/:id/mute", MastodonAPIController, :mute_conversation)
+ post("/statuses/:id/unmute", MastodonAPIController, :unmute_conversation)
post("/notifications/clear", MastodonAPIController, :clear_notifications)
post("/notifications/dismiss", MastodonAPIController, :dismiss_notification)
@@ -234,6 +236,9 @@ defmodule Pleroma.Web.Router do
get("/suggestions", MastodonAPIController, :suggestions)
get("/endorsements", MastodonAPIController, :empty_array)
+
+ post("/pleroma/flavour/:flavour", MastodonAPIController, :set_flavour)
+ get("/pleroma/flavour", MastodonAPIController, :get_flavour)
end
scope "/api/web", Pleroma.Web.MastodonAPI do
@@ -387,6 +392,9 @@ defmodule Pleroma.Web.Router do
get("/qvitter/mutes", TwitterAPI.Controller, :raw_empty_array)
get("/externalprofile/show", TwitterAPI.Controller, :external_profile)
+
+ get("/oauth_tokens", TwitterAPI.Controller, :oauth_tokens)
+ delete("/oauth_tokens/:id", TwitterAPI.Controller, :revoke_token)
end
pipeline :ap_relay do
@@ -466,8 +474,8 @@ defmodule Pleroma.Web.Router do
scope "/", Pleroma.Web.ActivityPub do
pipe_through(:activitypub)
- post("/users/:nickname/inbox", ActivityPubController, :inbox)
post("/inbox", ActivityPubController, :inbox)
+ post("/users/:nickname/inbox", ActivityPubController, :inbox)
end
scope "/.well-known", Pleroma.Web do
diff --git a/lib/pleroma/web/templates/layout/app.html.eex b/lib/pleroma/web/templates/layout/app.html.eex
index 8dd3284d6..520e4b3d5 100644
--- a/lib/pleroma/web/templates/layout/app.html.eex
+++ b/lib/pleroma/web/templates/layout/app.html.eex
@@ -67,6 +67,32 @@
font-weight: 500;
font-size: 16px;
}
+
+ .alert-danger {
+ box-sizing: border-box;
+ width: 100%;
+ color: #D8000C;
+ background-color: #FFD2D2;
+ border-radius: 4px;
+ border: none;
+ padding: 10px;
+ margin-top: 20px;
+ font-weight: 500;
+ font-size: 16px;
+ }
+
+ .alert-info {
+ box-sizing: border-box;
+ width: 100%;
+ color: #00529B;
+ background-color: #BDE5F8;
+ border-radius: 4px;
+ border: none;
+ padding: 10px;
+ margin-top: 20px;
+ font-weight: 500;
+ font-size: 16px;
+ }
</style>
</head>
<body>
diff --git a/lib/pleroma/web/templates/mastodon_api/mastodon/index.html.eex b/lib/pleroma/web/templates/mastodon_api/mastodon/index.html.eex
index 9a725e420..5659c7828 100644
--- a/lib/pleroma/web/templates/mastodon_api/mastodon/index.html.eex
+++ b/lib/pleroma/web/templates/mastodon_api/mastodon/index.html.eex
@@ -8,7 +8,7 @@
</title>
<link rel="icon" type="image/png" href="/favicon.png"/>
<script crossorigin='anonymous' src="/packs/locales.js"></script>
-<script crossorigin='anonymous' src="/packs/locales/glitch/en.js"></script>
+<script crossorigin='anonymous' src="/packs/locales/<%= @flavour %>/en.js"></script>
<link rel='preload' as='script' crossorigin='anonymous' href='/packs/features/getting_started.js'>
<link rel='preload' as='script' crossorigin='anonymous' href='/packs/features/compose.js'>
@@ -19,10 +19,10 @@
<script src="/packs/core/common.js"></script>
<link rel="stylesheet" media="all" href="/packs/core/common.css" />
-<script src="/packs/flavours/glitch/common.js"></script>
-<link rel="stylesheet" media="all" href="/packs/flavours/glitch/common.css" />
+<script src="/packs/flavours/<%= @flavour %>/common.js"></script>
+<link rel="stylesheet" media="all" href="/packs/flavours/<%= @flavour %>/common.css" />
-<script src="/packs/flavours/glitch/home.js"></script>
+<script src="/packs/flavours/<%= @flavour %>/home.js"></script>
</head>
<body class='app-body no-reduce-motion system-font'>
<div class='app-holder' data-props='{&quot;locale&quot;:&quot;en&quot;}' id='mastodon'>
diff --git a/lib/pleroma/web/templates/o_auth/o_auth/show.html.eex b/lib/pleroma/web/templates/o_auth/o_auth/show.html.eex
index de2241ec9..32c458f0c 100644
--- a/lib/pleroma/web/templates/o_auth/o_auth/show.html.eex
+++ b/lib/pleroma/web/templates/o_auth/o_auth/show.html.eex
@@ -1,5 +1,9 @@
+<%= if get_flash(@conn, :info) do %>
<p class="alert alert-info" role="alert"><%= get_flash(@conn, :info) %></p>
+<% end %>
+<%= if get_flash(@conn, :error) do %>
<p class="alert alert-danger" role="alert"><%= get_flash(@conn, :error) %></p>
+<% end %>
<h2>OAuth Authorization</h2>
<%= form_for @conn, o_auth_path(@conn, :authorize), [as: "authorization"], fn f -> %>
<%= label f, :name, "Name or email" %>
diff --git a/lib/pleroma/web/twitter_api/twitter_api.ex b/lib/pleroma/web/twitter_api/twitter_api.ex
index 162beb9be..db521a3ad 100644
--- a/lib/pleroma/web/twitter_api/twitter_api.ex
+++ b/lib/pleroma/web/twitter_api/twitter_api.ex
@@ -310,8 +310,16 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
else
_e ->
changeset = Object.context_mapping(context)
- {:ok, object} = Object.insert_or_get(changeset)
- object.id
+
+ case Repo.insert(changeset) do
+ {:ok, %{id: id}} ->
+ id
+
+ # This should be solved by an upsert, but it seems ecto
+ # has problems accessing the constraint inside the jsonb.
+ {:error, _} ->
+ Object.get_cached_by_ap_id(context).id
+ end
end
end
diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex
index c2f0dc2a9..b815379fd 100644
--- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex
+++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex
@@ -8,6 +8,10 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
import Pleroma.Web.ControllerHelper, only: [json_response: 3]
alias Ecto.Changeset
+ alias Pleroma.Web.TwitterAPI.{TwitterAPI, UserView, ActivityView, NotificationView, TokenView}
+ alias Pleroma.Web.CommonAPI
+ alias Pleroma.{Repo, Activity, Object, User, Notification}
+ alias Pleroma.Web.OAuth.Token
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.CommonAPI
@@ -524,6 +528,9 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
def friends(%{assigns: %{user: for_user}} = conn, params) do
{:ok, page} = Ecto.Type.cast(:integer, params["page"] || 1)
+ {:ok, export} = Ecto.Type.cast(:boolean, params["all"] || false)
+
+ page = if export, do: nil, else: page
with {:ok, user} <- TwitterAPI.get_user(conn.assigns[:user], params),
{:ok, friends} <- User.get_friends(user, page) do
@@ -542,6 +549,20 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
end
end
+ def oauth_tokens(%{assigns: %{user: user}} = conn, _params) do
+ with oauth_tokens <- Token.get_user_tokens(user) do
+ conn
+ |> put_view(TokenView)
+ |> render("index.json", %{tokens: oauth_tokens})
+ end
+ end
+
+ def revoke_token(%{assigns: %{user: user}} = conn, %{"id" => id} = _params) do
+ Token.delete_user_token(user, id)
+
+ json_reply(conn, 201, "")
+ end
+
def blocks(%{assigns: %{user: user}} = conn, _params) do
with blocked_users <- User.blocked_users(user) do
conn
@@ -570,7 +591,7 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
{:ok, _activity} <-
ActivityPub.accept(%{
to: [follower.ap_id],
- actor: followed.ap_id,
+ actor: followed,
object: follow_activity.data["id"],
type: "Accept"
}) do
@@ -590,7 +611,7 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
{:ok, _activity} <-
ActivityPub.reject(%{
to: [follower.ap_id],
- actor: followed.ap_id,
+ actor: followed,
object: follow_activity.data["id"],
type: "Reject"
}) do
diff --git a/lib/pleroma/web/twitter_api/views/token_view.ex b/lib/pleroma/web/twitter_api/views/token_view.ex
new file mode 100644
index 000000000..3ff314913
--- /dev/null
+++ b/lib/pleroma/web/twitter_api/views/token_view.ex
@@ -0,0 +1,21 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.TwitterAPI.TokenView do
+ use Pleroma.Web, :view
+
+ def render("index.json", %{tokens: tokens}) do
+ tokens
+ |> render_many(Pleroma.Web.TwitterAPI.TokenView, "show.json")
+ |> Enum.filter(&Enum.any?/1)
+ end
+
+ def render("show.json", %{token: token_entry}) do
+ %{
+ id: token_entry.id,
+ valid_until: token_entry.valid_until,
+ app_name: token_entry.app.client_name
+ }
+ end
+end
diff --git a/lib/pleroma/web/twitter_api/views/user_view.ex b/lib/pleroma/web/twitter_api/views/user_view.ex
index a09450df7..df7384476 100644
--- a/lib/pleroma/web/twitter_api/views/user_view.ex
+++ b/lib/pleroma/web/twitter_api/views/user_view.ex
@@ -113,10 +113,12 @@ defmodule Pleroma.Web.TwitterAPI.UserView do
"fields" => fields,
# Pleroma extension
- "pleroma" => %{
- "confirmation_pending" => user_info.confirmation_pending,
- "tags" => user.tags
- }
+ "pleroma" =>
+ %{
+ "confirmation_pending" => user_info.confirmation_pending,
+ "tags" => user.tags
+ }
+ |> maybe_with_follow_request_count(user, for_user)
}
data =
@@ -132,6 +134,14 @@ defmodule Pleroma.Web.TwitterAPI.UserView do
end
end
+ defp maybe_with_follow_request_count(data, %User{id: id, info: %{locked: true}} = user, %User{
+ id: id
+ }) do
+ Map.put(data, "follow_request_count", user.info.follow_request_count)
+ end
+
+ defp maybe_with_follow_request_count(data, _, _), do: data
+
defp maybe_with_role(data, %User{id: id} = user, %User{id: id}) do
Map.merge(data, %{"role" => role(user), "show_role" => user.info.show_role})
end
diff --git a/mix.exs b/mix.exs
index d46998891..ee1c00bb9 100644
--- a/mix.exs
+++ b/mix.exs
@@ -21,7 +21,14 @@ defmodule Pleroma.Mixfile do
homepage_url: "https://pleroma.social/",
docs: [
logo: "priv/static/static/logo.png",
- extras: ["README.md", "docs/config.md", "docs/Pleroma-API.md", "docs/Admin-API.md"],
+ extras: [
+ "README.md",
+ "docs/config.md",
+ "docs/Pleroma-API.md",
+ "docs/Admin-API.md",
+ "docs/Clients.md",
+ "docs/Differences-in-MastodonAPI-Responses.md"
+ ],
main: "readme",
output: "priv/static/doc"
]
diff --git a/priv/repo/migrations/20190205114625_create_thread_mutes.exs b/priv/repo/migrations/20190205114625_create_thread_mutes.exs
new file mode 100644
index 000000000..8e9eccbae
--- /dev/null
+++ b/priv/repo/migrations/20190205114625_create_thread_mutes.exs
@@ -0,0 +1,12 @@
+defmodule Pleroma.Repo.Migrations.CreateThreadMutes do
+ use Ecto.Migration
+
+ def change do
+ create table(:thread_mutes) do
+ add :user_id, references(:users, type: :uuid, on_delete: :delete_all)
+ add :context, :string
+ end
+
+ create unique_index(:thread_mutes, [:user_id, :context], name: :unique_index)
+ end
+end
diff --git a/priv/static/schemas/litepub-0.1.jsonld b/priv/static/schemas/litepub-0.1.jsonld
index 15645646a..f36b231c5 100644
--- a/priv/static/schemas/litepub-0.1.jsonld
+++ b/priv/static/schemas/litepub-0.1.jsonld
@@ -19,7 +19,11 @@
"value": "schema:value",
"sensitive": "as:sensitive",
"litepub": "http://litepub.social/ns#",
- "directMessage": "litepub:directMessage"
+ "directMessage": "litepub:directMessage",
+ "oauthRegistrationEndpoint": {
+ "@id": "litepub:oauthRegistrationEndpoint",
+ "@type": "@id"
+ }
}
]
}
diff --git a/test/formatter_test.exs b/test/formatter_test.exs
index 2e717194b..f14077d25 100644
--- a/test/formatter_test.exs
+++ b/test/formatter_test.exs
@@ -197,7 +197,7 @@ defmodule Pleroma.FormatterTest do
{subs, text} = Formatter.add_user_links({[], text}, mentions)
- assert length(subs) == 0
+ assert Enum.empty?(subs)
Enum.each(subs, fn {uuid, _} -> assert String.contains?(text, uuid) end)
expected_text = "@a hi"
diff --git a/test/media_proxy_test.exs b/test/media_proxy_test.exs
index 05d927422..ddbadfbf5 100644
--- a/test/media_proxy_test.exs
+++ b/test/media_proxy_test.exs
@@ -140,6 +140,15 @@ defmodule Pleroma.MediaProxyTest do
assert String.starts_with?(encoded, Pleroma.Config.get([:media_proxy, :base_url]))
end
+
+ # https://git.pleroma.social/pleroma/pleroma/issues/580
+ test "encoding S3 links (must preserve `%2F`)" do
+ url =
+ "https://s3.amazonaws.com/example/test.png?X-Amz-Credential=your-access-key-id%2F20130721%2Fus-east-1%2Fs3%2Faws4_request"
+
+ encoded = url(url)
+ assert decode_result(encoded) == url
+ end
end
describe "when disabled" do
diff --git a/test/notification_test.exs b/test/notification_test.exs
index 94fb0ab15..755874a3d 100644
--- a/test/notification_test.exs
+++ b/test/notification_test.exs
@@ -6,7 +6,8 @@ defmodule Pleroma.NotificationTest do
use Pleroma.DataCase
alias Pleroma.Web.TwitterAPI.TwitterAPI
alias Pleroma.Web.CommonAPI
- alias Pleroma.{User, Notification}
+ alias Pleroma.User
+ alias Pleroma.Notification
alias Pleroma.Web.ActivityPub.Transmogrifier
import Pleroma.Factory
@@ -299,7 +300,7 @@ defmodule Pleroma.NotificationTest do
{:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
- assert length(Notification.for_user(user)) == 0
+ assert Enum.empty?(Notification.for_user(user))
{:ok, _, _} = CommonAPI.favorite(activity.id, other_user)
@@ -307,7 +308,7 @@ defmodule Pleroma.NotificationTest do
{:ok, _} = CommonAPI.delete(activity.id, user)
- assert length(Notification.for_user(user)) == 0
+ assert Enum.empty?(Notification.for_user(user))
end
test "liking an activity results in 1 notification, then 0 if the activity is unliked" do
@@ -316,7 +317,7 @@ defmodule Pleroma.NotificationTest do
{:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
- assert length(Notification.for_user(user)) == 0
+ assert Enum.empty?(Notification.for_user(user))
{:ok, _, _} = CommonAPI.favorite(activity.id, other_user)
@@ -324,7 +325,7 @@ defmodule Pleroma.NotificationTest do
{:ok, _, _, _} = CommonAPI.unfavorite(activity.id, other_user)
- assert length(Notification.for_user(user)) == 0
+ assert Enum.empty?(Notification.for_user(user))
end
test "repeating an activity results in 1 notification, then 0 if the activity is deleted" do
@@ -333,7 +334,7 @@ defmodule Pleroma.NotificationTest do
{:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
- assert length(Notification.for_user(user)) == 0
+ assert Enum.empty?(Notification.for_user(user))
{:ok, _, _} = CommonAPI.repeat(activity.id, other_user)
@@ -341,7 +342,7 @@ defmodule Pleroma.NotificationTest do
{:ok, _} = CommonAPI.delete(activity.id, user)
- assert length(Notification.for_user(user)) == 0
+ assert Enum.empty?(Notification.for_user(user))
end
test "repeating an activity results in 1 notification, then 0 if the activity is unrepeated" do
@@ -350,7 +351,7 @@ defmodule Pleroma.NotificationTest do
{:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
- assert length(Notification.for_user(user)) == 0
+ assert Enum.empty?(Notification.for_user(user))
{:ok, _, _} = CommonAPI.repeat(activity.id, other_user)
@@ -358,7 +359,7 @@ defmodule Pleroma.NotificationTest do
{:ok, _, _} = CommonAPI.unrepeat(activity.id, other_user)
- assert length(Notification.for_user(user)) == 0
+ assert Enum.empty?(Notification.for_user(user))
end
test "liking an activity which is already deleted does not generate a notification" do
@@ -367,15 +368,15 @@ defmodule Pleroma.NotificationTest do
{:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
- assert length(Notification.for_user(user)) == 0
+ assert Enum.empty?(Notification.for_user(user))
{:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
- assert length(Notification.for_user(user)) == 0
+ assert Enum.empty?(Notification.for_user(user))
{:error, _} = CommonAPI.favorite(activity.id, other_user)
- assert length(Notification.for_user(user)) == 0
+ assert Enum.empty?(Notification.for_user(user))
end
test "repeating an activity which is already deleted does not generate a notification" do
@@ -384,15 +385,15 @@ defmodule Pleroma.NotificationTest do
{:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
- assert length(Notification.for_user(user)) == 0
+ assert Enum.empty?(Notification.for_user(user))
{:ok, _deletion_activity} = CommonAPI.delete(activity.id, user)
- assert length(Notification.for_user(user)) == 0
+ assert Enum.empty?(Notification.for_user(user))
{:error, _} = CommonAPI.repeat(activity.id, other_user)
- assert length(Notification.for_user(user)) == 0
+ assert Enum.empty?(Notification.for_user(user))
end
test "replying to a deleted post without tagging does not generate a notification" do
@@ -408,7 +409,7 @@ defmodule Pleroma.NotificationTest do
"in_reply_to_status_id" => activity.id
})
- assert length(Notification.for_user(user)) == 0
+ assert Enum.empty?(Notification.for_user(user))
end
end
end
diff --git a/test/object_test.exs b/test/object_test.exs
index ab6431012..a820a34ee 100644
--- a/test/object_test.exs
+++ b/test/object_test.exs
@@ -5,7 +5,8 @@
defmodule Pleroma.ObjectTest do
use Pleroma.DataCase
import Pleroma.Factory
- alias Pleroma.{Repo, Object}
+ alias Pleroma.Repo
+ alias Pleroma.Object
test "returns an object by it's AP id" do
object = insert(:note)
@@ -57,32 +58,4 @@ defmodule Pleroma.ObjectTest do
assert cached_object.data["type"] == "Tombstone"
end
end
-
- describe "insert_or_get" do
- test "inserting the same object twice (by id) just returns the original object" do
- data = %{data: %{"id" => Ecto.UUID.generate()}}
- cng = Object.change(%Object{}, data)
- {:ok, object} = Object.insert_or_get(cng)
- {:ok, second_object} = Object.insert_or_get(cng)
-
- Cachex.clear(:object_cache)
- {:ok, third_object} = Object.insert_or_get(cng)
-
- assert object == second_object
- assert object == third_object
- end
- end
-
- describe "create" do
- test "inserts an object for a given data set" do
- data = %{"id" => Ecto.UUID.generate()}
-
- {:ok, object} = Object.create(data)
- assert object.data["id"] == data["id"]
-
- # Works when doing it twice.
- {:ok, object} = Object.create(data)
- assert object.data["id"] == data["id"]
- end
- end
end
diff --git a/test/support/builders/user_builder.ex b/test/support/builders/user_builder.ex
index 7a1ca79b5..611a5be18 100644
--- a/test/support/builders/user_builder.ex
+++ b/test/support/builders/user_builder.ex
@@ -1,5 +1,6 @@
defmodule Pleroma.Builders.UserBuilder do
- alias Pleroma.{User, Repo}
+ alias Pleroma.User
+ alias Pleroma.Repo
def build(data \\ %{}) do
user = %User{
diff --git a/test/support/factory.ex b/test/support/factory.ex
index 0c21093ce..7a91549f5 100644
--- a/test/support/factory.ex
+++ b/test/support/factory.ex
@@ -227,4 +227,17 @@ defmodule Pleroma.Factory do
unreachable_since: nil
}
end
+
+ def oauth_token_factory do
+ user = insert(:user)
+ oauth_app = insert(:oauth_app)
+
+ %Pleroma.Web.OAuth.Token{
+ token: :crypto.strong_rand_bytes(32) |> Base.url_encode64(),
+ refresh_token: :crypto.strong_rand_bytes(32) |> Base.url_encode64(),
+ user_id: user.id,
+ app_id: oauth_app.id,
+ valid_until: NaiveDateTime.add(NaiveDateTime.utc_now(), 60 * 10)
+ }
+ end
end
diff --git a/test/tasks/relay_test.exs b/test/tasks/relay_test.exs
index 96fac4811..64ff07753 100644
--- a/test/tasks/relay_test.exs
+++ b/test/tasks/relay_test.exs
@@ -4,7 +4,9 @@
defmodule Mix.Tasks.Pleroma.RelayTest do
alias Pleroma.Activity
- alias Pleroma.Web.ActivityPub.{ActivityPub, Relay, Utils}
+ alias Pleroma.Web.ActivityPub.ActivityPub
+ alias Pleroma.Web.ActivityPub.Utils
+ alias Pleroma.Web.ActivityPub.Relay
alias Pleroma.User
use Pleroma.DataCase
diff --git a/test/tasks/user_test.exs b/test/tasks/user_test.exs
index 44271898c..7b814d171 100644
--- a/test/tasks/user_test.exs
+++ b/test/tasks/user_test.exs
@@ -151,7 +151,7 @@ defmodule Mix.Tasks.Pleroma.UserTest do
assert message =~ "Successfully unsubscribed"
user = User.get_by_nickname(user.nickname)
- assert length(user.following) == 0
+ assert Enum.empty?(user.following)
assert user.info.deactivated
end
diff --git a/test/user_test.exs b/test/user_test.exs
index 523ab1ea4..92991d063 100644
--- a/test/user_test.exs
+++ b/test/user_test.exs
@@ -4,7 +4,9 @@
defmodule Pleroma.UserTest do
alias Pleroma.Builders.UserBuilder
- alias Pleroma.{User, Repo, Activity}
+ alias Pleroma.Activity
+ alias Pleroma.Repo
+ alias Pleroma.User
alias Pleroma.Web.CommonAPI
use Pleroma.DataCase
@@ -55,18 +57,21 @@ defmodule Pleroma.UserTest do
followed_two = insert(:user)
blocked = insert(:user)
not_followed = insert(:user)
+ reverse_blocked = insert(:user)
{:ok, user} = User.block(user, blocked)
+ {:ok, reverse_blocked} = User.block(reverse_blocked, user)
{:ok, user} = User.follow(user, followed_zero)
- {:ok, user} = User.follow_all(user, [followed_one, followed_two, blocked])
+ {:ok, user} = User.follow_all(user, [followed_one, followed_two, blocked, reverse_blocked])
assert User.following?(user, followed_one)
assert User.following?(user, followed_two)
assert User.following?(user, followed_zero)
refute User.following?(user, not_followed)
refute User.following?(user, blocked)
+ refute User.following?(user, reverse_blocked)
end
test "follow_all follows mutliple users without duplicating" do
@@ -191,6 +196,26 @@ defmodule Pleroma.UserTest do
assert User.following?(registered_user, user)
refute User.following?(registered_user, remote_user)
+
+ Pleroma.Config.put([:instance, :autofollowed_nicknames], [])
+ end
+
+ test "it sends a welcome message if it is set" do
+ welcome_user = insert(:user)
+
+ Pleroma.Config.put([:instance, :welcome_user_nickname], welcome_user.nickname)
+ Pleroma.Config.put([:instance, :welcome_message], "Hello, this is a cool site")
+
+ cng = User.register_changeset(%User{}, @full_user_data)
+ {:ok, registered_user} = User.register(cng)
+
+ activity = Repo.one(Pleroma.Activity)
+ assert registered_user.ap_id in activity.recipients
+ assert activity.data["object"]["content"] =~ "cool site"
+ assert activity.actor == welcome_user.ap_id
+
+ Pleroma.Config.put([:instance, :welcome_user_nickname], nil)
+ Pleroma.Config.put([:instance, :welcome_message], nil)
end
test "it requires an email, name, nickname and password, bio is optional" do
@@ -873,6 +898,16 @@ defmodule Pleroma.UserTest do
assert [] == User.search(query)
end)
end
+
+ test "works with URIs" do
+ results = User.search("http://mastodon.example.org/users/admin", true)
+ result = results |> List.first()
+
+ user = User.get_by_ap_id("http://mastodon.example.org/users/admin")
+
+ assert length(results) == 1
+ assert user == result |> Map.put(:search_rank, nil)
+ end
end
test "auth_active?/1 works correctly" do
diff --git a/test/web/activity_pub/activity_pub_controller_test.exs b/test/web/activity_pub/activity_pub_controller_test.exs
index 570bee6b3..398bedf77 100644
--- a/test/web/activity_pub/activity_pub_controller_test.exs
+++ b/test/web/activity_pub/activity_pub_controller_test.exs
@@ -5,8 +5,13 @@
defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
use Pleroma.Web.ConnCase
import Pleroma.Factory
- alias Pleroma.Web.ActivityPub.{UserView, ObjectView}
- alias Pleroma.{Object, Repo, Activity, User, Instances}
+ alias Pleroma.Web.ActivityPub.UserView
+ alias Pleroma.Web.ActivityPub.ObjectView
+ alias Pleroma.Object
+ alias Pleroma.Repo
+ alias Pleroma.Activity
+ alias Pleroma.User
+ alias Pleroma.Instances
setup_all do
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
@@ -397,7 +402,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|> json_response(200)
assert result["first"]["orderedItems"] == []
- assert result["totalItems"] == 1
+ assert result["totalItems"] == 0
end
test "it works for more than 10 users", %{conn: conn} do
@@ -452,7 +457,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|> json_response(200)
assert result["first"]["orderedItems"] == []
- assert result["totalItems"] == 1
+ assert result["totalItems"] == 0
end
test "it works for more than 10 users", %{conn: conn} do
diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs
index a55961ac4..a6f8b822a 100644
--- a/test/web/activity_pub/activity_pub_test.exs
+++ b/test/web/activity_pub/activity_pub_test.exs
@@ -7,7 +7,10 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.CommonAPI
- alias Pleroma.{Activity, Object, User, Instances}
+ alias Pleroma.Activity
+ alias Pleroma.Object
+ alias Pleroma.User
+ alias Pleroma.Instances
alias Pleroma.Builders.ActivityBuilder
import Pleroma.Factory
diff --git a/test/web/activity_pub/mrf/hellthread_policy_test.exs b/test/web/activity_pub/mrf/hellthread_policy_test.exs
new file mode 100644
index 000000000..eb6ee4d04
--- /dev/null
+++ b/test/web/activity_pub/mrf/hellthread_policy_test.exs
@@ -0,0 +1,73 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.MRF.HellthreadPolicyTest do
+ use Pleroma.DataCase
+ import Pleroma.Factory
+
+ import Pleroma.Web.ActivityPub.MRF.HellthreadPolicy
+
+ setup do
+ user = insert(:user)
+
+ message = %{
+ "actor" => user.ap_id,
+ "cc" => [user.follower_address],
+ "type" => "Create",
+ "to" => [
+ "https://www.w3.org/ns/activitystreams#Public",
+ "https://instance.tld/users/user1",
+ "https://instance.tld/users/user2",
+ "https://instance.tld/users/user3"
+ ]
+ }
+
+ [user: user, message: message]
+ end
+
+ describe "reject" do
+ test "rejects the message if the recipient count is above reject_threshold", %{
+ message: message
+ } do
+ Pleroma.Config.put([:mrf_hellthread], %{delist_threshold: 0, reject_threshold: 2})
+
+ {:reject, nil} = filter(message)
+ end
+
+ test "does not reject the message if the recipient count is below reject_threshold", %{
+ message: message
+ } do
+ Pleroma.Config.put([:mrf_hellthread], %{delist_threshold: 0, reject_threshold: 3})
+
+ assert {:ok, ^message} = filter(message)
+ end
+ end
+
+ describe "delist" do
+ test "delists the message if the recipient count is above delist_threshold", %{
+ user: user,
+ message: message
+ } do
+ Pleroma.Config.put([:mrf_hellthread], %{delist_threshold: 2, reject_threshold: 0})
+
+ {:ok, message} = filter(message)
+ assert user.follower_address in message["to"]
+ assert "https://www.w3.org/ns/activitystreams#Public" in message["cc"]
+ end
+
+ test "does not delist the message if the recipient count is below delist_threshold", %{
+ message: message
+ } do
+ Pleroma.Config.put([:mrf_hellthread], %{delist_threshold: 4, reject_threshold: 0})
+
+ assert {:ok, ^message} = filter(message)
+ end
+ end
+
+ test "excludes follower collection and public URI from threshold count", %{message: message} do
+ Pleroma.Config.put([:mrf_hellthread], %{delist_threshold: 0, reject_threshold: 3})
+
+ assert {:ok, ^message} = filter(message)
+ end
+end
diff --git a/test/web/activity_pub/mrf/keyword_policy_test.exs b/test/web/activity_pub/mrf/keyword_policy_test.exs
index 67a5858d7..602892a37 100644
--- a/test/web/activity_pub/mrf/keyword_policy_test.exs
+++ b/test/web/activity_pub/mrf/keyword_policy_test.exs
@@ -12,18 +12,35 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do
end
describe "rejecting based on keywords" do
- test "rejects if string matches" do
+ test "rejects if string matches in content" do
Pleroma.Config.put([:mrf_keyword, :reject], ["pun"])
message = %{
"type" => "Create",
- "object" => %{"content" => "just a daily reminder that compLAINer is a good pun"}
+ "object" => %{
+ "content" => "just a daily reminder that compLAINer is a good pun",
+ "summary" => ""
+ }
}
assert {:reject, nil} == KeywordPolicy.filter(message)
end
- test "rejects if regex matches" do
+ test "rejects if string matches in summary" do
+ Pleroma.Config.put([:mrf_keyword, :reject], ["pun"])
+
+ message = %{
+ "type" => "Create",
+ "object" => %{
+ "summary" => "just a daily reminder that compLAINer is a good pun",
+ "content" => ""
+ }
+ }
+
+ assert {:reject, nil} == KeywordPolicy.filter(message)
+ end
+
+ test "rejects if regex matches in content" do
Pleroma.Config.put([:mrf_keyword, :reject], [~r/comp[lL][aA][iI][nN]er/])
assert true ==
@@ -31,7 +48,25 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do
message = %{
"type" => "Create",
"object" => %{
- "content" => "just a daily reminder that #{content} is a good pun"
+ "content" => "just a daily reminder that #{content} is a good pun",
+ "summary" => ""
+ }
+ }
+
+ {:reject, nil} == KeywordPolicy.filter(message)
+ end)
+ end
+
+ test "rejects if regex matches in summary" do
+ Pleroma.Config.put([:mrf_keyword, :reject], [~r/comp[lL][aA][iI][nN]er/])
+
+ assert true ==
+ Enum.all?(["complainer", "compLainer", "compLAiNer", "compLAINer"], fn content ->
+ message = %{
+ "type" => "Create",
+ "object" => %{
+ "summary" => "just a daily reminder that #{content} is a good pun",
+ "content" => ""
}
}
@@ -41,13 +76,16 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do
end
describe "delisting from ftl based on keywords" do
- test "delists if string matches" do
+ test "delists if string matches in content" do
Pleroma.Config.put([:mrf_keyword, :federated_timeline_removal], ["pun"])
message = %{
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
"type" => "Create",
- "object" => %{"content" => "just a daily reminder that compLAINer is a good pun"}
+ "object" => %{
+ "content" => "just a daily reminder that compLAINer is a good pun",
+ "summary" => ""
+ }
}
{:ok, result} = KeywordPolicy.filter(message)
@@ -55,7 +93,45 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do
refute ["https://www.w3.org/ns/activitystreams#Public"] == result["to"]
end
- test "delists if regex matches" do
+ test "delists if string matches in summary" do
+ Pleroma.Config.put([:mrf_keyword, :federated_timeline_removal], ["pun"])
+
+ message = %{
+ "to" => ["https://www.w3.org/ns/activitystreams#Public"],
+ "type" => "Create",
+ "object" => %{
+ "summary" => "just a daily reminder that compLAINer is a good pun",
+ "content" => ""
+ }
+ }
+
+ {:ok, result} = KeywordPolicy.filter(message)
+ assert ["https://www.w3.org/ns/activitystreams#Public"] == result["cc"]
+ refute ["https://www.w3.org/ns/activitystreams#Public"] == result["to"]
+ end
+
+ test "delists if regex matches in content" do
+ Pleroma.Config.put([:mrf_keyword, :federated_timeline_removal], [~r/comp[lL][aA][iI][nN]er/])
+
+ assert true ==
+ Enum.all?(["complainer", "compLainer", "compLAiNer", "compLAINer"], fn content ->
+ message = %{
+ "type" => "Create",
+ "to" => ["https://www.w3.org/ns/activitystreams#Public"],
+ "object" => %{
+ "content" => "just a daily reminder that #{content} is a good pun",
+ "summary" => ""
+ }
+ }
+
+ {:ok, result} = KeywordPolicy.filter(message)
+
+ ["https://www.w3.org/ns/activitystreams#Public"] == result["cc"] and
+ not (["https://www.w3.org/ns/activitystreams#Public"] == result["to"])
+ end)
+ end
+
+ test "delists if regex matches in summary" do
Pleroma.Config.put([:mrf_keyword, :federated_timeline_removal], [~r/comp[lL][aA][iI][nN]er/])
assert true ==
@@ -64,7 +140,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do
"type" => "Create",
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
"object" => %{
- "content" => "just a daily reminder that #{content} is a good pun"
+ "summary" => "just a daily reminder that #{content} is a good pun",
+ "content" => ""
}
}
@@ -77,20 +154,33 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do
end
describe "replacing keywords" do
- test "replaces keyword if string matches" do
+ test "replaces keyword if string matches in content" do
Pleroma.Config.put([:mrf_keyword, :replace], [{"opensource", "free software"}])
message = %{
"type" => "Create",
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
- "object" => %{"content" => "ZFS is opensource"}
+ "object" => %{"content" => "ZFS is opensource", "summary" => ""}
}
{:ok, %{"object" => %{"content" => result}}} = KeywordPolicy.filter(message)
assert result == "ZFS is free software"
end
- test "replaces keyword if regex matches" do
+ test "replaces keyword if string matches in summary" do
+ Pleroma.Config.put([:mrf_keyword, :replace], [{"opensource", "free software"}])
+
+ message = %{
+ "type" => "Create",
+ "to" => ["https://www.w3.org/ns/activitystreams#Public"],
+ "object" => %{"summary" => "ZFS is opensource", "content" => ""}
+ }
+
+ {:ok, %{"object" => %{"summary" => result}}} = KeywordPolicy.filter(message)
+ assert result == "ZFS is free software"
+ end
+
+ test "replaces keyword if regex matches in content" do
Pleroma.Config.put([:mrf_keyword, :replace], [
{~r/open(-|\s)?source\s?(software)?/, "free software"}
])
@@ -100,12 +190,30 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do
message = %{
"type" => "Create",
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
- "object" => %{"content" => "ZFS is #{content}"}
+ "object" => %{"content" => "ZFS is #{content}", "summary" => ""}
}
{:ok, %{"object" => %{"content" => result}}} = KeywordPolicy.filter(message)
result == "ZFS is free software"
end)
end
+
+ test "replaces keyword if regex matches in summary" do
+ Pleroma.Config.put([:mrf_keyword, :replace], [
+ {~r/open(-|\s)?source\s?(software)?/, "free software"}
+ ])
+
+ assert true ==
+ Enum.all?(["opensource", "open-source", "open source"], fn content ->
+ message = %{
+ "type" => "Create",
+ "to" => ["https://www.w3.org/ns/activitystreams#Public"],
+ "object" => %{"summary" => "ZFS is #{content}", "content" => ""}
+ }
+
+ {:ok, %{"object" => %{"summary" => result}}} = KeywordPolicy.filter(message)
+ result == "ZFS is free software"
+ end)
+ end
end
end
diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs
index e5e3c8d33..86c66deff 100644
--- a/test/web/activity_pub/transmogrifier_test.exs
+++ b/test/web/activity_pub/transmogrifier_test.exs
@@ -1128,4 +1128,58 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
)
end
end
+
+ describe "reserialization" do
+ test "successfully reserializes a message with inReplyTo == nil" do
+ user = insert(:user)
+
+ message = %{
+ "@context" => "https://www.w3.org/ns/activitystreams",
+ "to" => ["https://www.w3.org/ns/activitystreams#Public"],
+ "cc" => [],
+ "type" => "Create",
+ "object" => %{
+ "to" => ["https://www.w3.org/ns/activitystreams#Public"],
+ "cc" => [],
+ "type" => "Note",
+ "content" => "Hi",
+ "inReplyTo" => nil,
+ "attributedTo" => user.ap_id
+ },
+ "actor" => user.ap_id
+ }
+
+ {:ok, activity} = Transmogrifier.handle_incoming(message)
+
+ {:ok, _} = Transmogrifier.prepare_outgoing(activity.data)
+ end
+
+ test "successfully reserializes a message with AS2 objects in IR" do
+ user = insert(:user)
+
+ message = %{
+ "@context" => "https://www.w3.org/ns/activitystreams",
+ "to" => ["https://www.w3.org/ns/activitystreams#Public"],
+ "cc" => [],
+ "type" => "Create",
+ "object" => %{
+ "to" => ["https://www.w3.org/ns/activitystreams#Public"],
+ "cc" => [],
+ "type" => "Note",
+ "content" => "Hi",
+ "inReplyTo" => nil,
+ "attributedTo" => user.ap_id,
+ "tag" => [
+ %{"name" => "#2hu", "href" => "http://example.com/2hu", "type" => "Hashtag"},
+ %{"name" => "Bob", "href" => "http://example.com/bob", "type" => "Mention"}
+ ]
+ },
+ "actor" => user.ap_id
+ }
+
+ {:ok, activity} = Transmogrifier.handle_incoming(message)
+
+ {:ok, _} = Transmogrifier.prepare_outgoing(activity.data)
+ end
+ end
end
diff --git a/test/web/activity_pub/views/user_view_test.exs b/test/web/activity_pub/views/user_view_test.exs
index 7fc870e96..0bc1d4728 100644
--- a/test/web/activity_pub/views/user_view_test.exs
+++ b/test/web/activity_pub/views/user_view_test.exs
@@ -15,4 +15,43 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do
assert String.contains?(result["publicKey"]["publicKeyPem"], "BEGIN PUBLIC KEY")
end
+
+ describe "endpoints" do
+ test "local users have a usable endpoints structure" do
+ user = insert(:user)
+ {:ok, user} = Pleroma.Web.WebFinger.ensure_keys_present(user)
+
+ result = UserView.render("user.json", %{user: user})
+
+ assert result["id"] == user.ap_id
+
+ %{
+ "sharedInbox" => _,
+ "oauthAuthorizationEndpoint" => _,
+ "oauthRegistrationEndpoint" => _,
+ "oauthTokenEndpoint" => _
+ } = result["endpoints"]
+ end
+
+ test "remote users have an empty endpoints structure" do
+ user = insert(:user, local: false)
+ {:ok, user} = Pleroma.Web.WebFinger.ensure_keys_present(user)
+
+ result = UserView.render("user.json", %{user: user})
+
+ assert result["id"] == user.ap_id
+ assert result["endpoints"] == %{}
+ end
+
+ test "instance users do not expose oAuth endpoints" do
+ user = insert(:user, nickname: nil, local: true)
+ {:ok, user} = Pleroma.Web.WebFinger.ensure_keys_present(user)
+
+ result = UserView.render("user.json", %{user: user})
+
+ refute result["endpoints"]["oauthAuthorizationEndpoint"]
+ refute result["endpoints"]["oauthRegistrationEndpoint"]
+ refute result["endpoints"]["oauthTokenEndpoint"]
+ end
+ end
end
diff --git a/test/web/admin_api/admin_api_controller_test.exs b/test/web/admin_api/admin_api_controller_test.exs
index 42450a7b6..a27c26f95 100644
--- a/test/web/admin_api/admin_api_controller_test.exs
+++ b/test/web/admin_api/admin_api_controller_test.exs
@@ -5,7 +5,8 @@
defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
use Pleroma.Web.ConnCase
- alias Pleroma.{Repo, User}
+ alias Pleroma.Repo
+ alias Pleroma.User
import Pleroma.Factory
describe "/api/pleroma/admin/user" do
diff --git a/test/web/common_api/common_api_test.exs b/test/web/common_api/common_api_test.exs
index a7d9e6161..870648fb5 100644
--- a/test/web/common_api/common_api_test.exs
+++ b/test/web/common_api/common_api_test.exs
@@ -2,7 +2,7 @@
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
-defmodule Pleroma.Web.CommonAPI.Test do
+defmodule Pleroma.Web.CommonAPITest do
use Pleroma.DataCase
alias Pleroma.Web.CommonAPI
alias Pleroma.User
@@ -164,4 +164,30 @@ defmodule Pleroma.Web.CommonAPI.Test do
assert %User{info: %{pinned_activities: []}} = user
end
end
+
+ describe "mute tests" do
+ setup do
+ user = insert(:user)
+
+ activity = insert(:note_activity)
+
+ [user: user, activity: activity]
+ end
+
+ test "add mute", %{user: user, activity: activity} do
+ {:ok, _} = CommonAPI.add_mute(user, activity)
+ assert CommonAPI.thread_muted?(user, activity)
+ end
+
+ test "remove mute", %{user: user, activity: activity} do
+ CommonAPI.add_mute(user, activity)
+ {:ok, _} = CommonAPI.remove_mute(user, activity)
+ refute CommonAPI.thread_muted?(user, activity)
+ end
+
+ test "check that mutes can't be duplicate", %{user: user, activity: activity} do
+ CommonAPI.add_mute(user, activity)
+ {:error, _} = CommonAPI.add_mute(user, activity)
+ end
+ end
end
diff --git a/test/web/common_api/common_api_utils_test.exs b/test/web/common_api/common_api_utils_test.exs
index 754bc7255..faed6b685 100644
--- a/test/web/common_api/common_api_utils_test.exs
+++ b/test/web/common_api/common_api_utils_test.exs
@@ -5,7 +5,7 @@
defmodule Pleroma.Web.CommonAPI.UtilsTest do
alias Pleroma.Web.CommonAPI.Utils
alias Pleroma.Web.Endpoint
- alias Pleroma.Builders.{UserBuilder}
+ alias Pleroma.Builders.UserBuilder
use Pleroma.DataCase
test "it adds attachment links to a given text and attachment set" do
diff --git a/test/web/federator_test.exs b/test/web/federator_test.exs
index b56694a8b..08279f230 100644
--- a/test/web/federator_test.exs
+++ b/test/web/federator_test.exs
@@ -3,7 +3,8 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.FederatorTest do
- alias Pleroma.Web.{CommonAPI, Federator}
+ alias Pleroma.Web.CommonAPI
+ alias Pleroma.Web.Federator
alias Pleroma.Instances
use Pleroma.DataCase
import Pleroma.Factory
diff --git a/test/web/mastodon_api/mastodon_api_controller_test.exs b/test/web/mastodon_api/mastodon_api_controller_test.exs
index f8da86004..e43bc4508 100644
--- a/test/web/mastodon_api/mastodon_api_controller_test.exs
+++ b/test/web/mastodon_api/mastodon_api_controller_test.exs
@@ -6,8 +6,13 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
use Pleroma.Web.ConnCase
alias Pleroma.Web.TwitterAPI.TwitterAPI
- alias Pleroma.{Repo, User, Object, Activity, Notification}
- alias Pleroma.Web.{OStatus, CommonAPI}
+ alias Pleroma.Repo
+ alias Pleroma.User
+ alias Pleroma.Object
+ alias Pleroma.Activity
+ alias Pleroma.Notification
+ alias Pleroma.Web.OStatus
+ alias Pleroma.Web.CommonAPI
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.MastodonAPI.FilterView
alias Ecto.Changeset
@@ -31,7 +36,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
|> assign(:user, user)
|> get("/api/v1/timelines/home")
- assert length(json_response(conn, 200)) == 0
+ assert Enum.empty?(json_response(conn, 200))
{:ok, user} = User.follow(user, following)
@@ -932,7 +937,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
end
test "/api/v1/follow_requests/:id/authorize works" do
- user = insert(:user, %{info: %Pleroma.User.Info{locked: true}})
+ user = insert(:user, %{info: %User.Info{locked: true}})
other_user = insert(:user)
{:ok, _activity} = ActivityPub.follow(other_user, user)
@@ -941,6 +946,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
other_user = Repo.get(User, other_user.id)
assert User.following?(other_user, user) == false
+ assert user.info.follow_request_count == 1
conn =
build_conn()
@@ -954,6 +960,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
other_user = Repo.get(User, other_user.id)
assert User.following?(other_user, user) == true
+ assert user.info.follow_request_count == 0
end
test "verify_credentials", %{conn: conn} do
@@ -974,6 +981,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
{:ok, _activity} = ActivityPub.follow(other_user, user)
+ user = Repo.get(User, user.id)
+ assert user.info.follow_request_count == 1
+
conn =
build_conn()
|> assign(:user, user)
@@ -986,6 +996,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
other_user = Repo.get(User, other_user.id)
assert User.following?(other_user, user) == false
+ assert user.info.follow_request_count == 0
end
end
@@ -1749,4 +1760,61 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
assert [json_response(response2, 200)] == json_response(bookmarks, 200)
end
+
+ describe "conversation muting" do
+ setup do
+ user = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "HIE"})
+
+ [user: user, activity: activity]
+ end
+
+ test "mute conversation", %{conn: conn, user: user, activity: activity} do
+ id_str = to_string(activity.id)
+
+ assert %{"id" => ^id_str, "muted" => true} =
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/statuses/#{activity.id}/mute")
+ |> json_response(200)
+ end
+
+ test "unmute conversation", %{conn: conn, user: user, activity: activity} do
+ {:ok, _} = CommonAPI.add_mute(user, activity)
+
+ id_str = to_string(activity.id)
+ user = refresh_record(user)
+
+ assert %{"id" => ^id_str, "muted" => false} =
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/statuses/#{activity.id}/unmute")
+ |> json_response(200)
+ end
+ end
+
+ test "flavours switching (Pleroma Extension)", %{conn: conn} do
+ user = insert(:user)
+
+ get_old_flavour =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/pleroma/flavour")
+
+ assert "glitch" == json_response(get_old_flavour, 200)
+
+ set_flavour =
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/pleroma/flavour/vanilla")
+
+ assert "vanilla" == json_response(set_flavour, 200)
+
+ get_new_flavour =
+ conn
+ |> assign(:user, user)
+ |> post("/api/v1/pleroma/flavour/vanilla")
+
+ assert json_response(set_flavour, 200) == json_response(get_new_flavour, 200)
+ end
end
diff --git a/test/web/mastodon_api/status_view_test.exs b/test/web/mastodon_api/status_view_test.exs
index 2106253f2..0dc9c538c 100644
--- a/test/web/mastodon_api/status_view_test.exs
+++ b/test/web/mastodon_api/status_view_test.exs
@@ -5,7 +5,8 @@
defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
use Pleroma.DataCase
- alias Pleroma.Web.MastodonAPI.{StatusView, AccountView}
+ alias Pleroma.Web.MastodonAPI.AccountView
+ alias Pleroma.Web.MastodonAPI.StatusView
alias Pleroma.User
alias Pleroma.Web.OStatus
alias Pleroma.Web.CommonAPI
diff --git a/test/web/oauth/authorization_test.exs b/test/web/oauth/authorization_test.exs
index 3b1ddada8..81618e935 100644
--- a/test/web/oauth/authorization_test.exs
+++ b/test/web/oauth/authorization_test.exs
@@ -4,7 +4,8 @@
defmodule Pleroma.Web.OAuth.AuthorizationTest do
use Pleroma.DataCase
- alias Pleroma.Web.OAuth.{Authorization, App}
+ alias Pleroma.Web.OAuth.Authorization
+ alias Pleroma.Web.OAuth.App
import Pleroma.Factory
test "create an authorization token for a valid app" do
diff --git a/test/web/oauth/oauth_controller_test.exs b/test/web/oauth/oauth_controller_test.exs
index e0d3cb55f..2315f9a34 100644
--- a/test/web/oauth/oauth_controller_test.exs
+++ b/test/web/oauth/oauth_controller_test.exs
@@ -7,7 +7,8 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
import Pleroma.Factory
alias Pleroma.Repo
- alias Pleroma.Web.OAuth.{Authorization, Token}
+ alias Pleroma.Web.OAuth.Authorization
+ alias Pleroma.Web.OAuth.Token
test "redirects with oauth authorization" do
user = insert(:user)
diff --git a/test/web/oauth/token_test.exs b/test/web/oauth/token_test.exs
index 9a241d61a..4dab4a308 100644
--- a/test/web/oauth/token_test.exs
+++ b/test/web/oauth/token_test.exs
@@ -4,7 +4,9 @@
defmodule Pleroma.Web.OAuth.TokenTest do
use Pleroma.DataCase
- alias Pleroma.Web.OAuth.{App, Token, Authorization}
+ alias Pleroma.Web.OAuth.App
+ alias Pleroma.Web.OAuth.Authorization
+ alias Pleroma.Web.OAuth.Token
alias Pleroma.Repo
import Pleroma.Factory
diff --git a/test/web/ostatus/activity_representer_test.exs b/test/web/ostatus/activity_representer_test.exs
index 0869f2fd5..eebc5c040 100644
--- a/test/web/ostatus/activity_representer_test.exs
+++ b/test/web/ostatus/activity_representer_test.exs
@@ -6,7 +6,9 @@ defmodule Pleroma.Web.OStatus.ActivityRepresenterTest do
use Pleroma.DataCase
alias Pleroma.Web.OStatus.ActivityRepresenter
- alias Pleroma.{User, Activity, Object}
+ alias Pleroma.Activity
+ alias Pleroma.User
+ alias Pleroma.Object
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.OStatus
diff --git a/test/web/ostatus/feed_representer_test.exs b/test/web/ostatus/feed_representer_test.exs
index 55717dec7..efd4e7217 100644
--- a/test/web/ostatus/feed_representer_test.exs
+++ b/test/web/ostatus/feed_representer_test.exs
@@ -6,7 +6,9 @@ defmodule Pleroma.Web.OStatus.FeedRepresenterTest do
use Pleroma.DataCase
import Pleroma.Factory
alias Pleroma.User
- alias Pleroma.Web.OStatus.{FeedRepresenter, UserRepresenter, ActivityRepresenter}
+ alias Pleroma.Web.OStatus.ActivityRepresenter
+ alias Pleroma.Web.OStatus.FeedRepresenter
+ alias Pleroma.Web.OStatus.UserRepresenter
alias Pleroma.Web.OStatus
test "returns a feed of the last 20 items of the user" do
diff --git a/test/web/ostatus/incoming_documents/delete_handling_test.exs b/test/web/ostatus/incoming_documents/delete_handling_test.exs
index d97cd79f4..d295cc539 100644
--- a/test/web/ostatus/incoming_documents/delete_handling_test.exs
+++ b/test/web/ostatus/incoming_documents/delete_handling_test.exs
@@ -4,7 +4,9 @@ defmodule Pleroma.Web.OStatus.DeleteHandlingTest do
import Pleroma.Factory
import Tesla.Mock
- alias Pleroma.{Repo, Activity, Object}
+ alias Pleroma.Repo
+ alias Pleroma.Activity
+ alias Pleroma.Object
alias Pleroma.Web.OStatus
setup do
diff --git a/test/web/ostatus/ostatus_controller_test.exs b/test/web/ostatus/ostatus_controller_test.exs
index 3145ca9a1..da9c72be8 100644
--- a/test/web/ostatus/ostatus_controller_test.exs
+++ b/test/web/ostatus/ostatus_controller_test.exs
@@ -5,7 +5,9 @@
defmodule Pleroma.Web.OStatus.OStatusControllerTest do
use Pleroma.Web.ConnCase
import Pleroma.Factory
- alias Pleroma.{User, Repo, Object}
+ alias Pleroma.User
+ alias Pleroma.Repo
+ alias Pleroma.Object
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.OStatus.ActivityRepresenter
diff --git a/test/web/ostatus/ostatus_test.exs b/test/web/ostatus/ostatus_test.exs
index dbe5de2e2..b4b19ab05 100644
--- a/test/web/ostatus/ostatus_test.exs
+++ b/test/web/ostatus/ostatus_test.exs
@@ -6,7 +6,11 @@ defmodule Pleroma.Web.OStatusTest do
use Pleroma.DataCase
alias Pleroma.Web.OStatus
alias Pleroma.Web.XML
- alias Pleroma.{Object, Repo, User, Activity, Instances}
+ alias Pleroma.Object
+ alias Pleroma.Repo
+ alias Pleroma.User
+ alias Pleroma.Activity
+ alias Pleroma.Instances
import Pleroma.Factory
import ExUnit.CaptureLog
diff --git a/test/web/salmon/salmon_test.exs b/test/web/salmon/salmon_test.exs
index c539a28b2..9e583ba40 100644
--- a/test/web/salmon/salmon_test.exs
+++ b/test/web/salmon/salmon_test.exs
@@ -5,7 +5,9 @@
defmodule Pleroma.Web.Salmon.SalmonTest do
use Pleroma.DataCase
alias Pleroma.Web.Salmon
- alias Pleroma.{Repo, Activity, User}
+ alias Pleroma.Activity
+ alias Pleroma.Repo
+ alias Pleroma.User
import Pleroma.Factory
@magickey "RSA.pu0s-halox4tu7wmES1FVSx6u-4wc0YrUFXcqWXZG4-27UmbCOpMQftRCldNRfyA-qLbz-eqiwQhh-1EwUvjsD4cYbAHNGHwTvDOyx5AKthQUP44ykPv7kjKGh3DWKySJvcs9tlUG87hlo7AvnMo9pwRS_Zz2CacQ-MKaXyDepk=.AQAB"
diff --git a/test/web/twitter_api/representers/activity_representer_test.exs b/test/web/twitter_api/representers/activity_representer_test.exs
index ea5813733..365c7f659 100644
--- a/test/web/twitter_api/representers/activity_representer_test.exs
+++ b/test/web/twitter_api/representers/activity_representer_test.exs
@@ -4,8 +4,11 @@
defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenterTest do
use Pleroma.DataCase
- alias Pleroma.{User, Activity, Object}
- alias Pleroma.Web.TwitterAPI.Representers.{ActivityRepresenter, ObjectRepresenter}
+ alias Pleroma.User
+ alias Pleroma.Activity
+ alias Pleroma.Object
+ alias Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter
+ alias Pleroma.Web.TwitterAPI.Representers.ObjectRepresenter
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.TwitterAPI.UserView
import Pleroma.Factory
diff --git a/test/web/twitter_api/twitter_api_controller_test.exs b/test/web/twitter_api/twitter_api_controller_test.exs
index 855ae1526..1571ab68e 100644
--- a/test/web/twitter_api/twitter_api_controller_test.exs
+++ b/test/web/twitter_api/twitter_api_controller_test.exs
@@ -5,9 +5,15 @@
defmodule Pleroma.Web.TwitterAPI.ControllerTest do
use Pleroma.Web.ConnCase
alias Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter
- alias Pleroma.Builders.{ActivityBuilder, UserBuilder}
- alias Pleroma.{Repo, Activity, User, Object, Notification}
+ alias Pleroma.Builders.ActivityBuilder
+ alias Pleroma.Builders.UserBuilder
+ alias Pleroma.Repo
+ alias Pleroma.Activity
+ alias Pleroma.User
+ alias Pleroma.Object
+ alias Pleroma.Notification
alias Pleroma.Web.ActivityPub.ActivityPub
+ alias Pleroma.Web.OAuth.Token
alias Pleroma.Web.TwitterAPI.UserView
alias Pleroma.Web.TwitterAPI.NotificationView
alias Pleroma.Web.CommonAPI
@@ -635,6 +641,24 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
assert json_response(conn, 200) ==
UserView.render("show.json", %{user: followed, for: current_user})
end
+
+ test "for restricted account", %{conn: conn, user: current_user} do
+ followed = insert(:user, info: %User.Info{locked: true})
+
+ conn =
+ conn
+ |> with_credentials(current_user.nickname, "test")
+ |> post("/api/friendships/create.json", %{user_id: followed.id})
+
+ current_user = Repo.get(User, current_user.id)
+ followed = Repo.get(User, followed.id)
+
+ refute User.ap_followers(followed) in current_user.following
+ assert followed.info.follow_request_count == 1
+
+ assert json_response(conn, 200) ==
+ UserView.render("show.json", %{user: followed, for: current_user})
+ end
end
describe "POST /friendships/destroy.json" do
@@ -1213,7 +1237,7 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
assert Enum.sort(expected) == Enum.sort(result)
end
- test "it returns 20 friends per page", %{conn: conn} do
+ test "it returns 20 friends per page, except if 'export' is set to true", %{conn: conn} do
user = insert(:user)
followeds = insert_list(21, :user)
@@ -1237,6 +1261,14 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
result = json_response(res_conn, 200)
assert length(result) == 1
+
+ res_conn =
+ conn
+ |> assign(:user, user)
+ |> get("/api/statuses/friends", %{all: true})
+
+ result = json_response(res_conn, 200)
+ assert length(result) == 21
end
test "it returns a given user's friends with user_id", %{conn: conn} do
@@ -1671,15 +1703,19 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
other_user = Repo.get(User, other_user.id)
assert User.following?(other_user, user) == false
+ assert user.info.follow_request_count == 1
conn =
build_conn()
|> assign(:user, user)
|> post("/api/pleroma/friendships/approve", %{"user_id" => other_user.id})
+ user = Repo.get(User, user.id)
+
assert relationship = json_response(conn, 200)
assert other_user.id == relationship["id"]
assert relationship["follows_you"] == true
+ assert user.info.follow_request_count == 0
end
end
@@ -1694,15 +1730,19 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
other_user = Repo.get(User, other_user.id)
assert User.following?(other_user, user) == false
+ assert user.info.follow_request_count == 1
conn =
build_conn()
|> assign(:user, user)
|> post("/api/pleroma/friendships/deny", %{"user_id" => other_user.id})
+ user = Repo.get(User, user.id)
+
assert relationship = json_response(conn, 200)
assert other_user.id == relationship["id"]
assert relationship["follows_you"] == false
+ assert user.info.follow_request_count == 0
end
end
@@ -1876,4 +1916,38 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
ActivityRepresenter.to_map(activity, %{user: user, for: user})
end
end
+
+ describe "GET /api/oauth_tokens" do
+ setup do
+ token = insert(:oauth_token) |> Repo.preload(:user)
+
+ %{token: token}
+ end
+
+ test "renders list", %{token: token} do
+ response =
+ build_conn()
+ |> assign(:user, token.user)
+ |> get("/api/oauth_tokens")
+
+ keys =
+ json_response(response, 200)
+ |> hd()
+ |> Map.keys()
+
+ assert keys -- ["id", "app_name", "valid_until"] == []
+ end
+
+ test "revoke token", %{token: token} do
+ response =
+ build_conn()
+ |> assign(:user, token.user)
+ |> delete("/api/oauth_tokens/#{token.id}")
+
+ tokens = Token.get_user_tokens(token.user)
+
+ assert tokens == []
+ assert response.status == 201
+ end
+ end
end
diff --git a/test/web/twitter_api/twitter_api_test.exs b/test/web/twitter_api/twitter_api_test.exs
index 48ddbcf50..aa2a4d650 100644
--- a/test/web/twitter_api/twitter_api_test.exs
+++ b/test/web/twitter_api/twitter_api_test.exs
@@ -4,8 +4,13 @@
defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do
use Pleroma.DataCase
- alias Pleroma.Web.TwitterAPI.{TwitterAPI, UserView}
- alias Pleroma.{Activity, User, Object, Repo, UserInviteToken}
+ alias Pleroma.Web.TwitterAPI.TwitterAPI
+ alias Pleroma.Web.TwitterAPI.UserView
+ alias Pleroma.Activity
+ alias Pleroma.User
+ alias Pleroma.Object
+ alias Pleroma.Repo
+ alias Pleroma.UserInviteToken
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.TwitterAPI.ActivityView
diff --git a/test/web/twitter_api/views/notification_view_test.exs b/test/web/twitter_api/views/notification_view_test.exs
index 8367fc6c7..3a67f7292 100644
--- a/test/web/twitter_api/views/notification_view_test.exs
+++ b/test/web/twitter_api/views/notification_view_test.exs
@@ -5,7 +5,8 @@
defmodule Pleroma.Web.TwitterAPI.NotificationViewTest do
use Pleroma.DataCase
- alias Pleroma.{User, Notification}
+ alias Pleroma.User
+ alias Pleroma.Notification
alias Pleroma.Web.TwitterAPI.TwitterAPI
alias Pleroma.Web.TwitterAPI.NotificationView
alias Pleroma.Web.TwitterAPI.UserView
diff --git a/test/web/websub/websub_controller_test.exs b/test/web/websub/websub_controller_test.exs
index 6492df2a0..87b01d89b 100644
--- a/test/web/websub/websub_controller_test.exs
+++ b/test/web/websub/websub_controller_test.exs
@@ -6,7 +6,8 @@ defmodule Pleroma.Web.Websub.WebsubControllerTest do
use Pleroma.Web.ConnCase
import Pleroma.Factory
alias Pleroma.Web.Websub.WebsubClientSubscription
- alias Pleroma.{Repo, Activity}
+ alias Pleroma.Activity
+ alias Pleroma.Repo
alias Pleroma.Web.Websub
test "websub subscription request", %{conn: conn} do
@@ -80,7 +81,7 @@ defmodule Pleroma.Web.Websub.WebsubControllerTest do
assert response(conn, 500) == "Error"
- assert length(Repo.all(Activity)) == 0
+ assert Enum.empty?(Repo.all(Activity))
end
end
end
diff --git a/test/web/websub/websub_test.exs b/test/web/websub/websub_test.exs
index 9751d161d..9a9b9df02 100644
--- a/test/web/websub/websub_test.exs
+++ b/test/web/websub/websub_test.exs
@@ -5,7 +5,8 @@
defmodule Pleroma.Web.WebsubTest do
use Pleroma.DataCase
alias Pleroma.Web.Websub
- alias Pleroma.Web.Websub.{WebsubServerSubscription, WebsubClientSubscription}
+ alias Pleroma.Web.Websub.WebsubServerSubscription
+ alias Pleroma.Web.Websub.WebsubClientSubscription
import Pleroma.Factory
alias Pleroma.Web.Router.Helpers
import Tesla.Mock