mirror of
https://git.pleroma.social/pleroma/pleroma.git
synced 2024-12-23 00:26:30 +00:00
Merge branch 'develop' into issue/1383
This commit is contained in:
commit
2c40c8b4a2
49 changed files with 773 additions and 97 deletions
|
@ -12,8 +12,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||
|
||||
### Changed
|
||||
- **Breaking:** Pleroma won't start if it detects unapplied migrations
|
||||
- **Breaking:** attachments are removed along with statuses when there are no other references to it
|
||||
- **Breaking:** attachments are removed along with statuses. Does not affect duplicate files and attachments without status.
|
||||
- **Breaking:** Elixir >=1.8 is now required (was >= 1.7)
|
||||
- **Breaking:** `Pleroma.Plugs.RemoteIp` and `:rate_limiter` enabled by default. Please ensure your reverse proxy forwards the real IP!
|
||||
- **Breaking:** attachment links (`config :pleroma, :instance, no_attachment_links` and `config :pleroma, Pleroma.Upload, link_name`) disabled by default
|
||||
- **Breaking:** OAuth: defaulted `[:auth, :enforce_oauth_admin_scope_usage]` setting to `true` which demands `admin` OAuth scope to perform admin actions (in addition to `is_admin` flag on User); make sure to use bundled or newer versions of AdminFE & PleromaFE to access admin / moderator features.
|
||||
- **Breaking:** Dynamic configuration has been rearchitected. The `:pleroma, :instance, dynamic_configuration` setting has been replaced with `config :pleroma, configurable_from_database`. Please backup your configuration to a file and run the migration task to ensure consistency with the new schema.
|
||||
|
@ -27,6 +28,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||
- Deprecated `User.Info` embedded schema (fields moved to `User`)
|
||||
- Store status data inside Flag activity
|
||||
- Deprecated (reorganized as `UserRelationship` entity) User fields with user AP IDs (`blocks`, `mutes`, `muted_reblogs`, `muted_notifications`, `subscribers`).
|
||||
- Rate limiter is now disabled for localhost/socket (unless remoteip plug is enabled)
|
||||
- Logger: default log level changed from `warn` to `info`.
|
||||
- Config mix task `migrate_to_db` truncates `config` table before migrating the config file.
|
||||
<details>
|
||||
|
@ -104,6 +106,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||
- Mastodon API: Change emoji reaction reply format once more
|
||||
- Configuration: `feed.logo` option for tag feed.
|
||||
- Tag feed: `/tags/:tag.rss` - list public statuses by hashtag.
|
||||
- Mastodon API: Add `reacted` property to `emoji_reactions`
|
||||
</details>
|
||||
|
||||
### Fixed
|
||||
|
|
|
@ -586,11 +586,21 @@ config :pleroma, :env, Mix.env()
|
|||
config :http_signatures,
|
||||
adapter: Pleroma.Signature
|
||||
|
||||
config :pleroma, :rate_limit, authentication: {60_000, 15}
|
||||
config :pleroma, :rate_limit,
|
||||
authentication: {60_000, 15},
|
||||
search: [{1000, 10}, {1000, 30}],
|
||||
app_account_creation: {1_800_000, 25},
|
||||
relations_actions: {10_000, 10},
|
||||
relation_id_action: {60_000, 2},
|
||||
statuses_actions: {10_000, 15},
|
||||
status_id_action: {60_000, 3},
|
||||
password_reset: {1_800_000, 5},
|
||||
account_confirmation_resend: {8_640_000, 5},
|
||||
ap_routes: {60_000, 15}
|
||||
|
||||
config :pleroma, Pleroma.ActivityExpiration, enabled: true
|
||||
|
||||
config :pleroma, Pleroma.Plugs.RemoteIp, enabled: false
|
||||
config :pleroma, Pleroma.Plugs.RemoteIp, enabled: true
|
||||
|
||||
config :pleroma, :static_fe, enabled: false
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ Has these additional fields under the `pleroma` object:
|
|||
- `spoiler_text`: a map consisting of alternate representations of the `spoiler_text` property with the key being it's mimetype. Currently the only alternate representation supported is `text/plain`
|
||||
- `expires_at`: a datetime (iso8601) that states when the post will expire (be deleted automatically), or empty if the post won't expire
|
||||
- `thread_muted`: true if the thread the post belongs to is muted
|
||||
- `emoji_reactions`: A list with emoji / reaction maps. The format is {emoji: "☕", count: 1}. Contains no information about the reacting users, for that use the `emoji_reactions_by` endpoint.
|
||||
- `emoji_reactions`: A list with emoji / reaction maps. The format is `{emoji: "☕", count: 1, reacted: true}`. Contains no information about the reacting users, for that use the `emoji_reactions_by` endpoint.
|
||||
|
||||
## Attachments
|
||||
|
||||
|
|
|
@ -455,7 +455,7 @@ Emoji reactions work a lot like favourites do. They make it possible to react to
|
|||
* Example Response:
|
||||
```json
|
||||
[
|
||||
{"emoji": "😀", "count": 2, "accounts": [{"id" => "xyz.."...}, {"id" => "zyx..."}]},
|
||||
{"emoji": "☕", "count": 1, "accounts": [{"id" => "abc..."}]}
|
||||
{"emoji": "😀", "count": 2, "reacted": true, "accounts": [{"id" => "xyz.."...}, {"id" => "zyx..."}]},
|
||||
{"emoji": "☕", "count": 1, "reacted": false, "accounts": [{"id" => "abc..."}]}
|
||||
]
|
||||
```
|
||||
|
|
|
@ -308,16 +308,15 @@ This will make Pleroma listen on `127.0.0.1` port `8080` and generate urls start
|
|||
Available options:
|
||||
|
||||
* `enabled` - Enable/disable the plug. Defaults to `false`.
|
||||
* `headers` - A list of strings naming the `req_headers` to use when deriving the `remote_ip`. Order does not matter. Defaults to `~w[forwarded x-forwarded-for x-client-ip x-real-ip]`.
|
||||
* `headers` - A list of strings naming the `req_headers` to use when deriving the `remote_ip`. Order does not matter. Defaults to `["x-forwarded-for"]`.
|
||||
* `proxies` - A list of strings in [CIDR](https://en.wikipedia.org/wiki/CIDR) notation specifying the IPs of known proxies. Defaults to `[]`.
|
||||
* `reserved` - Defaults to [localhost](https://en.wikipedia.org/wiki/Localhost) and [private network](https://en.wikipedia.org/wiki/Private_network).
|
||||
|
||||
|
||||
### :rate_limit
|
||||
|
||||
This is an advanced feature and disabled by default.
|
||||
|
||||
If your instance is behind a reverse proxy you must enable and configure [`Pleroma.Plugs.RemoteIp`](#pleroma-plugs-remoteip).
|
||||
!!! note
|
||||
If your instance is behind a reverse proxy ensure [`Pleroma.Plugs.RemoteIp`](#pleroma-plugs-remoteip) is enabled (it is enabled by default).
|
||||
|
||||
A keyword list of rate limiters where a key is a limiter name and value is the limiter configuration. The basic configuration is a tuple where:
|
||||
|
||||
|
@ -326,14 +325,31 @@ A keyword list of rate limiters where a key is a limiter name and value is the l
|
|||
|
||||
It is also possible to have different limits for unauthenticated and authenticated users: the keyword value must be a list of two tuples where the first one is a config for unauthenticated users and the second one is for authenticated.
|
||||
|
||||
For example:
|
||||
|
||||
```elixir
|
||||
config :pleroma, :rate_limit,
|
||||
authentication: {60_000, 15},
|
||||
search: [{1000, 10}, {1000, 30}]
|
||||
```
|
||||
|
||||
Means that:
|
||||
|
||||
1. In 60 seconds, 15 authentication attempts can be performed from the same IP address.
|
||||
2. In 1 second, 10 search requests can be performed from the same IP adress by unauthenticated users, while authenticated users can perform 30 search requests per second.
|
||||
|
||||
Supported rate limiters:
|
||||
|
||||
* `:search` for the search requests (account & status search etc.)
|
||||
* `:app_account_creation` for registering user accounts from the same IP address
|
||||
* `:relations_actions` for actions on relations with all users (follow, unfollow)
|
||||
* `:relation_id_action` for actions on relation with a specific user (follow, unfollow)
|
||||
* `:statuses_actions` for create / delete / fav / unfav / reblog / unreblog actions on any statuses
|
||||
* `:status_id_action` for fav / unfav or reblog / unreblog actions on the same status by the same user
|
||||
* `:search` - Account/Status search.
|
||||
* `:app_account_creation` - Account registration from the API.
|
||||
* `:relations_actions` - Following/Unfollowing in general.
|
||||
* `:relation_id_action` - Following/Unfollowing for a specific user.
|
||||
* `:statuses_actions` - Status actions such as: (un)repeating, (un)favouriting, creating, deleting.
|
||||
* `:status_id_action` - (un)Repeating/(un)Favouriting a particular status.
|
||||
* `:authentication` - Authentication actions, i.e getting an OAuth token.
|
||||
* `:password_reset` - Requesting password reset emails.
|
||||
* `:account_confirmation_resend` - Requesting resending account confirmation emails.
|
||||
* `:ap_routes` - Requesting statuses via ActivityPub.
|
||||
|
||||
### :web_cache_ttl
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ defmodule Pleroma.Application do
|
|||
def start(_type, _args) do
|
||||
Pleroma.HTML.compile_scrubbers()
|
||||
Pleroma.Config.DeprecationWarnings.warn()
|
||||
Pleroma.Plugs.HTTPSecurityPlug.warn_if_disabled()
|
||||
Pleroma.Repo.check_migrations_applied!()
|
||||
setup_instrumenters()
|
||||
load_custom_modules()
|
||||
|
|
|
@ -6,6 +6,8 @@ defmodule Pleroma.Plugs.HTTPSecurityPlug do
|
|||
alias Pleroma.Config
|
||||
import Plug.Conn
|
||||
|
||||
require Logger
|
||||
|
||||
def init(opts), do: opts
|
||||
|
||||
def call(conn, _options) do
|
||||
|
@ -90,6 +92,51 @@ defmodule Pleroma.Plugs.HTTPSecurityPlug do
|
|||
|> Enum.join("; ")
|
||||
end
|
||||
|
||||
def warn_if_disabled do
|
||||
unless Config.get([:http_security, :enabled]) do
|
||||
Logger.warn("
|
||||
.i;;;;i.
|
||||
iYcviii;vXY:
|
||||
.YXi .i1c.
|
||||
.YC. . in7.
|
||||
.vc. ...... ;1c.
|
||||
i7, .. .;1;
|
||||
i7, .. ... .Y1i
|
||||
,7v .6MMM@; .YX,
|
||||
.7;. ..IMMMMMM1 :t7.
|
||||
.;Y. ;$MMMMMM9. :tc.
|
||||
vY. .. .nMMM@MMU. ;1v.
|
||||
i7i ... .#MM@M@C. .....:71i
|
||||
it: .... $MMM@9;.,i;;;i,;tti
|
||||
:t7. ..... 0MMMWv.,iii:::,,;St.
|
||||
.nC. ..... IMMMQ..,::::::,.,czX.
|
||||
.ct: ....... .ZMMMI..,:::::::,,:76Y.
|
||||
c2: ......,i..Y$M@t..:::::::,,..inZY
|
||||
vov ......:ii..c$MBc..,,,,,,,,,,..iI9i
|
||||
i9Y ......iii:..7@MA,..,,,,,,,,,....;AA:
|
||||
iIS. ......:ii::..;@MI....,............;Ez.
|
||||
.I9. ......:i::::...8M1..................C0z.
|
||||
.z9; ......:i::::,.. .i:...................zWX.
|
||||
vbv ......,i::::,,. ................. :AQY
|
||||
c6Y. .,...,::::,,..:t0@@QY. ................ :8bi
|
||||
:6S. ..,,...,:::,,,..EMMMMMMI. ............... .;bZ,
|
||||
:6o, .,,,,..:::,,,..i#MMMMMM#v................. YW2.
|
||||
.n8i ..,,,,,,,::,,,,.. tMMMMM@C:.................. .1Wn
|
||||
7Uc. .:::,,,,,::,,,,.. i1t;,..................... .UEi
|
||||
7C...::::::::::::,,,,.. .................... vSi.
|
||||
;1;...,,::::::,......... .................. Yz:
|
||||
v97,......... .voC.
|
||||
izAotX7777777777777777777777777777777777777777Y7n92:
|
||||
.;CoIIIIIUAA666666699999ZZZZZZZZZZZZZZZZZZZZ6ov.
|
||||
|
||||
HTTP Security is disabled. Please re-enable it to prevent users from attacking
|
||||
your instance and your users via malicious posts:
|
||||
|
||||
config :pleroma, :http_security, enabled: true
|
||||
")
|
||||
end
|
||||
end
|
||||
|
||||
defp maybe_send_sts_header(conn, true) do
|
||||
max_age_sts = Config.get([:http_security, :sts_max_age])
|
||||
max_age_ct = Config.get([:http_security, :ct_max_age])
|
||||
|
|
|
@ -67,6 +67,8 @@ defmodule Pleroma.Plugs.RateLimiter do
|
|||
alias Pleroma.Plugs.RateLimiter.LimiterSupervisor
|
||||
alias Pleroma.User
|
||||
|
||||
require Logger
|
||||
|
||||
def init(opts) do
|
||||
limiter_name = Keyword.get(opts, :name)
|
||||
|
||||
|
@ -89,18 +91,39 @@ defmodule Pleroma.Plugs.RateLimiter do
|
|||
def call(conn, nil), do: conn
|
||||
|
||||
def call(conn, settings) do
|
||||
settings
|
||||
|> incorporate_conn_info(conn)
|
||||
|> check_rate()
|
||||
|> case do
|
||||
{:ok, _count} ->
|
||||
case disabled?() do
|
||||
true ->
|
||||
if Pleroma.Config.get(:env) == :prod,
|
||||
do: Logger.warn("Rate limiter is disabled for localhost/socket")
|
||||
|
||||
conn
|
||||
|
||||
{:error, _count} ->
|
||||
render_throttled_error(conn)
|
||||
false ->
|
||||
settings
|
||||
|> incorporate_conn_info(conn)
|
||||
|> check_rate()
|
||||
|> case do
|
||||
{:ok, _count} ->
|
||||
conn
|
||||
|
||||
{:error, _count} ->
|
||||
render_throttled_error(conn)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def disabled? do
|
||||
localhost_or_socket =
|
||||
Pleroma.Config.get([Pleroma.Web.Endpoint, :http, :ip])
|
||||
|> Tuple.to_list()
|
||||
|> Enum.join(".")
|
||||
|> String.match?(~r/^local|^127.0.0.1/)
|
||||
|
||||
remote_ip_disabled = not Pleroma.Config.get([Pleroma.Plugs.RemoteIp, :enabled])
|
||||
|
||||
localhost_or_socket and remote_ip_disabled
|
||||
end
|
||||
|
||||
def inspect_bucket(conn, name_root, settings) do
|
||||
settings =
|
||||
settings
|
||||
|
|
|
@ -10,10 +10,7 @@ defmodule Pleroma.Plugs.RemoteIp do
|
|||
@behaviour Plug
|
||||
|
||||
@headers ~w[
|
||||
forwarded
|
||||
x-forwarded-for
|
||||
x-client-ip
|
||||
x-real-ip
|
||||
]
|
||||
|
||||
# https://en.wikipedia.org/wiki/Localhost
|
||||
|
|
|
@ -325,12 +325,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
def react_with_emoji(user, object, emoji, options \\ []) do
|
||||
with local <- Keyword.get(options, :local, true),
|
||||
activity_id <- Keyword.get(options, :activity_id, nil),
|
||||
Pleroma.Emoji.is_unicode_emoji?(emoji),
|
||||
true <- Pleroma.Emoji.is_unicode_emoji?(emoji),
|
||||
reaction_data <- make_emoji_reaction_data(user, object, emoji, activity_id),
|
||||
{:ok, activity} <- insert(reaction_data, local),
|
||||
{:ok, object} <- add_emoji_reaction_to_object(activity, object),
|
||||
:ok <- maybe_federate(activity) do
|
||||
{:ok, activity, object}
|
||||
else
|
||||
e -> {:error, e}
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -345,6 +347,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
{:ok, object} <- remove_emoji_reaction_from_object(reaction_activity, object),
|
||||
:ok <- maybe_federate(activity) do
|
||||
{:ok, activity, object}
|
||||
else
|
||||
e -> {:error, e}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -256,7 +256,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
|||
emoji_reactions =
|
||||
with %{data: %{"reactions" => emoji_reactions}} <- object do
|
||||
Enum.map(emoji_reactions, fn [emoji, users] ->
|
||||
%{emoji: emoji, count: length(users)}
|
||||
%{
|
||||
emoji: emoji,
|
||||
count: length(users),
|
||||
reacted: !!(opts[:for] && opts[:for].ap_id in users)
|
||||
}
|
||||
end)
|
||||
else
|
||||
_ -> []
|
||||
|
|
|
@ -573,11 +573,14 @@ keeping it in cache for #{div(cache_ms, 1000)}s")
|
|||
assumed to be emojis and stored in the new `pack.json` file.
|
||||
"""
|
||||
def import_from_fs(conn, _params) do
|
||||
with {:ok, results} <- File.ls(emoji_dir_path()) do
|
||||
emoji_path = emoji_dir_path()
|
||||
|
||||
with {:ok, %{access: :read_write}} <- File.stat(emoji_path),
|
||||
{:ok, results} <- File.ls(emoji_path) do
|
||||
imported_pack_names =
|
||||
results
|
||||
|> Enum.filter(fn file ->
|
||||
dir_path = Path.join(emoji_dir_path(), file)
|
||||
dir_path = Path.join(emoji_path, file)
|
||||
# Find the directories that do NOT have pack.json
|
||||
File.dir?(dir_path) and not File.exists?(Path.join(dir_path, "pack.json"))
|
||||
end)
|
||||
|
@ -585,6 +588,11 @@ keeping it in cache for #{div(cache_ms, 1000)}s")
|
|||
|
||||
json(conn, imported_pack_names)
|
||||
else
|
||||
{:ok, %{access: _}} ->
|
||||
conn
|
||||
|> put_status(:internal_server_error)
|
||||
|> json(%{error: "Error: emoji pack directory must be writable"})
|
||||
|
||||
{:error, _} ->
|
||||
conn
|
||||
|> put_status(:internal_server_error)
|
||||
|
|
|
@ -47,13 +47,16 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do
|
|||
Object.normalize(activity) do
|
||||
reactions =
|
||||
emoji_reactions
|
||||
|> Enum.map(fn [emoji, users] ->
|
||||
users = Enum.map(users, &User.get_cached_by_ap_id/1)
|
||||
|> Enum.map(fn [emoji, user_ap_ids] ->
|
||||
users =
|
||||
Enum.map(user_ap_ids, &User.get_cached_by_ap_id/1)
|
||||
|> Enum.filter(& &1)
|
||||
|
||||
%{
|
||||
emoji: emoji,
|
||||
count: length(users),
|
||||
accounts: AccountView.render("index.json", %{users: users, for: user, as: :user})
|
||||
accounts: AccountView.render("index.json", %{users: users, for: user, as: :user}),
|
||||
reacted: !!(user && user.ap_id in user_ap_ids)
|
||||
}
|
||||
end)
|
||||
|
||||
|
|
|
@ -48,6 +48,6 @@ defmodule Pleroma.Web.RichMedia.Parsers.MetaTagsParser do
|
|||
defp maybe_put_title(meta, _), do: meta
|
||||
|
||||
defp get_page_title(html) do
|
||||
Floki.find(html, "title") |> List.first() |> Floki.text()
|
||||
Floki.find(html, "html head title") |> List.first() |> Floki.text()
|
||||
end
|
||||
end
|
||||
|
|
|
@ -138,7 +138,8 @@ defmodule Pleroma.Web.Streamer.Worker do
|
|||
|
||||
with parent <- Object.normalize(item) || item,
|
||||
true <-
|
||||
Enum.all?([blocked_ap_ids, muted_ap_ids, reblog_muted_ap_ids], &(item.actor not in &1)),
|
||||
Enum.all?([blocked_ap_ids, muted_ap_ids], &(item.actor not in &1)),
|
||||
true <- item.data["type"] != "Announce" || item.actor not in reblog_muted_ap_ids,
|
||||
true <- Enum.all?([blocked_ap_ids, muted_ap_ids], &(parent.data["actor"] not in &1)),
|
||||
true <- MapSet.disjoint?(recipients, recipient_blocks),
|
||||
%{host: item_host} <- URI.parse(item.actor),
|
||||
|
|
|
@ -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/vendors~app.b2603a50868c68a1c192.css rel=stylesheet><link href=/static/css/app.ae04505b31bb0ee2765e.css rel=stylesheet><link href=/static/fontello.1579102213354.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.86bc6d5e06d2e17976c5.js></script><script type=text/javascript src=/static/js/app.a43640742dacfb13b6b0.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/vendors~app.b2603a50868c68a1c192.css rel=stylesheet><link href=/static/css/app.ae04505b31bb0ee2765e.css rel=stylesheet><link href=/static/fontello.1580232989700.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.9ab182239f3a2abee89f.js></script><script type=text/javascript src=/static/js/app.9cfed8f3d06c299128ea.js></script></body></html>
|
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Binary file not shown.
Binary file not shown.
BIN
priv/static/static/font/fontello.1580232989700.woff2
Normal file
BIN
priv/static/static/font/fontello.1580232989700.woff2
Normal file
Binary file not shown.
136
priv/static/static/fontello.1580232989700.css
vendored
Normal file
136
priv/static/static/fontello.1580232989700.css
vendored
Normal file
|
@ -0,0 +1,136 @@
|
|||
@font-face {
|
||||
font-family: "Icons";
|
||||
src: url("./font/fontello.1580232989700.eot");
|
||||
src: url("./font/fontello.1580232989700.eot") format("embedded-opentype"),
|
||||
url("./font/fontello.1580232989700.woff2") format("woff2"),
|
||||
url("./font/fontello.1580232989700.woff") format("woff"),
|
||||
url("./font/fontello.1580232989700.ttf") format("truetype"),
|
||||
url("./font/fontello.1580232989700.svg") format("svg");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
[class^="icon-"]::before,
|
||||
[class*=" icon-"]::before {
|
||||
font-family: "Icons";
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
speak: none;
|
||||
display: inline-block;
|
||||
text-decoration: inherit;
|
||||
width: 1em;
|
||||
margin-right: .2em;
|
||||
text-align: center;
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
line-height: 1em;
|
||||
margin-left: .2em;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-spin4::before { content: "\e834"; }
|
||||
|
||||
.icon-cancel::before { content: "\e800"; }
|
||||
|
||||
.icon-upload::before { content: "\e801"; }
|
||||
|
||||
.icon-spin3::before { content: "\e832"; }
|
||||
|
||||
.icon-reply::before { content: "\f112"; }
|
||||
|
||||
.icon-star::before { content: "\e802"; }
|
||||
|
||||
.icon-star-empty::before { content: "\e803"; }
|
||||
|
||||
.icon-retweet::before { content: "\e804"; }
|
||||
|
||||
.icon-eye-off::before { content: "\e805"; }
|
||||
|
||||
.icon-binoculars::before { content: "\f1e5"; }
|
||||
|
||||
.icon-cog::before { content: "\e807"; }
|
||||
|
||||
.icon-user-plus::before { content: "\f234"; }
|
||||
|
||||
.icon-menu::before { content: "\f0c9"; }
|
||||
|
||||
.icon-logout::before { content: "\e808"; }
|
||||
|
||||
.icon-down-open::before { content: "\e809"; }
|
||||
|
||||
.icon-attach::before { content: "\e80a"; }
|
||||
|
||||
.icon-link-ext::before { content: "\f08e"; }
|
||||
|
||||
.icon-link-ext-alt::before { content: "\f08f"; }
|
||||
|
||||
.icon-picture::before { content: "\e80b"; }
|
||||
|
||||
.icon-video::before { content: "\e80c"; }
|
||||
|
||||
.icon-right-open::before { content: "\e80d"; }
|
||||
|
||||
.icon-left-open::before { content: "\e80e"; }
|
||||
|
||||
.icon-up-open::before { content: "\e80f"; }
|
||||
|
||||
.icon-comment-empty::before { content: "\f0e5"; }
|
||||
|
||||
.icon-mail-alt::before { content: "\f0e0"; }
|
||||
|
||||
.icon-lock::before { content: "\e811"; }
|
||||
|
||||
.icon-lock-open-alt::before { content: "\f13e"; }
|
||||
|
||||
.icon-globe::before { content: "\e812"; }
|
||||
|
||||
.icon-brush::before { content: "\e813"; }
|
||||
|
||||
.icon-search::before { content: "\e806"; }
|
||||
|
||||
.icon-adjust::before { content: "\e816"; }
|
||||
|
||||
.icon-thumbs-up-alt::before { content: "\f164"; }
|
||||
|
||||
.icon-attention::before { content: "\e814"; }
|
||||
|
||||
.icon-plus-squared::before { content: "\f0fe"; }
|
||||
|
||||
.icon-plus::before { content: "\e815"; }
|
||||
|
||||
.icon-edit::before { content: "\e817"; }
|
||||
|
||||
.icon-play-circled::before { content: "\f144"; }
|
||||
|
||||
.icon-pencil::before { content: "\e818"; }
|
||||
|
||||
.icon-chart-bar::before { content: "\e81b"; }
|
||||
|
||||
.icon-smile::before { content: "\f118"; }
|
||||
|
||||
.icon-bell-alt::before { content: "\f0f3"; }
|
||||
|
||||
.icon-wrench::before { content: "\e81a"; }
|
||||
|
||||
.icon-pin::before { content: "\e819"; }
|
||||
|
||||
.icon-ellipsis::before { content: "\f141"; }
|
||||
|
||||
.icon-bell-ringing-o::before { content: "\e810"; }
|
||||
|
||||
.icon-zoom-in::before { content: "\e81c"; }
|
||||
|
||||
.icon-gauge::before { content: "\f0e4"; }
|
||||
|
||||
.icon-users::before { content: "\e81d"; }
|
||||
|
||||
.icon-info-circled::before { content: "\e81f"; }
|
||||
|
||||
.icon-home-2::before { content: "\e821"; }
|
||||
|
||||
.icon-chat::before { content: "\e81e"; }
|
||||
|
||||
.icon-login::before { content: "\e820"; }
|
||||
|
||||
.icon-arrow-curved::before { content: "\e822"; }
|
|
@ -1,2 +1,2 @@
|
|||
(window.webpackJsonp=window.webpackJsonp||[]).push([[2],{567:function(t,e,i){var c=i(568);"string"==typeof c&&(c=[[t.i,c,""]]),c.locals&&(t.exports=c.locals);(0,i(3).default)("cc6cdea4",c,!0,{})},568:function(t,e,i){(t.exports=i(2)(!1)).push([t.i,".sticker-picker{width:100%}.sticker-picker .contents{min-height:250px}.sticker-picker .contents .sticker-picker-content{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:0 4px}.sticker-picker .contents .sticker-picker-content .sticker{display:-ms-flexbox;display:flex;-ms-flex:1 1 auto;flex:1 1 auto;margin:4px;width:56px;height:56px}.sticker-picker .contents .sticker-picker-content .sticker img{height:100%}.sticker-picker .contents .sticker-picker-content .sticker img:hover{filter:drop-shadow(0 0 5px var(--link,#d8a070))}",""])},569:function(t,e,i){"use strict";i.r(e);var c=i(88),n={components:{TabSwitcher:i(49).a},data:function(){return{meta:{stickers:[]},path:""}},computed:{pack:function(){return this.$store.state.instance.stickers||[]}},methods:{clear:function(){this.meta={stickers:[]}},pick:function(t,e){var i=this,n=this.$store;fetch(t).then(function(t){t.blob().then(function(t){var a=new File([t],e,{mimetype:"image/png"}),s=new FormData;s.append("file",a),c.a.uploadMedia({store:n,formData:s}).then(function(t){i.$emit("uploaded",t),i.clear()},function(t){console.warn("Can't attach sticker"),console.warn(t),i.$emit("upload-failed","default")})})})}}},a=i(0);var s=function(t){i(567)},r=Object(a.a)(n,function(){var t=this,e=t.$createElement,i=t._self._c||e;return i("div",{staticClass:"sticker-picker"},[i("tab-switcher",{staticClass:"tab-switcher",attrs:{"render-only-focused":!0,"scrollable-tabs":""}},t._l(t.pack,function(e){return i("div",{key:e.path,staticClass:"sticker-picker-content",attrs:{"image-tooltip":e.meta.title,image:e.path+e.meta.tabIcon}},t._l(e.meta.stickers,function(c){return i("div",{key:c,staticClass:"sticker",on:{click:function(i){i.stopPropagation(),i.preventDefault(),t.pick(e.path+c,e.meta.title)}}},[i("img",{attrs:{src:e.path+c}})])}),0)}),0)],1)},[],!1,s,null,null);e.default=r.exports}}]);
|
||||
//# sourceMappingURL=2.8896ea39a0ea8016391a.js.map
|
||||
(window.webpackJsonp=window.webpackJsonp||[]).push([[2],{575:function(t,e,i){var c=i(576);"string"==typeof c&&(c=[[t.i,c,""]]),c.locals&&(t.exports=c.locals);(0,i(3).default)("cc6cdea4",c,!0,{})},576:function(t,e,i){(t.exports=i(2)(!1)).push([t.i,".sticker-picker{width:100%}.sticker-picker .contents{min-height:250px}.sticker-picker .contents .sticker-picker-content{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:0 4px}.sticker-picker .contents .sticker-picker-content .sticker{display:-ms-flexbox;display:flex;-ms-flex:1 1 auto;flex:1 1 auto;margin:4px;width:56px;height:56px}.sticker-picker .contents .sticker-picker-content .sticker img{height:100%}.sticker-picker .contents .sticker-picker-content .sticker img:hover{filter:drop-shadow(0 0 5px var(--link,#d8a070))}",""])},577:function(t,e,i){"use strict";i.r(e);var c=i(88),n={components:{TabSwitcher:i(51).a},data:function(){return{meta:{stickers:[]},path:""}},computed:{pack:function(){return this.$store.state.instance.stickers||[]}},methods:{clear:function(){this.meta={stickers:[]}},pick:function(t,e){var i=this,n=this.$store;fetch(t).then(function(t){t.blob().then(function(t){var a=new File([t],e,{mimetype:"image/png"}),s=new FormData;s.append("file",a),c.a.uploadMedia({store:n,formData:s}).then(function(t){i.$emit("uploaded",t),i.clear()},function(t){console.warn("Can't attach sticker"),console.warn(t),i.$emit("upload-failed","default")})})})}}},a=i(0);var s=function(t){i(575)},r=Object(a.a)(n,function(){var t=this,e=t.$createElement,i=t._self._c||e;return i("div",{staticClass:"sticker-picker"},[i("tab-switcher",{staticClass:"tab-switcher",attrs:{"render-only-focused":!0,"scrollable-tabs":""}},t._l(t.pack,function(e){return i("div",{key:e.path,staticClass:"sticker-picker-content",attrs:{"image-tooltip":e.meta.title,image:e.path+e.meta.tabIcon}},t._l(e.meta.stickers,function(c){return i("div",{key:c,staticClass:"sticker",on:{click:function(i){i.stopPropagation(),i.preventDefault(),t.pick(e.path+c,e.meta.title)}}},[i("img",{attrs:{src:e.path+c}})])}),0)}),0)],1)},[],!1,s,null,null);e.default=r.exports}}]);
|
||||
//# sourceMappingURL=2.59b096781ddca107175d.js.map
|
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.9cfed8f3d06c299128ea.js
Normal file
2
priv/static/static/js/app.9cfed8f3d06c299128ea.js
Normal file
File diff suppressed because one or more lines are too long
1
priv/static/static/js/app.9cfed8f3d06c299128ea.js.map
Normal file
1
priv/static/static/js/app.9cfed8f3d06c299128ea.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
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
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,4 +1,4 @@
|
|||
var serviceWorkerOption = {"assets":["/static/fontello.1579102213354.css","/static/font/fontello.1579102213354.eot","/static/font/fontello.1579102213354.svg","/static/font/fontello.1579102213354.ttf","/static/font/fontello.1579102213354.woff","/static/font/fontello.1579102213354.woff2","/static/img/nsfw.74818f9.png","/static/css/app.ae04505b31bb0ee2765e.css","/static/js/app.a43640742dacfb13b6b0.js","/static/css/vendors~app.b2603a50868c68a1c192.css","/static/js/vendors~app.86bc6d5e06d2e17976c5.js","/static/js/2.8896ea39a0ea8016391a.js"]};
|
||||
var serviceWorkerOption = {"assets":["/static/fontello.1580232989700.css","/static/font/fontello.1580232989700.eot","/static/font/fontello.1580232989700.svg","/static/font/fontello.1580232989700.ttf","/static/font/fontello.1580232989700.woff","/static/font/fontello.1580232989700.woff2","/static/img/nsfw.74818f9.png","/static/css/app.ae04505b31bb0ee2765e.css","/static/js/app.9cfed8f3d06c299128ea.js","/static/css/vendors~app.b2603a50868c68a1c192.css","/static/js/vendors~app.9ab182239f3a2abee89f.js","/static/js/2.59b096781ddca107175d.js"]};
|
||||
|
||||
!function(e){var n={};function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:r})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,n){if(1&n&&(e=t(e)),8&n)return e;if(4&n&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(t.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var o in e)t.d(r,o,function(n){return e[n]}.bind(null,o));return r},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},t.p="/",t(t.s=1)}([function(e,n){
|
||||
/*!
|
||||
|
|
File diff suppressed because one or more lines are too long
30
test/fixtures/emoji-reaction-no-emoji.json
vendored
Normal file
30
test/fixtures/emoji-reaction-no-emoji.json
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"type": "EmojiReaction",
|
||||
"signature": {
|
||||
"type": "RsaSignature2017",
|
||||
"signatureValue": "fdxMfQSMwbC6wP6sh6neS/vM5879K67yQkHTbiT5Npr5wAac0y6+o3Ij+41tN3rL6wfuGTosSBTHOtta6R4GCOOhCaCSLMZKypnp1VltCzLDoyrZELnYQIC8gpUXVmIycZbREk22qWUe/w7DAFaKK4UscBlHDzeDVcA0K3Se5Sluqi9/Zh+ldAnEzj/rSEPDjrtvf5wGNf3fHxbKSRKFt90JvKK6hS+vxKUhlRFDf6/SMETw+EhwJSNW4d10yMUakqUWsFv4Acq5LW7l+HpYMvlYY1FZhNde1+uonnCyuQDyvzkff8zwtEJmAXC4RivO/VVLa17SmqheJZfI8oluVg==",
|
||||
"creator": "http://mastodon.example.org/users/admin#main-key",
|
||||
"created": "2018-02-17T18:57:49Z"
|
||||
},
|
||||
"object": "http://localtesting.pleroma.lol/objects/eb92579d-3417-42a8-8652-2492c2d4f454",
|
||||
"content": "~",
|
||||
"nickname": "lain",
|
||||
"id": "http://mastodon.example.org/users/admin#reactions/2",
|
||||
"actor": "http://mastodon.example.org/users/admin",
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://w3id.org/security/v1",
|
||||
{
|
||||
"toot": "http://joinmastodon.org/ns#",
|
||||
"sensitive": "as:sensitive",
|
||||
"ostatus": "http://ostatus.org#",
|
||||
"movedTo": "as:movedTo",
|
||||
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
|
||||
"inReplyToAtomUri": "ostatus:inReplyToAtomUri",
|
||||
"conversation": "ostatus:conversation",
|
||||
"atomUri": "ostatus:atomUri",
|
||||
"Hashtag": "as:Hashtag",
|
||||
"Emoji": "toot:Emoji"
|
||||
}
|
||||
]
|
||||
}
|
30
test/fixtures/emoji-reaction-too-long.json
vendored
Normal file
30
test/fixtures/emoji-reaction-too-long.json
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"type": "EmojiReaction",
|
||||
"signature": {
|
||||
"type": "RsaSignature2017",
|
||||
"signatureValue": "fdxMfQSMwbC6wP6sh6neS/vM5879K67yQkHTbiT5Npr5wAac0y6+o3Ij+41tN3rL6wfuGTosSBTHOtta6R4GCOOhCaCSLMZKypnp1VltCzLDoyrZELnYQIC8gpUXVmIycZbREk22qWUe/w7DAFaKK4UscBlHDzeDVcA0K3Se5Sluqi9/Zh+ldAnEzj/rSEPDjrtvf5wGNf3fHxbKSRKFt90JvKK6hS+vxKUhlRFDf6/SMETw+EhwJSNW4d10yMUakqUWsFv4Acq5LW7l+HpYMvlYY1FZhNde1+uonnCyuQDyvzkff8zwtEJmAXC4RivO/VVLa17SmqheJZfI8oluVg==",
|
||||
"creator": "http://mastodon.example.org/users/admin#main-key",
|
||||
"created": "2018-02-17T18:57:49Z"
|
||||
},
|
||||
"object": "http://localtesting.pleroma.lol/objects/eb92579d-3417-42a8-8652-2492c2d4f454",
|
||||
"content": "👌👌",
|
||||
"nickname": "lain",
|
||||
"id": "http://mastodon.example.org/users/admin#reactions/2",
|
||||
"actor": "http://mastodon.example.org/users/admin",
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
"https://w3id.org/security/v1",
|
||||
{
|
||||
"toot": "http://joinmastodon.org/ns#",
|
||||
"sensitive": "as:sensitive",
|
||||
"ostatus": "http://ostatus.org#",
|
||||
"movedTo": "as:movedTo",
|
||||
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
|
||||
"inReplyToAtomUri": "ostatus:inReplyToAtomUri",
|
||||
"conversation": "ostatus:conversation",
|
||||
"atomUri": "ostatus:atomUri",
|
||||
"Hashtag": "as:Hashtag",
|
||||
"Emoji": "toot:Emoji"
|
||||
}
|
||||
]
|
||||
}
|
228
test/fixtures/nypd-facial-recognition-children-teenagers4.html
vendored
Normal file
228
test/fixtures/nypd-facial-recognition-children-teenagers4.html
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -16,6 +16,7 @@ defmodule Pleroma.Plugs.RateLimiterTest do
|
|||
test "config is required for plug to work" do
|
||||
limiter_name = :test_init
|
||||
Pleroma.Config.put([:rate_limit, limiter_name], {1, 1})
|
||||
Pleroma.Config.put([Pleroma.Web.Endpoint, :http, :ip], {8, 8, 8, 8})
|
||||
|
||||
assert %{limits: {1, 1}, name: :test_init, opts: [name: :test_init]} ==
|
||||
RateLimiter.init(name: limiter_name)
|
||||
|
@ -23,11 +24,39 @@ defmodule Pleroma.Plugs.RateLimiterTest do
|
|||
assert nil == RateLimiter.init(name: :foo)
|
||||
end
|
||||
|
||||
test "it is disabled for localhost" do
|
||||
limiter_name = :test_init
|
||||
Pleroma.Config.put([:rate_limit, limiter_name], {1, 1})
|
||||
Pleroma.Config.put([Pleroma.Web.Endpoint, :http, :ip], {127, 0, 0, 1})
|
||||
Pleroma.Config.put([Pleroma.Plugs.RemoteIp, :enabled], false)
|
||||
|
||||
assert RateLimiter.disabled?() == true
|
||||
end
|
||||
|
||||
test "it is disabled for socket" do
|
||||
limiter_name = :test_init
|
||||
Pleroma.Config.put([:rate_limit, limiter_name], {1, 1})
|
||||
Pleroma.Config.put([Pleroma.Web.Endpoint, :http, :ip], {:local, "/path/to/pleroma.sock"})
|
||||
Pleroma.Config.put([Pleroma.Plugs.RemoteIp, :enabled], false)
|
||||
|
||||
assert RateLimiter.disabled?() == true
|
||||
end
|
||||
|
||||
test "it is enabled for socket when remote ip is enabled" do
|
||||
limiter_name = :test_init
|
||||
Pleroma.Config.put([:rate_limit, limiter_name], {1, 1})
|
||||
Pleroma.Config.put([Pleroma.Web.Endpoint, :http, :ip], {:local, "/path/to/pleroma.sock"})
|
||||
Pleroma.Config.put([Pleroma.Plugs.RemoteIp, :enabled], true)
|
||||
|
||||
assert RateLimiter.disabled?() == false
|
||||
end
|
||||
|
||||
test "it restricts based on config values" do
|
||||
limiter_name = :test_opts
|
||||
scale = 80
|
||||
limit = 5
|
||||
|
||||
Pleroma.Config.put([Pleroma.Web.Endpoint, :http, :ip], {8, 8, 8, 8})
|
||||
Pleroma.Config.put([:rate_limit, limiter_name], {scale, limit})
|
||||
|
||||
opts = RateLimiter.init(name: limiter_name)
|
||||
|
@ -61,6 +90,7 @@ defmodule Pleroma.Plugs.RateLimiterTest do
|
|||
limiter_name = :test_bucket_name
|
||||
|
||||
Pleroma.Config.put([:rate_limit, limiter_name], {1000, 5})
|
||||
Pleroma.Config.put([Pleroma.Web.Endpoint, :http, :ip], {8, 8, 8, 8})
|
||||
|
||||
base_bucket_name = "#{limiter_name}:group1"
|
||||
opts = RateLimiter.init(name: limiter_name, bucket_name: base_bucket_name)
|
||||
|
@ -75,6 +105,7 @@ defmodule Pleroma.Plugs.RateLimiterTest do
|
|||
test "`params` option allows different queries to be tracked independently" do
|
||||
limiter_name = :test_params
|
||||
Pleroma.Config.put([:rate_limit, limiter_name], {1000, 5})
|
||||
Pleroma.Config.put([Pleroma.Web.Endpoint, :http, :ip], {8, 8, 8, 8})
|
||||
|
||||
opts = RateLimiter.init(name: limiter_name, params: ["id"])
|
||||
|
||||
|
@ -90,6 +121,7 @@ defmodule Pleroma.Plugs.RateLimiterTest do
|
|||
test "it supports combination of options modifying bucket name" do
|
||||
limiter_name = :test_options_combo
|
||||
Pleroma.Config.put([:rate_limit, limiter_name], {1000, 5})
|
||||
Pleroma.Config.put([Pleroma.Web.Endpoint, :http, :ip], {8, 8, 8, 8})
|
||||
|
||||
base_bucket_name = "#{limiter_name}:group1"
|
||||
opts = RateLimiter.init(name: limiter_name, bucket_name: base_bucket_name, params: ["id"])
|
||||
|
@ -109,6 +141,7 @@ defmodule Pleroma.Plugs.RateLimiterTest do
|
|||
test "are restricted based on remote IP" do
|
||||
limiter_name = :test_unauthenticated
|
||||
Pleroma.Config.put([:rate_limit, limiter_name], [{1000, 5}, {1, 10}])
|
||||
Pleroma.Config.put([Pleroma.Web.Endpoint, :http, :ip], {8, 8, 8, 8})
|
||||
|
||||
opts = RateLimiter.init(name: limiter_name)
|
||||
|
||||
|
@ -147,6 +180,7 @@ defmodule Pleroma.Plugs.RateLimiterTest do
|
|||
|
||||
scale = 50
|
||||
limit = 5
|
||||
Pleroma.Config.put([Pleroma.Web.Endpoint, :http, :ip], {8, 8, 8, 8})
|
||||
Pleroma.Config.put([:rate_limit, limiter_name], [{1000, 1}, {scale, limit}])
|
||||
|
||||
opts = RateLimiter.init(name: limiter_name)
|
||||
|
@ -169,6 +203,7 @@ defmodule Pleroma.Plugs.RateLimiterTest do
|
|||
test "diffrerent users are counted independently" do
|
||||
limiter_name = :test_authenticated
|
||||
Pleroma.Config.put([:rate_limit, limiter_name], [{1, 10}, {1000, 5}])
|
||||
Pleroma.Config.put([Pleroma.Web.Endpoint, :http, :ip], {8, 8, 8, 8})
|
||||
|
||||
opts = RateLimiter.init(name: limiter_name)
|
||||
|
||||
|
|
|
@ -395,6 +395,25 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
|||
assert data["content"] == "👌"
|
||||
end
|
||||
|
||||
test "it reject invalid emoji reactions" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/emoji-reaction-too-long.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", activity.data["object"])
|
||||
|
||||
assert :error = Transmogrifier.handle_incoming(data)
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/emoji-reaction-no-emoji.json")
|
||||
|> Poison.decode!()
|
||||
|> Map.put("object", activity.data["object"])
|
||||
|
||||
assert :error = Transmogrifier.handle_incoming(data)
|
||||
end
|
||||
|
||||
test "it works for incoming emoji reaction undos" do
|
||||
user = insert(:user)
|
||||
|
||||
|
|
|
@ -238,7 +238,9 @@ defmodule Pleroma.Web.CommonAPITest do
|
|||
assert reaction.data["actor"] == user.ap_id
|
||||
assert reaction.data["content"] == "👍"
|
||||
|
||||
# TODO: test error case.
|
||||
{:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"})
|
||||
|
||||
{:error, _} = CommonAPI.react_with_emoji(activity.id, user, ".")
|
||||
end
|
||||
|
||||
test "unreacting to a status with an emoji" do
|
||||
|
|
|
@ -668,6 +668,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|
|||
end
|
||||
|
||||
test "rate limit", %{conn: conn} do
|
||||
Pleroma.Config.put([Pleroma.Plugs.RemoteIp, :enabled], true)
|
||||
app_token = insert(:oauth_token, user: nil)
|
||||
|
||||
conn =
|
||||
|
|
|
@ -37,8 +37,15 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
|||
status = StatusView.render("show.json", activity: activity)
|
||||
|
||||
assert status[:pleroma][:emoji_reactions] == [
|
||||
%{emoji: "☕", count: 2},
|
||||
%{emoji: "🍵", count: 1}
|
||||
%{emoji: "☕", count: 2, reacted: false},
|
||||
%{emoji: "🍵", count: 1, reacted: false}
|
||||
]
|
||||
|
||||
status = StatusView.render("show.json", activity: activity, for: user)
|
||||
|
||||
assert status[:pleroma][:emoji_reactions] == [
|
||||
%{emoji: "☕", count: 2, reacted: true},
|
||||
%{emoji: "🍵", count: 1, reacted: false}
|
||||
]
|
||||
end
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
|
|||
use Pleroma.Web.ConnCase
|
||||
|
||||
import Tesla.Mock
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
@emoji_dir_path Path.join(
|
||||
|
|
|
@ -25,9 +25,14 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIControllerTest do
|
|||
|> assign(:user, other_user)
|
||||
|> assign(:token, insert(:oauth_token, user: other_user, scopes: ["write:statuses"]))
|
||||
|> post("/api/v1/pleroma/statuses/#{activity.id}/react_with_emoji", %{"emoji" => "☕"})
|
||||
|> json_response(200)
|
||||
|
||||
assert %{"id" => id} = json_response(result, 200)
|
||||
assert %{"id" => id} = result
|
||||
assert to_string(activity.id) == id
|
||||
|
||||
assert result["pleroma"]["emoji_reactions"] == [
|
||||
%{"emoji" => "☕", "count" => 1, "reacted" => true}
|
||||
]
|
||||
end
|
||||
|
||||
test "POST /api/v1/pleroma/statuses/:id/unreact_with_emoji", %{conn: conn} do
|
||||
|
@ -54,6 +59,7 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIControllerTest do
|
|||
test "GET /api/v1/pleroma/statuses/:id/emoji_reactions_by", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
doomed_user = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "#cofe"})
|
||||
|
||||
|
@ -65,14 +71,29 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIControllerTest do
|
|||
assert result == []
|
||||
|
||||
{:ok, _, _} = CommonAPI.react_with_emoji(activity.id, other_user, "🎅")
|
||||
{:ok, _, _} = CommonAPI.react_with_emoji(activity.id, doomed_user, "🎅")
|
||||
|
||||
User.perform(:delete, doomed_user)
|
||||
|
||||
result =
|
||||
conn
|
||||
|> get("/api/v1/pleroma/statuses/#{activity.id}/emoji_reactions_by")
|
||||
|> json_response(200)
|
||||
|
||||
[%{"emoji" => "🎅", "count" => 1, "accounts" => [represented_user]}] = result
|
||||
[%{"emoji" => "🎅", "count" => 1, "accounts" => [represented_user], "reacted" => false}] =
|
||||
result
|
||||
|
||||
assert represented_user["id"] == other_user.id
|
||||
|
||||
result =
|
||||
conn
|
||||
|> assign(:user, other_user)
|
||||
|> assign(:token, insert(:oauth_token, user: other_user, scopes: ["read:statuses"]))
|
||||
|> get("/api/v1/pleroma/statuses/#{activity.id}/emoji_reactions_by")
|
||||
|> json_response(200)
|
||||
|
||||
assert [%{"emoji" => "🎅", "count" => 1, "accounts" => [_represented_user], "reacted" => true}] =
|
||||
result
|
||||
end
|
||||
|
||||
test "/api/v1/pleroma/conversations/:id" do
|
||||
|
|
|
@ -85,4 +85,19 @@ defmodule Pleroma.Web.RichMedia.Parsers.TwitterCardTest do
|
|||
image: image_path
|
||||
}}
|
||||
end
|
||||
|
||||
test "takes first founded title in html head if there is html markup error" do
|
||||
html = File.read!("test/fixtures/nypd-facial-recognition-children-teenagers4.html")
|
||||
|
||||
assert TwitterCard.parse(html, %{}) ==
|
||||
{:ok,
|
||||
%{
|
||||
site: nil,
|
||||
title:
|
||||
"She Was Arrested at 14. Then Her Photo Went to a Facial Recognition Database. - The New York Times",
|
||||
"app:id:googleplay": "com.nytimes.android",
|
||||
"app:name:googleplay": "NYTimes",
|
||||
"app:url:googleplay": "nytimes://reader/id/100000006583622"
|
||||
}}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -65,6 +65,9 @@ defmodule Pleroma.Web.StreamerTest do
|
|||
blocked = insert(:user)
|
||||
{:ok, _user_relationship} = User.block(user, blocked)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => ":("})
|
||||
{:ok, notif, _} = CommonAPI.favorite(activity.id, blocked)
|
||||
|
||||
task = Task.async(fn -> refute_receive {:text, _}, @streamer_timeout end)
|
||||
|
||||
Streamer.add_socket(
|
||||
|
@ -72,9 +75,6 @@ defmodule Pleroma.Web.StreamerTest do
|
|||
%{transport_pid: task.pid, assigns: %{user: user}}
|
||||
)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => ":("})
|
||||
{:ok, notif, _} = CommonAPI.favorite(activity.id, blocked)
|
||||
|
||||
Streamer.stream("user:notification", notif)
|
||||
Task.await(task)
|
||||
end
|
||||
|
@ -83,6 +83,11 @@ defmodule Pleroma.Web.StreamerTest do
|
|||
user: user
|
||||
} do
|
||||
user2 = insert(:user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "super hot take"})
|
||||
{:ok, activity} = CommonAPI.add_mute(user, activity)
|
||||
{:ok, notif, _} = CommonAPI.favorite(activity.id, user2)
|
||||
|
||||
task = Task.async(fn -> refute_receive {:text, _}, @streamer_timeout end)
|
||||
|
||||
Streamer.add_socket(
|
||||
|
@ -90,9 +95,6 @@ defmodule Pleroma.Web.StreamerTest do
|
|||
%{transport_pid: task.pid, assigns: %{user: user}}
|
||||
)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "super hot take"})
|
||||
{:ok, activity} = CommonAPI.add_mute(user, activity)
|
||||
{:ok, notif, _} = CommonAPI.favorite(activity.id, user2)
|
||||
Streamer.stream("user:notification", notif)
|
||||
Task.await(task)
|
||||
end
|
||||
|
@ -101,6 +103,11 @@ defmodule Pleroma.Web.StreamerTest do
|
|||
user: user
|
||||
} do
|
||||
user2 = insert(:user, %{ap_id: "https://hecking-lewd-place.com/user/meanie"})
|
||||
|
||||
{:ok, user} = User.block_domain(user, "hecking-lewd-place.com")
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "super hot take"})
|
||||
{:ok, notif, _} = CommonAPI.favorite(activity.id, user2)
|
||||
|
||||
task = Task.async(fn -> refute_receive {:text, _}, @streamer_timeout end)
|
||||
|
||||
Streamer.add_socket(
|
||||
|
@ -108,10 +115,6 @@ defmodule Pleroma.Web.StreamerTest do
|
|||
%{transport_pid: task.pid, assigns: %{user: user}}
|
||||
)
|
||||
|
||||
{:ok, user} = User.block_domain(user, "hecking-lewd-place.com")
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "super hot take"})
|
||||
{:ok, notif, _} = CommonAPI.favorite(activity.id, user2)
|
||||
|
||||
Streamer.stream("user:notification", notif)
|
||||
Task.await(task)
|
||||
end
|
||||
|
@ -267,6 +270,8 @@ defmodule Pleroma.Web.StreamerTest do
|
|||
blocked_user = insert(:user)
|
||||
{:ok, _user_relationship} = User.block(user, blocked_user)
|
||||
|
||||
{:ok, activity} = CommonAPI.post(blocked_user, %{"status" => "Test"})
|
||||
|
||||
task =
|
||||
Task.async(fn ->
|
||||
refute_receive {:text, _}, 1_000
|
||||
|
@ -277,8 +282,6 @@ defmodule Pleroma.Web.StreamerTest do
|
|||
user: user
|
||||
}
|
||||
|
||||
{:ok, activity} = CommonAPI.post(blocked_user, %{"status" => "Test"})
|
||||
|
||||
topics = %{
|
||||
"public" => [fake_socket]
|
||||
}
|
||||
|
@ -335,6 +338,12 @@ defmodule Pleroma.Web.StreamerTest do
|
|||
{:ok, list} = List.create("Test", user_a)
|
||||
{:ok, list} = List.follow(list, user_b)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user_b, %{
|
||||
"status" => "@#{user_c.nickname} Test",
|
||||
"visibility" => "direct"
|
||||
})
|
||||
|
||||
task =
|
||||
Task.async(fn ->
|
||||
refute_receive {:text, _}, 1_000
|
||||
|
@ -345,12 +354,6 @@ defmodule Pleroma.Web.StreamerTest do
|
|||
user: user_a
|
||||
}
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user_b, %{
|
||||
"status" => "@#{user_c.nickname} Test",
|
||||
"visibility" => "direct"
|
||||
})
|
||||
|
||||
topics = %{
|
||||
"list:#{list.id}" => [fake_socket]
|
||||
}
|
||||
|
@ -367,6 +370,12 @@ defmodule Pleroma.Web.StreamerTest do
|
|||
{:ok, list} = List.create("Test", user_a)
|
||||
{:ok, list} = List.follow(list, user_b)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user_b, %{
|
||||
"status" => "Test",
|
||||
"visibility" => "private"
|
||||
})
|
||||
|
||||
task =
|
||||
Task.async(fn ->
|
||||
refute_receive {:text, _}, 1_000
|
||||
|
@ -377,12 +386,6 @@ defmodule Pleroma.Web.StreamerTest do
|
|||
user: user_a
|
||||
}
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user_b, %{
|
||||
"status" => "Test",
|
||||
"visibility" => "private"
|
||||
})
|
||||
|
||||
topics = %{
|
||||
"list:#{list.id}" => [fake_socket]
|
||||
}
|
||||
|
@ -401,6 +404,12 @@ defmodule Pleroma.Web.StreamerTest do
|
|||
{:ok, list} = List.create("Test", user_a)
|
||||
{:ok, list} = List.follow(list, user_b)
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user_b, %{
|
||||
"status" => "Test",
|
||||
"visibility" => "private"
|
||||
})
|
||||
|
||||
task =
|
||||
Task.async(fn ->
|
||||
assert_receive {:text, _}, 1_000
|
||||
|
@ -411,12 +420,6 @@ defmodule Pleroma.Web.StreamerTest do
|
|||
user: user_a
|
||||
}
|
||||
|
||||
{:ok, activity} =
|
||||
CommonAPI.post(user_b, %{
|
||||
"status" => "Test",
|
||||
"visibility" => "private"
|
||||
})
|
||||
|
||||
Streamer.add_socket(
|
||||
"list:#{list.id}",
|
||||
fake_socket
|
||||
|
@ -433,6 +436,9 @@ defmodule Pleroma.Web.StreamerTest do
|
|||
user3 = insert(:user)
|
||||
CommonAPI.hide_reblogs(user1, user2)
|
||||
|
||||
{:ok, create_activity} = CommonAPI.post(user3, %{"status" => "I'm kawen"})
|
||||
{:ok, announce_activity, _} = CommonAPI.repeat(create_activity.id, user2)
|
||||
|
||||
task =
|
||||
Task.async(fn ->
|
||||
refute_receive {:text, _}, 1_000
|
||||
|
@ -443,9 +449,6 @@ defmodule Pleroma.Web.StreamerTest do
|
|||
user: user1
|
||||
}
|
||||
|
||||
{:ok, create_activity} = CommonAPI.post(user3, %{"status" => "I'm kawen"})
|
||||
{:ok, announce_activity, _} = CommonAPI.repeat(create_activity.id, user2)
|
||||
|
||||
topics = %{
|
||||
"public" => [fake_socket]
|
||||
}
|
||||
|
@ -455,6 +458,34 @@ defmodule Pleroma.Web.StreamerTest do
|
|||
Task.await(task)
|
||||
end
|
||||
|
||||
test "it does send non-reblog notification for reblog-muted actors" do
|
||||
user1 = insert(:user)
|
||||
user2 = insert(:user)
|
||||
user3 = insert(:user)
|
||||
CommonAPI.hide_reblogs(user1, user2)
|
||||
|
||||
{:ok, create_activity} = CommonAPI.post(user3, %{"status" => "I'm kawen"})
|
||||
{:ok, favorite_activity, _} = CommonAPI.favorite(create_activity.id, user2)
|
||||
|
||||
task =
|
||||
Task.async(fn ->
|
||||
assert_receive {:text, _}, 1_000
|
||||
end)
|
||||
|
||||
fake_socket = %StreamerSocket{
|
||||
transport_pid: task.pid,
|
||||
user: user1
|
||||
}
|
||||
|
||||
topics = %{
|
||||
"public" => [fake_socket]
|
||||
}
|
||||
|
||||
Worker.push_to_socket(topics, "public", favorite_activity)
|
||||
|
||||
Task.await(task)
|
||||
end
|
||||
|
||||
test "it doesn't send posts from muted threads" do
|
||||
user = insert(:user)
|
||||
user2 = insert(:user)
|
||||
|
|
Loading…
Reference in a new issue