summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md4
-rw-r--r--config/config.exs15
-rw-r--r--docs/api/pleroma_api.md39
-rw-r--r--docs/config.md10
-rw-r--r--docs/config/howto_mongooseim.md10
-rw-r--r--docs/config/mrf.md9
-rw-r--r--lib/pleroma/activity.ex12
-rw-r--r--lib/pleroma/application.ex19
-rw-r--r--lib/pleroma/formatter.ex2
-rw-r--r--lib/pleroma/http/connection.ex2
-rw-r--r--lib/pleroma/user.ex20
-rw-r--r--lib/pleroma/user/info.ex9
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub.ex8
-rw-r--r--lib/pleroma/web/mastodon_api/mastodon_api_controller.ex37
-rw-r--r--lib/pleroma/web/mastodon_api/views/status_view.ex8
-rw-r--r--lib/pleroma/web/mongooseim/mongoose_im_controller.ex41
-rw-r--r--lib/pleroma/web/router.ex15
-rw-r--r--lib/pleroma/web/twitter_api/views/activity_view.ex8
-rw-r--r--test/activity_test.exs26
-rw-r--r--test/fixtures/sound.mp3bin0 -> 521 bytes
-rw-r--r--test/formatter_test.exs9
-rw-r--r--test/user_test.exs2
-rw-r--r--test/web/admin_api/admin_api_controller_test.exs4
-rw-r--r--test/web/fallback_test.exs52
-rw-r--r--test/web/mastodon_api/mastodon_api_controller_test.exs66
-rw-r--r--test/web/mongooseim/mongoose_im_controller_test.exs59
26 files changed, 467 insertions, 19 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 87101db30..3ff70e6e5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [unreleased]
### Added
+- [MongooseIM](https://github.com/esl/MongooseIM) http authentication support.
- LDAP authentication
- External OAuth provider authentication
- A [job queue](https://git.pleroma.social/pleroma/pleroma_job_queue) for federation, emails, web push, etc.
@@ -23,6 +24,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Configuration: `report_uri` option
- Pleroma API: User subscriptions
- Pleroma API: Healthcheck endpoint
+- Pleroma API: `/api/v1/pleroma/mascot` per-user frontend mascot configuration endpoints
- Admin API: Endpoints for listing/revoking invite tokens
- Admin API: Endpoints for making users follow/unfollow each other
- Admin API: added filters (role, tags, email, name) for users endpoint
@@ -72,6 +74,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Don't ship finmoji by default, they can be installed as an emoji pack
- Hide deactivated users and their statuses
- Posts which are marked sensitive or tagged nsfw no longer have link previews.
+- HTTP connection timeout is now set to 10 seconds.
+- Respond with a 404 Not implemented JSON error message when requested API is not implemented
### Fixed
- Added an FTS index on objects. Running `vacuum analyze` and setting a larger `work_mem` is recommended.
diff --git a/config/config.exs b/config/config.exs
index bab47a8a2..c3301b2ed 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -276,6 +276,19 @@ config :pleroma, :frontend_configurations,
showInstanceSpecificPanel: true
}
+config :pleroma, :assets,
+ mascots: [
+ pleroma_fox_tan: %{
+ url: "/images/pleroma-fox-tan-smol.png",
+ mime_type: "image/png"
+ },
+ pleroma_fox_tan_shy: %{
+ url: "/images/pleroma-fox-tan-shy.png",
+ mime_type: "image/png"
+ }
+ ],
+ default_mascot: :pleroma_fox_tan
+
config :pleroma, :activitypub,
accept_blocks: true,
unfollow_blocked: true,
@@ -371,6 +384,7 @@ config :pleroma, Pleroma.User,
"activities",
"api",
"auth",
+ "check_password",
"dev",
"friend-requests",
"inbox",
@@ -391,6 +405,7 @@ config :pleroma, Pleroma.User,
"status",
"tag",
"user-search",
+ "user_exists",
"users",
"web"
]
diff --git a/docs/api/pleroma_api.md b/docs/api/pleroma_api.md
index dd0b6ca73..4d99a2d2b 100644
--- a/docs/api/pleroma_api.md
+++ b/docs/api/pleroma_api.md
@@ -252,6 +252,45 @@ See [Admin-API](Admin-API.md)
]
```
+## `/api/v1/pleroma/mascot`
+### Gets user mascot image
+* Method `GET`
+* Authentication: required
+
+* Response: JSON. Returns a mastodon media attachment entity.
+* Example response:
+```json
+{
+ "id": "abcdefg",
+ "url": "https://pleroma.example.org/media/abcdefg.png",
+ "type": "image",
+ "pleroma": {
+ "mime_type": "image/png"
+ }
+}
+```
+
+### Updates user mascot image
+* Method `PUT`
+* Authentication: required
+* Params:
+ * `image`: Multipart image
+* Response: JSON. Returns a mastodon media attachment entity
+ when successful, otherwise returns HTTP 415 `{"error": "error_msg"}`
+* Example response:
+```json
+{
+ "id": "abcdefg",
+ "url": "https://pleroma.example.org/media/abcdefg.png",
+ "type": "image",
+ "pleroma": {
+ "mime_type": "image/png"
+ }
+}
+```
+* Note: Behaves exactly the same as `POST /api/v1/upload`.
+ Can only accept images - any attempt to upload non-image files will be met with `HTTP 415 Unsupported Media Type`.
+
## `/api/pleroma/notification_settings`
### Updates user notification settings
* Method `PUT`
diff --git a/docs/config.md b/docs/config.md
index 450d73fda..197326bbd 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -203,6 +203,16 @@ This section is used to configure Pleroma-FE, unless ``:managed_config`` in ``:i
* `hide_post_stats`: Hide notices statistics(repeats, favorites, …)
* `hide_user_stats`: Hide profile statistics(posts, posts per day, followers, followings, …)
+## :assets
+
+This section configures assets to be used with various frontends. Currently the only option
+relates to mascots on the mastodon frontend
+
+* `mascots`: KeywordList of mascots, each element __MUST__ contain both a `url` and a
+ `mime_type` key.
+* `default_mascot`: An element from `mascots` - This will be used as the default mascot
+ on MastoFE (default: `:pleroma_fox_tan`)
+
## :mrf_simple
* `media_removal`: List of instances to remove medias from
* `media_nsfw`: List of instances to put medias as NSFW(sensitive) from
diff --git a/docs/config/howto_mongooseim.md b/docs/config/howto_mongooseim.md
new file mode 100644
index 000000000..a33e590a1
--- /dev/null
+++ b/docs/config/howto_mongooseim.md
@@ -0,0 +1,10 @@
+# Configuring MongooseIM (XMPP Server) to use Pleroma for authentication
+
+If you want to give your Pleroma users an XMPP (chat) account, you can configure [MongooseIM](https://github.com/esl/MongooseIM) to use your Pleroma server for user authentication, automatically giving every local user an XMPP account.
+
+In general, you just have to follow the configuration described at [https://mongooseim.readthedocs.io/en/latest/authentication-backends/HTTP-authentication-module/](https://mongooseim.readthedocs.io/en/latest/authentication-backends/HTTP-authentication-module/) and do these changes to your mongooseim.cfg.
+
+1. Set the auth_method to `{auth_method, http}`.
+2. Add the http auth pool like this: `{http, global, auth, [{workers, 50}], [{server, "https://yourpleromainstance.com"}]}`
+
+Restart your MongooseIM server, your users should now be able to connect with their Pleroma credentials.
diff --git a/docs/config/mrf.md b/docs/config/mrf.md
index 2cc16cef0..45be18fc5 100644
--- a/docs/config/mrf.md
+++ b/docs/config/mrf.md
@@ -5,11 +5,12 @@ Possible uses include:
* marking incoming messages with media from a given account or instance as sensitive
* rejecting messages from a specific instance
+* rejecting reports (flags) from a specific instance
* removing/unlisting messages from the public timelines
* removing media from messages
* sending only public messages to a specific instance
-The MRF provides user-configurable policies. The default policy is `NoOpPolicy`, which disables the MRF functionality. Pleroma also includes an easy to use policy called `SimplePolicy` which maps messages matching certain pre-defined criterion to actions built into the policy module.
+The MRF provides user-configurable policies. The default policy is `NoOpPolicy`, which disables the MRF functionality. Pleroma also includes an easy to use policy called `SimplePolicy` which maps messages matching certain pre-defined criterion to actions built into the policy module.
It is possible to use multiple, active MRF policies at the same time.
## Quarantine Instances
@@ -41,12 +42,13 @@ Once `SimplePolicy` is enabled, you can configure various groups in the `:mrf_si
* `media_nsfw`: Servers in this group will have the #nsfw tag and sensitive setting injected into incoming messages which contain media.
* `reject`: Servers in this group will have their messages rejected.
* `federated_timeline_removal`: Servers in this group will have their messages unlisted from the public timelines by flipping the `to` and `cc` fields.
+* `report_removal`: Servers in this group will have their reports (flags) rejected.
Servers should be configured as lists.
### Example
-This example will enable `SimplePolicy`, block media from `illegalporn.biz`, mark media as NSFW from `porn.biz` and `porn.business`, reject messages from `spam.com` and remove messages from `spam.university` from the federated timeline:
+This example will enable `SimplePolicy`, block media from `illegalporn.biz`, mark media as NSFW from `porn.biz` and `porn.business`, reject messages from `spam.com`, remove messages from `spam.university` from the federated timeline and block reports (flags) from `whiny.whiner`:
```
config :pleroma, :instance,
@@ -56,7 +58,8 @@ config :pleroma, :mrf_simple,
media_removal: ["illegalporn.biz"],
media_nsfw: ["porn.biz", "porn.business"],
reject: ["spam.com"],
- federated_timeline_removal: ["spam.university"]
+ federated_timeline_removal: ["spam.university"],
+ report_removal: ["whiny.whiner"]
```
diff --git a/lib/pleroma/activity.ex b/lib/pleroma/activity.ex
index 4e54b15ba..99589590c 100644
--- a/lib/pleroma/activity.ex
+++ b/lib/pleroma/activity.ex
@@ -10,6 +10,7 @@ defmodule Pleroma.Activity do
alias Pleroma.Notification
alias Pleroma.Object
alias Pleroma.Repo
+ alias Pleroma.ThreadMute
alias Pleroma.User
import Ecto.Changeset
@@ -37,6 +38,7 @@ defmodule Pleroma.Activity do
field(:local, :boolean, default: true)
field(:actor, :string)
field(:recipients, {:array, :string}, default: [])
+ field(:thread_muted?, :boolean, virtual: true)
# This is a fake relation, do not use outside of with_preloaded_bookmark/get_bookmark
has_one(:bookmark, Bookmark)
has_many(:notifications, Notification, on_delete: :delete_all)
@@ -90,6 +92,16 @@ defmodule Pleroma.Activity do
def with_preloaded_bookmark(query, _), do: query
+ def with_set_thread_muted_field(query, %User{} = user) do
+ from([a] in query,
+ left_join: tm in ThreadMute,
+ on: tm.user_id == ^user.id and tm.context == fragment("?->>'context'", a.data),
+ select: %Activity{a | thread_muted?: not is_nil(tm.id)}
+ )
+ end
+
+ def with_set_thread_muted_field(query, _), do: query
+
def get_by_ap_id(ap_id) do
Repo.one(
from(
diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex
index eeb415084..dab45a0b2 100644
--- a/lib/pleroma/application.ex
+++ b/lib/pleroma/application.ex
@@ -131,19 +131,22 @@ defmodule Pleroma.Application do
defp setup_instrumenters do
require Prometheus.Registry
- :ok =
- :telemetry.attach(
- "prometheus-ecto",
- [:pleroma, :repo, :query],
- &Pleroma.Repo.Instrumenter.handle_event/4,
- %{}
- )
+ if Application.get_env(:prometheus, Pleroma.Repo.Instrumenter) do
+ :ok =
+ :telemetry.attach(
+ "prometheus-ecto",
+ [:pleroma, :repo, :query],
+ &Pleroma.Repo.Instrumenter.handle_event/4,
+ %{}
+ )
+
+ Pleroma.Repo.Instrumenter.setup()
+ end
Prometheus.Registry.register_collector(:prometheus_process_collector)
Pleroma.Web.Endpoint.MetricsExporter.setup()
Pleroma.Web.Endpoint.PipelineInstrumenter.setup()
Pleroma.Web.Endpoint.Instrumenter.setup()
- Pleroma.Repo.Instrumenter.setup()
end
def enabled_hackney_pools do
diff --git a/lib/pleroma/formatter.ex b/lib/pleroma/formatter.ex
index 3d7c36d21..3e3b9fe97 100644
--- a/lib/pleroma/formatter.ex
+++ b/lib/pleroma/formatter.ex
@@ -8,7 +8,7 @@ defmodule Pleroma.Formatter do
alias Pleroma.User
alias Pleroma.Web.MediaProxy
- @safe_mention_regex ~r/^(\s*(?<mentions>@.+?\s+)+)(?<rest>.*)/
+ @safe_mention_regex ~r/^(\s*(?<mentions>@.+?\s+)+)(?<rest>.*)/s
@link_regex ~r"((?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~%:/?#[\]@!\$&'\(\)\*\+,;=.]+)|[0-9a-z+\-\.]+:[0-9a-z$-_.+!*'(),]+"ui
@markdown_characters_regex ~r/(`|\*|_|{|}|[|]|\(|\)|#|\+|-|\.|!)/
diff --git a/lib/pleroma/http/connection.ex b/lib/pleroma/http/connection.ex
index c0173465a..558005c19 100644
--- a/lib/pleroma/http/connection.ex
+++ b/lib/pleroma/http/connection.ex
@@ -8,7 +8,7 @@ defmodule Pleroma.HTTP.Connection do
"""
@hackney_options [
- connect_timeout: 2_000,
+ connect_timeout: 10_000,
recv_timeout: 20_000,
follow_redirect: true,
pool: :federation
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 28da310ee..05fe58f7c 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -1402,4 +1402,24 @@ defmodule Pleroma.User do
|> put_embed(:info, info_changeset)
|> update_and_set_cache()
end
+
+ def get_mascot(%{info: %{mascot: %{} = mascot}}) when not is_nil(mascot) do
+ mascot
+ end
+
+ def get_mascot(%{info: %{mascot: mascot}}) when is_nil(mascot) do
+ # use instance-default
+ config = Pleroma.Config.get([:assets, :mascots])
+ default_mascot = Pleroma.Config.get([:assets, :default_mascot])
+ mascot = Keyword.get(config, default_mascot)
+
+ %{
+ "id" => "default-mascot",
+ "url" => mascot[:url],
+ "preview_url" => mascot[:url],
+ "pleroma" => %{
+ "mime_type" => mascot[:mime_type]
+ }
+ }
+ end
end
diff --git a/lib/pleroma/user/info.ex b/lib/pleroma/user/info.ex
index 5f0cefc00..6397e2737 100644
--- a/lib/pleroma/user/info.ex
+++ b/lib/pleroma/user/info.ex
@@ -43,6 +43,7 @@ defmodule Pleroma.User.Info do
field(:hide_favorites, :boolean, default: true)
field(:pinned_activities, {:array, :string}, default: [])
field(:flavour, :string, default: nil)
+ field(:mascot, :map, default: nil)
field(:emoji, {:array, :map}, default: [])
field(:notification_settings, :map,
@@ -248,6 +249,14 @@ defmodule Pleroma.User.Info do
|> validate_required([:flavour])
end
+ def mascot_update(info, url) do
+ params = %{mascot: url}
+
+ info
+ |> cast(params, [:mascot])
+ |> validate_required([:mascot])
+ end
+
def set_source_data(info, source_data) do
params = %{source_data: source_data}
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index 5c3156978..3d9679ec0 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -834,6 +834,13 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|> Activity.with_preloaded_bookmark(opts["user"])
end
+ defp maybe_set_thread_muted_field(query, %{"skip_preload" => true}), do: query
+
+ defp maybe_set_thread_muted_field(query, opts) do
+ query
+ |> Activity.with_set_thread_muted_field(opts["user"])
+ end
+
defp maybe_order(query, %{order: :desc}) do
query
|> order_by(desc: :id)
@@ -852,6 +859,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
base_query
|> maybe_preload_objects(opts)
|> maybe_preload_bookmarks(opts)
+ |> maybe_set_thread_muted_field(opts)
|> maybe_order(opts)
|> restrict_recipients(recipients, opts["user"])
|> restrict_tag(opts)
diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
index 1051861ff..1ec0f30a1 100644
--- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
+++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
@@ -707,6 +707,41 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
end
end
+ def set_mascot(%{assigns: %{user: user}} = conn, %{"file" => file}) do
+ with {:ok, object} <- ActivityPub.upload(file, actor: User.ap_id(user)),
+ %{} = attachment_data <- Map.put(object.data, "id", object.id),
+ %{type: type} = rendered <-
+ StatusView.render("attachment.json", %{attachment: attachment_data}) do
+ # Reject if not an image
+ if type == "image" do
+ # Sure!
+ # Save to the user's info
+ info_changeset = User.Info.mascot_update(user.info, rendered)
+
+ user_changeset =
+ user
+ |> Ecto.Changeset.change()
+ |> Ecto.Changeset.put_embed(:info, info_changeset)
+
+ {:ok, _user} = User.update_and_set_cache(user_changeset)
+
+ conn
+ |> json(rendered)
+ else
+ conn
+ |> put_resp_content_type("application/json")
+ |> send_resp(415, Jason.encode!(%{"error" => "mascots can only be images"}))
+ end
+ end
+ end
+
+ def get_mascot(%{assigns: %{user: user}} = conn, _params) do
+ mascot = User.get_mascot(user)
+
+ conn
+ |> json(mascot)
+ end
+
def favourited_by(%{assigns: %{user: user}} = conn, %{"id" => id}) do
with %Activity{data: %{"object" => object}} <- Repo.get(Activity, id),
%Object{data: %{"likes" => likes}} <- Object.normalize(object) do
@@ -1329,7 +1364,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
display_sensitive_media: false,
reduce_motion: false,
max_toot_chars: limit,
- mascot: "/images/pleroma-fox-tan-smol.png"
+ mascot: User.get_mascot(user)["url"]
},
rights: %{
delete_others_notice: present?(user.info.is_moderator),
diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex
index c93d915e5..e55f9b96e 100644
--- a/lib/pleroma/web/mastodon_api/views/status_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/status_view.ex
@@ -157,6 +157,12 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
bookmarked = Activity.get_bookmark(activity, opts[:for]) != nil
+ thread_muted? =
+ case activity.thread_muted? do
+ thread_muted? when is_boolean(thread_muted?) -> thread_muted?
+ nil -> CommonAPI.thread_muted?(user, activity)
+ end
+
attachment_data = object.data["attachment"] || []
attachments = render_many(attachment_data, StatusView, "attachment.json", as: :attachment)
@@ -228,7 +234,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
reblogged: reblogged?(activity, opts[:for]),
favourited: present?(favorited),
bookmarked: present?(bookmarked),
- muted: CommonAPI.thread_muted?(user, activity) || User.mutes?(opts[:for], user),
+ muted: thread_muted? || User.mutes?(opts[:for], user),
pinned: pinned?(activity, user),
sensitive: sensitive,
spoiler_text: summary_html,
diff --git a/lib/pleroma/web/mongooseim/mongoose_im_controller.ex b/lib/pleroma/web/mongooseim/mongoose_im_controller.ex
new file mode 100644
index 000000000..489d5d3a5
--- /dev/null
+++ b/lib/pleroma/web/mongooseim/mongoose_im_controller.ex
@@ -0,0 +1,41 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.MongooseIM.MongooseIMController do
+ use Pleroma.Web, :controller
+ alias Comeonin.Pbkdf2
+ alias Pleroma.Repo
+ alias Pleroma.User
+
+ def user_exists(conn, %{"user" => username}) do
+ with %User{} <- Repo.get_by(User, nickname: username, local: true) do
+ conn
+ |> json(true)
+ else
+ _ ->
+ conn
+ |> put_status(:not_found)
+ |> json(false)
+ end
+ end
+
+ def check_password(conn, %{"user" => username, "pass" => password}) do
+ with %User{password_hash: password_hash} <-
+ Repo.get_by(User, nickname: username, local: true),
+ true <- Pbkdf2.checkpw(password, password_hash) do
+ conn
+ |> json(true)
+ else
+ false ->
+ conn
+ |> put_status(403)
+ |> json(false)
+
+ _ ->
+ conn
+ |> put_status(:not_found)
+ |> json(false)
+ end
+ end
+end
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index 6a4e4a1d4..352268b96 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -352,6 +352,9 @@ defmodule Pleroma.Web.Router do
post("/pleroma/flavour/:flavour", MastodonAPIController, :set_flavour)
+ get("/pleroma/mascot", MastodonAPIController, :get_mascot)
+ put("/pleroma/mascot", MastodonAPIController, :set_mascot)
+
post("/reports", MastodonAPIController, :reports)
end
@@ -704,9 +707,15 @@ defmodule Pleroma.Web.Router do
end
end
+ scope "/", Pleroma.Web.MongooseIM do
+ get("/user_exists", MongooseIMController, :user_exists)
+ get("/check_password", MongooseIMController, :check_password)
+ end
+
scope "/", Fallback do
get("/registration/:token", RedirectController, :registration_page)
get("/:maybe_nickname_or_id", RedirectController, :redirector_with_meta)
+ get("/api*path", RedirectController, :api_not_implemented)
get("/*path", RedirectController, :redirector)
options("/*path", RedirectController, :empty)
@@ -718,6 +727,12 @@ defmodule Fallback.RedirectController do
alias Pleroma.User
alias Pleroma.Web.Metadata
+ def api_not_implemented(conn, _params) do
+ conn
+ |> put_status(404)
+ |> json(%{error: "Not implemented"})
+ end
+
def redirector(conn, _params, code \\ 200) do
conn
|> put_resp_content_type("text/html")
diff --git a/lib/pleroma/web/twitter_api/views/activity_view.ex b/lib/pleroma/web/twitter_api/views/activity_view.ex
index 44bcafe0e..e84af84dc 100644
--- a/lib/pleroma/web/twitter_api/views/activity_view.ex
+++ b/lib/pleroma/web/twitter_api/views/activity_view.ex
@@ -284,6 +284,12 @@ defmodule Pleroma.Web.TwitterAPI.ActivityView do
Pleroma.Web.RichMedia.Helpers.fetch_data_for_activity(activity)
)
+ thread_muted? =
+ case activity.thread_muted? do
+ thread_muted? when is_boolean(thread_muted?) -> thread_muted?
+ nil -> CommonAPI.thread_muted?(user, activity)
+ end
+
%{
"id" => activity.id,
"uri" => object.data["id"],
@@ -314,7 +320,7 @@ defmodule Pleroma.Web.TwitterAPI.ActivityView do
"summary" => summary,
"summary_html" => summary |> Formatter.emojify(object.data["emoji"]),
"card" => card,
- "muted" => CommonAPI.thread_muted?(user, activity) || User.mutes?(opts[:for], user)
+ "muted" => thread_muted? || User.mutes?(opts[:for], user)
}
end
diff --git a/test/activity_test.exs b/test/activity_test.exs
index 7e91d534b..15c95502a 100644
--- a/test/activity_test.exs
+++ b/test/activity_test.exs
@@ -6,6 +6,7 @@ defmodule Pleroma.ActivityTest do
use Pleroma.DataCase
alias Pleroma.Activity
alias Pleroma.Bookmark
+ alias Pleroma.ThreadMute
import Pleroma.Factory
test "returns an activity by it's AP id" do
@@ -47,6 +48,31 @@ defmodule Pleroma.ActivityTest do
assert queried_activity.bookmark == bookmark3
end
+ test "setting thread_muted?" do
+ activity = insert(:note_activity)
+ user = insert(:user)
+ annoyed_user = insert(:user)
+ {:ok, _} = ThreadMute.add_mute(annoyed_user.id, activity.data["context"])
+
+ activity_with_unset_thread_muted_field =
+ Ecto.Query.from(Activity)
+ |> Repo.one()
+
+ activity_for_user =
+ Ecto.Query.from(Activity)
+ |> Activity.with_set_thread_muted_field(user)
+ |> Repo.one()
+
+ activity_for_annoyed_user =
+ Ecto.Query.from(Activity)
+ |> Activity.with_set_thread_muted_field(annoyed_user)
+ |> Repo.one()
+
+ assert activity_with_unset_thread_muted_field.thread_muted? == nil
+ assert activity_for_user.thread_muted? == false
+ assert activity_for_annoyed_user.thread_muted? == true
+ end
+
describe "getting a bookmark" do
test "when association is loaded" do
user = insert(:user)
diff --git a/test/fixtures/sound.mp3 b/test/fixtures/sound.mp3
new file mode 100644
index 000000000..9f0f661a3
--- /dev/null
+++ b/test/fixtures/sound.mp3
Binary files differ
diff --git a/test/formatter_test.exs b/test/formatter_test.exs
index 5e7011160..47b91b121 100644
--- a/test/formatter_test.exs
+++ b/test/formatter_test.exs
@@ -206,6 +206,15 @@ defmodule Pleroma.FormatterTest do
assert mentions == []
assert expected_text == text
end
+
+ test "given the 'safe_mention' option, it will keep text after newlines" do
+ user = insert(:user)
+ text = " @#{user.nickname}\n hey dude\n\nhow are you doing?"
+
+ {expected_text, _, _} = Formatter.linkify(text, safe_mention: true)
+
+ assert expected_text =~ "how are you doing?"
+ end
end
describe ".parse_tags" do
diff --git a/test/user_test.exs b/test/user_test.exs
index 10e463ff8..cb6afbe07 100644
--- a/test/user_test.exs
+++ b/test/user_test.exs
@@ -902,7 +902,7 @@ defmodule Pleroma.UserTest do
assert [activity] == ActivityPub.fetch_public_activities(%{}) |> Repo.preload(:bookmark)
- assert [activity] ==
+ assert [%{activity | thread_muted?: CommonAPI.thread_muted?(user2, activity)}] ==
ActivityPub.fetch_activities([user2.ap_id | user2.following], %{"user" => user2})
{:ok, _user} = User.deactivate(user)
diff --git a/test/web/admin_api/admin_api_controller_test.exs b/test/web/admin_api/admin_api_controller_test.exs
index ca12c7215..c15c67e31 100644
--- a/test/web/admin_api/admin_api_controller_test.exs
+++ b/test/web/admin_api/admin_api_controller_test.exs
@@ -397,14 +397,14 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
end
end
- test "/api/pleroma/admin/invite_token" do
+ test "/api/pleroma/admin/users/invite_token" do
admin = insert(:user, info: %{is_admin: true})
conn =
build_conn()
|> assign(:user, admin)
|> put_req_header("accept", "application/json")
- |> get("/api/pleroma/admin/invite_token")
+ |> get("/api/pleroma/admin/users/invite_token")
assert conn.status == 200
end
diff --git a/test/web/fallback_test.exs b/test/web/fallback_test.exs
new file mode 100644
index 000000000..cc78b3ae1
--- /dev/null
+++ b/test/web/fallback_test.exs
@@ -0,0 +1,52 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.FallbackTest do
+ use Pleroma.Web.ConnCase
+ import Pleroma.Factory
+
+ test "GET /registration/:token", %{conn: conn} do
+ assert conn
+ |> get("/registration/foo")
+ |> html_response(200) =~ "<!--server-generated-meta-->"
+ end
+
+ test "GET /:maybe_nickname_or_id", %{conn: conn} do
+ user = insert(:user)
+
+ assert conn
+ |> get("/foo")
+ |> html_response(200) =~ "<!--server-generated-meta-->"
+
+ refute conn
+ |> get("/" <> user.nickname)
+ |> html_response(200) =~ "<!--server-generated-meta-->"
+ end
+
+ test "GET /api*path", %{conn: conn} do
+ assert conn
+ |> get("/api/foo")
+ |> json_response(404) == %{"error" => "Not implemented"}
+ end
+
+ test "GET /*path", %{conn: conn} do
+ assert conn
+ |> get("/foo")
+ |> html_response(200) =~ "<!--server-generated-meta-->"
+
+ assert conn
+ |> get("/foo/bar")
+ |> html_response(200) =~ "<!--server-generated-meta-->"
+ end
+
+ test "OPTIONS /*path", %{conn: conn} do
+ assert conn
+ |> options("/foo")
+ |> response(204) == ""
+
+ assert conn
+ |> options("/foo/bar")
+ |> response(204) == ""
+ end
+end
diff --git a/test/web/mastodon_api/mastodon_api_controller_test.exs b/test/web/mastodon_api/mastodon_api_controller_test.exs
index cbff141c8..1d9f5a816 100644
--- a/test/web/mastodon_api/mastodon_api_controller_test.exs
+++ b/test/web/mastodon_api/mastodon_api_controller_test.exs
@@ -1455,6 +1455,72 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
assert object.data["actor"] == User.ap_id(user)
end
+ test "mascot upload", %{conn: conn} do
+ user = insert(:user)
+
+ non_image_file = %Plug.Upload{
+ content_type: "audio/mpeg",
+ path: Path.absname("test/fixtures/sound.mp3"),
+ filename: "sound.mp3"
+ }
+
+ conn =
+ conn
+ |> assign(:user, user)
+ |> put("/api/v1/pleroma/mascot", %{"file" => non_image_file})
+
+ assert json_response(conn, 415)
+
+ file = %Plug.Upload{
+ content_type: "image/jpg",
+ path: Path.absname("test/fixtures/image.jpg"),
+ filename: "an_image.jpg"
+ }
+
+ conn =
+ build_conn()
+ |> assign(:user, user)
+ |> put("/api/v1/pleroma/mascot", %{"file" => file})
+
+ assert %{"id" => _, "type" => image} = json_response(conn, 200)
+ end
+
+ test "mascot retrieving", %{conn: conn} do
+ user = insert(:user)
+ # When user hasn't set a mascot, we should just get pleroma tan back
+ conn =
+ conn
+ |> assign(:user, user)
+ |> get("/api/v1/pleroma/mascot")
+
+ assert %{"url" => url} = json_response(conn, 200)
+ assert url =~ "pleroma-fox-tan-smol"
+
+ # When a user sets their mascot, we should get that back
+ file = %Plug.Upload{
+ content_type: "image/jpg",
+ path: Path.absname("test/fixtures/image.jpg"),
+ filename: "an_image.jpg"
+ }
+
+ conn =
+ build_conn()
+ |> assign(:user, user)
+ |> put("/api/v1/pleroma/mascot", %{"file" => file})
+
+ assert json_response(conn, 200)
+
+ user = User.get_cached_by_id(user.id)
+
+ conn =
+ build_conn()
+ |> assign(:user, user)
+ |> get("/api/v1/pleroma/mascot")
+
+ assert %{"url" => url, "type" => "image"} = json_response(conn, 200)
+ assert url =~ "an_image"
+ end
+
test "hashtag timeline", %{conn: conn} do
following = insert(:user)
diff --git a/test/web/mongooseim/mongoose_im_controller_test.exs b/test/web/mongooseim/mongoose_im_controller_test.exs
new file mode 100644
index 000000000..eb83999bb
--- /dev/null
+++ b/test/web/mongooseim/mongoose_im_controller_test.exs
@@ -0,0 +1,59 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.MongooseIMController do
+ use Pleroma.Web.ConnCase
+ import Pleroma.Factory
+
+ test "/user_exists", %{conn: conn} do
+ _user = insert(:user, nickname: "lain")
+ _remote_user = insert(:user, nickname: "alice", local: false)
+
+ res =
+ conn
+ |> get(mongoose_im_path(conn, :user_exists), user: "lain")
+ |> json_response(200)
+
+ assert res == true
+
+ res =
+ conn
+ |> get(mongoose_im_path(conn, :user_exists), user: "alice")
+ |> json_response(404)
+
+ assert res == false
+
+ res =
+ conn
+ |> get(mongoose_im_path(conn, :user_exists), user: "bob")
+ |> json_response(404)
+
+ assert res == false
+ end
+
+ test "/check_password", %{conn: conn} do
+ user = insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt("cool"))
+
+ res =
+ conn
+ |> get(mongoose_im_path(conn, :check_password), user: user.nickname, pass: "cool")
+ |> json_response(200)
+
+ assert res == true
+
+ res =
+ conn
+ |> get(mongoose_im_path(conn, :check_password), user: user.nickname, pass: "uncool")
+ |> json_response(403)
+
+ assert res == false
+
+ res =
+ conn
+ |> get(mongoose_im_path(conn, :check_password), user: "nobody", pass: "cool")
+ |> json_response(404)
+
+ assert res == false
+ end
+end