forked from AkkomaGang/akkoma
Merge branch 'release/2.1.2' into 'stable'
Release/2.1.2 See merge request pleroma/secteam/pleroma!17
This commit is contained in:
commit
a0f5e8b27e
45 changed files with 336 additions and 89 deletions
22
CHANGELOG.md
22
CHANGELOG.md
|
@ -3,6 +3,28 @@ All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
|
|
||||||
|
## [2.1.2] - 2020-09-17
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
- Fix most MRF rules either crashing or not being applied to objects passed into the Common Pipeline (ChatMessage, Question, Answer, Audio, Event).
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Welcome Chat messages preventing user registration with MRF Simple Policy applied to the local instance.
|
||||||
|
- Mastodon API: the public timeline returning an error when the `reply_visibility` parameter is set to `self` for an unauthenticated user.
|
||||||
|
- Mastodon Streaming API: Handler crashes on authentication failures, resulting in error logs.
|
||||||
|
- Mastodon Streaming API: Error logs on client pings.
|
||||||
|
- Rich media: Log spam on failures. Now the error is only logged once per attempt.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Rich Media: A HEAD request is now done to the url, to ensure it has the appropriate content type and size before proceeding with a GET.
|
||||||
|
|
||||||
|
### Upgrade notes
|
||||||
|
|
||||||
|
1. Restart Pleroma
|
||||||
|
|
||||||
## [2.1.1] - 2020-09-08
|
## [2.1.1] - 2020-09-08
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
|
@ -744,7 +744,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp restrict_replies(query, %{
|
defp restrict_replies(query, %{
|
||||||
reply_filtering_user: user,
|
reply_filtering_user: %User{} = user,
|
||||||
reply_visibility: "self"
|
reply_visibility: "self"
|
||||||
}) do
|
}) do
|
||||||
from(
|
from(
|
||||||
|
@ -760,7 +760,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp restrict_replies(query, %{
|
defp restrict_replies(query, %{
|
||||||
reply_filtering_user: user,
|
reply_filtering_user: %User{} = user,
|
||||||
reply_visibility: "following"
|
reply_visibility: "following"
|
||||||
}) do
|
}) do
|
||||||
from(
|
from(
|
||||||
|
|
|
@ -5,16 +5,34 @@
|
||||||
defmodule Pleroma.Web.ActivityPub.MRF do
|
defmodule Pleroma.Web.ActivityPub.MRF do
|
||||||
@callback filter(Map.t()) :: {:ok | :reject, Map.t()}
|
@callback filter(Map.t()) :: {:ok | :reject, Map.t()}
|
||||||
|
|
||||||
def filter(policies, %{} = object) do
|
def filter(policies, %{} = message) do
|
||||||
policies
|
policies
|
||||||
|> Enum.reduce({:ok, object}, fn
|
|> Enum.reduce({:ok, message}, fn
|
||||||
policy, {:ok, object} -> policy.filter(object)
|
policy, {:ok, message} -> policy.filter(message)
|
||||||
_, error -> error
|
_, error -> error
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
def filter(%{} = object), do: get_policies() |> filter(object)
|
def filter(%{} = object), do: get_policies() |> filter(object)
|
||||||
|
|
||||||
|
def pipeline_filter(%{} = message, meta) do
|
||||||
|
object = meta[:object_data]
|
||||||
|
ap_id = message["object"]
|
||||||
|
|
||||||
|
if object && ap_id do
|
||||||
|
with {:ok, message} <- filter(Map.put(message, "object", object)) do
|
||||||
|
meta = Keyword.put(meta, :object_data, message["object"])
|
||||||
|
{:ok, Map.put(message, "object", ap_id), meta}
|
||||||
|
else
|
||||||
|
{err, message} -> {err, message, meta}
|
||||||
|
end
|
||||||
|
else
|
||||||
|
{err, message} = filter(message)
|
||||||
|
|
||||||
|
{err, message, meta}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def get_policies do
|
def get_policies do
|
||||||
Pleroma.Config.get([:mrf, :policies], []) |> get_policies()
|
Pleroma.Config.get([:mrf, :policies], []) |> get_policies()
|
||||||
end
|
end
|
||||||
|
|
|
@ -20,9 +20,17 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
|
||||||
String.match?(string, pattern)
|
String.match?(string, pattern)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp check_reject(%{"object" => %{"content" => content, "summary" => summary}} = message) do
|
defp object_payload(%{} = object) do
|
||||||
|
[object["content"], object["summary"], object["name"]]
|
||||||
|
|> Enum.filter(& &1)
|
||||||
|
|> Enum.join("\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
defp check_reject(%{"object" => %{} = object} = message) do
|
||||||
|
payload = object_payload(object)
|
||||||
|
|
||||||
if Enum.any?(Pleroma.Config.get([:mrf_keyword, :reject]), fn pattern ->
|
if Enum.any?(Pleroma.Config.get([:mrf_keyword, :reject]), fn pattern ->
|
||||||
string_matches?(content, pattern) or string_matches?(summary, pattern)
|
string_matches?(payload, pattern)
|
||||||
end) do
|
end) do
|
||||||
{:reject, "[KeywordPolicy] Matches with rejected keyword"}
|
{:reject, "[KeywordPolicy] Matches with rejected keyword"}
|
||||||
else
|
else
|
||||||
|
@ -30,12 +38,12 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp check_ftl_removal(
|
defp check_ftl_removal(%{"to" => to, "object" => %{} = object} = message) do
|
||||||
%{"to" => to, "object" => %{"content" => content, "summary" => summary}} = message
|
payload = object_payload(object)
|
||||||
) do
|
|
||||||
if Pleroma.Constants.as_public() in to and
|
if Pleroma.Constants.as_public() in to and
|
||||||
Enum.any?(Pleroma.Config.get([:mrf_keyword, :federated_timeline_removal]), fn pattern ->
|
Enum.any?(Pleroma.Config.get([:mrf_keyword, :federated_timeline_removal]), fn pattern ->
|
||||||
string_matches?(content, pattern) or string_matches?(summary, pattern)
|
string_matches?(payload, pattern)
|
||||||
end) do
|
end) do
|
||||||
to = List.delete(to, Pleroma.Constants.as_public())
|
to = List.delete(to, Pleroma.Constants.as_public())
|
||||||
cc = [Pleroma.Constants.as_public() | message["cc"] || []]
|
cc = [Pleroma.Constants.as_public() | message["cc"] || []]
|
||||||
|
@ -51,35 +59,24 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp check_replace(%{"object" => %{"content" => content, "summary" => summary}} = message) do
|
defp check_replace(%{"object" => %{} = object} = message) do
|
||||||
content =
|
object =
|
||||||
if is_binary(content) do
|
["content", "name", "summary"]
|
||||||
content
|
|> Enum.filter(fn field -> Map.has_key?(object, field) && object[field] end)
|
||||||
else
|
|> Enum.reduce(object, fn field, object ->
|
||||||
""
|
data =
|
||||||
end
|
|
||||||
|
|
||||||
summary =
|
|
||||||
if is_binary(summary) do
|
|
||||||
summary
|
|
||||||
else
|
|
||||||
""
|
|
||||||
end
|
|
||||||
|
|
||||||
{content, summary} =
|
|
||||||
Enum.reduce(
|
Enum.reduce(
|
||||||
Pleroma.Config.get([:mrf_keyword, :replace]),
|
Pleroma.Config.get([:mrf_keyword, :replace]),
|
||||||
{content, summary},
|
object[field],
|
||||||
fn {pattern, replacement}, {content_acc, summary_acc} ->
|
fn {pat, repl}, acc -> String.replace(acc, pat, repl) end
|
||||||
{String.replace(content_acc, pattern, replacement),
|
|
||||||
String.replace(summary_acc, pattern, replacement)}
|
|
||||||
end
|
|
||||||
)
|
)
|
||||||
|
|
||||||
{:ok,
|
Map.put(object, field, data)
|
||||||
message
|
end)
|
||||||
|> put_in(["object", "content"], content)
|
|
||||||
|> put_in(["object", "summary"], summary)}
|
message = Map.put(message, "object", object)
|
||||||
|
|
||||||
|
{:ok, message}
|
||||||
end
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
|
|
|
@ -66,7 +66,8 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
|
||||||
"type" => "Create",
|
"type" => "Create",
|
||||||
"object" => child_object
|
"object" => child_object
|
||||||
} = object
|
} = object
|
||||||
) do
|
)
|
||||||
|
when is_map(child_object) do
|
||||||
media_nsfw =
|
media_nsfw =
|
||||||
Config.get([:mrf_simple, :media_nsfw])
|
Config.get([:mrf_simple, :media_nsfw])
|
||||||
|> MRF.subdomains_regex()
|
|> MRF.subdomains_regex()
|
||||||
|
|
|
@ -28,8 +28,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SubchainPolicy do
|
||||||
}"
|
}"
|
||||||
)
|
)
|
||||||
|
|
||||||
subchain
|
MRF.filter(subchain, message)
|
||||||
|> MRF.filter(message)
|
|
||||||
else
|
else
|
||||||
_e -> {:ok, message}
|
_e -> {:ok, message}
|
||||||
end
|
end
|
||||||
|
|
|
@ -26,13 +26,17 @@ defmodule Pleroma.Web.ActivityPub.Pipeline do
|
||||||
|
|
||||||
{:error, e} ->
|
{:error, e} ->
|
||||||
{:error, e}
|
{:error, e}
|
||||||
|
|
||||||
|
{:reject, e} ->
|
||||||
|
{:reject, e}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def do_common_pipeline(object, meta) do
|
def do_common_pipeline(object, meta) do
|
||||||
with {_, {:ok, validated_object, meta}} <-
|
with {_, {:ok, validated_object, meta}} <-
|
||||||
{:validate_object, ObjectValidator.validate(object, meta)},
|
{:validate_object, ObjectValidator.validate(object, meta)},
|
||||||
{_, {:ok, mrfd_object}} <- {:mrf_object, MRF.filter(validated_object)},
|
{_, {:ok, mrfd_object, meta}} <-
|
||||||
|
{:mrf_object, MRF.pipeline_filter(validated_object, meta)},
|
||||||
{_, {:ok, activity, meta}} <-
|
{_, {:ok, activity, meta}} <-
|
||||||
{:persist_object, ActivityPub.persist(mrfd_object, meta)},
|
{:persist_object, ActivityPub.persist(mrfd_object, meta)},
|
||||||
{_, {:ok, activity, meta}} <-
|
{_, {:ok, activity, meta}} <-
|
||||||
|
@ -40,7 +44,7 @@ defmodule Pleroma.Web.ActivityPub.Pipeline do
|
||||||
{_, {:ok, _}} <- {:federation, maybe_federate(activity, meta)} do
|
{_, {:ok, _}} <- {:federation, maybe_federate(activity, meta)} do
|
||||||
{:ok, activity, meta}
|
{:ok, activity, meta}
|
||||||
else
|
else
|
||||||
{:mrf_object, {:reject, _}} -> {:ok, nil, meta}
|
{:mrf_object, {:reject, message, _}} -> {:reject, message}
|
||||||
e -> {:error, e}
|
e -> {:error, e}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -311,7 +311,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||||
def fix_emoji(%{"tag" => tags} = object) when is_list(tags) do
|
def fix_emoji(%{"tag" => tags} = object) when is_list(tags) do
|
||||||
emoji =
|
emoji =
|
||||||
tags
|
tags
|
||||||
|> Enum.filter(fn data -> data["type"] == "Emoji" and data["icon"] end)
|
|> Enum.filter(fn data -> is_map(data) and data["type"] == "Emoji" and data["icon"] end)
|
||||||
|> Enum.reduce(%{}, fn data, mapping ->
|
|> Enum.reduce(%{}, fn data, mapping ->
|
||||||
name = String.trim(data["name"], ":")
|
name = String.trim(data["name"], ":")
|
||||||
|
|
||||||
|
|
|
@ -184,7 +184,8 @@ defmodule Pleroma.Web.ApiSpec.ChatOperation do
|
||||||
"application/json",
|
"application/json",
|
||||||
ChatMessage
|
ChatMessage
|
||||||
),
|
),
|
||||||
400 => Operation.response("Bad Request", "application/json", ApiError)
|
400 => Operation.response("Bad Request", "application/json", ApiError),
|
||||||
|
422 => Operation.response("MRF Rejection", "application/json", ApiError)
|
||||||
},
|
},
|
||||||
security: [
|
security: [
|
||||||
%{
|
%{
|
||||||
|
|
|
@ -55,7 +55,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
|
||||||
"application/json",
|
"application/json",
|
||||||
%Schema{oneOf: [Status, ScheduledStatus]}
|
%Schema{oneOf: [Status, ScheduledStatus]}
|
||||||
),
|
),
|
||||||
422 => Operation.response("Bad Request", "application/json", ApiError)
|
422 => Operation.response("Bad Request / MRF Rejection", "application/json", ApiError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -49,6 +49,9 @@ defmodule Pleroma.Web.CommonAPI do
|
||||||
local: true
|
local: true
|
||||||
)} do
|
)} do
|
||||||
{:ok, activity}
|
{:ok, activity}
|
||||||
|
else
|
||||||
|
{:common_pipeline, {:reject, _} = e} -> e
|
||||||
|
e -> e
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -37,12 +37,12 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do
|
||||||
else
|
else
|
||||||
{:error, :bad_topic} ->
|
{:error, :bad_topic} ->
|
||||||
Logger.debug("#{__MODULE__} bad topic #{inspect(req)}")
|
Logger.debug("#{__MODULE__} bad topic #{inspect(req)}")
|
||||||
{:ok, req} = :cowboy_req.reply(404, req)
|
req = :cowboy_req.reply(404, req)
|
||||||
{:ok, req, state}
|
{:ok, req, state}
|
||||||
|
|
||||||
{:error, :unauthorized} ->
|
{:error, :unauthorized} ->
|
||||||
Logger.debug("#{__MODULE__} authentication error: #{inspect(req)}")
|
Logger.debug("#{__MODULE__} authentication error: #{inspect(req)}")
|
||||||
{:ok, req} = :cowboy_req.reply(401, req)
|
req = :cowboy_req.reply(401, req)
|
||||||
{:ok, req, state}
|
{:ok, req, state}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -64,7 +64,9 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do
|
||||||
{:ok, %{state | timer: timer()}}
|
{:ok, %{state | timer: timer()}}
|
||||||
end
|
end
|
||||||
|
|
||||||
# We never receive messages.
|
# We only receive pings for now
|
||||||
|
def websocket_handle(:ping, state), do: {:ok, state}
|
||||||
|
|
||||||
def websocket_handle(frame, state) do
|
def websocket_handle(frame, state) do
|
||||||
Logger.error("#{__MODULE__} received frame: #{inspect(frame)}")
|
Logger.error("#{__MODULE__} received frame: #{inspect(frame)}")
|
||||||
{:ok, state}
|
{:ok, state}
|
||||||
|
@ -98,6 +100,10 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do
|
||||||
{:reply, :ping, %{state | timer: nil, count: 0}, :hibernate}
|
{:reply, :ping, %{state | timer: nil, count: 0}, :hibernate}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# State can be `[]` only in case we terminate before switching to websocket,
|
||||||
|
# we already log errors for these cases in `init/1`, so just do nothing here
|
||||||
|
def terminate(_reason, _req, []), do: :ok
|
||||||
|
|
||||||
def terminate(reason, _req, state) do
|
def terminate(reason, _req, state) do
|
||||||
Logger.debug(
|
Logger.debug(
|
||||||
"#{__MODULE__} terminating websocket connection for user #{
|
"#{__MODULE__} terminating websocket connection for user #{
|
||||||
|
|
|
@ -145,7 +145,10 @@ defmodule Pleroma.Web.OAuth.OAuthController do
|
||||||
def after_create_authorization(%Plug.Conn{} = conn, %Authorization{} = auth, %{
|
def after_create_authorization(%Plug.Conn{} = conn, %Authorization{} = auth, %{
|
||||||
"authorization" => %{"redirect_uri" => @oob_token_redirect_uri}
|
"authorization" => %{"redirect_uri" => @oob_token_redirect_uri}
|
||||||
}) do
|
}) do
|
||||||
render(conn, "oob_authorization_created.html", %{auth: auth})
|
# Enforcing the view to reuse the template when calling from other controllers
|
||||||
|
conn
|
||||||
|
|> put_view(OAuthView)
|
||||||
|
|> render("oob_authorization_created.html", %{auth: auth})
|
||||||
end
|
end
|
||||||
|
|
||||||
def after_create_authorization(%Plug.Conn{} = conn, %Authorization{} = auth, %{
|
def after_create_authorization(%Plug.Conn{} = conn, %Authorization{} = auth, %{
|
||||||
|
|
|
@ -90,6 +90,16 @@ defmodule Pleroma.Web.PleromaAPI.ChatController do
|
||||||
conn
|
conn
|
||||||
|> put_view(MessageReferenceView)
|
|> put_view(MessageReferenceView)
|
||||||
|> render("show.json", chat_message_reference: cm_ref)
|
|> render("show.json", chat_message_reference: cm_ref)
|
||||||
|
else
|
||||||
|
{:reject, message} ->
|
||||||
|
conn
|
||||||
|
|> put_status(:unprocessable_entity)
|
||||||
|
|> json(%{error: message})
|
||||||
|
|
||||||
|
{:error, message} ->
|
||||||
|
conn
|
||||||
|
|> put_status(:bad_request)
|
||||||
|
|> json(%{error: message})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -96,6 +96,50 @@ defmodule Pleroma.Web.RichMedia.Helpers do
|
||||||
@rich_media_options
|
@rich_media_options
|
||||||
end
|
end
|
||||||
|
|
||||||
Pleroma.HTTP.get(url, headers, adapter: options)
|
head_check =
|
||||||
|
case Pleroma.HTTP.head(url, headers, adapter: options) do
|
||||||
|
# If the HEAD request didn't reach the server for whatever reason,
|
||||||
|
# we assume the GET that comes right after won't either
|
||||||
|
{:error, _} = e ->
|
||||||
|
e
|
||||||
|
|
||||||
|
{:ok, %Tesla.Env{status: 200, headers: headers}} ->
|
||||||
|
with :ok <- check_content_type(headers),
|
||||||
|
:ok <- check_content_length(headers),
|
||||||
|
do: :ok
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
|
||||||
|
with :ok <- head_check, do: Pleroma.HTTP.get(url, headers, adapter: options)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp check_content_type(headers) do
|
||||||
|
case List.keyfind(headers, "content-type", 0) do
|
||||||
|
{_, content_type} ->
|
||||||
|
case Plug.Conn.Utils.media_type(content_type) do
|
||||||
|
{:ok, "text", "html", _} -> :ok
|
||||||
|
_ -> {:error, {:content_type, content_type}}
|
||||||
|
end
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@max_body @rich_media_options[:max_body]
|
||||||
|
defp check_content_length(headers) do
|
||||||
|
case List.keyfind(headers, "content-length", 0) do
|
||||||
|
{_, maybe_content_length} ->
|
||||||
|
case Integer.parse(maybe_content_length) do
|
||||||
|
{content_length, ""} when content_length <= @max_body -> :ok
|
||||||
|
{_, ""} -> {:error, :body_too_large}
|
||||||
|
_ -> :ok
|
||||||
|
end
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
:ok
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -31,6 +31,14 @@ defmodule Pleroma.Web.RichMedia.Parser do
|
||||||
{:ok, _data} = res ->
|
{:ok, _data} = res ->
|
||||||
res
|
res
|
||||||
|
|
||||||
|
{:error, :body_too_large} = e ->
|
||||||
|
e
|
||||||
|
|
||||||
|
{:error, {:content_type, _}} = e ->
|
||||||
|
e
|
||||||
|
|
||||||
|
# The TTL is not set for the errors above, since they are unlikely to change
|
||||||
|
# with time
|
||||||
{:error, _} = e ->
|
{:error, _} = e ->
|
||||||
ttl = Pleroma.Config.get([:rich_media, :failure_backoff], 60_000)
|
ttl = Pleroma.Config.get([:rich_media, :failure_backoff], 60_000)
|
||||||
Cachex.expire(:rich_media_cache, url, ttl)
|
Cachex.expire(:rich_media_cache, url, ttl)
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
<h1>Successfully authorized</h1>
|
<h1>Successfully authorized</h1>
|
||||||
<h2>Token code is <%= @auth.token %></h2>
|
<h2>Token code is <br><%= @auth.token %></h2>
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
<h1>Authorization exists</h1>
|
<h1>Authorization exists</h1>
|
||||||
<h2>Access token is <%= @token.token %></h2>
|
<h2>Access token is <br><%= @token.token %></h2>
|
||||||
|
|
2
mix.exs
2
mix.exs
|
@ -4,7 +4,7 @@ defmodule Pleroma.Mixfile do
|
||||||
def project do
|
def project do
|
||||||
[
|
[
|
||||||
app: :pleroma,
|
app: :pleroma,
|
||||||
version: version("2.1.1"),
|
version: version("2.1.2"),
|
||||||
elixir: "~> 1.9",
|
elixir: "~> 1.9",
|
||||||
elixirc_paths: elixirc_paths(Mix.env()),
|
elixirc_paths: elixirc_paths(Mix.env()),
|
||||||
compilers: [:phoenix, :gettext] ++ Mix.compilers(),
|
compilers: [:phoenix, :gettext] ++ Mix.compilers(),
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1,user-scalable=no"><title>Pleroma</title><!--server-generated-meta--><link rel=icon type=image/png href=/favicon.png><link href=/static/css/app.77b1644622e3bae24b6b.css rel=stylesheet><link href=/static/fontello.1599568314856.css rel=stylesheet></head><body class=hidden><noscript>To use Pleroma, please enable JavaScript.</noscript><div id=app></div><script type=text/javascript src=/static/js/vendors~app.90c4af83c1ae68f4cd95.js></script><script type=text/javascript src=/static/js/app.55d173dc5e39519aa518.js></script></body></html>
|
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1,user-scalable=no"><title>Pleroma</title><!--server-generated-meta--><link rel=icon type=image/png href=/favicon.png><link href=/static/css/app.77b1644622e3bae24b6b.css rel=stylesheet><link href=/static/fontello.1600365488745.css rel=stylesheet></head><body class=hidden><noscript>To use Pleroma, please enable JavaScript.</noscript><div id=app></div><script type=text/javascript src=/static/js/vendors~app.90c4af83c1ae68f4cd95.js></script><script type=text/javascript src=/static/js/app.826c44232e0a76bbd9ba.js></script></body></html>
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -92,6 +92,8 @@
|
||||||
|
|
||||||
<glyph glyph-name="block" unicode="" d="M732 359q0 90-48 164l-421-420q76-50 166-50 62 0 118 25t96 65 65 97 24 119z m-557-167l421 421q-75 50-167 50-83 0-153-40t-110-111-41-153q0-91 50-167z m682 167q0-88-34-168t-91-137-137-92-166-34-167 34-137 92-91 137-34 168 34 167 91 137 137 91 167 34 166-34 137-91 91-137 34-167z" horiz-adv-x="857.1" />
|
<glyph glyph-name="block" unicode="" d="M732 359q0 90-48 164l-421-420q76-50 166-50 62 0 118 25t96 65 65 97 24 119z m-557-167l421 421q-75 50-167 50-83 0-153-40t-110-111-41-153q0-91 50-167z m682 167q0-88-34-168t-91-137-137-92-166-34-167 34-137 92-91 137-34 168 34 167 91 137 137 91 167 34 166-34 137-91 91-137 34-167z" horiz-adv-x="857.1" />
|
||||||
|
|
||||||
|
<glyph glyph-name="megaphone" unicode="" d="M929 500q29 0 50-21t21-51-21-50-50-21v-214q0-29-22-50t-50-22q-233 194-453 212-32-10-51-36t-17-57 22-51q-11-19-13-37t4-32 19-31 26-28 35-28q-17-32-63-46t-94-7-73 31q-4 13-17 49t-18 53-12 50-9 56 2 55 12 62h-68q-36 0-63 26t-26 63v107q0 37 26 63t63 26h268q243 0 500 215 29 0 50-22t22-50v-214z m-72-337v532q-220-168-428-191v-151q210-23 428-190z" horiz-adv-x="1000" />
|
||||||
|
|
||||||
<glyph glyph-name="spin3" unicode="" d="M494 857c-266 0-483-210-494-472-1-19 13-20 13-20l84 0c16 0 19 10 19 18 10 199 176 358 378 358 107 0 205-45 273-118l-58-57c-11-12-11-27 5-31l247-50c21-5 46 11 37 44l-58 227c-2 9-16 22-29 13l-65-60c-89 91-214 148-352 148z m409-508c-16 0-19-10-19-18-10-199-176-358-377-358-108 0-205 45-274 118l59 57c10 12 10 27-5 31l-248 50c-21 5-46-11-37-44l58-227c2-9 16-22 30-13l64 60c89-91 214-148 353-148 265 0 482 210 493 473 1 18-13 19-13 19l-84 0z" horiz-adv-x="1000" />
|
<glyph glyph-name="spin3" unicode="" d="M494 857c-266 0-483-210-494-472-1-19 13-20 13-20l84 0c16 0 19 10 19 18 10 199 176 358 378 358 107 0 205-45 273-118l-58-57c-11-12-11-27 5-31l247-50c21-5 46 11 37 44l-58 227c-2 9-16 22-29 13l-65-60c-89 91-214 148-352 148z m409-508c-16 0-19-10-19-18-10-199-176-358-377-358-108 0-205 45-274 118l59 57c10 12 10 27-5 31l-248 50c-21 5-46-11-37-44l58-227c2-9 16-22 30-13l64 60c89-91 214-148 353-148 265 0 482 210 493 473 1 18-13 19-13 19l-84 0z" horiz-adv-x="1000" />
|
||||||
|
|
||||||
<glyph glyph-name="spin4" unicode="" d="M498 857c-114 0-228-39-320-116l0 0c173 140 428 130 588-31 134-134 164-332 89-495-10-29-5-50 12-68 21-20 61-23 84 0 3 3 12 15 15 24 71 180 33 393-112 539-99 98-228 147-356 147z m-409-274c-14 0-29-5-39-16-3-3-13-15-15-24-71-180-34-393 112-539 185-185 479-195 676-31l0 0c-173-140-428-130-589 31-134 134-163 333-89 495 11 29 6 50-12 68-11 11-27 17-44 16z" horiz-adv-x="1001" />
|
<glyph glyph-name="spin4" unicode="" d="M498 857c-114 0-228-39-320-116l0 0c173 140 428 130 588-31 134-134 164-332 89-495-10-29-5-50 12-68 21-20 61-23 84 0 3 3 12 15 15 24 71 180 33 393-112 539-99 98-228 147-356 147z m-409-274c-14 0-29-5-39-16-3-3-13-15-15-24-71-180-34-393 112-539 185-185 479-195 676-31l0 0c-173-140-428-130-589 31-134 134-163 333-89 495 11 29 6 50-12 68-11 11-27 17-44 16z" horiz-adv-x="1001" />
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
Binary file not shown.
BIN
priv/static/static/font/fontello.1600365488745.woff
Normal file
BIN
priv/static/static/font/fontello.1600365488745.woff
Normal file
Binary file not shown.
BIN
priv/static/static/font/fontello.1600365488745.woff2
Normal file
BIN
priv/static/static/font/fontello.1600365488745.woff2
Normal file
Binary file not shown.
|
@ -1,11 +1,11 @@
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "Icons";
|
font-family: "Icons";
|
||||||
src: url("./font/fontello.1599568314856.eot");
|
src: url("./font/fontello.1600365488745.eot");
|
||||||
src: url("./font/fontello.1599568314856.eot") format("embedded-opentype"),
|
src: url("./font/fontello.1600365488745.eot") format("embedded-opentype"),
|
||||||
url("./font/fontello.1599568314856.woff2") format("woff2"),
|
url("./font/fontello.1600365488745.woff2") format("woff2"),
|
||||||
url("./font/fontello.1599568314856.woff") format("woff"),
|
url("./font/fontello.1600365488745.woff") format("woff"),
|
||||||
url("./font/fontello.1599568314856.ttf") format("truetype"),
|
url("./font/fontello.1600365488745.ttf") format("truetype"),
|
||||||
url("./font/fontello.1599568314856.svg") format("svg");
|
url("./font/fontello.1600365488745.svg") format("svg");
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
@ -156,3 +156,5 @@
|
||||||
.icon-doc::before { content: "\e829"; }
|
.icon-doc::before { content: "\e829"; }
|
||||||
|
|
||||||
.icon-block::before { content: "\e82a"; }
|
.icon-block::before { content: "\e82a"; }
|
||||||
|
|
||||||
|
.icon-megaphone::before { content: "\e82b"; }
|
|
@ -405,6 +405,12 @@
|
||||||
"css": "block",
|
"css": "block",
|
||||||
"code": 59434,
|
"code": 59434,
|
||||||
"src": "fontawesome"
|
"src": "fontawesome"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uid": "3e674995cacc2b09692c096ea7eb6165",
|
||||||
|
"css": "megaphone",
|
||||||
|
"code": 59435,
|
||||||
|
"src": "fontawesome"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
priv/static/static/js/2.e852a6b4b3bba752b838.js.map
Normal file
1
priv/static/static/js/2.e852a6b4b3bba752b838.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
priv/static/static/js/app.826c44232e0a76bbd9ba.js
Normal file
2
priv/static/static/js/app.826c44232e0a76bbd9ba.js
Normal file
File diff suppressed because one or more lines are too long
1
priv/static/static/js/app.826c44232e0a76bbd9ba.js.map
Normal file
1
priv/static/static/js/app.826c44232e0a76bbd9ba.js.map
Normal file
File diff suppressed because one or more lines are too long
|
@ -1,4 +1,4 @@
|
||||||
var serviceWorkerOption = {"assets":["/static/fontello.1599568314856.css","/static/font/fontello.1599568314856.eot","/static/font/fontello.1599568314856.svg","/static/font/fontello.1599568314856.ttf","/static/font/fontello.1599568314856.woff","/static/font/fontello.1599568314856.woff2","/static/img/nsfw.74818f9.png","/static/css/app.77b1644622e3bae24b6b.css","/static/js/app.55d173dc5e39519aa518.js","/static/js/vendors~app.90c4af83c1ae68f4cd95.js","/static/css/2.0778a6a864a1307a6c41.css","/static/js/2.c92f4803ff24726cea58.js","/static/css/3.b2603a50868c68a1c192.css","/static/js/3.7d21accf4e5bd07e3ebf.js","/static/js/4.5719922a4e807145346d.js","/static/js/5.cf05c5ddbdbac890ae35.js","/static/js/6.ecfd3302a692de148391.js","/static/js/7.dd44c3d58fb9dced093d.js","/static/js/8.636322a87bb10a1754f8.js","/static/js/9.6010dbcce7b4d7c05a18.js","/static/js/10.46fbbdfaf0d4800f349b.js","/static/js/11.708cc2513c53879a92cc.js","/static/js/12.b3bf0bc313861d6ec36b.js","/static/js/13.adb8a942514d735722c4.js","/static/js/14.d015d9b2ea16407e389c.js","/static/js/15.19866e6a366ccf982284.js","/static/js/16.38a984effd54736f6a2c.js","/static/js/17.9c25507194320db2e85b.js","/static/js/18.94946caca48930c224c7.js","/static/js/19.233c81ac2c28d55e9f13.js","/static/js/20.818c38d27369c3a4d677.js","/static/js/21.ce4cda179d888ca6bc2a.js","/static/js/22.2ea93c6cc569ef0256ab.js","/static/js/23.a57a7845cc20fafd06d1.js","/static/js/24.35eb55a657b5485f8491.js","/static/js/25.5a9efe20e3ae1352e6d2.js","/static/js/26.cf13231d524e5ca3b3e6.js","/static/js/27.fca8d4f6e444bd14f376.js","/static/js/28.e0f9f164e0bfd890dc61.js","/static/js/29.0b69359f0fe5c0785746.js","/static/js/30.fce58be0b52ca3e32fa4.js"]};
|
var serviceWorkerOption = {"assets":["/static/fontello.1600365488745.css","/static/font/fontello.1600365488745.eot","/static/font/fontello.1600365488745.svg","/static/font/fontello.1600365488745.ttf","/static/font/fontello.1600365488745.woff","/static/font/fontello.1600365488745.woff2","/static/img/nsfw.74818f9.png","/static/css/app.77b1644622e3bae24b6b.css","/static/js/app.826c44232e0a76bbd9ba.js","/static/js/vendors~app.90c4af83c1ae68f4cd95.js","/static/css/2.0778a6a864a1307a6c41.css","/static/js/2.e852a6b4b3bba752b838.js","/static/css/3.b2603a50868c68a1c192.css","/static/js/3.7d21accf4e5bd07e3ebf.js","/static/js/4.5719922a4e807145346d.js","/static/js/5.cf05c5ddbdbac890ae35.js","/static/js/6.ecfd3302a692de148391.js","/static/js/7.dd44c3d58fb9dced093d.js","/static/js/8.636322a87bb10a1754f8.js","/static/js/9.6010dbcce7b4d7c05a18.js","/static/js/10.46fbbdfaf0d4800f349b.js","/static/js/11.708cc2513c53879a92cc.js","/static/js/12.b3bf0bc313861d6ec36b.js","/static/js/13.adb8a942514d735722c4.js","/static/js/14.d015d9b2ea16407e389c.js","/static/js/15.19866e6a366ccf982284.js","/static/js/16.38a984effd54736f6a2c.js","/static/js/17.9c25507194320db2e85b.js","/static/js/18.94946caca48930c224c7.js","/static/js/19.233c81ac2c28d55e9f13.js","/static/js/20.818c38d27369c3a4d677.js","/static/js/21.ce4cda179d888ca6bc2a.js","/static/js/22.2ea93c6cc569ef0256ab.js","/static/js/23.a57a7845cc20fafd06d1.js","/static/js/24.35eb55a657b5485f8491.js","/static/js/25.5a9efe20e3ae1352e6d2.js","/static/js/26.cf13231d524e5ca3b3e6.js","/static/js/27.fca8d4f6e444bd14f376.js","/static/js/28.e0f9f164e0bfd890dc61.js","/static/js/29.0b69359f0fe5c0785746.js","/static/js/30.fce58be0b52ca3e32fa4.js"]};
|
||||||
|
|
||||||
!function(t){var e={};function n(r){if(e[r])return e[r].exports;var o=e[r]={i:r,l:!1,exports:{}};return t[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)n.d(r,o,function(e){return t[e]}.bind(null,o));return r},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="/",n(n.s=196)}([function(t,e){var n=Array.isArray;t.exports=n},function(t,e,n){t.exports=n(53)},function(t,e,n){var r=n(32),o="object"==typeof self&&self&&self.Object===Object&&self,i=r||o||Function("return this")();t.exports=i},function(t,e,n){var r=n(97),o=n(100);t.exports=function(t,e){var n=o(t,e);return r(n)?n:void 0}},function(t,e,n){var r=n(8),o=n(64),i=n(65),a="[object Null]",s="[object Undefined]",c=r?r.toStringTag:void 0;t.exports=function(t){return null==t?void 0===t?s:a:c&&c in Object(t)?o(t):i(t)}},function(t,e){t.exports=function(t){return null!=t&&"object"==typeof t}},function(t,e){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(t){"object"==typeof window&&(n=window)}t.exports=n},function(t,e,n){var r=n(31),o=n(20);t.exports=function(t){return null!=t&&o(t.length)&&!r(t)}},function(t,e,n){var r=n(2).Symbol;t.exports=r},function(t,e){t.exports=function(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)}},function(t,e,n){var r=n(4),o=n(5),i="[object Symbol]";t.exports=function(t){return"symbol"==typeof t||o(t)&&r(t)==i}},function(t,e,n){var r=n(72),o=n(78),i=n(7);t.exports=function(t){return i(t)?r(t):o(t)}},function(t,e,n){var r=n(87),o=n(88),i=n(89),a=n(90),s=n(91);function c(t){var e=-1,n=null==t?0:t.length;for(this.clear();++e<n;){var r=t[e];this.set(r[0],r[1])}}c.prototype.clear=r,c.prototype.delete=o,c.prototype.get=i,c.prototype.has=a,c.prototype.set=s,t.exports=c},function(t,e,n){var r=n(24);t.exports=function(t,e){for(var n=t.length;n--;)if(r(t[n][0],e))return n;return-1}},function(t,e,n){var r=n(3)(Object,"create");t.exports=r},function(t,e,n){var r=n(109);t.exports=function(t,e){var n=t.__data__;return r(e)?n["string"==typeof e?"string":"hash"]:n.map}},function(t,e,n){var r=n(10),o=1/0;t.exports=function(t){if("string"==typeof t||r(t))return t;var e=t+"";return"0"==e&&1/t==-o?"-0":e}},function(t,e){t.exports=function(t){return t}},function(t,e,n){var r=n(42),o=n(164),i=n(37),a=n(0);t.exports=function(t,e){return(a(t)?r:o)(t,i(e,3))}},function(t,e){t.exports=function(t){return t.webpackPolyfill||(t.deprecate=function(){},t.paths=[],t.children||(t.children=[]),Object.defineProperty(t,"loaded",{enumerable:!0,get:function(){return t.l}}),Object.defineProperty(t,"id",{enumerable:!0,get:function(){return t.i}}),t.webpackPolyfill=1),t}},function(t,e){var n=9007199254740991;t.exports=function(t){return"number"==typeof t&&t>-1&&t%1==0&&t<=n}},function(t,e){t.exports=function(t,e){for(var n=-1,r=null==t?0:t.length,o=Array(r);++n<r;)o[n]=e(t[n],n,t);return o}},function(t,e,n){var r=n(74),o=n(5),i=Object.prototype,a=i.hasOwnProperty,s=i.propertyIsEnumerable,c=r(function(){return arguments}())?r:function(t){return o(t)&&a.call(t,"callee")&&!s.call(t,"callee")};t.exports=c},function(t,e){var n=9007199254740991,r=/^(?:0|[1-9]\d*)$/;t.exports=function(t,e){var o=typeof t;return!!(e=null==e?n:e)&&("number"==o||"symbol"!=o&&r.test(t))&&t>-1&&t%1==0&&t<e}},function(t,e){t.exports=function(t,e){return t===e||t!=t&&e!=e}},function(t,e,n){var r=n(3)(n(2),"Map");t.exports=r},function(t,e,n){var r=n(101),o=n(108),i=n(110),a=n(111),s=n(112);function c(t){var e=-1,n=null==t?0:t.length;for(this.clear();++e<n;){var r=t[e];this.set(r[0],r[1])}}c.prototype.clear=r,c.prototype.delete=o,c.prototype.get=i,c.prototype.has=a,c.prototype.set=s,t.exports=c},function(t,e,n){var r=n(0),o=n(10),i=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,a=/^\w*$/;t.exports=function(t,e){if(r(t))return!1;var n=typeof t;return!("number"!=n&&"symbol"!=n&&"boolean"!=n&&null!=t&&!o(t))||a.test(t)||!i.test(t)||null!=e&&t in Object(e)}},function(t,e){
|
!function(t){var e={};function n(r){if(e[r])return e[r].exports;var o=e[r]={i:r,l:!1,exports:{}};return t[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)n.d(r,o,function(e){return t[e]}.bind(null,o));return r},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="/",n(n.s=196)}([function(t,e){var n=Array.isArray;t.exports=n},function(t,e,n){t.exports=n(53)},function(t,e,n){var r=n(32),o="object"==typeof self&&self&&self.Object===Object&&self,i=r||o||Function("return this")();t.exports=i},function(t,e,n){var r=n(97),o=n(100);t.exports=function(t,e){var n=o(t,e);return r(n)?n:void 0}},function(t,e,n){var r=n(8),o=n(64),i=n(65),a="[object Null]",s="[object Undefined]",c=r?r.toStringTag:void 0;t.exports=function(t){return null==t?void 0===t?s:a:c&&c in Object(t)?o(t):i(t)}},function(t,e){t.exports=function(t){return null!=t&&"object"==typeof t}},function(t,e){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(t){"object"==typeof window&&(n=window)}t.exports=n},function(t,e,n){var r=n(31),o=n(20);t.exports=function(t){return null!=t&&o(t.length)&&!r(t)}},function(t,e,n){var r=n(2).Symbol;t.exports=r},function(t,e){t.exports=function(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)}},function(t,e,n){var r=n(4),o=n(5),i="[object Symbol]";t.exports=function(t){return"symbol"==typeof t||o(t)&&r(t)==i}},function(t,e,n){var r=n(72),o=n(78),i=n(7);t.exports=function(t){return i(t)?r(t):o(t)}},function(t,e,n){var r=n(87),o=n(88),i=n(89),a=n(90),s=n(91);function c(t){var e=-1,n=null==t?0:t.length;for(this.clear();++e<n;){var r=t[e];this.set(r[0],r[1])}}c.prototype.clear=r,c.prototype.delete=o,c.prototype.get=i,c.prototype.has=a,c.prototype.set=s,t.exports=c},function(t,e,n){var r=n(24);t.exports=function(t,e){for(var n=t.length;n--;)if(r(t[n][0],e))return n;return-1}},function(t,e,n){var r=n(3)(Object,"create");t.exports=r},function(t,e,n){var r=n(109);t.exports=function(t,e){var n=t.__data__;return r(e)?n["string"==typeof e?"string":"hash"]:n.map}},function(t,e,n){var r=n(10),o=1/0;t.exports=function(t){if("string"==typeof t||r(t))return t;var e=t+"";return"0"==e&&1/t==-o?"-0":e}},function(t,e){t.exports=function(t){return t}},function(t,e,n){var r=n(42),o=n(164),i=n(37),a=n(0);t.exports=function(t,e){return(a(t)?r:o)(t,i(e,3))}},function(t,e){t.exports=function(t){return t.webpackPolyfill||(t.deprecate=function(){},t.paths=[],t.children||(t.children=[]),Object.defineProperty(t,"loaded",{enumerable:!0,get:function(){return t.l}}),Object.defineProperty(t,"id",{enumerable:!0,get:function(){return t.i}}),t.webpackPolyfill=1),t}},function(t,e){var n=9007199254740991;t.exports=function(t){return"number"==typeof t&&t>-1&&t%1==0&&t<=n}},function(t,e){t.exports=function(t,e){for(var n=-1,r=null==t?0:t.length,o=Array(r);++n<r;)o[n]=e(t[n],n,t);return o}},function(t,e,n){var r=n(74),o=n(5),i=Object.prototype,a=i.hasOwnProperty,s=i.propertyIsEnumerable,c=r(function(){return arguments}())?r:function(t){return o(t)&&a.call(t,"callee")&&!s.call(t,"callee")};t.exports=c},function(t,e){var n=9007199254740991,r=/^(?:0|[1-9]\d*)$/;t.exports=function(t,e){var o=typeof t;return!!(e=null==e?n:e)&&("number"==o||"symbol"!=o&&r.test(t))&&t>-1&&t%1==0&&t<e}},function(t,e){t.exports=function(t,e){return t===e||t!=t&&e!=e}},function(t,e,n){var r=n(3)(n(2),"Map");t.exports=r},function(t,e,n){var r=n(101),o=n(108),i=n(110),a=n(111),s=n(112);function c(t){var e=-1,n=null==t?0:t.length;for(this.clear();++e<n;){var r=t[e];this.set(r[0],r[1])}}c.prototype.clear=r,c.prototype.delete=o,c.prototype.get=i,c.prototype.has=a,c.prototype.set=s,t.exports=c},function(t,e,n){var r=n(0),o=n(10),i=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,a=/^\w*$/;t.exports=function(t,e){if(r(t))return!1;var n=typeof t;return!("number"!=n&&"symbol"!=n&&"boolean"!=n&&null!=t&&!o(t))||a.test(t)||!i.test(t)||null!=e&&t in Object(e)}},function(t,e){
|
||||||
/*!
|
/*!
|
||||||
|
|
|
@ -99,30 +99,30 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
|
||||||
test "accepts the 'user' stream", %{token: token} = _state do
|
test "accepts the 'user' stream", %{token: token} = _state do
|
||||||
assert {:ok, _} = start_socket("?stream=user&access_token=#{token.token}")
|
assert {:ok, _} = start_socket("?stream=user&access_token=#{token.token}")
|
||||||
|
|
||||||
assert capture_log(fn ->
|
capture_log(fn ->
|
||||||
assert {:error, {401, _}} = start_socket("?stream=user")
|
assert {:error, {401, _}} = start_socket("?stream=user")
|
||||||
Process.sleep(30)
|
Process.sleep(30)
|
||||||
end) =~ ":badarg"
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "accepts the 'user:notification' stream", %{token: token} = _state do
|
test "accepts the 'user:notification' stream", %{token: token} = _state do
|
||||||
assert {:ok, _} = start_socket("?stream=user:notification&access_token=#{token.token}")
|
assert {:ok, _} = start_socket("?stream=user:notification&access_token=#{token.token}")
|
||||||
|
|
||||||
assert capture_log(fn ->
|
capture_log(fn ->
|
||||||
assert {:error, {401, _}} = start_socket("?stream=user:notification")
|
assert {:error, {401, _}} = start_socket("?stream=user:notification")
|
||||||
Process.sleep(30)
|
Process.sleep(30)
|
||||||
end) =~ ":badarg"
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "accepts valid token on Sec-WebSocket-Protocol header", %{token: token} do
|
test "accepts valid token on Sec-WebSocket-Protocol header", %{token: token} do
|
||||||
assert {:ok, _} = start_socket("?stream=user", [{"Sec-WebSocket-Protocol", token.token}])
|
assert {:ok, _} = start_socket("?stream=user", [{"Sec-WebSocket-Protocol", token.token}])
|
||||||
|
|
||||||
assert capture_log(fn ->
|
capture_log(fn ->
|
||||||
assert {:error, {401, _}} =
|
assert {:error, {401, _}} =
|
||||||
start_socket("?stream=user", [{"Sec-WebSocket-Protocol", "I am a friend"}])
|
start_socket("?stream=user", [{"Sec-WebSocket-Protocol", "I am a friend"}])
|
||||||
|
|
||||||
Process.sleep(30)
|
Process.sleep(30)
|
||||||
end) =~ ":badarg"
|
end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1436,4 +1436,21 @@ defmodule HttpRequestMock do
|
||||||
inspect(headers)
|
inspect(headers)
|
||||||
}"}
|
}"}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Most of the rich media mocks are missing HEAD requests, so we just return 404.
|
||||||
|
@rich_media_mocks [
|
||||||
|
"https://example.com/ogp",
|
||||||
|
"https://example.com/ogp-missing-data",
|
||||||
|
"https://example.com/twitter-card"
|
||||||
|
]
|
||||||
|
def head(url, _query, _body, _headers) when url in @rich_media_mocks do
|
||||||
|
{:ok, %Tesla.Env{status: 404, body: ""}}
|
||||||
|
end
|
||||||
|
|
||||||
|
def head(url, query, body, headers) do
|
||||||
|
{:error,
|
||||||
|
"Mock response not implemented for HEAD #{inspect(url)}, #{query}, #{inspect(body)}, #{
|
||||||
|
inspect(headers)
|
||||||
|
}"}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -440,6 +440,45 @@ defmodule Pleroma.UserTest do
|
||||||
assert activity.actor == welcome_user.ap_id
|
assert activity.actor == welcome_user.ap_id
|
||||||
end
|
end
|
||||||
|
|
||||||
|
setup do:
|
||||||
|
clear_config(:mrf_simple,
|
||||||
|
media_removal: [],
|
||||||
|
media_nsfw: [],
|
||||||
|
federated_timeline_removal: [],
|
||||||
|
report_removal: [],
|
||||||
|
reject: [],
|
||||||
|
followers_only: [],
|
||||||
|
accept: [],
|
||||||
|
avatar_removal: [],
|
||||||
|
banner_removal: [],
|
||||||
|
reject_deletes: []
|
||||||
|
)
|
||||||
|
|
||||||
|
setup do:
|
||||||
|
clear_config(:mrf,
|
||||||
|
policies: [
|
||||||
|
Pleroma.Web.ActivityPub.MRF.SimplePolicy
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
test "it sends a welcome chat message when Simple policy applied to local instance" do
|
||||||
|
Pleroma.Config.put([:mrf_simple, :media_nsfw], ["localhost"])
|
||||||
|
|
||||||
|
welcome_user = insert(:user)
|
||||||
|
Pleroma.Config.put([:welcome, :chat_message, :enabled], true)
|
||||||
|
Pleroma.Config.put([:welcome, :chat_message, :sender_nickname], welcome_user.nickname)
|
||||||
|
Pleroma.Config.put([:welcome, :chat_message, :message], "Hello, this is a chat message")
|
||||||
|
|
||||||
|
cng = User.register_changeset(%User{}, @full_user_data)
|
||||||
|
{:ok, registered_user} = User.register(cng)
|
||||||
|
ObanHelpers.perform_all()
|
||||||
|
|
||||||
|
activity = Repo.one(Pleroma.Activity)
|
||||||
|
assert registered_user.ap_id in activity.recipients
|
||||||
|
assert Object.normalize(activity).data["content"] =~ "chat message"
|
||||||
|
assert activity.actor == welcome_user.ap_id
|
||||||
|
end
|
||||||
|
|
||||||
test "it sends a welcome email message if it is set" do
|
test "it sends a welcome email message if it is set" do
|
||||||
welcome_user = insert(:user)
|
welcome_user = insert(:user)
|
||||||
Pleroma.Config.put([:welcome, :email, :enabled], true)
|
Pleroma.Config.put([:welcome, :email, :enabled], true)
|
||||||
|
|
|
@ -1773,6 +1773,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
||||||
|> Enum.map(& &1.id)
|
|> Enum.map(& &1.id)
|
||||||
|
|
||||||
assert activities_ids == []
|
assert activities_ids == []
|
||||||
|
|
||||||
|
activities_ids =
|
||||||
|
%{}
|
||||||
|
|> Map.put(:reply_visibility, "self")
|
||||||
|
|> Map.put(:reply_filtering_user, nil)
|
||||||
|
|> ActivityPub.fetch_public_activities()
|
||||||
|
|
||||||
|
assert activities_ids == []
|
||||||
end
|
end
|
||||||
|
|
||||||
test "home timeline", %{users: %{u1: user}} do
|
test "home timeline", %{users: %{u1: user}} do
|
||||||
|
|
|
@ -26,7 +26,7 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do
|
||||||
{
|
{
|
||||||
Pleroma.Web.ActivityPub.MRF,
|
Pleroma.Web.ActivityPub.MRF,
|
||||||
[],
|
[],
|
||||||
[filter: fn o -> {:ok, o} end]
|
[pipeline_filter: fn o, m -> {:ok, o, m} end]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Pleroma.Web.ActivityPub.ActivityPub,
|
Pleroma.Web.ActivityPub.ActivityPub,
|
||||||
|
@ -51,7 +51,7 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do
|
||||||
Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)
|
Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)
|
||||||
|
|
||||||
assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta))
|
assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta))
|
||||||
assert_called(Pleroma.Web.ActivityPub.MRF.filter(activity))
|
assert_called(Pleroma.Web.ActivityPub.MRF.pipeline_filter(activity, meta))
|
||||||
assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta))
|
assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta))
|
||||||
assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta))
|
assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta))
|
||||||
refute called(Pleroma.Web.Federator.publish(activity))
|
refute called(Pleroma.Web.Federator.publish(activity))
|
||||||
|
@ -68,7 +68,7 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do
|
||||||
{
|
{
|
||||||
Pleroma.Web.ActivityPub.MRF,
|
Pleroma.Web.ActivityPub.MRF,
|
||||||
[],
|
[],
|
||||||
[filter: fn o -> {:ok, o} end]
|
[pipeline_filter: fn o, m -> {:ok, o, m} end]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Pleroma.Web.ActivityPub.ActivityPub,
|
Pleroma.Web.ActivityPub.ActivityPub,
|
||||||
|
@ -93,7 +93,7 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do
|
||||||
Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)
|
Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)
|
||||||
|
|
||||||
assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta))
|
assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta))
|
||||||
assert_called(Pleroma.Web.ActivityPub.MRF.filter(activity))
|
assert_called(Pleroma.Web.ActivityPub.MRF.pipeline_filter(activity, meta))
|
||||||
assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta))
|
assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta))
|
||||||
assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta))
|
assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta))
|
||||||
assert_called(Pleroma.Web.Federator.publish(activity))
|
assert_called(Pleroma.Web.Federator.publish(activity))
|
||||||
|
@ -109,7 +109,7 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do
|
||||||
{
|
{
|
||||||
Pleroma.Web.ActivityPub.MRF,
|
Pleroma.Web.ActivityPub.MRF,
|
||||||
[],
|
[],
|
||||||
[filter: fn o -> {:ok, o} end]
|
[pipeline_filter: fn o, m -> {:ok, o, m} end]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Pleroma.Web.ActivityPub.ActivityPub,
|
Pleroma.Web.ActivityPub.ActivityPub,
|
||||||
|
@ -131,7 +131,7 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do
|
||||||
Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)
|
Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)
|
||||||
|
|
||||||
assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta))
|
assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta))
|
||||||
assert_called(Pleroma.Web.ActivityPub.MRF.filter(activity))
|
assert_called(Pleroma.Web.ActivityPub.MRF.pipeline_filter(activity, meta))
|
||||||
assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta))
|
assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta))
|
||||||
assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta))
|
assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta))
|
||||||
end
|
end
|
||||||
|
@ -148,7 +148,7 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do
|
||||||
{
|
{
|
||||||
Pleroma.Web.ActivityPub.MRF,
|
Pleroma.Web.ActivityPub.MRF,
|
||||||
[],
|
[],
|
||||||
[filter: fn o -> {:ok, o} end]
|
[pipeline_filter: fn o, m -> {:ok, o, m} end]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Pleroma.Web.ActivityPub.ActivityPub,
|
Pleroma.Web.ActivityPub.ActivityPub,
|
||||||
|
@ -170,7 +170,7 @@ defmodule Pleroma.Web.ActivityPub.PipelineTest do
|
||||||
Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)
|
Pleroma.Web.ActivityPub.Pipeline.common_pipeline(activity, meta)
|
||||||
|
|
||||||
assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta))
|
assert_called(Pleroma.Web.ActivityPub.ObjectValidator.validate(activity, meta))
|
||||||
assert_called(Pleroma.Web.ActivityPub.MRF.filter(activity))
|
assert_called(Pleroma.Web.ActivityPub.MRF.pipeline_filter(activity, meta))
|
||||||
assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta))
|
assert_called(Pleroma.Web.ActivityPub.ActivityPub.persist(activity, meta))
|
||||||
assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta))
|
assert_called(Pleroma.Web.ActivityPub.SideEffects.handle(activity, meta))
|
||||||
end
|
end
|
||||||
|
|
|
@ -213,6 +213,17 @@ defmodule Pleroma.Web.CommonAPITest do
|
||||||
|
|
||||||
assert message == :content_too_long
|
assert message == :content_too_long
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "it reject messages via MRF" do
|
||||||
|
clear_config([:mrf_keyword, :reject], ["GNO"])
|
||||||
|
clear_config([:mrf, :policies], [Pleroma.Web.ActivityPub.MRF.KeywordPolicy])
|
||||||
|
|
||||||
|
author = insert(:user)
|
||||||
|
recipient = insert(:user)
|
||||||
|
|
||||||
|
assert {:reject, "[KeywordPolicy] Matches with rejected keyword"} ==
|
||||||
|
CommonAPI.post_chat_message(author, recipient, "GNO/Linux")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "unblocking" do
|
describe "unblocking" do
|
||||||
|
|
|
@ -100,7 +100,7 @@ defmodule Pleroma.Web.PleromaAPI.ChatControllerTest do
|
||||||
|> post("/api/v1/pleroma/chats/#{chat.id}/messages")
|
|> post("/api/v1/pleroma/chats/#{chat.id}/messages")
|
||||||
|> json_response_and_validate_schema(400)
|
|> json_response_and_validate_schema(400)
|
||||||
|
|
||||||
assert result
|
assert %{"error" => "no_content"} == result
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it works with an attachment", %{conn: conn, user: user} do
|
test "it works with an attachment", %{conn: conn, user: user} do
|
||||||
|
@ -126,6 +126,23 @@ defmodule Pleroma.Web.PleromaAPI.ChatControllerTest do
|
||||||
|
|
||||||
assert result["attachment"]
|
assert result["attachment"]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "gets MRF reason when rejected", %{conn: conn, user: user} do
|
||||||
|
clear_config([:mrf_keyword, :reject], ["GNO"])
|
||||||
|
clear_config([:mrf, :policies], [Pleroma.Web.ActivityPub.MRF.KeywordPolicy])
|
||||||
|
|
||||||
|
other_user = insert(:user)
|
||||||
|
|
||||||
|
{:ok, chat} = Chat.get_or_create(user.id, other_user.ap_id)
|
||||||
|
|
||||||
|
result =
|
||||||
|
conn
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|
|> post("/api/v1/pleroma/chats/#{chat.id}/messages", %{"content" => "GNO/Linux"})
|
||||||
|
|> json_response_and_validate_schema(422)
|
||||||
|
|
||||||
|
assert %{"error" => "[KeywordPolicy] Matches with rejected keyword"} == result
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "DELETE /api/v1/pleroma/chats/:id/messages/:message_id" do
|
describe "DELETE /api/v1/pleroma/chats/:id/messages/:message_id" do
|
||||||
|
|
|
@ -56,6 +56,27 @@ defmodule Pleroma.Web.RichMedia.ParserTest do
|
||||||
|
|
||||||
%{method: :get, url: "http://example.com/error"} ->
|
%{method: :get, url: "http://example.com/error"} ->
|
||||||
{:error, :overload}
|
{:error, :overload}
|
||||||
|
|
||||||
|
%{
|
||||||
|
method: :head,
|
||||||
|
url: "http://example.com/huge-page"
|
||||||
|
} ->
|
||||||
|
%Tesla.Env{
|
||||||
|
status: 200,
|
||||||
|
headers: [{"content-length", "2000001"}, {"content-type", "text/html"}]
|
||||||
|
}
|
||||||
|
|
||||||
|
%{
|
||||||
|
method: :head,
|
||||||
|
url: "http://example.com/pdf-file"
|
||||||
|
} ->
|
||||||
|
%Tesla.Env{
|
||||||
|
status: 200,
|
||||||
|
headers: [{"content-length", "1000000"}, {"content-type", "application/pdf"}]
|
||||||
|
}
|
||||||
|
|
||||||
|
%{method: :head} ->
|
||||||
|
%Tesla.Env{status: 404, body: "", headers: []}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
:ok
|
:ok
|
||||||
|
@ -146,4 +167,12 @@ defmodule Pleroma.Web.RichMedia.ParserTest do
|
||||||
test "returns error if getting page was not successful" do
|
test "returns error if getting page was not successful" do
|
||||||
assert {:error, :overload} = Parser.parse("http://example.com/error")
|
assert {:error, :overload} = Parser.parse("http://example.com/error")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "does a HEAD request to check if the body is too large" do
|
||||||
|
assert {:error, :body_too_large} = Parser.parse("http://example.com/huge-page")
|
||||||
|
end
|
||||||
|
|
||||||
|
test "does a HEAD request to check if the body is html" do
|
||||||
|
assert {:error, {:content_type, _}} = Parser.parse("http://example.com/pdf-file")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue