diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index fd0c5c8d4..9a754ed78 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -229,7 +229,7 @@ arm:
only: *release-only
tags:
- arm32
- image: elixir:1.10.3
+ image: arm32v7/elixir:1.10.3
cache: *release-cache
variables: *release-variables
before_script: *before-release
@@ -241,7 +241,7 @@ arm-musl:
only: *release-only
tags:
- arm32
- image: elixir:1.10.3-alpine
+ image: arm32v7/elixir:1.10.3-alpine
cache: *release-cache
variables: *release-variables
before_script: *before-release-musl
@@ -253,7 +253,7 @@ arm64:
only: *release-only
tags:
- arm
- image: elixir:1.10.3
+ image: arm64v8/elixir:1.10.3
cache: *release-cache
variables: *release-variables
before_script: *before-release
@@ -265,8 +265,7 @@ arm64-musl:
only: *release-only
tags:
- arm
- # TODO: Replace with upstream image when 1.9.0 comes out
- image: elixir:1.10.3-alpine
+ image: arm64v8/elixir:1.10.3-alpine
cache: *release-cache
variables: *release-variables
before_script: *before-release-musl
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 33ff9a9f0..8658d5440 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -28,6 +28,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Pleroma API: Add `idempotency_key` to the chat message entity that can be used for optimistic message sending.
- Pleroma API: (`GET /api/v1/pleroma/federation_status`) Add a way to get a list of unreachable instances.
- Mastodon API: User and conversation mutes can now auto-expire if `expires_in` parameter was given while adding the mute.
+- Admin API: An endpoint to manage frontends
@@ -41,11 +42,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## Unreleased (Patch)
+
+### Changed
+
+- Fix ability to update Pleroma Chat push notifications with PUT /api/v1/push/subscription and alert type pleroma:chat_mention
+
### Fixed
- Config generation: rename `Pleroma.Upload.Filter.ExifTool` to `Pleroma.Upload.Filter.Exiftool`.
- S3 Uploads with Elixir 1.11.
- Fixed Emoji Reaction activity filtering from blocked and muted accounts
+- Mix task pleroma.user delete_activities for source installations.
## [2.2.0] - 2020-11-12
diff --git a/config/config.exs b/config/config.exs
index 0b8a75aad..1ac140ed0 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -129,7 +129,6 @@
dispatch: [
{:_,
[
- {"/api/fedsocket/v1", Pleroma.Web.FedSockets.IncomingHandler, []},
{"/api/v1/streaming", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
{"/websocket", Phoenix.Endpoint.CowboyWebSocket,
{Phoenix.Transports.WebSocket,
diff --git a/config/description.exs b/config/description.exs
index 0552b37e0..a663d8127 100644
--- a/config/description.exs
+++ b/config/description.exs
@@ -272,19 +272,6 @@
}
]
},
- %{
- group: :pleroma,
- key: :fed_sockets,
- type: :group,
- description: "Websocket based federation",
- children: [
- %{
- key: :enabled,
- type: :boolean,
- description: "Enable FedSockets"
- }
- ]
- },
%{
group: :pleroma,
key: Pleroma.Emails.Mailer,
diff --git a/docs/API/admin_api.md b/docs/API/admin_api.md
index f7b5bcae7..19ac6a65f 100644
--- a/docs/API/admin_api.md
+++ b/docs/API/admin_api.md
@@ -1499,3 +1499,66 @@ Returns the content of the document
"url": "https://example.com/instance/panel.html"
}
```
+
+## `GET /api/pleroma/admin/frontends
+
+### List available frontends
+
+- Response:
+
+```json
+[
+ {
+ "build_url": "https://git.pleroma.social/pleroma/fedi-fe/-/jobs/artifacts/${ref}/download?job=build",
+ "git": "https://git.pleroma.social/pleroma/fedi-fe",
+ "installed": true,
+ "name": "fedi-fe",
+ "ref": "master"
+ },
+ {
+ "build_url": "https://git.pleroma.social/lambadalambda/kenoma/-/jobs/artifacts/${ref}/download?job=build",
+ "git": "https://git.pleroma.social/lambadalambda/kenoma",
+ "installed": false,
+ "name": "kenoma",
+ "ref": "master"
+ }
+]
+```
+
+## `POST /api/pleroma/admin/frontends/install`
+
+### Install a frontend
+
+- Params:
+ - `name`: frontend name, required
+ - `ref`: frontend ref
+ - `file`: path to a frontend zip file
+ - `build_url`: build URL
+ - `build_dir`: build directory
+
+- Response:
+
+```json
+[
+ {
+ "build_url": "https://git.pleroma.social/pleroma/fedi-fe/-/jobs/artifacts/${ref}/download?job=build",
+ "git": "https://git.pleroma.social/pleroma/fedi-fe",
+ "installed": true,
+ "name": "fedi-fe",
+ "ref": "master"
+ },
+ {
+ "build_url": "https://git.pleroma.social/lambadalambda/kenoma/-/jobs/artifacts/${ref}/download?job=build",
+ "git": "https://git.pleroma.social/lambadalambda/kenoma",
+ "installed": false,
+ "name": "kenoma",
+ "ref": "master"
+ }
+]
+```
+
+```json
+{
+ "error": "Could not install frontend"
+}
+```
diff --git a/docs/API/differences_in_mastoapi_responses.md b/docs/API/differences_in_mastoapi_responses.md
index 17999da55..843496482 100644
--- a/docs/API/differences_in_mastoapi_responses.md
+++ b/docs/API/differences_in_mastoapi_responses.md
@@ -233,7 +233,7 @@ Post here request with `grant_type=refresh_token` to obtain new access token. Re
`POST /api/v1/accounts`
-Has theses additional parameters (which are the same as in Pleroma-API):
+Has these additional parameters (which are the same as in Pleroma-API):
- `fullname`: optional
- `bio`: optional
@@ -261,6 +261,16 @@ Has theses additional parameters (which are the same as in Pleroma-API):
- `pleroma.metadata.post_formats`: A list of the allowed post format types
- `vapid_public_key`: The public key needed for push messages
+## Push Subscription
+
+`POST /api/v1/push/subscription`
+`PUT /api/v1/push/subscription`
+
+Permits these additional alert types:
+
+- pleroma:chat_mention
+- pleroma:emoji_reaction
+
## Markers
Has these additional fields under the `pleroma` object:
diff --git a/docs/configuration/cheatsheet.md b/docs/configuration/cheatsheet.md
index ebf95ebc9..4d18ac30a 100644
--- a/docs/configuration/cheatsheet.md
+++ b/docs/configuration/cheatsheet.md
@@ -220,18 +220,6 @@ config :pleroma, :mrf_user_allowlist, %{
* `total_user_limit`: the number of scheduled activities a user is allowed to create in total (Default: `300`)
* `enabled`: whether scheduled activities are sent to the job queue to be executed
-## FedSockets
-FedSockets is an experimental feature allowing for Pleroma backends to federate using a persistant websocket connection as opposed to making each federation a seperate http connection. This feature is currently off by default. It is configurable throught he following options.
-
-### :fedsockets
-* `enabled`: Enables FedSockets for this instance. `false` by default.
-* `connection_duration`: Time an idle websocket is kept open.
-* `rejection_duration`: Failures to connect via FedSockets will not be retried for this period of time.
-* `fed_socket_fetches` and `fed_socket_rejections`: Settings passed to `cachex` for the fetch registry, and rejection stacks. See `Pleroma.Web.FedSockets` for more details.
-
-
-## Frontends
-
### :frontend_configurations
This can be used to configure a keyword list that keeps the configuration data for any kind of frontend. By default, settings for `pleroma_fe` and `masto_fe` are configured. You can find the documentation for `pleroma_fe` configuration into [Pleroma-FE configuration and customization for instance administrators](/frontend/CONFIGURATION/#options).
diff --git a/installation/pleroma.nginx b/installation/pleroma.nginx
index d613befd2..9890cb2b1 100644
--- a/installation/pleroma.nginx
+++ b/installation/pleroma.nginx
@@ -93,9 +93,4 @@ server {
chunked_transfer_encoding on;
proxy_pass http://phoenix;
}
-
- location /api/fedsocket/v1 {
- proxy_request_buffering off;
- proxy_pass http://phoenix/api/fedsocket/v1;
- }
}
diff --git a/lib/mix/pleroma.ex b/lib/mix/pleroma.ex
index 49ba2aae4..3de11efce 100644
--- a/lib/mix/pleroma.ex
+++ b/lib/mix/pleroma.ex
@@ -14,7 +14,7 @@ defmodule Mix.Pleroma do
:swoosh,
:timex
]
- @cachex_children ["object", "user", "scrubber"]
+ @cachex_children ["object", "user", "scrubber", "web_resp"]
@doc "Common functions to be reused in mix tasks"
def start_pleroma do
Pleroma.Config.Holder.save_default()
diff --git a/lib/mix/tasks/pleroma/frontend.ex b/lib/mix/tasks/pleroma/frontend.ex
index cbce81ab9..f15dbc38b 100644
--- a/lib/mix/tasks/pleroma/frontend.ex
+++ b/lib/mix/tasks/pleroma/frontend.ex
@@ -17,8 +17,6 @@ def run(["install", "none" | _args]) do
end
def run(["install", frontend | args]) do
- log_level = Logger.level()
- Logger.configure(level: :warn)
start_pleroma()
{options, [], []} =
@@ -33,109 +31,6 @@ def run(["install", frontend | args]) do
]
)
- instance_static_dir =
- with nil <- options[:static_dir] do
- Pleroma.Config.get!([:instance, :static_dir])
- end
-
- cmd_frontend_info = %{
- "name" => frontend,
- "ref" => options[:ref],
- "build_url" => options[:build_url],
- "build_dir" => options[:build_dir]
- }
-
- config_frontend_info = Pleroma.Config.get([:frontends, :available, frontend], %{})
-
- frontend_info =
- Map.merge(config_frontend_info, cmd_frontend_info, fn _key, config, cmd ->
- # This only overrides things that are actually set
- cmd || config
- end)
-
- ref = frontend_info["ref"]
-
- unless ref do
- raise "No ref given or configured"
- end
-
- dest =
- Path.join([
- instance_static_dir,
- "frontends",
- frontend,
- ref
- ])
-
- fe_label = "#{frontend} (#{ref})"
-
- tmp_dir = Path.join([instance_static_dir, "frontends", "tmp"])
-
- with {_, :ok} <-
- {:download_or_unzip, download_or_unzip(frontend_info, tmp_dir, options[:file])},
- shell_info("Installing #{fe_label} to #{dest}"),
- :ok <- install_frontend(frontend_info, tmp_dir, dest) do
- File.rm_rf!(tmp_dir)
- shell_info("Frontend #{fe_label} installed to #{dest}")
-
- Logger.configure(level: log_level)
- else
- {:download_or_unzip, _} ->
- shell_info("Could not download or unzip the frontend")
-
- _e ->
- shell_info("Could not install the frontend")
- end
- end
-
- defp download_or_unzip(frontend_info, temp_dir, file) do
- if file do
- with {:ok, zip} <- File.read(Path.expand(file)) do
- unzip(zip, temp_dir)
- end
- else
- download_build(frontend_info, temp_dir)
- end
- end
-
- def unzip(zip, dest) do
- with {:ok, unzipped} <- :zip.unzip(zip, [:memory]) do
- File.rm_rf!(dest)
- File.mkdir_p!(dest)
-
- Enum.each(unzipped, fn {filename, data} ->
- path = filename
-
- new_file_path = Path.join(dest, path)
-
- new_file_path
- |> Path.dirname()
- |> File.mkdir_p!()
-
- File.write!(new_file_path, data)
- end)
-
- :ok
- end
- end
-
- defp download_build(frontend_info, dest) do
- shell_info("Downloading pre-built bundle for #{frontend_info["name"]}")
- url = String.replace(frontend_info["build_url"], "${ref}", frontend_info["ref"])
-
- with {:ok, %{status: 200, body: zip_body}} <-
- Pleroma.HTTP.get(url, [], pool: :media, recv_timeout: 120_000) do
- unzip(zip_body, dest)
- else
- e -> {:error, e}
- end
- end
-
- defp install_frontend(frontend_info, source, dest) do
- from = frontend_info["build_dir"] || "dist"
- File.rm_rf!(dest)
- File.mkdir_p!(dest)
- File.cp_r!(Path.join([source, from]), dest)
- :ok
+ Pleroma.Frontend.install(frontend, options)
end
end
diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex
index 7c4cd9626..8f08a6222 100644
--- a/lib/pleroma/application.ex
+++ b/lib/pleroma/application.ex
@@ -207,8 +207,7 @@ defp dont_run_in_test(_) do
name: Pleroma.Web.Streamer.registry(),
keys: :duplicate,
partitions: System.schedulers_online()
- ]},
- Pleroma.Web.FedSockets.Supervisor
+ ]}
]
end
diff --git a/lib/pleroma/frontend.ex b/lib/pleroma/frontend.ex
new file mode 100644
index 000000000..bf935a728
--- /dev/null
+++ b/lib/pleroma/frontend.ex
@@ -0,0 +1,110 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Frontend do
+ alias Pleroma.Config
+
+ require Logger
+
+ def install(name, opts \\ []) do
+ frontend_info = %{
+ "ref" => opts[:ref],
+ "build_url" => opts[:build_url],
+ "build_dir" => opts[:build_dir]
+ }
+
+ frontend_info =
+ [:frontends, :available, name]
+ |> Config.get(%{})
+ |> Map.merge(frontend_info, fn _key, config, cmd ->
+ # This only overrides things that are actually set
+ cmd || config
+ end)
+
+ ref = frontend_info["ref"]
+
+ unless ref do
+ raise "No ref given or configured"
+ end
+
+ dest = Path.join([dir(), name, ref])
+
+ label = "#{name} (#{ref})"
+ tmp_dir = Path.join(dir(), "tmp")
+
+ with {_, :ok} <-
+ {:download_or_unzip, download_or_unzip(frontend_info, tmp_dir, opts[:file])},
+ Logger.info("Installing #{label} to #{dest}"),
+ :ok <- install_frontend(frontend_info, tmp_dir, dest) do
+ File.rm_rf!(tmp_dir)
+ Logger.info("Frontend #{label} installed to #{dest}")
+ else
+ {:download_or_unzip, _} ->
+ Logger.info("Could not download or unzip the frontend")
+ {:error, "Could not download or unzip the frontend"}
+
+ _e ->
+ Logger.info("Could not install the frontend")
+ {:error, "Could not install the frontend"}
+ end
+ end
+
+ def dir(opts \\ []) do
+ if is_nil(opts[:static_dir]) do
+ Pleroma.Config.get!([:instance, :static_dir])
+ else
+ opts[:static_dir]
+ end
+ |> Path.join("frontends")
+ end
+
+ defp download_or_unzip(frontend_info, temp_dir, nil),
+ do: download_build(frontend_info, temp_dir)
+
+ defp download_or_unzip(_frontend_info, temp_dir, file) do
+ with {:ok, zip} <- File.read(Path.expand(file)) do
+ unzip(zip, temp_dir)
+ end
+ end
+
+ def unzip(zip, dest) do
+ with {:ok, unzipped} <- :zip.unzip(zip, [:memory]) do
+ File.rm_rf!(dest)
+ File.mkdir_p!(dest)
+
+ Enum.each(unzipped, fn {filename, data} ->
+ path = filename
+
+ new_file_path = Path.join(dest, path)
+
+ new_file_path
+ |> Path.dirname()
+ |> File.mkdir_p!()
+
+ File.write!(new_file_path, data)
+ end)
+ end
+ end
+
+ defp download_build(frontend_info, dest) do
+ Logger.info("Downloading pre-built bundle for #{frontend_info["name"]}")
+ url = String.replace(frontend_info["build_url"], "${ref}", frontend_info["ref"])
+
+ with {:ok, %{status: 200, body: zip_body}} <-
+ Pleroma.HTTP.get(url, [], pool: :media, recv_timeout: 120_000) do
+ unzip(zip_body, dest)
+ else
+ {:error, e} -> {:error, e}
+ e -> {:error, e}
+ end
+ end
+
+ defp install_frontend(frontend_info, source, dest) do
+ from = frontend_info["build_dir"] || "dist"
+ File.rm_rf!(dest)
+ File.mkdir_p!(dest)
+ File.cp_r!(Path.join([source, from]), dest)
+ :ok
+ end
+end
diff --git a/lib/pleroma/object/fetcher.ex b/lib/pleroma/object/fetcher.ex
index ae4301738..20d8f687d 100644
--- a/lib/pleroma/object/fetcher.ex
+++ b/lib/pleroma/object/fetcher.ex
@@ -12,7 +12,6 @@ defmodule Pleroma.Object.Fetcher do
alias Pleroma.Web.ActivityPub.ObjectValidator
alias Pleroma.Web.ActivityPub.Transmogrifier
alias Pleroma.Web.Federator
- alias Pleroma.Web.FedSockets
require Logger
require Pleroma.Constants
@@ -183,16 +182,16 @@ defp maybe_date_fetch(headers, date) do
end
end
- def fetch_and_contain_remote_object_from_id(prm, opts \\ [])
+ def fetch_and_contain_remote_object_from_id(id)
- def fetch_and_contain_remote_object_from_id(%{"id" => id}, opts),
- do: fetch_and_contain_remote_object_from_id(id, opts)
+ def fetch_and_contain_remote_object_from_id(%{"id" => id}),
+ do: fetch_and_contain_remote_object_from_id(id)
- def fetch_and_contain_remote_object_from_id(id, opts) when is_binary(id) do
+ def fetch_and_contain_remote_object_from_id(id) when is_binary(id) do
Logger.debug("Fetching object #{id} via AP")
with {:scheme, true} <- {:scheme, String.starts_with?(id, "http")},
- {:ok, body} <- get_object(id, opts),
+ {:ok, body} <- get_object(id),
{:ok, data} <- safe_json_decode(body),
:ok <- Containment.contain_origin_from_id(id, data) do
{:ok, data}
@@ -208,22 +207,10 @@ def fetch_and_contain_remote_object_from_id(id, opts) when is_binary(id) do
end
end
- def fetch_and_contain_remote_object_from_id(_id, _opts),
+ def fetch_and_contain_remote_object_from_id(_id),
do: {:error, "id must be a string"}
- defp get_object(id, opts) do
- with false <- Keyword.get(opts, :force_http, false),
- {:ok, fedsocket} <- FedSockets.get_or_create_fed_socket(id) do
- Logger.debug("fetching via fedsocket - #{inspect(id)}")
- FedSockets.fetch(fedsocket, id)
- else
- _other ->
- Logger.debug("fetching via http - #{inspect(id)}")
- get_object_http(id)
- end
- end
-
- defp get_object_http(id) do
+ defp get_object(id) do
date = Pleroma.Signature.signed_date()
headers =
diff --git a/lib/pleroma/signature.ex b/lib/pleroma/signature.ex
index e388993b7..3aa6909d2 100644
--- a/lib/pleroma/signature.ex
+++ b/lib/pleroma/signature.ex
@@ -39,7 +39,7 @@ def key_id_to_actor_id(key_id) do
def fetch_public_key(conn) do
with %{"keyId" => kid} <- HTTPSignatures.signature_for_conn(conn),
{:ok, actor_id} <- key_id_to_actor_id(kid),
- {:ok, public_key} <- User.get_public_key_for_ap_id(actor_id, force_http: true) do
+ {:ok, public_key} <- User.get_public_key_for_ap_id(actor_id) do
{:ok, public_key}
else
e ->
@@ -50,8 +50,8 @@ def fetch_public_key(conn) do
def refetch_public_key(conn) do
with %{"keyId" => kid} <- HTTPSignatures.signature_for_conn(conn),
{:ok, actor_id} <- key_id_to_actor_id(kid),
- {:ok, _user} <- ActivityPub.make_user_from_ap_id(actor_id, force_http: true),
- {:ok, public_key} <- User.get_public_key_for_ap_id(actor_id, force_http: true) do
+ {:ok, _user} <- ActivityPub.make_user_from_ap_id(actor_id),
+ {:ok, public_key} <- User.get_public_key_for_ap_id(actor_id) do
{:ok, public_key}
else
e ->
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 66f5efca7..bcd5256c8 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -1789,12 +1789,12 @@ def html_filter_policy(%User{no_rich_text: true}) do
def html_filter_policy(_), do: Config.get([:markup, :scrub_policy])
- def fetch_by_ap_id(ap_id, opts \\ []), do: ActivityPub.make_user_from_ap_id(ap_id, opts)
+ def fetch_by_ap_id(ap_id), do: ActivityPub.make_user_from_ap_id(ap_id)
- def get_or_fetch_by_ap_id(ap_id, opts \\ []) do
+ def get_or_fetch_by_ap_id(ap_id) do
cached_user = get_cached_by_ap_id(ap_id)
- maybe_fetched_user = needs_update?(cached_user) && fetch_by_ap_id(ap_id, opts)
+ maybe_fetched_user = needs_update?(cached_user) && fetch_by_ap_id(ap_id)
case {cached_user, maybe_fetched_user} do
{_, {:ok, %User{} = user}} ->
@@ -1867,8 +1867,8 @@ def public_key(%{public_key: public_key_pem}) when is_binary(public_key_pem) do
def public_key(_), do: {:error, "key not found"}
- def get_public_key_for_ap_id(ap_id, opts \\ []) do
- with {:ok, %User{} = user} <- get_or_fetch_by_ap_id(ap_id, opts),
+ def get_public_key_for_ap_id(ap_id) do
+ with {:ok, %User{} = user} <- get_or_fetch_by_ap_id(ap_id),
{:ok, public_key} <- public_key(user) do
{:ok, public_key}
else
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index d8f685d38..35f71b7ae 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -1289,12 +1289,10 @@ defp object_to_user_data(data) do
def fetch_follow_information_for_user(user) do
with {:ok, following_data} <-
- Fetcher.fetch_and_contain_remote_object_from_id(user.following_address,
- force_http: true
- ),
+ Fetcher.fetch_and_contain_remote_object_from_id(user.following_address),
{:ok, hide_follows} <- collection_private(following_data),
{:ok, followers_data} <-
- Fetcher.fetch_and_contain_remote_object_from_id(user.follower_address, force_http: true),
+ Fetcher.fetch_and_contain_remote_object_from_id(user.follower_address),
{:ok, hide_followers} <- collection_private(followers_data) do
{:ok,
%{
@@ -1368,8 +1366,8 @@ def user_data_from_user_object(data) do
end
end
- def fetch_and_prepare_user_from_ap_id(ap_id, opts \\ []) do
- with {:ok, data} <- Fetcher.fetch_and_contain_remote_object_from_id(ap_id, opts),
+ def fetch_and_prepare_user_from_ap_id(ap_id) do
+ with {:ok, data} <- Fetcher.fetch_and_contain_remote_object_from_id(ap_id),
{:ok, data} <- user_data_from_user_object(data) do
{:ok, maybe_update_follow_information(data)}
else
@@ -1412,13 +1410,13 @@ def maybe_handle_clashing_nickname(data) do
end
end
- def make_user_from_ap_id(ap_id, opts \\ []) do
+ def make_user_from_ap_id(ap_id) do
user = User.get_cached_by_ap_id(ap_id)
if user && !User.ap_enabled?(user) do
Transmogrifier.upgrade_user_from_ap_id(ap_id)
else
- with {:ok, data} <- fetch_and_prepare_user_from_ap_id(ap_id, opts) do
+ with {:ok, data} <- fetch_and_prepare_user_from_ap_id(ap_id) do
if user do
user
|> User.remote_user_changeset(data)
diff --git a/lib/pleroma/web/activity_pub/publisher.ex b/lib/pleroma/web/activity_pub/publisher.ex
index a2930c1cd..5ab3562bf 100644
--- a/lib/pleroma/web/activity_pub/publisher.ex
+++ b/lib/pleroma/web/activity_pub/publisher.ex
@@ -13,7 +13,6 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
alias Pleroma.User
alias Pleroma.Web.ActivityPub.Relay
alias Pleroma.Web.ActivityPub.Transmogrifier
- alias Pleroma.Web.FedSockets
require Pleroma.Constants
@@ -50,28 +49,6 @@ def is_representable?(%Activity{} = activity) do
"""
def publish_one(%{inbox: inbox, json: json, actor: %User{} = actor, id: id} = params) do
Logger.debug("Federating #{id} to #{inbox}")
-
- case FedSockets.get_or_create_fed_socket(inbox) do
- {:ok, fedsocket} ->
- Logger.debug("publishing via fedsockets - #{inspect(inbox)}")
- FedSockets.publish(fedsocket, json)
-
- _ ->
- Logger.debug("publishing via http - #{inspect(inbox)}")
- http_publish(inbox, actor, json, params)
- end
- end
-
- def publish_one(%{actor_id: actor_id} = params) do
- actor = User.get_cached_by_id(actor_id)
-
- params
- |> Map.delete(:actor_id)
- |> Map.put(:actor, actor)
- |> publish_one()
- end
-
- defp http_publish(inbox, actor, json, params) do
uri = %{path: path} = URI.parse(inbox)
digest = "SHA-256=" <> (:crypto.hash(:sha256, json) |> Base.encode64())
@@ -110,6 +87,15 @@ defp http_publish(inbox, actor, json, params) do
end
end
+ def publish_one(%{actor_id: actor_id} = params) do
+ actor = User.get_cached_by_id(actor_id)
+
+ params
+ |> Map.delete(:actor_id)
+ |> Map.put(:actor, actor)
+ |> publish_one()
+ end
+
defp signature_host(%URI{port: port, scheme: scheme, host: host}) do
if port == URI.default_port(scheme) do
host
diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
index 0bcd1db22..565d32433 100644
--- a/lib/pleroma/web/activity_pub/transmogrifier.ex
+++ b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -1008,7 +1008,7 @@ def perform(:user_upgrade, user) do
def upgrade_user_from_ap_id(ap_id) do
with %User{local: false} = user <- User.get_cached_by_ap_id(ap_id),
- {:ok, data} <- ActivityPub.fetch_and_prepare_user_from_ap_id(ap_id, force_http: true),
+ {:ok, data} <- ActivityPub.fetch_and_prepare_user_from_ap_id(ap_id),
{:ok, user} <- update_user(user, data) do
TransmogrifierWorker.enqueue("user_upgrade", %{"user_id" => user.id})
{:ok, user}
diff --git a/lib/pleroma/web/admin_api/controllers/frontend_controller.ex b/lib/pleroma/web/admin_api/controllers/frontend_controller.ex
new file mode 100644
index 000000000..fac3522b8
--- /dev/null
+++ b/lib/pleroma/web/admin_api/controllers/frontend_controller.ex
@@ -0,0 +1,40 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.AdminAPI.FrontendController do
+ use Pleroma.Web, :controller
+
+ alias Pleroma.Config
+ alias Pleroma.Web.Plugs.OAuthScopesPlug
+
+ plug(Pleroma.Web.ApiSpec.CastAndValidate)
+ plug(OAuthScopesPlug, %{scopes: ["write"], admin: true} when action == :install)
+ plug(OAuthScopesPlug, %{scopes: ["read"], admin: true} when action == :index)
+ action_fallback(Pleroma.Web.AdminAPI.FallbackController)
+
+ defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.Admin.FrontendOperation
+
+ def index(conn, _params) do
+ installed = installed()
+
+ frontends =
+ [:frontends, :available]
+ |> Config.get([])
+ |> Enum.map(fn {name, desc} ->
+ Map.put(desc, "installed", name in installed)
+ end)
+
+ render(conn, "index.json", frontends: frontends)
+ end
+
+ def install(%{body_params: params} = conn, _params) do
+ with :ok <- Pleroma.Frontend.install(params.name, Map.delete(params, :name)) do
+ index(conn, %{})
+ end
+ end
+
+ defp installed do
+ File.ls!(Pleroma.Frontend.dir())
+ end
+end
diff --git a/lib/pleroma/web/admin_api/views/frontend_view.ex b/lib/pleroma/web/admin_api/views/frontend_view.ex
new file mode 100644
index 000000000..374841d0b
--- /dev/null
+++ b/lib/pleroma/web/admin_api/views/frontend_view.ex
@@ -0,0 +1,21 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.AdminAPI.FrontendView do
+ use Pleroma.Web, :view
+
+ def render("index.json", %{frontends: frontends}) do
+ render_many(frontends, __MODULE__, "show.json")
+ end
+
+ def render("show.json", %{frontend: frontend}) do
+ %{
+ name: frontend["name"],
+ git: frontend["git"],
+ build_url: frontend["build_url"],
+ ref: frontend["ref"],
+ installed: frontend["installed"]
+ }
+ end
+end
diff --git a/lib/pleroma/web/api_spec/operations/admin/frontend_operation.ex b/lib/pleroma/web/api_spec/operations/admin/frontend_operation.ex
new file mode 100644
index 000000000..96d4cdee7
--- /dev/null
+++ b/lib/pleroma/web/api_spec/operations/admin/frontend_operation.ex
@@ -0,0 +1,85 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ApiSpec.Admin.FrontendOperation do
+ alias OpenApiSpex.Operation
+ alias OpenApiSpex.Schema
+ alias Pleroma.Web.ApiSpec.Schemas.ApiError
+
+ import Pleroma.Web.ApiSpec.Helpers
+
+ def open_api_operation(action) do
+ operation = String.to_existing_atom("#{action}_operation")
+ apply(__MODULE__, operation, [])
+ end
+
+ def index_operation do
+ %Operation{
+ tags: ["Admin", "Reports"],
+ summary: "Get a list of available frontends",
+ operationId: "AdminAPI.FrontendController.index",
+ security: [%{"oAuth" => ["read"]}],
+ responses: %{
+ 200 => Operation.response("Response", "application/json", list_of_frontends()),
+ 403 => Operation.response("Forbidden", "application/json", ApiError)
+ }
+ }
+ end
+
+ def install_operation do
+ %Operation{
+ tags: ["Admin", "Reports"],
+ summary: "Install a frontend",
+ operationId: "AdminAPI.FrontendController.install",
+ security: [%{"oAuth" => ["read"]}],
+ requestBody: request_body("Parameters", install_request(), required: true),
+ responses: %{
+ 200 => Operation.response("Response", "application/json", list_of_frontends()),
+ 403 => Operation.response("Forbidden", "application/json", ApiError),
+ 400 => Operation.response("Error", "application/json", ApiError)
+ }
+ }
+ end
+
+ defp list_of_frontends do
+ %Schema{
+ type: :array,
+ items: %Schema{
+ type: :object,
+ properties: %{
+ name: %Schema{type: :string},
+ git: %Schema{type: :string, format: :uri, nullable: true},
+ build_url: %Schema{type: :string, format: :uri, nullable: true},
+ ref: %Schema{type: :string},
+ installed: %Schema{type: :boolean}
+ }
+ }
+ }
+ end
+
+ defp install_request do
+ %Schema{
+ title: "FrontendInstallRequest",
+ type: :object,
+ required: [:name],
+ properties: %{
+ name: %Schema{
+ type: :string
+ },
+ ref: %Schema{
+ type: :string
+ },
+ file: %Schema{
+ type: :string
+ },
+ build_url: %Schema{
+ type: :string
+ },
+ build_dir: %Schema{
+ type: :string
+ }
+ }
+ }
+ end
+end
diff --git a/lib/pleroma/web/api_spec/operations/subscription_operation.ex b/lib/pleroma/web/api_spec/operations/subscription_operation.ex
index 775dd795d..67c7ea8f3 100644
--- a/lib/pleroma/web/api_spec/operations/subscription_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/subscription_operation.ex
@@ -146,6 +146,11 @@ defp create_request do
allOf: [BooleanLike],
nullable: true,
description: "Receive chat notifications?"
+ },
+ "pleroma:emoji_reaction": %Schema{
+ allOf: [BooleanLike],
+ nullable: true,
+ description: "Receive emoji reaction notifications?"
}
}
}
@@ -210,6 +215,16 @@ defp update_request do
allOf: [BooleanLike],
nullable: true,
description: "Receive poll notifications?"
+ },
+ "pleroma:chat_mention": %Schema{
+ allOf: [BooleanLike],
+ nullable: true,
+ description: "Receive chat notifications?"
+ },
+ "pleroma:emoji_reaction": %Schema{
+ allOf: [BooleanLike],
+ nullable: true,
+ description: "Receive emoji reaction notifications?"
}
}
}
diff --git a/lib/pleroma/web/fed_sockets.ex b/lib/pleroma/web/fed_sockets.ex
deleted file mode 100644
index 1fd5899c8..000000000
--- a/lib/pleroma/web/fed_sockets.ex
+++ /dev/null
@@ -1,185 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.FedSockets do
- @moduledoc """
- This documents the FedSockets framework. A framework for federating
- ActivityPub objects between servers via persistant WebSocket connections.
-
- FedSockets allow servers to authenticate on first contact and maintain that
- connection, eliminating the need to authenticate every time data needs to be shared.
-
- ## Protocol
- FedSockets currently support 2 types of data transfer:
- * `publish` method which doesn't require a response
- * `fetch` method requires a response be sent
-
- ### Publish
- The publish operation sends a json encoded map of the shape:
- %{action: :publish, data: json}
- and accepts (but does not require) a reply of form:
- %{"action" => "publish_reply"}
-
- The outgoing params represent
- * data: ActivityPub object encoded into json
-
-
- ### Fetch
- The fetch operation sends a json encoded map of the shape:
- %{action: :fetch, data: id, uuid: fetch_uuid}
- and requires a reply of form:
- %{"action" => "fetch_reply", "uuid" => uuid, "data" => data}
-
- The outgoing params represent
- * id: an ActivityPub object URI
- * uuid: a unique uuid generated by the sender
-
- The reply params represent
- * data: an ActivityPub object encoded into json
- * uuid: the uuid sent along with the fetch request
-
- ## Examples
- Clients of FedSocket transfers shouldn't need to use any of the functions outside of this module.
-
- A typical publish operation can be performed through the following code, and a fetch operation in a similar manner.
-
- case FedSockets.get_or_create_fed_socket(inbox) do
- {:ok, fedsocket} ->
- FedSockets.publish(fedsocket, json)
-
- _ ->
- alternative_publish(inbox, actor, json, params)
- end
-
- ## Configuration
- FedSockets have the following config settings
-
- config :pleroma, :fed_sockets,
- enabled: true,
- ping_interval: :timer.seconds(15),
- connection_duration: :timer.hours(1),
- rejection_duration: :timer.hours(1),
- fed_socket_fetches: [
- default: 12_000,
- interval: 3_000,
- lazy: false
- ]
- * enabled - turn FedSockets on or off with this flag. Can be toggled at runtime.
- * connection_duration - How long a FedSocket can sit idle before it's culled.
- * rejection_duration - After failing to make a FedSocket connection a host will be excluded
- from further connections for this amount of time
- * fed_socket_fetches - Use these parameters to pass options to the Cachex queue backing the FetchRegistry
- * fed_socket_rejections - Use these parameters to pass options to the Cachex queue backing the FedRegistry
-
- Cachex options are
- * default: the minimum amount of time a fetch can wait before it times out.
- * interval: the interval between checks for timed out entries. This plus the default represent the maximum time allowed
- * lazy: leave at false for consistant and fast lookups, set to true for stricter timeout enforcement
-
- """
- require Logger
-
- alias Pleroma.Web.FedSockets.FedRegistry
- alias Pleroma.Web.FedSockets.FedSocket
- alias Pleroma.Web.FedSockets.SocketInfo
-
- @doc """
- returns a FedSocket for the given origin. Will reuse an existing one or create a new one.
-
- address is expected to be a fully formed URL such as:
- "http://www.example.com" or "http://www.example.com:8080"
-
- It can and usually does include additional path parameters,
- but these are ignored as the FedSockets are organized by host and port info alone.
- """
- def get_or_create_fed_socket(address) do
- with {:cache, {:error, :missing}} <- {:cache, get_fed_socket(address)},
- {:connect, {:ok, _pid}} <- {:connect, FedSocket.connect_to_host(address)},
- {:cache, {:ok, fed_socket}} <- {:cache, get_fed_socket(address)} do
- Logger.debug("fedsocket created for - #{inspect(address)}")
- {:ok, fed_socket}
- else
- {:cache, {:ok, socket}} ->
- Logger.debug("fedsocket found in cache - #{inspect(address)}")
- {:ok, socket}
-
- {:cache, {:error, :rejected} = e} ->
- e
-
- {:connect, {:error, _host}} ->
- Logger.debug("set host rejected for - #{inspect(address)}")
- FedRegistry.set_host_rejected(address)
- {:error, :rejected}
-
- {_, {:error, :disabled}} ->
- {:error, :disabled}
-
- {_, {:error, reason}} ->
- Logger.warn("get_or_create_fed_socket error - #{inspect(reason)}")
- {:error, reason}
- end
- end
-
- @doc """
- returns a FedSocket for the given origin. Will not create a new FedSocket if one does not exist.
-
- address is expected to be a fully formed URL such as:
- "http://www.example.com" or "http://www.example.com:8080"
- """
- def get_fed_socket(address) do
- origin = SocketInfo.origin(address)
-
- with {:config, true} <- {:config, Pleroma.Config.get([:fed_sockets, :enabled], false)},
- {:ok, socket} <- FedRegistry.get_fed_socket(origin) do
- {:ok, socket}
- else
- {:config, _} ->
- {:error, :disabled}
-
- {:error, :rejected} ->
- Logger.debug("FedSocket previously rejected - #{inspect(origin)}")
- {:error, :rejected}
-
- {:error, reason} ->
- {:error, reason}
- end
- end
-
- @doc """
- Sends the supplied data via the publish protocol.
- It will not block waiting for a reply.
- Returns :ok but this is not an indication of a successful transfer.
-
- the data is expected to be JSON encoded binary data.
- """
- def publish(%SocketInfo{} = fed_socket, json) do
- FedSocket.publish(fed_socket, json)
- end
-
- @doc """
- Sends the supplied data via the fetch protocol.
- It will block waiting for a reply or timeout.
-
- Returns {:ok, object} where object is the requested object (or nil)
- {:error, :timeout} in the event the message was not responded to
-
- the id is expected to be the URI of an ActivityPub object.
- """
- def fetch(%SocketInfo{} = fed_socket, id) do
- FedSocket.fetch(fed_socket, id)
- end
-
- @doc """
- Disconnect all and restart FedSockets.
- This is mainly used in development and testing but could be useful in production.
- """
- def reset do
- FedRegistry
- |> Process.whereis()
- |> Process.exit(:testing)
- end
-
- def uri_for_origin(origin),
- do: "ws://#{origin}/api/fedsocket/v1"
-end
diff --git a/lib/pleroma/web/fed_sockets/fed_registry.ex b/lib/pleroma/web/fed_sockets/fed_registry.ex
deleted file mode 100644
index e00ea69c0..000000000
--- a/lib/pleroma/web/fed_sockets/fed_registry.ex
+++ /dev/null
@@ -1,185 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.FedSockets.FedRegistry do
- @moduledoc """
- The FedRegistry stores the active FedSockets for quick retrieval.
-
- The storage and retrieval portion of the FedRegistry is done in process through
- elixir's `Registry` module for speed and its ability to monitor for terminated processes.
-
- Dropped connections will be caught by `Registry` and deleted. Since the next
- message will initiate a new connection there is no reason to try and reconnect at that point.
-
- Normally outside modules should have no need to call or use the FedRegistry themselves.
- """
-
- alias Pleroma.Web.FedSockets.FedSocket
- alias Pleroma.Web.FedSockets.SocketInfo
-
- require Logger
-
- @default_rejection_duration 15 * 60 * 1000
- @rejections :fed_socket_rejections
-
- @doc """
- Retrieves a FedSocket from the Registry given it's origin.
-
- The origin is expected to be a string identifying the endpoint "example.com" or "example2.com:8080"
-
- Will return:
- * {:ok, fed_socket} for working FedSockets
- * {:error, :rejected} for origins that have been tried and refused within the rejection duration interval
- * {:error, some_reason} usually :missing for unknown origins
- """
- def get_fed_socket(origin) do
- case get_registry_data(origin) do
- {:error, reason} ->
- {:error, reason}
-
- {:ok, %{state: :connected} = socket_info} ->
- {:ok, socket_info}
- end
- end
-
- @doc """
- Adds a connected FedSocket to the Registry.
-
- Always returns {:ok, fed_socket}
- """
- def add_fed_socket(origin, pid \\ nil) do
- origin
- |> SocketInfo.build(pid)
- |> SocketInfo.connect()
- |> add_socket_info
- end
-
- defp add_socket_info(%{origin: origin, state: :connected} = socket_info) do
- case Registry.register(FedSockets.Registry, origin, socket_info) do
- {:ok, _owner} ->
- clear_prior_rejection(origin)
- Logger.debug("fedsocket added: #{inspect(origin)}")
-
- {:ok, socket_info}
-
- {:error, {:already_registered, _pid}} ->
- FedSocket.close(socket_info)
- existing_socket_info = Registry.lookup(FedSockets.Registry, origin)
-
- {:ok, existing_socket_info}
-
- _ ->
- {:error, :error_adding_socket}
- end
- end
-
- @doc """
- Mark this origin as having rejected a connection attempt.
- This will keep it from getting additional connection attempts
- for a period of time specified in the config.
-
- Always returns {:ok, new_reg_data}
- """
- def set_host_rejected(uri) do
- new_reg_data =
- uri
- |> SocketInfo.origin()
- |> get_or_create_registry_data()
- |> set_to_rejected()
- |> save_registry_data()
-
- {:ok, new_reg_data}
- end
-
- @doc """
- Retrieves the FedRegistryData from the Registry given it's origin.
-
- The origin is expected to be a string identifying the endpoint "example.com" or "example2.com:8080"
-
- Will return:
- * {:ok, fed_registry_data} for known origins
- * {:error, :missing} for uniknown origins
- * {:error, :cache_error} indicating some low level runtime issues
- """
- def get_registry_data(origin) do
- case Registry.lookup(FedSockets.Registry, origin) do
- [] ->
- if is_rejected?(origin) do
- Logger.debug("previously rejected fedsocket requested")
- {:error, :rejected}
- else
- {:error, :missing}
- end
-
- [{_pid, %{state: :connected} = socket_info}] ->
- {:ok, socket_info}
-
- _ ->
- {:error, :cache_error}
- end
- end
-
- @doc """
- Retrieves a map of all sockets from the Registry. The keys are the origins and the values are the corresponding SocketInfo
- """
- def list_all do
- (list_all_connected() ++ list_all_rejected())
- |> Enum.into(%{})
- end
-
- defp list_all_connected do
- FedSockets.Registry
- |> Registry.select([{{:"$1", :_, :"$3"}, [], [{{:"$1", :"$3"}}]}])
- end
-
- defp list_all_rejected do
- {:ok, keys} = Cachex.keys(@rejections)
-
- {:ok, registry_data} =
- Cachex.execute(@rejections, fn worker ->
- Enum.map(keys, fn k -> {k, Cachex.get!(worker, k)} end)
- end)
-
- registry_data
- end
-
- defp clear_prior_rejection(origin),
- do: Cachex.del(@rejections, origin)
-
- defp is_rejected?(origin) do
- case Cachex.get(@rejections, origin) do
- {:ok, nil} ->
- false
-
- {:ok, _} ->
- true
- end
- end
-
- defp get_or_create_registry_data(origin) do
- case get_registry_data(origin) do
- {:error, :missing} ->
- %SocketInfo{origin: origin}
-
- {:ok, socket_info} ->
- socket_info
- end
- end
-
- defp save_registry_data(%SocketInfo{origin: origin, state: :connected} = socket_info) do
- {:ok, true} = Registry.update_value(FedSockets.Registry, origin, fn _ -> socket_info end)
- socket_info
- end
-
- defp save_registry_data(%SocketInfo{origin: origin, state: :rejected} = socket_info) do
- rejection_expiration =
- Pleroma.Config.get([:fed_sockets, :rejection_duration], @default_rejection_duration)
-
- {:ok, true} = Cachex.put(@rejections, origin, socket_info, ttl: rejection_expiration)
- socket_info
- end
-
- defp set_to_rejected(%SocketInfo{} = socket_info),
- do: %SocketInfo{socket_info | state: :rejected}
-end
diff --git a/lib/pleroma/web/fed_sockets/fed_socket.ex b/lib/pleroma/web/fed_sockets/fed_socket.ex
deleted file mode 100644
index 98d64e65a..000000000
--- a/lib/pleroma/web/fed_sockets/fed_socket.ex
+++ /dev/null
@@ -1,137 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.FedSockets.FedSocket do
- @moduledoc """
- The FedSocket module abstracts the actions to be taken taken on connections regardless of
- whether the connection started as inbound or outbound.
-
-
- Normally outside modules will have no need to call the FedSocket module directly.
- """
-
- alias Pleroma.Object
- alias Pleroma.Object.Containment
- alias Pleroma.User
- alias Pleroma.Web.ActivityPub.ObjectView
- alias Pleroma.Web.ActivityPub.UserView
- alias Pleroma.Web.ActivityPub.Visibility
- alias Pleroma.Web.FedSockets.FetchRegistry
- alias Pleroma.Web.FedSockets.IngesterWorker
- alias Pleroma.Web.FedSockets.OutgoingHandler
- alias Pleroma.Web.FedSockets.SocketInfo
-
- require Logger
-
- @shake "61dd18f7-f1e6-49a4-939a-a749fcdc1103"
-
- def connect_to_host(uri) do
- case OutgoingHandler.start_link(uri) do
- {:ok, pid} ->
- {:ok, pid}
-
- error ->
- {:error, error}
- end
- end
-
- def close(%SocketInfo{pid: socket_pid}),
- do: Process.send(socket_pid, :close, [])
-
- def publish(%SocketInfo{pid: socket_pid}, json) do
- %{action: :publish, data: json}
- |> Jason.encode!()
- |> send_packet(socket_pid)
- end
-
- def fetch(%SocketInfo{pid: socket_pid}, id) do
- fetch_uuid = FetchRegistry.register_fetch(id)
-
- %{action: :fetch, data: id, uuid: fetch_uuid}
- |> Jason.encode!()
- |> send_packet(socket_pid)
-
- wait_for_fetch_to_return(fetch_uuid, 0)
- end
-
- def receive_package(%SocketInfo{} = fed_socket, json) do
- json
- |> Jason.decode!()
- |> process_package(fed_socket)
- end
-
- defp wait_for_fetch_to_return(uuid, cntr) do
- case FetchRegistry.check_fetch(uuid) do
- {:error, :waiting} ->
- Process.sleep(:math.pow(cntr, 3) |> Kernel.trunc())
- wait_for_fetch_to_return(uuid, cntr + 1)
-
- {:error, :missing} ->
- Logger.error("FedSocket fetch timed out - #{inspect(uuid)}")
- {:error, :timeout}
-
- {:ok, _fr} ->
- FetchRegistry.pop_fetch(uuid)
- end
- end
-
- defp process_package(%{"action" => "publish", "data" => data}, %{origin: origin} = _fed_socket) do
- if Containment.contain_origin(origin, data) do
- IngesterWorker.enqueue("ingest", %{"object" => data})
- end
-
- {:reply, %{"action" => "publish_reply", "status" => "processed"}}
- end
-
- defp process_package(%{"action" => "fetch_reply", "uuid" => uuid, "data" => data}, _fed_socket) do
- FetchRegistry.register_fetch_received(uuid, data)
- {:noreply, nil}
- end
-
- defp process_package(%{"action" => "fetch", "uuid" => uuid, "data" => ap_id}, _fed_socket) do
- {:ok, data} = render_fetched_data(ap_id, uuid)
- {:reply, data}
- end
-
- defp process_package(%{"action" => "publish_reply"}, _fed_socket) do
- {:noreply, nil}
- end
-
- defp process_package(other, _fed_socket) do
- Logger.warn("unknown json packages received #{inspect(other)}")
- {:noreply, nil}
- end
-
- defp render_fetched_data(ap_id, uuid) do
- {:ok,
- %{
- "action" => "fetch_reply",
- "status" => "processed",
- "uuid" => uuid,
- "data" => represent_item(ap_id)
- }}
- end
-
- defp represent_item(ap_id) do
- case User.get_by_ap_id(ap_id) do
- nil ->
- object = Object.get_cached_by_ap_id(ap_id)
-
- if Visibility.is_public?(object) do
- Phoenix.View.render_to_string(ObjectView, "object.json", object: object)
- else
- nil
- end
-
- user ->
- Phoenix.View.render_to_string(UserView, "user.json", user: user)
- end
- end
-
- defp send_packet(data, socket_pid) do
- Process.send(socket_pid, {:send, data}, [])
- end
-
- def shake, do: @shake
-end
diff --git a/lib/pleroma/web/fed_sockets/fetch_registry.ex b/lib/pleroma/web/fed_sockets/fetch_registry.ex
deleted file mode 100644
index 7897f0fc6..000000000
--- a/lib/pleroma/web/fed_sockets/fetch_registry.ex
+++ /dev/null
@@ -1,151 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.FedSockets.FetchRegistry do
- @moduledoc """
- The FetchRegistry acts as a broker for fetch requests and return values.
- This allows calling processes to block while waiting for a reply.
- It doesn't impose it's own process instead using `Cachex` to handle fetches in process, allowing
- multi threaded processes to avoid bottlenecking.
-
- Normally outside modules will have no need to call or use the FetchRegistry themselves.
-
- The `Cachex` parameters can be controlled from the config. Since exact timeout intervals
- aren't necessary the following settings are used by default:
-
- config :pleroma, :fed_sockets,
- fed_socket_fetches: [
- default: 12_000,
- interval: 3_000,
- lazy: false
- ]
-
- """
-
- defmodule FetchRegistryData do
- defstruct uuid: nil,
- sent_json: nil,
- received_json: nil,
- sent_at: nil,
- received_at: nil
- end
-
- alias Ecto.UUID
-
- require Logger
-
- @fetches :fed_socket_fetches
-
- @doc """
- Registers a json request wth the FetchRegistry and returns the identifying UUID.
- """
- def register_fetch(json) do
- %FetchRegistryData{uuid: uuid} =
- json
- |> new_registry_data
- |> save_registry_data
-
- uuid
- end
-
- @doc """
- Reports on the status of a Fetch given the identifying UUID.
-
- Will return
- * {:ok, fetched_object} if a fetch has completed
- * {:error, :waiting} if a fetch is still pending
- * {:error, other_error} usually :missing to indicate a fetch that has timed out
- """
- def check_fetch(uuid) do
- case get_registry_data(uuid) do
- {:ok, %FetchRegistryData{received_at: nil}} ->
- {:error, :waiting}
-
- {:ok, %FetchRegistryData{} = reg_data} ->
- {:ok, reg_data}
-
- e ->
- e
- end
- end
-
- @doc """
- Retrieves the response to a fetch given the identifying UUID.
- The completed fetch will be deleted from the FetchRegistry
-
- Will return
- * {:ok, fetched_object} if a fetch has completed
- * {:error, :waiting} if a fetch is still pending
- * {:error, other_error} usually :missing to indicate a fetch that has timed out
- """
- def pop_fetch(uuid) do
- case check_fetch(uuid) do
- {:ok, %FetchRegistryData{received_json: received_json}} ->
- delete_registry_data(uuid)
- {:ok, received_json}
-
- e ->
- e
- end
- end
-
- @doc """
- This is called to register a fetch has returned.
- It expects the result data along with the UUID that was sent in the request
-
- Will return the fetched object or :error
- """
- def register_fetch_received(uuid, data) do
- case get_registry_data(uuid) do
- {:ok, %FetchRegistryData{received_at: nil} = reg_data} ->
- reg_data
- |> set_fetch_received(data)
- |> save_registry_data()
-
- {:ok, %FetchRegistryData{} = reg_data} ->
- Logger.warn("tried to add fetched data twice - #{uuid}")
- reg_data
-
- {:error, _} ->
- Logger.warn("Error adding fetch to registry - #{uuid}")
- :error
- end
- end
-
- defp new_registry_data(json) do
- %FetchRegistryData{
- uuid: UUID.generate(),
- sent_json: json,
- sent_at: :erlang.monotonic_time(:millisecond)
- }
- end
-
- defp get_registry_data(origin) do
- case Cachex.get(@fetches, origin) do
- {:ok, nil} ->
- {:error, :missing}
-
- {:ok, reg_data} ->
- {:ok, reg_data}
-
- _ ->
- {:error, :cache_error}
- end
- end
-
- defp set_fetch_received(%FetchRegistryData{} = reg_data, data),
- do: %FetchRegistryData{
- reg_data
- | received_at: :erlang.monotonic_time(:millisecond),
- received_json: data
- }
-
- defp save_registry_data(%FetchRegistryData{uuid: uuid} = reg_data) do
- {:ok, true} = Cachex.put(@fetches, uuid, reg_data)
- reg_data
- end
-
- defp delete_registry_data(origin),
- do: {:ok, true} = Cachex.del(@fetches, origin)
-end
diff --git a/lib/pleroma/web/fed_sockets/incoming_handler.ex b/lib/pleroma/web/fed_sockets/incoming_handler.ex
deleted file mode 100644
index 49d0d9d84..000000000
--- a/lib/pleroma/web/fed_sockets/incoming_handler.ex
+++ /dev/null
@@ -1,88 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.FedSockets.IncomingHandler do
- require Logger
-
- alias Pleroma.Web.FedSockets.FedRegistry
- alias Pleroma.Web.FedSockets.FedSocket
- alias Pleroma.Web.FedSockets.SocketInfo
-
- import HTTPSignatures, only: [validate_conn: 1, split_signature: 1]
-
- @behaviour :cowboy_websocket
-
- def init(req, state) do
- shake = FedSocket.shake()
-
- with true <- Pleroma.Config.get([:fed_sockets, :enabled]),
- sec_protocol <- :cowboy_req.header("sec-websocket-protocol", req, nil),
- headers = %{"(request-target)" => ^shake} <- :cowboy_req.headers(req),
- true <- validate_conn(%{req_headers: headers}),
- %{"keyId" => origin} <- split_signature(headers["signature"]) do
- req =
- if is_nil(sec_protocol) do
- req
- else
- :cowboy_req.set_resp_header("sec-websocket-protocol", sec_protocol, req)
- end
-
- {:cowboy_websocket, req, %{origin: origin}, %{}}
- else
- _ ->
- {:ok, req, state}
- end
- end
-
- def websocket_init(%{origin: origin}) do
- case FedRegistry.add_fed_socket(origin) do
- {:ok, socket_info} ->
- {:ok, socket_info}
-
- e ->
- Logger.error("FedSocket websocket_init failed - #{inspect(e)}")
- {:error, inspect(e)}
- end
- end
-
- # Use the ping to check if the connection should be expired
- def websocket_handle(:ping, socket_info) do
- if SocketInfo.expired?(socket_info) do
- {:stop, socket_info}
- else
- {:ok, socket_info, :hibernate}
- end
- end
-
- def websocket_handle({:text, data}, socket_info) do
- socket_info = SocketInfo.touch(socket_info)
-
- case FedSocket.receive_package(socket_info, data) do
- {:noreply, _} ->
- {:ok, socket_info}
-
- {:reply, reply} ->
- {:reply, {:text, Jason.encode!(reply)}, socket_info}
-
- {:error, reason} ->
- Logger.error("incoming error - receive_package: #{inspect(reason)}")
- {:ok, socket_info}
- end
- end
-
- def websocket_info({:send, message}, socket_info) do
- socket_info = SocketInfo.touch(socket_info)
-
- {:reply, {:text, message}, socket_info}
- end
-
- def websocket_info(:close, state) do
- {:stop, state}
- end
-
- def websocket_info(message, state) do
- Logger.debug("#{__MODULE__} unknown message #{inspect(message)}")
- {:ok, state}
- end
-end
diff --git a/lib/pleroma/web/fed_sockets/ingester_worker.ex b/lib/pleroma/web/fed_sockets/ingester_worker.ex
deleted file mode 100644
index 325f2a4ab..000000000
--- a/lib/pleroma/web/fed_sockets/ingester_worker.ex
+++ /dev/null
@@ -1,33 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.FedSockets.IngesterWorker do
- use Pleroma.Workers.WorkerHelper, queue: "ingestion_queue"
- require Logger
-
- alias Pleroma.Web.Federator
-
- @impl Oban.Worker
- def perform(%Job{args: %{"op" => "ingest", "object" => ingestee}}) do
- try do
- ingestee
- |> Jason.decode!()
- |> do_ingestion()
- rescue
- e ->
- Logger.error("IngesterWorker error - #{inspect(e)}")
- e
- end
- end
-
- defp do_ingestion(params) do
- case Federator.incoming_ap_doc(params) do
- {:error, reason} ->
- {:error, reason}
-
- {:ok, object} ->
- {:ok, object}
- end
- end
-end
diff --git a/lib/pleroma/web/fed_sockets/outgoing_handler.ex b/lib/pleroma/web/fed_sockets/outgoing_handler.ex
deleted file mode 100644
index e235a7c43..000000000
--- a/lib/pleroma/web/fed_sockets/outgoing_handler.ex
+++ /dev/null
@@ -1,151 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.FedSockets.OutgoingHandler do
- use GenServer
-
- require Logger
-
- alias Pleroma.Application
- alias Pleroma.Web.ActivityPub.InternalFetchActor
- alias Pleroma.Web.FedSockets
- alias Pleroma.Web.FedSockets.FedRegistry
- alias Pleroma.Web.FedSockets.FedSocket
- alias Pleroma.Web.FedSockets.SocketInfo
-
- def start_link(uri) do
- GenServer.start_link(__MODULE__, %{uri: uri})
- end
-
- def init(%{uri: uri}) do
- case initiate_connection(uri) do
- {:ok, ws_origin, conn_pid} ->
- FedRegistry.add_fed_socket(ws_origin, conn_pid)
-
- {:error, reason} ->
- Logger.debug("Outgoing connection failed - #{inspect(reason)}")
- :ignore
- end
- end
-
- def handle_info({:gun_ws, conn_pid, _ref, {:text, data}}, socket_info) do
- socket_info = SocketInfo.touch(socket_info)
-
- case FedSocket.receive_package(socket_info, data) do
- {:noreply, _} ->
- {:noreply, socket_info}
-
- {:reply, reply} ->
- :gun.ws_send(conn_pid, {:text, Jason.encode!(reply)})
- {:noreply, socket_info}
-
- {:error, reason} ->
- Logger.error("incoming error - receive_package: #{inspect(reason)}")
- {:noreply, socket_info}
- end
- end
-
- def handle_info(:close, state) do
- Logger.debug("Sending close frame !!!!!!!")
- {:close, state}
- end
-
- def handle_info({:gun_down, _pid, _prot, :closed, _}, state) do
- {:stop, :normal, state}
- end
-
- def handle_info({:send, data}, %{conn_pid: conn_pid} = socket_info) do
- socket_info = SocketInfo.touch(socket_info)
- :gun.ws_send(conn_pid, {:text, data})
- {:noreply, socket_info}
- end
-
- def handle_info({:gun_ws, _, _, :pong}, state) do
- {:noreply, state, :hibernate}
- end
-
- def handle_info(msg, state) do
- Logger.debug("#{__MODULE__} unhandled event #{inspect(msg)}")
- {:noreply, state}
- end
-
- def terminate(reason, state) do
- Logger.debug(
- "#{__MODULE__} terminating outgoing connection for #{inspect(state)} for #{inspect(reason)}"
- )
-
- {:ok, state}
- end
-
- def initiate_connection(uri) do
- ws_uri =
- uri
- |> SocketInfo.origin()
- |> FedSockets.uri_for_origin()
-
- %{host: host, port: port, path: path} = URI.parse(ws_uri)
-
- with {:ok, conn_pid} <- :gun.open(to_charlist(host), port, %{protocols: [:http]}),
- {:ok, _} <- :gun.await_up(conn_pid),
- reference <-
- :gun.get(conn_pid, to_charlist(path), [
- {'user-agent', to_charlist(Application.user_agent())}
- ]),
- {:response, :fin, 204, _} <- :gun.await(conn_pid, reference),
- headers <- build_headers(uri),
- ref <- :gun.ws_upgrade(conn_pid, to_charlist(path), headers, %{silence_pings: false}) do
- receive do
- {:gun_upgrade, ^conn_pid, ^ref, [<<"websocket">>], _} ->
- {:ok, ws_uri, conn_pid}
- after
- 15_000 ->
- Logger.debug("Fedsocket timeout connecting to #{inspect(uri)}")
- {:error, :timeout}
- end
- else
- {:response, :nofin, 404, _} ->
- {:error, :fedsockets_not_supported}
-
- e ->
- Logger.debug("Fedsocket error connecting to #{inspect(uri)}")
- {:error, e}
- end
- end
-
- defp build_headers(uri) do
- host_for_sig = uri |> URI.parse() |> host_signature()
-
- shake = FedSocket.shake()
- digest = "SHA-256=" <> (:crypto.hash(:sha256, shake) |> Base.encode64())
- date = Pleroma.Signature.signed_date()
- shake_size = byte_size(shake)
-
- signature_opts = %{
- "(request-target)": shake,
- "content-length": to_charlist("#{shake_size}"),
- date: date,
- digest: digest,
- host: host_for_sig
- }
-
- signature = Pleroma.Signature.sign(InternalFetchActor.get_actor(), signature_opts)
-
- [
- {'signature', to_charlist(signature)},
- {'date', date},
- {'digest', to_charlist(digest)},
- {'content-length', to_charlist("#{shake_size}")},
- {to_charlist("(request-target)"), to_charlist(shake)},
- {'user-agent', to_charlist(Application.user_agent())}
- ]
- end
-
- defp host_signature(%{host: host, scheme: scheme, port: port}) do
- if port == URI.default_port(scheme) do
- host
- else
- "#{host}:#{port}"
- end
- end
-end
diff --git a/lib/pleroma/web/fed_sockets/socket_info.ex b/lib/pleroma/web/fed_sockets/socket_info.ex
deleted file mode 100644
index d6fdffe1a..000000000
--- a/lib/pleroma/web/fed_sockets/socket_info.ex
+++ /dev/null
@@ -1,52 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.FedSockets.SocketInfo do
- defstruct origin: nil,
- pid: nil,
- conn_pid: nil,
- state: :default,
- connected_until: nil
-
- alias Pleroma.Web.FedSockets.SocketInfo
- @default_connection_duration 15 * 60 * 1000
-
- def build(uri, conn_pid \\ nil) do
- uri
- |> build_origin()
- |> build_pids(conn_pid)
- |> touch()
- end
-
- def touch(%SocketInfo{} = socket_info),
- do: %{socket_info | connected_until: new_ttl()}
-
- def connect(%SocketInfo{} = socket_info),
- do: %{socket_info | state: :connected}
-
- def expired?(%{connected_until: connected_until}),
- do: connected_until < :erlang.monotonic_time(:millisecond)
-
- def origin(uri),
- do: build_origin(uri).origin
-
- defp build_pids(socket_info, conn_pid),
- do: struct(socket_info, pid: self(), conn_pid: conn_pid)
-
- defp build_origin(uri) when is_binary(uri),
- do: uri |> URI.parse() |> build_origin
-
- defp build_origin(%{host: host, port: nil, scheme: scheme}),
- do: build_origin(%{host: host, port: URI.default_port(scheme)})
-
- defp build_origin(%{host: host, port: port}),
- do: %SocketInfo{origin: "#{host}:#{port}"}
-
- defp new_ttl do
- connection_duration =
- Pleroma.Config.get([:fed_sockets, :connection_duration], @default_connection_duration)
-
- :erlang.monotonic_time(:millisecond) + connection_duration
- end
-end
diff --git a/lib/pleroma/web/fed_sockets/supervisor.ex b/lib/pleroma/web/fed_sockets/supervisor.ex
deleted file mode 100644
index a5f4bebfb..000000000
--- a/lib/pleroma/web/fed_sockets/supervisor.ex
+++ /dev/null
@@ -1,59 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.FedSockets.Supervisor do
- use Supervisor
- import Cachex.Spec
-
- def start_link(opts) do
- Supervisor.start_link(__MODULE__, opts, name: __MODULE__)
- end
-
- def init(args) do
- children = [
- build_cache(:fed_socket_fetches, args),
- build_cache(:fed_socket_rejections, args),
- {Registry, keys: :unique, name: FedSockets.Registry, meta: [rejected: %{}]}
- ]
-
- opts = [strategy: :one_for_all, name: Pleroma.Web.Streamer.Supervisor]
- Supervisor.init(children, opts)
- end
-
- defp build_cache(name, args) do
- opts = get_opts(name, args)
-
- %{
- id: String.to_atom("#{name}_cache"),
- start: {Cachex, :start_link, [name, opts]},
- type: :worker
- }
- end
-
- defp get_opts(cache_name, args)
- when cache_name in [:fed_socket_fetches, :fed_socket_rejections] do
- default = get_opts_or_config(args, cache_name, :default, 15_000)
- interval = get_opts_or_config(args, cache_name, :interval, 3_000)
- lazy = get_opts_or_config(args, cache_name, :lazy, false)
-
- [expiration: expiration(default: default, interval: interval, lazy: lazy)]
- end
-
- defp get_opts(name, args) do
- Keyword.get(args, name, [])
- end
-
- defp get_opts_or_config(args, name, key, default) do
- args
- |> Keyword.get(name, [])
- |> Keyword.get(key)
- |> case do
- nil ->
- Pleroma.Config.get([:fed_sockets, name, key], default)
-
- value ->
- value
- end
- end
-end
diff --git a/lib/pleroma/web/push/impl.ex b/lib/pleroma/web/push/impl.ex
index da535aa68..82152dffa 100644
--- a/lib/pleroma/web/push/impl.ex
+++ b/lib/pleroma/web/push/impl.ex
@@ -16,7 +16,7 @@ defmodule Pleroma.Web.Push.Impl do
require Logger
import Ecto.Query
- @types ["Create", "Follow", "Announce", "Like", "Move"]
+ @types ["Create", "Follow", "Announce", "Like", "Move", "EmojiReact"]
@doc "Performs sending notifications for user subscriptions"
@spec perform(Notification.t()) :: list(any) | :error | {:error, :unknown_type}
@@ -149,6 +149,15 @@ def format_body(
"@#{actor.nickname} repeated: #{Utils.scrub_html_and_truncate(content, 80)}"
end
+ def format_body(
+ %{activity: %{data: %{"type" => "EmojiReact", "content" => content}}},
+ actor,
+ _object,
+ _mastodon_type
+ ) do
+ "@#{actor.nickname} reacted with #{content}"
+ end
+
def format_body(
%{activity: %{data: %{"type" => type}}} = notification,
actor,
@@ -179,6 +188,7 @@ def format_title(%{type: type}, mastodon_type) do
"reblog" -> "New Repeat"
"favourite" -> "New Favorite"
"pleroma:chat_mention" -> "New Chat Message"
+ "pleroma:emoji_reaction" -> "New Reaction"
type -> "New #{String.capitalize(type || "event")}"
end
end
diff --git a/lib/pleroma/web/push/subscription.ex b/lib/pleroma/web/push/subscription.ex
index 5b5aa0d59..749a573ba 100644
--- a/lib/pleroma/web/push/subscription.ex
+++ b/lib/pleroma/web/push/subscription.ex
@@ -25,7 +25,8 @@ defmodule Pleroma.Web.Push.Subscription do
timestamps()
end
- @supported_alert_types ~w[follow favourite mention reblog pleroma:chat_mention]a
+ # credo:disable-for-next-line Credo.Check.Readability.MaxLineLength
+ @supported_alert_types ~w[follow favourite mention reblog pleroma:chat_mention pleroma:emoji_reaction]a
defp alerts(%{data: %{alerts: alerts}}) do
alerts = Map.take(alerts, @supported_alert_types)
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index 0f0538182..75a885377 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -244,6 +244,9 @@ defmodule Pleroma.Web.Router do
get("/chats/:id/messages", ChatController, :messages)
delete("/chats/:id/messages/:message_id", ChatController, :delete_message)
+ get("/frontends", FrontendController, :index)
+ post("/frontends/install", FrontendController, :install)
+
post("/backups", AdminAPIController, :create_backup)
end
diff --git a/priv/static/adminfe/chunk-03c5.f59788cf.css b/priv/static/adminfe/chunk-03c5.e6a0e2d0.css
similarity index 100%
rename from priv/static/adminfe/chunk-03c5.f59788cf.css
rename to priv/static/adminfe/chunk-03c5.e6a0e2d0.css
diff --git a/priv/static/adminfe/chunk-9d55.e2cb1409.css b/priv/static/adminfe/chunk-0492.15b0611f.css
similarity index 100%
rename from priv/static/adminfe/chunk-9d55.e2cb1409.css
rename to priv/static/adminfe/chunk-0492.15b0611f.css
diff --git a/priv/static/adminfe/chunk-342d.e342722b.css b/priv/static/adminfe/chunk-04b0.7e25cd78.css
similarity index 97%
rename from priv/static/adminfe/chunk-342d.e342722b.css
rename to priv/static/adminfe/chunk-04b0.7e25cd78.css
index b0fd8dcb3..8dfdc0dcf 100644
Binary files a/priv/static/adminfe/chunk-342d.e342722b.css and b/priv/static/adminfe/chunk-04b0.7e25cd78.css differ
diff --git a/priv/static/adminfe/chunk-546f.692d1ab2.css b/priv/static/adminfe/chunk-0537.cd83e5d6.css
similarity index 100%
rename from priv/static/adminfe/chunk-546f.692d1ab2.css
rename to priv/static/adminfe/chunk-0537.cd83e5d6.css
diff --git a/priv/static/adminfe/chunk-170f.fea927c5.css b/priv/static/adminfe/chunk-170f.fea927c5.css
new file mode 100644
index 000000000..a4ab52d51
Binary files /dev/null and b/priv/static/adminfe/chunk-170f.fea927c5.css differ
diff --git a/priv/static/adminfe/chunk-176e.a3c8376d.css b/priv/static/adminfe/chunk-176e.d9a630b2.css
similarity index 100%
rename from priv/static/adminfe/chunk-176e.a3c8376d.css
rename to priv/static/adminfe/chunk-176e.d9a630b2.css
diff --git a/priv/static/adminfe/chunk-521f.b745ee5d.css b/priv/static/adminfe/chunk-1944.731ba892.css
similarity index 62%
rename from priv/static/adminfe/chunk-521f.b745ee5d.css
rename to priv/static/adminfe/chunk-1944.731ba892.css
index 7e8ffb651..6392d8e75 100644
Binary files a/priv/static/adminfe/chunk-521f.b745ee5d.css and b/priv/static/adminfe/chunk-1944.731ba892.css differ
diff --git a/priv/static/adminfe/chunk-654d.94689c39.css b/priv/static/adminfe/chunk-654d.94689c39.css
deleted file mode 100644
index 483d88545..000000000
Binary files a/priv/static/adminfe/chunk-654d.94689c39.css and /dev/null differ
diff --git a/priv/static/adminfe/chunk-68ea9.dac85813.css b/priv/static/adminfe/chunk-68ea9.8331e95e.css
similarity index 100%
rename from priv/static/adminfe/chunk-68ea9.dac85813.css
rename to priv/static/adminfe/chunk-68ea9.8331e95e.css
diff --git a/priv/static/adminfe/chunk-6e81.1c0f2da2.css b/priv/static/adminfe/chunk-6e81.559b76f9.css
similarity index 100%
rename from priv/static/adminfe/chunk-6e81.1c0f2da2.css
rename to priv/static/adminfe/chunk-6e81.559b76f9.css
diff --git a/priv/static/adminfe/chunk-7968.283bc086.css b/priv/static/adminfe/chunk-7968.283bc086.css
new file mode 100644
index 000000000..5d9863d3a
Binary files /dev/null and b/priv/static/adminfe/chunk-7968.283bc086.css differ
diff --git a/priv/static/adminfe/chunk-7c6b.365cbeda.css b/priv/static/adminfe/chunk-7c6b.b633878a.css
similarity index 100%
rename from priv/static/adminfe/chunk-7c6b.365cbeda.css
rename to priv/static/adminfe/chunk-7c6b.b633878a.css
diff --git a/priv/static/adminfe/chunk-850d.cc4f0ac6.css b/priv/static/adminfe/chunk-850d.cc4f0ac6.css
deleted file mode 100644
index 1cb2ead63..000000000
Binary files a/priv/static/adminfe/chunk-850d.cc4f0ac6.css and /dev/null differ
diff --git a/priv/static/adminfe/chunk-8fbb.dd321643.css b/priv/static/adminfe/chunk-8fbb.dd321643.css
new file mode 100644
index 000000000..f50d974bd
Binary files /dev/null and b/priv/static/adminfe/chunk-8fbb.dd321643.css differ
diff --git a/priv/static/adminfe/chunk-3365.201aa8e6.css b/priv/static/adminfe/chunk-ad1e.1a3c5339.css
similarity index 100%
rename from priv/static/adminfe/chunk-3365.201aa8e6.css
rename to priv/static/adminfe/chunk-ad1e.1a3c5339.css
diff --git a/priv/static/adminfe/chunk-commons.c0eb3eb7.css b/priv/static/adminfe/chunk-commons.f7c3d390.css
similarity index 100%
rename from priv/static/adminfe/chunk-commons.c0eb3eb7.css
rename to priv/static/adminfe/chunk-commons.f7c3d390.css
diff --git a/priv/static/adminfe/chunk-d34d.b0dd6fb4.css b/priv/static/adminfe/chunk-e660.9e75af5b.css
similarity index 100%
rename from priv/static/adminfe/chunk-d34d.b0dd6fb4.css
rename to priv/static/adminfe/chunk-e660.9e75af5b.css
diff --git a/priv/static/adminfe/chunk-f364.6b5f3f0d.css b/priv/static/adminfe/chunk-f364.6b5f3f0d.css
new file mode 100644
index 000000000..ec665da84
Binary files /dev/null and b/priv/static/adminfe/chunk-f364.6b5f3f0d.css differ
diff --git a/priv/static/adminfe/chunk-f625.25a6a4ae.css b/priv/static/adminfe/chunk-f625.bcd0ea3b.css
similarity index 100%
rename from priv/static/adminfe/chunk-f625.25a6a4ae.css
rename to priv/static/adminfe/chunk-f625.bcd0ea3b.css
diff --git a/priv/static/adminfe/index.html b/priv/static/adminfe/index.html
index d6b9b22b8..e6af40e97 100644
--- a/priv/static/adminfe/index.html
+++ b/priv/static/adminfe/index.html
@@ -1 +1 @@
-
Admin FE
\ No newline at end of file
+Admin FE
\ No newline at end of file
diff --git a/priv/static/adminfe/static/js/app.69891fda.js b/priv/static/adminfe/static/js/app.69891fda.js
deleted file mode 100644
index 3d04d9273..000000000
Binary files a/priv/static/adminfe/static/js/app.69891fda.js and /dev/null differ
diff --git a/priv/static/adminfe/static/js/app.69891fda.js.map b/priv/static/adminfe/static/js/app.69891fda.js.map
deleted file mode 100644
index 0131793e9..000000000
Binary files a/priv/static/adminfe/static/js/app.69891fda.js.map and /dev/null differ
diff --git a/priv/static/adminfe/static/js/app.c67f9a2f.js b/priv/static/adminfe/static/js/app.c67f9a2f.js
new file mode 100644
index 000000000..65f9d4a29
Binary files /dev/null and b/priv/static/adminfe/static/js/app.c67f9a2f.js differ
diff --git a/priv/static/adminfe/static/js/app.c67f9a2f.js.map b/priv/static/adminfe/static/js/app.c67f9a2f.js.map
new file mode 100644
index 000000000..41b4375aa
Binary files /dev/null and b/priv/static/adminfe/static/js/app.c67f9a2f.js.map differ
diff --git a/priv/static/adminfe/static/js/chunk-03c5.1c694c49.js b/priv/static/adminfe/static/js/chunk-03c5.6de0c4c7.js
similarity index 99%
rename from priv/static/adminfe/static/js/chunk-03c5.1c694c49.js
rename to priv/static/adminfe/static/js/chunk-03c5.6de0c4c7.js
index b4601abae..a89c65572 100644
Binary files a/priv/static/adminfe/static/js/chunk-03c5.1c694c49.js and b/priv/static/adminfe/static/js/chunk-03c5.6de0c4c7.js differ
diff --git a/priv/static/adminfe/static/js/chunk-03c5.1c694c49.js.map b/priv/static/adminfe/static/js/chunk-03c5.6de0c4c7.js.map
similarity index 99%
rename from priv/static/adminfe/static/js/chunk-03c5.1c694c49.js.map
rename to priv/static/adminfe/static/js/chunk-03c5.6de0c4c7.js.map
index 193c65bb1..963ff6dee 100644
Binary files a/priv/static/adminfe/static/js/chunk-03c5.1c694c49.js.map and b/priv/static/adminfe/static/js/chunk-03c5.6de0c4c7.js.map differ
diff --git a/priv/static/adminfe/static/js/chunk-0492.47abe1dc.js b/priv/static/adminfe/static/js/chunk-0492.47abe1dc.js
new file mode 100644
index 000000000..243ecde70
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-0492.47abe1dc.js differ
diff --git a/priv/static/adminfe/static/js/chunk-0492.47abe1dc.js.map b/priv/static/adminfe/static/js/chunk-0492.47abe1dc.js.map
new file mode 100644
index 000000000..f5e0d9ebc
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-0492.47abe1dc.js.map differ
diff --git a/priv/static/adminfe/static/js/chunk-04b0.90c6d24c.js b/priv/static/adminfe/static/js/chunk-04b0.90c6d24c.js
new file mode 100644
index 000000000..9d0352814
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-04b0.90c6d24c.js differ
diff --git a/priv/static/adminfe/static/js/chunk-04b0.90c6d24c.js.map b/priv/static/adminfe/static/js/chunk-04b0.90c6d24c.js.map
new file mode 100644
index 000000000..a9bee3721
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-04b0.90c6d24c.js.map differ
diff --git a/priv/static/adminfe/static/js/chunk-546f.81668ba7.js b/priv/static/adminfe/static/js/chunk-0537.74db16b0.js
similarity index 99%
rename from priv/static/adminfe/static/js/chunk-546f.81668ba7.js
rename to priv/static/adminfe/static/js/chunk-0537.74db16b0.js
index 252991021..35231e562 100644
Binary files a/priv/static/adminfe/static/js/chunk-546f.81668ba7.js and b/priv/static/adminfe/static/js/chunk-0537.74db16b0.js differ
diff --git a/priv/static/adminfe/static/js/chunk-546f.81668ba7.js.map b/priv/static/adminfe/static/js/chunk-0537.74db16b0.js.map
similarity index 99%
rename from priv/static/adminfe/static/js/chunk-546f.81668ba7.js.map
rename to priv/static/adminfe/static/js/chunk-0537.74db16b0.js.map
index 6a9d2a8dc..fa87bd76d 100644
Binary files a/priv/static/adminfe/static/js/chunk-546f.81668ba7.js.map and b/priv/static/adminfe/static/js/chunk-0537.74db16b0.js.map differ
diff --git a/priv/static/adminfe/static/js/chunk-170f.e1d6aac3.js b/priv/static/adminfe/static/js/chunk-170f.e1d6aac3.js
new file mode 100644
index 000000000..d40dc29bd
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-170f.e1d6aac3.js differ
diff --git a/priv/static/adminfe/static/js/chunk-170f.e1d6aac3.js.map b/priv/static/adminfe/static/js/chunk-170f.e1d6aac3.js.map
new file mode 100644
index 000000000..91d3bc70d
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-170f.e1d6aac3.js.map differ
diff --git a/priv/static/adminfe/static/js/chunk-176e.be050aba.js b/priv/static/adminfe/static/js/chunk-176e.f64cb745.js
similarity index 99%
rename from priv/static/adminfe/static/js/chunk-176e.be050aba.js
rename to priv/static/adminfe/static/js/chunk-176e.f64cb745.js
index cab83489b..dd60693da 100644
Binary files a/priv/static/adminfe/static/js/chunk-176e.be050aba.js and b/priv/static/adminfe/static/js/chunk-176e.f64cb745.js differ
diff --git a/priv/static/adminfe/static/js/chunk-176e.be050aba.js.map b/priv/static/adminfe/static/js/chunk-176e.f64cb745.js.map
similarity index 99%
rename from priv/static/adminfe/static/js/chunk-176e.be050aba.js.map
rename to priv/static/adminfe/static/js/chunk-176e.f64cb745.js.map
index bff959cd6..9ee6aa6e4 100644
Binary files a/priv/static/adminfe/static/js/chunk-176e.be050aba.js.map and b/priv/static/adminfe/static/js/chunk-176e.f64cb745.js.map differ
diff --git a/priv/static/adminfe/static/js/chunk-1944.7bed0c4b.js b/priv/static/adminfe/static/js/chunk-1944.7bed0c4b.js
new file mode 100644
index 000000000..87590c6ce
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-1944.7bed0c4b.js differ
diff --git a/priv/static/adminfe/static/js/chunk-1944.7bed0c4b.js.map b/priv/static/adminfe/static/js/chunk-1944.7bed0c4b.js.map
new file mode 100644
index 000000000..23229293e
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-1944.7bed0c4b.js.map differ
diff --git a/priv/static/adminfe/static/js/chunk-342d.479e01dd.js b/priv/static/adminfe/static/js/chunk-342d.479e01dd.js
deleted file mode 100644
index 5ee311c4a..000000000
Binary files a/priv/static/adminfe/static/js/chunk-342d.479e01dd.js and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-342d.479e01dd.js.map b/priv/static/adminfe/static/js/chunk-342d.479e01dd.js.map
deleted file mode 100644
index b73bbb0aa..000000000
Binary files a/priv/static/adminfe/static/js/chunk-342d.479e01dd.js.map and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-521f.748b331d.js b/priv/static/adminfe/static/js/chunk-521f.748b331d.js
deleted file mode 100644
index 570dab224..000000000
Binary files a/priv/static/adminfe/static/js/chunk-521f.748b331d.js and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-521f.748b331d.js.map b/priv/static/adminfe/static/js/chunk-521f.748b331d.js.map
deleted file mode 100644
index 3380bbbd5..000000000
Binary files a/priv/static/adminfe/static/js/chunk-521f.748b331d.js.map and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-654d.653b067f.js b/priv/static/adminfe/static/js/chunk-654d.653b067f.js
deleted file mode 100644
index 209873ec1..000000000
Binary files a/priv/static/adminfe/static/js/chunk-654d.653b067f.js and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-654d.653b067f.js.map b/priv/static/adminfe/static/js/chunk-654d.653b067f.js.map
deleted file mode 100644
index 72aca0e98..000000000
Binary files a/priv/static/adminfe/static/js/chunk-654d.653b067f.js.map and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-68ea9.9821cd6a.js b/priv/static/adminfe/static/js/chunk-68ea9.2b2877d5.js
similarity index 99%
rename from priv/static/adminfe/static/js/chunk-68ea9.9821cd6a.js
rename to priv/static/adminfe/static/js/chunk-68ea9.2b2877d5.js
index 02091ed84..60056454d 100644
Binary files a/priv/static/adminfe/static/js/chunk-68ea9.9821cd6a.js and b/priv/static/adminfe/static/js/chunk-68ea9.2b2877d5.js differ
diff --git a/priv/static/adminfe/static/js/chunk-68ea9.9821cd6a.js.map b/priv/static/adminfe/static/js/chunk-68ea9.2b2877d5.js.map
similarity index 99%
rename from priv/static/adminfe/static/js/chunk-68ea9.9821cd6a.js.map
rename to priv/static/adminfe/static/js/chunk-68ea9.2b2877d5.js.map
index 019cede66..9e26519c3 100644
Binary files a/priv/static/adminfe/static/js/chunk-68ea9.9821cd6a.js.map and b/priv/static/adminfe/static/js/chunk-68ea9.2b2877d5.js.map differ
diff --git a/priv/static/adminfe/static/js/chunk-6e81.ebe9039f.js b/priv/static/adminfe/static/js/chunk-6e81.afade883.js
similarity index 97%
rename from priv/static/adminfe/static/js/chunk-6e81.ebe9039f.js
rename to priv/static/adminfe/static/js/chunk-6e81.afade883.js
index cd79db1d3..3b5dd6c5c 100644
Binary files a/priv/static/adminfe/static/js/chunk-6e81.ebe9039f.js and b/priv/static/adminfe/static/js/chunk-6e81.afade883.js differ
diff --git a/priv/static/adminfe/static/js/chunk-6e81.ebe9039f.js.map b/priv/static/adminfe/static/js/chunk-6e81.afade883.js.map
similarity index 98%
rename from priv/static/adminfe/static/js/chunk-6e81.ebe9039f.js.map
rename to priv/static/adminfe/static/js/chunk-6e81.afade883.js.map
index 10b437760..a0f7fca19 100644
Binary files a/priv/static/adminfe/static/js/chunk-6e81.ebe9039f.js.map and b/priv/static/adminfe/static/js/chunk-6e81.afade883.js.map differ
diff --git a/priv/static/adminfe/static/js/chunk-7968.f51e3292.js b/priv/static/adminfe/static/js/chunk-7968.f51e3292.js
new file mode 100644
index 000000000..dc981706f
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-7968.f51e3292.js differ
diff --git a/priv/static/adminfe/static/js/chunk-7968.f51e3292.js.map b/priv/static/adminfe/static/js/chunk-7968.f51e3292.js.map
new file mode 100644
index 000000000..c2f0726b7
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-7968.f51e3292.js.map differ
diff --git a/priv/static/adminfe/static/js/chunk-7c6b.56a14571.js b/priv/static/adminfe/static/js/chunk-7c6b.34152862.js
similarity index 99%
rename from priv/static/adminfe/static/js/chunk-7c6b.56a14571.js
rename to priv/static/adminfe/static/js/chunk-7c6b.34152862.js
index df9b7d6ac..27d57d3ff 100644
Binary files a/priv/static/adminfe/static/js/chunk-7c6b.56a14571.js and b/priv/static/adminfe/static/js/chunk-7c6b.34152862.js differ
diff --git a/priv/static/adminfe/static/js/chunk-7c6b.56a14571.js.map b/priv/static/adminfe/static/js/chunk-7c6b.34152862.js.map
similarity index 99%
rename from priv/static/adminfe/static/js/chunk-7c6b.56a14571.js.map
rename to priv/static/adminfe/static/js/chunk-7c6b.34152862.js.map
index 6584ba082..78026f5f4 100644
Binary files a/priv/static/adminfe/static/js/chunk-7c6b.56a14571.js.map and b/priv/static/adminfe/static/js/chunk-7c6b.34152862.js.map differ
diff --git a/priv/static/adminfe/static/js/chunk-850d.3e6102c2.js b/priv/static/adminfe/static/js/chunk-850d.3e6102c2.js
deleted file mode 100644
index a2c2df2e7..000000000
Binary files a/priv/static/adminfe/static/js/chunk-850d.3e6102c2.js and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-850d.3e6102c2.js.map b/priv/static/adminfe/static/js/chunk-850d.3e6102c2.js.map
deleted file mode 100644
index 7f7718547..000000000
Binary files a/priv/static/adminfe/static/js/chunk-850d.3e6102c2.js.map and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-8fbb.c847ce9d.js b/priv/static/adminfe/static/js/chunk-8fbb.c847ce9d.js
new file mode 100644
index 000000000..74ffe9194
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-8fbb.c847ce9d.js differ
diff --git a/priv/static/adminfe/static/js/chunk-8fbb.c847ce9d.js.map b/priv/static/adminfe/static/js/chunk-8fbb.c847ce9d.js.map
new file mode 100644
index 000000000..b3c3b5fe8
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-8fbb.c847ce9d.js.map differ
diff --git a/priv/static/adminfe/static/js/chunk-9d55.7af22f45.js b/priv/static/adminfe/static/js/chunk-9d55.7af22f45.js
deleted file mode 100644
index 89d35af79..000000000
Binary files a/priv/static/adminfe/static/js/chunk-9d55.7af22f45.js and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-9d55.7af22f45.js.map b/priv/static/adminfe/static/js/chunk-9d55.7af22f45.js.map
deleted file mode 100644
index fa8694b8e..000000000
Binary files a/priv/static/adminfe/static/js/chunk-9d55.7af22f45.js.map and /dev/null differ
diff --git a/priv/static/adminfe/static/js/chunk-3365.b73c30a8.js b/priv/static/adminfe/static/js/chunk-ad1e.eba9db26.js
similarity index 99%
rename from priv/static/adminfe/static/js/chunk-3365.b73c30a8.js
rename to priv/static/adminfe/static/js/chunk-ad1e.eba9db26.js
index 421bf2a99..82ddd4df2 100644
Binary files a/priv/static/adminfe/static/js/chunk-3365.b73c30a8.js and b/priv/static/adminfe/static/js/chunk-ad1e.eba9db26.js differ
diff --git a/priv/static/adminfe/static/js/chunk-3365.b73c30a8.js.map b/priv/static/adminfe/static/js/chunk-ad1e.eba9db26.js.map
similarity index 99%
rename from priv/static/adminfe/static/js/chunk-3365.b73c30a8.js.map
rename to priv/static/adminfe/static/js/chunk-ad1e.eba9db26.js.map
index d2ad4d9aa..d74c2498f 100644
Binary files a/priv/static/adminfe/static/js/chunk-3365.b73c30a8.js.map and b/priv/static/adminfe/static/js/chunk-ad1e.eba9db26.js.map differ
diff --git a/priv/static/adminfe/static/js/chunk-commons.a6002038.js b/priv/static/adminfe/static/js/chunk-commons.4ae74caa.js
similarity index 99%
rename from priv/static/adminfe/static/js/chunk-commons.a6002038.js
rename to priv/static/adminfe/static/js/chunk-commons.4ae74caa.js
index 2b16da9c7..1ee2ea9e4 100644
Binary files a/priv/static/adminfe/static/js/chunk-commons.a6002038.js and b/priv/static/adminfe/static/js/chunk-commons.4ae74caa.js differ
diff --git a/priv/static/adminfe/static/js/chunk-commons.a6002038.js.map b/priv/static/adminfe/static/js/chunk-commons.4ae74caa.js.map
similarity index 99%
rename from priv/static/adminfe/static/js/chunk-commons.a6002038.js.map
rename to priv/static/adminfe/static/js/chunk-commons.4ae74caa.js.map
index 3c7d78861..41a884d15 100644
Binary files a/priv/static/adminfe/static/js/chunk-commons.a6002038.js.map and b/priv/static/adminfe/static/js/chunk-commons.4ae74caa.js.map differ
diff --git a/priv/static/adminfe/static/js/chunk-d34d.0f06fe76.js b/priv/static/adminfe/static/js/chunk-e660.feca27c4.js
similarity index 97%
rename from priv/static/adminfe/static/js/chunk-d34d.0f06fe76.js
rename to priv/static/adminfe/static/js/chunk-e660.feca27c4.js
index edd221e6e..5659d263e 100644
Binary files a/priv/static/adminfe/static/js/chunk-d34d.0f06fe76.js and b/priv/static/adminfe/static/js/chunk-e660.feca27c4.js differ
diff --git a/priv/static/adminfe/static/js/chunk-d34d.0f06fe76.js.map b/priv/static/adminfe/static/js/chunk-e660.feca27c4.js.map
similarity index 99%
rename from priv/static/adminfe/static/js/chunk-d34d.0f06fe76.js.map
rename to priv/static/adminfe/static/js/chunk-e660.feca27c4.js.map
index 6bcd4ed8b..cfc2e08af 100644
Binary files a/priv/static/adminfe/static/js/chunk-d34d.0f06fe76.js.map and b/priv/static/adminfe/static/js/chunk-e660.feca27c4.js.map differ
diff --git a/priv/static/adminfe/static/js/chunk-f364.1122502b.js b/priv/static/adminfe/static/js/chunk-f364.1122502b.js
new file mode 100644
index 000000000..facad2ed5
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-f364.1122502b.js differ
diff --git a/priv/static/adminfe/static/js/chunk-f364.1122502b.js.map b/priv/static/adminfe/static/js/chunk-f364.1122502b.js.map
new file mode 100644
index 000000000..f89dabe30
Binary files /dev/null and b/priv/static/adminfe/static/js/chunk-f364.1122502b.js.map differ
diff --git a/priv/static/adminfe/static/js/chunk-f625.29237434.js b/priv/static/adminfe/static/js/chunk-f625.904137fd.js
similarity index 99%
rename from priv/static/adminfe/static/js/chunk-f625.29237434.js
rename to priv/static/adminfe/static/js/chunk-f625.904137fd.js
index 522755a98..053590b28 100644
Binary files a/priv/static/adminfe/static/js/chunk-f625.29237434.js and b/priv/static/adminfe/static/js/chunk-f625.904137fd.js differ
diff --git a/priv/static/adminfe/static/js/chunk-f625.29237434.js.map b/priv/static/adminfe/static/js/chunk-f625.904137fd.js.map
similarity index 99%
rename from priv/static/adminfe/static/js/chunk-f625.29237434.js.map
rename to priv/static/adminfe/static/js/chunk-f625.904137fd.js.map
index 4f8774c3a..59c1c274e 100644
Binary files a/priv/static/adminfe/static/js/chunk-f625.29237434.js.map and b/priv/static/adminfe/static/js/chunk-f625.904137fd.js.map differ
diff --git a/priv/static/adminfe/static/js/runtime.8f631d12.js b/priv/static/adminfe/static/js/runtime.8f631d12.js
deleted file mode 100644
index 6fa7d9ee1..000000000
Binary files a/priv/static/adminfe/static/js/runtime.8f631d12.js and /dev/null differ
diff --git a/priv/static/adminfe/static/js/runtime.8f631d12.js.map b/priv/static/adminfe/static/js/runtime.8f631d12.js.map
deleted file mode 100644
index d5c20400e..000000000
Binary files a/priv/static/adminfe/static/js/runtime.8f631d12.js.map and /dev/null differ
diff --git a/priv/static/adminfe/static/js/runtime.ba96836e.js b/priv/static/adminfe/static/js/runtime.ba96836e.js
new file mode 100644
index 000000000..245c7fe20
Binary files /dev/null and b/priv/static/adminfe/static/js/runtime.ba96836e.js differ
diff --git a/priv/static/adminfe/static/js/runtime.ba96836e.js.map b/priv/static/adminfe/static/js/runtime.ba96836e.js.map
new file mode 100644
index 000000000..f3c5a82af
Binary files /dev/null and b/priv/static/adminfe/static/js/runtime.ba96836e.js.map differ
diff --git a/test/pleroma/frontend_test.exs b/test/pleroma/frontend_test.exs
new file mode 100644
index 000000000..223625857
--- /dev/null
+++ b/test/pleroma/frontend_test.exs
@@ -0,0 +1,72 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.FrontendTest do
+ use Pleroma.DataCase
+ alias Pleroma.Frontend
+
+ @dir "test/frontend_static_test"
+
+ setup do
+ File.mkdir_p!(@dir)
+ clear_config([:instance, :static_dir], @dir)
+
+ on_exit(fn ->
+ File.rm_rf(@dir)
+ end)
+ end
+
+ test "it downloads and unzips a known frontend" do
+ clear_config([:frontends, :available], %{
+ "pleroma" => %{
+ "ref" => "fantasy",
+ "name" => "pleroma",
+ "build_url" => "http://gensokyo.2hu/builds/${ref}"
+ }
+ })
+
+ Tesla.Mock.mock(fn %{url: "http://gensokyo.2hu/builds/fantasy"} ->
+ %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/frontend_dist.zip")}
+ end)
+
+ Frontend.install("pleroma")
+
+ assert File.exists?(Path.join([@dir, "frontends", "pleroma", "fantasy", "test.txt"]))
+ end
+
+ test "it also works given a file" do
+ clear_config([:frontends, :available], %{
+ "pleroma" => %{
+ "ref" => "fantasy",
+ "name" => "pleroma",
+ "build_dir" => ""
+ }
+ })
+
+ folder = Path.join([@dir, "frontends", "pleroma", "fantasy"])
+ previously_existing = Path.join([folder, "temp"])
+ File.mkdir_p!(folder)
+ File.write!(previously_existing, "yey")
+ assert File.exists?(previously_existing)
+
+ Frontend.install("pleroma", file: "test/fixtures/tesla_mock/frontend.zip")
+
+ assert File.exists?(Path.join([folder, "test.txt"]))
+ refute File.exists?(previously_existing)
+ end
+
+ test "it downloads and unzips unknown frontends" do
+ Tesla.Mock.mock(fn %{url: "http://gensokyo.2hu/madeup.zip"} ->
+ %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/frontend.zip")}
+ end)
+
+ Frontend.install("unknown",
+ ref: "baka",
+ build_url: "http://gensokyo.2hu/madeup.zip",
+ build_dir: ""
+ )
+
+ assert File.exists?(Path.join([@dir, "frontends", "unknown", "baka", "test.txt"]))
+ end
+end
diff --git a/test/pleroma/web/admin_api/controllers/frontend_controller_test.exs b/test/pleroma/web/admin_api/controllers/frontend_controller_test.exs
new file mode 100644
index 000000000..94873f6db
--- /dev/null
+++ b/test/pleroma/web/admin_api/controllers/frontend_controller_test.exs
@@ -0,0 +1,141 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.AdminAPI.FrontendControllerTest do
+ use Pleroma.Web.ConnCase
+
+ import Pleroma.Factory
+
+ alias Pleroma.Config
+
+ @dir "test/frontend_static_test"
+
+ setup do
+ clear_config([:instance, :static_dir], @dir)
+ File.mkdir_p!(Pleroma.Frontend.dir())
+
+ on_exit(fn ->
+ File.rm_rf(@dir)
+ end)
+
+ admin = insert(:user, is_admin: true)
+ token = insert(:oauth_admin_token, user: admin)
+
+ conn =
+ build_conn()
+ |> assign(:user, admin)
+ |> assign(:token, token)
+
+ {:ok, %{admin: admin, token: token, conn: conn}}
+ end
+
+ describe "GET /api/pleroma/admin/frontends" do
+ test "it lists available frontends", %{conn: conn} do
+ response =
+ conn
+ |> get("/api/pleroma/admin/frontends")
+ |> json_response_and_validate_schema(:ok)
+
+ assert Enum.map(response, & &1["name"]) ==
+ Enum.map(Config.get([:frontends, :available]), fn {_, map} -> map["name"] end)
+
+ refute Enum.any?(response, fn frontend -> frontend["installed"] == true end)
+ end
+ end
+
+ describe "POST /api/pleroma/admin/frontends/install" do
+ test "from available frontends", %{conn: conn} do
+ clear_config([:frontends, :available], %{
+ "pleroma" => %{
+ "ref" => "fantasy",
+ "name" => "pleroma",
+ "build_url" => "http://gensokyo.2hu/builds/${ref}"
+ }
+ })
+
+ Tesla.Mock.mock(fn %{url: "http://gensokyo.2hu/builds/fantasy"} ->
+ %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/frontend_dist.zip")}
+ end)
+
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/frontends/install", %{name: "pleroma"})
+ |> json_response_and_validate_schema(:ok)
+
+ assert File.exists?(Path.join([@dir, "frontends", "pleroma", "fantasy", "test.txt"]))
+
+ response =
+ conn
+ |> get("/api/pleroma/admin/frontends")
+ |> json_response_and_validate_schema(:ok)
+
+ assert response == [
+ %{
+ "build_url" => "http://gensokyo.2hu/builds/${ref}",
+ "git" => nil,
+ "installed" => true,
+ "name" => "pleroma",
+ "ref" => "fantasy"
+ }
+ ]
+ end
+
+ test "from a file", %{conn: conn} do
+ clear_config([:frontends, :available], %{
+ "pleroma" => %{
+ "ref" => "fantasy",
+ "name" => "pleroma",
+ "build_dir" => ""
+ }
+ })
+
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/frontends/install", %{
+ name: "pleroma",
+ file: "test/fixtures/tesla_mock/frontend.zip"
+ })
+ |> json_response_and_validate_schema(:ok)
+
+ assert File.exists?(Path.join([@dir, "frontends", "pleroma", "fantasy", "test.txt"]))
+ end
+
+ test "from an URL", %{conn: conn} do
+ Tesla.Mock.mock(fn %{url: "http://gensokyo.2hu/madeup.zip"} ->
+ %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/frontend.zip")}
+ end)
+
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/frontends/install", %{
+ name: "unknown",
+ ref: "baka",
+ build_url: "http://gensokyo.2hu/madeup.zip",
+ build_dir: ""
+ })
+ |> json_response_and_validate_schema(:ok)
+
+ assert File.exists?(Path.join([@dir, "frontends", "unknown", "baka", "test.txt"]))
+ end
+
+ test "failing returns an error", %{conn: conn} do
+ Tesla.Mock.mock(fn %{url: "http://gensokyo.2hu/madeup.zip"} ->
+ %Tesla.Env{status: 404, body: ""}
+ end)
+
+ result =
+ conn
+ |> put_req_header("content-type", "application/json")
+ |> post("/api/pleroma/admin/frontends/install", %{
+ name: "unknown",
+ ref: "baka",
+ build_url: "http://gensokyo.2hu/madeup.zip",
+ build_dir: ""
+ })
+ |> json_response_and_validate_schema(400)
+
+ assert result == %{"error" => "Could not download or unzip the frontend"}
+ end
+ end
+end
diff --git a/test/pleroma/web/fed_sockets/fed_registry_test.exs b/test/pleroma/web/fed_sockets/fed_registry_test.exs
deleted file mode 100644
index 73aaced46..000000000
--- a/test/pleroma/web/fed_sockets/fed_registry_test.exs
+++ /dev/null
@@ -1,124 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.FedSockets.FedRegistryTest do
- use ExUnit.Case
-
- alias Pleroma.Web.FedSockets
- alias Pleroma.Web.FedSockets.FedRegistry
- alias Pleroma.Web.FedSockets.SocketInfo
-
- @good_domain "http://good.domain"
- @good_domain_origin "good.domain:80"
-
- setup do
- start_supervised({Pleroma.Web.FedSockets.Supervisor, []})
- build_test_socket(@good_domain)
- Process.sleep(10)
-
- :ok
- end
-
- describe "add_fed_socket/1 without conflicting sockets" do
- test "can be added" do
- Process.sleep(10)
- assert {:ok, %SocketInfo{origin: origin}} = FedRegistry.get_fed_socket(@good_domain_origin)
- assert origin == "good.domain:80"
- end
-
- test "multiple origins can be added" do
- build_test_socket("http://anothergood.domain")
- Process.sleep(10)
-
- assert {:ok, %SocketInfo{origin: origin_1}} =
- FedRegistry.get_fed_socket(@good_domain_origin)
-
- assert {:ok, %SocketInfo{origin: origin_2}} =
- FedRegistry.get_fed_socket("anothergood.domain:80")
-
- assert origin_1 == "good.domain:80"
- assert origin_2 == "anothergood.domain:80"
- assert FedRegistry.list_all() |> Enum.count() == 2
- end
- end
-
- describe "add_fed_socket/1 when duplicate sockets conflict" do
- setup do
- build_test_socket(@good_domain)
- build_test_socket(@good_domain)
- Process.sleep(10)
- :ok
- end
-
- test "will be ignored" do
- assert {:ok, %SocketInfo{origin: origin, pid: _pid_one}} =
- FedRegistry.get_fed_socket(@good_domain_origin)
-
- assert origin == "good.domain:80"
-
- assert FedRegistry.list_all() |> Enum.count() == 1
- end
-
- test "the newer process will be closed" do
- pid_two = build_test_socket(@good_domain)
-
- assert {:ok, %SocketInfo{origin: origin, pid: _pid_one}} =
- FedRegistry.get_fed_socket(@good_domain_origin)
-
- assert origin == "good.domain:80"
- Process.sleep(10)
-
- refute Process.alive?(pid_two)
-
- assert FedRegistry.list_all() |> Enum.count() == 1
- end
- end
-
- describe "get_fed_socket/1" do
- test "returns missing for unknown hosts" do
- assert {:error, :missing} = FedRegistry.get_fed_socket("not_a_dmoain")
- end
-
- test "returns rejected for hosts previously rejected" do
- "rejected.domain:80"
- |> FedSockets.uri_for_origin()
- |> FedRegistry.set_host_rejected()
-
- assert {:error, :rejected} = FedRegistry.get_fed_socket("rejected.domain:80")
- end
-
- test "can retrieve a previously added SocketInfo" do
- build_test_socket(@good_domain)
- Process.sleep(10)
- assert {:ok, %SocketInfo{origin: origin}} = FedRegistry.get_fed_socket(@good_domain_origin)
- assert origin == "good.domain:80"
- end
-
- test "removes references to SocketInfos when the process crashes" do
- assert {:ok, %SocketInfo{origin: origin, pid: pid}} =
- FedRegistry.get_fed_socket(@good_domain_origin)
-
- assert origin == "good.domain:80"
-
- Process.exit(pid, :testing)
- Process.sleep(100)
- assert {:error, :missing} = FedRegistry.get_fed_socket(@good_domain_origin)
- end
- end
-
- def build_test_socket(uri) do
- Kernel.spawn(fn -> fed_socket_almost(uri) end)
- end
-
- def fed_socket_almost(origin) do
- FedRegistry.add_fed_socket(origin)
-
- receive do
- :close ->
- :ok
- after
- 5_000 -> :timeout
- end
- end
-end
diff --git a/test/pleroma/web/fed_sockets/fetch_registry_test.exs b/test/pleroma/web/fed_sockets/fetch_registry_test.exs
deleted file mode 100644
index 7bd2d995a..000000000
--- a/test/pleroma/web/fed_sockets/fetch_registry_test.exs
+++ /dev/null
@@ -1,67 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.FedSockets.FetchRegistryTest do
- use ExUnit.Case
-
- alias Pleroma.Web.FedSockets.FetchRegistry
- alias Pleroma.Web.FedSockets.FetchRegistry.FetchRegistryData
-
- @json_message "hello"
- @json_reply "hello back"
-
- setup do
- start_supervised(
- {Pleroma.Web.FedSockets.Supervisor,
- [
- ping_interval: 8,
- connection_duration: 15,
- rejection_duration: 5,
- fed_socket_fetches: [default: 10, interval: 10]
- ]}
- )
-
- :ok
- end
-
- test "fetches can be stored" do
- uuid = FetchRegistry.register_fetch(@json_message)
-
- assert {:error, :waiting} = FetchRegistry.check_fetch(uuid)
- end
-
- test "fetches can return" do
- uuid = FetchRegistry.register_fetch(@json_message)
- task = Task.async(fn -> FetchRegistry.register_fetch_received(uuid, @json_reply) end)
-
- assert {:error, :waiting} = FetchRegistry.check_fetch(uuid)
- Task.await(task)
-
- assert {:ok, %FetchRegistryData{received_json: received_json}} =
- FetchRegistry.check_fetch(uuid)
-
- assert received_json == @json_reply
- end
-
- test "fetches are deleted once popped from stack" do
- uuid = FetchRegistry.register_fetch(@json_message)
- task = Task.async(fn -> FetchRegistry.register_fetch_received(uuid, @json_reply) end)
- Task.await(task)
-
- assert {:ok, %FetchRegistryData{received_json: received_json}} =
- FetchRegistry.check_fetch(uuid)
-
- assert received_json == @json_reply
- assert {:ok, @json_reply} = FetchRegistry.pop_fetch(uuid)
-
- assert {:error, :missing} = FetchRegistry.check_fetch(uuid)
- end
-
- test "fetches can time out" do
- uuid = FetchRegistry.register_fetch(@json_message)
- assert {:error, :waiting} = FetchRegistry.check_fetch(uuid)
- Process.sleep(500)
- assert {:error, :missing} = FetchRegistry.check_fetch(uuid)
- end
-end
diff --git a/test/pleroma/web/fed_sockets/socket_info_test.exs b/test/pleroma/web/fed_sockets/socket_info_test.exs
deleted file mode 100644
index db3d6edcd..000000000
--- a/test/pleroma/web/fed_sockets/socket_info_test.exs
+++ /dev/null
@@ -1,118 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.FedSockets.SocketInfoTest do
- use ExUnit.Case
-
- alias Pleroma.Web.FedSockets
- alias Pleroma.Web.FedSockets.SocketInfo
-
- describe "uri_for_origin" do
- test "provides the fed_socket URL given the origin information" do
- endpoint = "example.com:4000"
- assert FedSockets.uri_for_origin(endpoint) =~ "ws://"
- assert FedSockets.uri_for_origin(endpoint) =~ endpoint
- end
- end
-
- describe "origin" do
- test "will provide the origin field given a url" do
- endpoint = "example.com:4000"
- assert SocketInfo.origin("ws://#{endpoint}") == endpoint
- assert SocketInfo.origin("http://#{endpoint}") == endpoint
- assert SocketInfo.origin("https://#{endpoint}") == endpoint
- end
-
- test "will proide the origin field given a uri" do
- endpoint = "example.com:4000"
- uri = URI.parse("http://#{endpoint}")
-
- assert SocketInfo.origin(uri) == endpoint
- end
- end
-
- describe "touch" do
- test "will update the TTL" do
- endpoint = "example.com:4000"
- socket = SocketInfo.build("ws://#{endpoint}")
- Process.sleep(2)
- touched_socket = SocketInfo.touch(socket)
-
- assert socket.connected_until < touched_socket.connected_until
- end
- end
-
- describe "expired?" do
- setup do
- start_supervised(
- {Pleroma.Web.FedSockets.Supervisor,
- [
- ping_interval: 8,
- connection_duration: 5,
- rejection_duration: 5,
- fed_socket_rejections: [lazy: true]
- ]}
- )
-
- :ok
- end
-
- test "tests if the TTL is exceeded" do
- endpoint = "example.com:4000"
- socket = SocketInfo.build("ws://#{endpoint}")
- refute SocketInfo.expired?(socket)
- Process.sleep(10)
-
- assert SocketInfo.expired?(socket)
- end
- end
-
- describe "creating outgoing connection records" do
- test "can be passed a string" do
- assert %{conn_pid: :pid, origin: _origin} = SocketInfo.build("example.com:4000", :pid)
- end
-
- test "can be passed a URI" do
- uri = URI.parse("http://example.com:4000")
- assert %{conn_pid: :pid, origin: origin} = SocketInfo.build(uri, :pid)
- assert origin =~ "example.com:4000"
- end
-
- test "will include the port number" do
- assert %{conn_pid: :pid, origin: origin} = SocketInfo.build("http://example.com:4000", :pid)
-
- assert origin =~ ":4000"
- end
-
- test "will provide the port if missing" do
- assert %{conn_pid: :pid, origin: "example.com:80"} =
- SocketInfo.build("http://example.com", :pid)
-
- assert %{conn_pid: :pid, origin: "example.com:443"} =
- SocketInfo.build("https://example.com", :pid)
- end
- end
-
- describe "creating incoming connection records" do
- test "can be passed a string" do
- assert %{pid: _, origin: _origin} = SocketInfo.build("example.com:4000")
- end
-
- test "can be passed a URI" do
- uri = URI.parse("example.com:4000")
- assert %{pid: _, origin: _origin} = SocketInfo.build(uri)
- end
-
- test "will include the port number" do
- assert %{pid: _, origin: origin} = SocketInfo.build("http://example.com:4000")
-
- assert origin =~ ":4000"
- end
-
- test "will provide the port if missing" do
- assert %{pid: _, origin: "example.com:80"} = SocketInfo.build("http://example.com")
- assert %{pid: _, origin: "example.com:443"} = SocketInfo.build("https://example.com")
- end
- end
-end
diff --git a/test/pleroma/web/mastodon_api/controllers/subscription_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/subscription_controller_test.exs
index d36bb1ae8..5ef39bdb2 100644
--- a/test/pleroma/web/mastodon_api/controllers/subscription_controller_test.exs
+++ b/test/pleroma/web/mastodon_api/controllers/subscription_controller_test.exs
@@ -45,21 +45,77 @@ defmacro assert_error_when_disable_push(do: yield) do
end
end
- describe "creates push subscription" do
- test "returns error when push disabled ", %{conn: conn} do
+ describe "when disabled" do
+ test "POST returns error", %{conn: conn} do
assert_error_when_disable_push do
conn
- |> post("/api/v1/push/subscription", %{subscription: @sub})
+ |> post("/api/v1/push/subscription", %{
+ "data" => %{"alerts" => %{"mention" => true}},
+ "subscription" => @sub
+ })
|> json_response_and_validate_schema(403)
end
end
+ test "GET returns error", %{conn: conn} do
+ assert_error_when_disable_push do
+ conn
+ |> get("/api/v1/push/subscription", %{})
+ |> json_response_and_validate_schema(403)
+ end
+ end
+
+ test "PUT returns error", %{conn: conn} do
+ assert_error_when_disable_push do
+ conn
+ |> put("/api/v1/push/subscription", %{data: %{"alerts" => %{"mention" => false}}})
+ |> json_response_and_validate_schema(403)
+ end
+ end
+
+ test "DELETE returns error", %{conn: conn} do
+ assert_error_when_disable_push do
+ conn
+ |> delete("/api/v1/push/subscription", %{})
+ |> json_response_and_validate_schema(403)
+ end
+ end
+ end
+
+ describe "creates push subscription" do
+ test "ignores unsupported types", %{conn: conn} do
+ result =
+ conn
+ |> post("/api/v1/push/subscription", %{
+ "data" => %{
+ "alerts" => %{
+ "fake_unsupported_type" => true
+ }
+ },
+ "subscription" => @sub
+ })
+ |> json_response_and_validate_schema(200)
+
+ refute %{
+ "alerts" => %{
+ "fake_unsupported_type" => true
+ }
+ } == result
+ end
+
test "successful creation", %{conn: conn} do
result =
conn
|> post("/api/v1/push/subscription", %{
"data" => %{
- "alerts" => %{"mention" => true, "test" => true, "pleroma:chat_mention" => true}
+ "alerts" => %{
+ "mention" => true,
+ "favourite" => true,
+ "follow" => true,
+ "reblog" => true,
+ "pleroma:chat_mention" => true,
+ "pleroma:emoji_reaction" => true
+ }
},
"subscription" => @sub
})
@@ -68,7 +124,14 @@ test "successful creation", %{conn: conn} do
[subscription] = Pleroma.Repo.all(Subscription)
assert %{
- "alerts" => %{"mention" => true, "pleroma:chat_mention" => true},
+ "alerts" => %{
+ "mention" => true,
+ "favourite" => true,
+ "follow" => true,
+ "reblog" => true,
+ "pleroma:chat_mention" => true,
+ "pleroma:emoji_reaction" => true
+ },
"endpoint" => subscription.endpoint,
"id" => to_string(subscription.id),
"server_key" => @server_key
@@ -77,14 +140,6 @@ test "successful creation", %{conn: conn} do
end
describe "gets a user subscription" do
- test "returns error when push disabled ", %{conn: conn} do
- assert_error_when_disable_push do
- conn
- |> get("/api/v1/push/subscription", %{})
- |> json_response_and_validate_schema(403)
- end
- end
-
test "returns error when user hasn't subscription", %{conn: conn} do
res =
conn
@@ -124,30 +179,47 @@ test "returns a user subsciption", %{conn: conn, user: user, token: token} do
insert(:push_subscription,
user: user,
token: token,
- data: %{"alerts" => %{"mention" => true}}
+ data: %{
+ "alerts" => %{
+ "mention" => true,
+ "favourite" => true,
+ "follow" => true,
+ "reblog" => true,
+ "pleroma:chat_mention" => true,
+ "pleroma:emoji_reaction" => true
+ }
+ }
)
%{conn: conn, user: user, token: token, subscription: subscription}
end
- test "returns error when push disabled ", %{conn: conn} do
- assert_error_when_disable_push do
- conn
- |> put("/api/v1/push/subscription", %{data: %{"alerts" => %{"mention" => false}}})
- |> json_response_and_validate_schema(403)
- end
- end
-
test "returns updated subsciption", %{conn: conn, subscription: subscription} do
res =
conn
|> put("/api/v1/push/subscription", %{
- data: %{"alerts" => %{"mention" => false, "follow" => true}}
+ data: %{
+ "alerts" => %{
+ "mention" => false,
+ "favourite" => false,
+ "follow" => false,
+ "reblog" => false,
+ "pleroma:chat_mention" => false,
+ "pleroma:emoji_reaction" => false
+ }
+ }
})
|> json_response_and_validate_schema(200)
expect = %{
- "alerts" => %{"follow" => true, "mention" => false},
+ "alerts" => %{
+ "mention" => false,
+ "favourite" => false,
+ "follow" => false,
+ "reblog" => false,
+ "pleroma:chat_mention" => false,
+ "pleroma:emoji_reaction" => false
+ },
"endpoint" => "https://example.com/example/1234",
"id" => to_string(subscription.id),
"server_key" => @server_key
@@ -158,14 +230,6 @@ test "returns updated subsciption", %{conn: conn, subscription: subscription} do
end
describe "deletes the user subscription" do
- test "returns error when push disabled ", %{conn: conn} do
- assert_error_when_disable_push do
- conn
- |> delete("/api/v1/push/subscription", %{})
- |> json_response_and_validate_schema(403)
- end
- end
-
test "returns error when user hasn't subscription", %{conn: conn} do
res =
conn
diff --git a/test/pleroma/web/push/impl_test.exs b/test/pleroma/web/push/impl_test.exs
index 7d8cc999a..2a4a8fd06 100644
--- a/test/pleroma/web/push/impl_test.exs
+++ b/test/pleroma/web/push/impl_test.exs
@@ -184,6 +184,24 @@ test "renders title and body for like activity" do
"New Favorite"
end
+ test "renders title and body for pleroma:emoji_reaction activity" do
+ user = insert(:user, nickname: "Bob")
+
+ {:ok, activity} =
+ CommonAPI.post(user, %{
+ status: "This post is a really good post!"
+ })
+
+ {:ok, activity} = CommonAPI.react_with_emoji(activity.id, user, "👍")
+ object = Object.normalize(activity)
+
+ assert Impl.format_body(%{activity: activity, type: "pleroma:emoji_reaction"}, user, object) ==
+ "@Bob reacted with 👍"
+
+ assert Impl.format_title(%{activity: activity, type: "pleroma:emoji_reaction"}) ==
+ "New Reaction"
+ end
+
test "renders title for create activity with direct visibility" do
user = insert(:user, nickname: "Bob")