forked from AkkomaGang/akkoma
Merge branch 'develop' of https://git.pleroma.social/pleroma/pleroma into develop
This commit is contained in:
commit
9bc70ca0c1
38 changed files with 786 additions and 235 deletions
|
@ -27,6 +27,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Mastodon API: Add `pleroma.direct_conversation_id` to the status endpoint (`GET /api/v1/statuses/:id`)
|
- Mastodon API: Add `pleroma.direct_conversation_id` to the status endpoint (`GET /api/v1/statuses/:id`)
|
||||||
- Mastodon API: `pleroma.thread_muted` to the Status entity
|
- Mastodon API: `pleroma.thread_muted` to the Status entity
|
||||||
- Mastodon API: Mark the direct conversation as read for the author when they send a new direct message
|
- Mastodon API: Mark the direct conversation as read for the author when they send a new direct message
|
||||||
|
- Mastodon API, streaming: Add `pleroma.direct_conversation_id` to the `conversation` stream event payload.
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@ -65,8 +66,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- OStatus: Extract RSS functionality
|
- OStatus: Extract RSS functionality
|
||||||
- Mastodon API: Add `pleroma.direct_conversation_id` to the status endpoint (`GET /api/v1/statuses/:id`)
|
- Mastodon API: Add `pleroma.direct_conversation_id` to the status endpoint (`GET /api/v1/statuses/:id`)
|
||||||
- Mastodon API: Mark the direct conversation as read for the author when they send a new direct message
|
- Mastodon API: Mark the direct conversation as read for the author when they send a new direct message
|
||||||
</details>
|
|
||||||
- Deprecated `User.Info` embedded schema (fields moved to `User`)
|
- Deprecated `User.Info` embedded schema (fields moved to `User`)
|
||||||
|
- Store status data inside Flag activity
|
||||||
|
</details>
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Report emails now include functional links to profiles of remote user accounts
|
- Report emails now include functional links to profiles of remote user accounts
|
||||||
|
|
|
@ -284,8 +284,8 @@
|
||||||
allow_tables: false,
|
allow_tables: false,
|
||||||
allow_fonts: false,
|
allow_fonts: false,
|
||||||
scrub_policy: [
|
scrub_policy: [
|
||||||
Pleroma.HTML.Transform.MediaProxy,
|
Pleroma.HTML.Scrubber.Default,
|
||||||
Pleroma.HTML.Scrubber.Default
|
Pleroma.HTML.Transform.MediaProxy
|
||||||
]
|
]
|
||||||
|
|
||||||
config :pleroma, :frontend_configurations,
|
config :pleroma, :frontend_configurations,
|
||||||
|
@ -603,6 +603,7 @@
|
||||||
activity_pub: nil,
|
activity_pub: nil,
|
||||||
activity_pub_question: 30_000
|
activity_pub_question: 30_000
|
||||||
|
|
||||||
|
config :swarm, node_blacklist: [~r/myhtmlex_.*$/]
|
||||||
# Import environment specific config. This must remain at the bottom
|
# Import environment specific config. This must remain at the bottom
|
||||||
# of this file so it overrides the configuration defined above.
|
# of this file so it overrides the configuration defined above.
|
||||||
import_config "#{Mix.env()}.exs"
|
import_config "#{Mix.env()}.exs"
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
defmodule Pleroma.BBS.Handler do
|
defmodule Pleroma.BBS.Handler do
|
||||||
use Sshd.ShellHandler
|
use Sshd.ShellHandler
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
|
alias Pleroma.HTML
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
|
|
||||||
|
@ -44,7 +45,7 @@ defp loop(state) do
|
||||||
def puts_activity(activity) do
|
def puts_activity(activity) do
|
||||||
status = Pleroma.Web.MastodonAPI.StatusView.render("show.json", %{activity: activity})
|
status = Pleroma.Web.MastodonAPI.StatusView.render("show.json", %{activity: activity})
|
||||||
IO.puts("-- #{status.id} by #{status.account.display_name} (#{status.account.acct})")
|
IO.puts("-- #{status.id} by #{status.account.display_name} (#{status.account.acct})")
|
||||||
IO.puts(HtmlSanitizeEx.strip_tags(status.content))
|
IO.puts(HTML.strip_tags(status.content))
|
||||||
IO.puts("")
|
IO.puts("")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
defmodule Pleroma.HTML do
|
defmodule Pleroma.HTML do
|
||||||
alias HtmlSanitizeEx.Scrubber
|
|
||||||
|
|
||||||
defp get_scrubbers(scrubber) when is_atom(scrubber), do: [scrubber]
|
defp get_scrubbers(scrubber) when is_atom(scrubber), do: [scrubber]
|
||||||
defp get_scrubbers(scrubbers) when is_list(scrubbers), do: scrubbers
|
defp get_scrubbers(scrubbers) when is_list(scrubbers), do: scrubbers
|
||||||
defp get_scrubbers(_), do: [Pleroma.HTML.Scrubber.Default]
|
defp get_scrubbers(_), do: [Pleroma.HTML.Scrubber.Default]
|
||||||
|
@ -24,9 +22,13 @@ def filter_tags(html, scrubbers) when is_list(scrubbers) do
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
def filter_tags(html, scrubber), do: Scrubber.scrub(html, scrubber)
|
def filter_tags(html, scrubber) do
|
||||||
|
{:ok, content} = FastSanitize.Sanitizer.scrub(html, scrubber)
|
||||||
|
content
|
||||||
|
end
|
||||||
|
|
||||||
def filter_tags(html), do: filter_tags(html, nil)
|
def filter_tags(html), do: filter_tags(html, nil)
|
||||||
def strip_tags(html), do: Scrubber.scrub(html, Scrubber.StripTags)
|
def strip_tags(html), do: filter_tags(html, FastSanitize.Sanitizer.StripTags)
|
||||||
|
|
||||||
def get_cached_scrubbed_html_for_activity(
|
def get_cached_scrubbed_html_for_activity(
|
||||||
content,
|
content,
|
||||||
|
@ -46,7 +48,7 @@ def get_cached_scrubbed_html_for_activity(
|
||||||
def get_cached_stripped_html_for_activity(content, activity, key) do
|
def get_cached_stripped_html_for_activity(content, activity, key) do
|
||||||
get_cached_scrubbed_html_for_activity(
|
get_cached_scrubbed_html_for_activity(
|
||||||
content,
|
content,
|
||||||
HtmlSanitizeEx.Scrubber.StripTags,
|
FastSanitize.Sanitizer.StripTags,
|
||||||
activity,
|
activity,
|
||||||
key,
|
key,
|
||||||
&HtmlEntities.decode/1
|
&HtmlEntities.decode/1
|
||||||
|
@ -106,16 +108,15 @@ defmodule Pleroma.HTML.Scrubber.TwitterText do
|
||||||
|
|
||||||
@valid_schemes Pleroma.Config.get([:uri_schemes, :valid_schemes], [])
|
@valid_schemes Pleroma.Config.get([:uri_schemes, :valid_schemes], [])
|
||||||
|
|
||||||
require HtmlSanitizeEx.Scrubber.Meta
|
require FastSanitize.Sanitizer.Meta
|
||||||
alias HtmlSanitizeEx.Scrubber.Meta
|
alias FastSanitize.Sanitizer.Meta
|
||||||
|
|
||||||
Meta.remove_cdata_sections_before_scrub()
|
|
||||||
Meta.strip_comments()
|
Meta.strip_comments()
|
||||||
|
|
||||||
# links
|
# links
|
||||||
Meta.allow_tag_with_uri_attributes("a", ["href", "data-user", "data-tag"], @valid_schemes)
|
Meta.allow_tag_with_uri_attributes(:a, ["href", "data-user", "data-tag"], @valid_schemes)
|
||||||
|
|
||||||
Meta.allow_tag_with_this_attribute_values("a", "class", [
|
Meta.allow_tag_with_this_attribute_values(:a, "class", [
|
||||||
"hashtag",
|
"hashtag",
|
||||||
"u-url",
|
"u-url",
|
||||||
"mention",
|
"mention",
|
||||||
|
@ -123,29 +124,29 @@ defmodule Pleroma.HTML.Scrubber.TwitterText do
|
||||||
"mention u-url"
|
"mention u-url"
|
||||||
])
|
])
|
||||||
|
|
||||||
Meta.allow_tag_with_this_attribute_values("a", "rel", [
|
Meta.allow_tag_with_this_attribute_values(:a, "rel", [
|
||||||
"tag",
|
"tag",
|
||||||
"nofollow",
|
"nofollow",
|
||||||
"noopener",
|
"noopener",
|
||||||
"noreferrer"
|
"noreferrer"
|
||||||
])
|
])
|
||||||
|
|
||||||
Meta.allow_tag_with_these_attributes("a", ["name", "title"])
|
Meta.allow_tag_with_these_attributes(:a, ["name", "title"])
|
||||||
|
|
||||||
# paragraphs and linebreaks
|
# paragraphs and linebreaks
|
||||||
Meta.allow_tag_with_these_attributes("br", [])
|
Meta.allow_tag_with_these_attributes(:br, [])
|
||||||
Meta.allow_tag_with_these_attributes("p", [])
|
Meta.allow_tag_with_these_attributes(:p, [])
|
||||||
|
|
||||||
# microformats
|
# microformats
|
||||||
Meta.allow_tag_with_this_attribute_values("span", "class", ["h-card"])
|
Meta.allow_tag_with_this_attribute_values(:span, "class", ["h-card"])
|
||||||
Meta.allow_tag_with_these_attributes("span", [])
|
Meta.allow_tag_with_these_attributes(:span, [])
|
||||||
|
|
||||||
# allow inline images for custom emoji
|
# allow inline images for custom emoji
|
||||||
if Pleroma.Config.get([:markup, :allow_inline_images]) do
|
if Pleroma.Config.get([:markup, :allow_inline_images]) do
|
||||||
# restrict img tags to http/https only, because of MediaProxy.
|
# restrict img tags to http/https only, because of MediaProxy.
|
||||||
Meta.allow_tag_with_uri_attributes("img", ["src"], ["http", "https"])
|
Meta.allow_tag_with_uri_attributes(:img, ["src"], ["http", "https"])
|
||||||
|
|
||||||
Meta.allow_tag_with_these_attributes("img", [
|
Meta.allow_tag_with_these_attributes(:img, [
|
||||||
"width",
|
"width",
|
||||||
"height",
|
"height",
|
||||||
"class",
|
"class",
|
||||||
|
@ -160,19 +161,18 @@ defmodule Pleroma.HTML.Scrubber.TwitterText do
|
||||||
defmodule Pleroma.HTML.Scrubber.Default do
|
defmodule Pleroma.HTML.Scrubber.Default do
|
||||||
@doc "The default HTML scrubbing policy: no "
|
@doc "The default HTML scrubbing policy: no "
|
||||||
|
|
||||||
require HtmlSanitizeEx.Scrubber.Meta
|
require FastSanitize.Sanitizer.Meta
|
||||||
alias HtmlSanitizeEx.Scrubber.Meta
|
alias FastSanitize.Sanitizer.Meta
|
||||||
# credo:disable-for-previous-line
|
# credo:disable-for-previous-line
|
||||||
# No idea how to fix this one…
|
# No idea how to fix this one…
|
||||||
|
|
||||||
@valid_schemes Pleroma.Config.get([:uri_schemes, :valid_schemes], [])
|
@valid_schemes Pleroma.Config.get([:uri_schemes, :valid_schemes], [])
|
||||||
|
|
||||||
Meta.remove_cdata_sections_before_scrub()
|
|
||||||
Meta.strip_comments()
|
Meta.strip_comments()
|
||||||
|
|
||||||
Meta.allow_tag_with_uri_attributes("a", ["href", "data-user", "data-tag"], @valid_schemes)
|
Meta.allow_tag_with_uri_attributes(:a, ["href", "data-user", "data-tag"], @valid_schemes)
|
||||||
|
|
||||||
Meta.allow_tag_with_this_attribute_values("a", "class", [
|
Meta.allow_tag_with_this_attribute_values(:a, "class", [
|
||||||
"hashtag",
|
"hashtag",
|
||||||
"u-url",
|
"u-url",
|
||||||
"mention",
|
"mention",
|
||||||
|
@ -180,7 +180,7 @@ defmodule Pleroma.HTML.Scrubber.Default do
|
||||||
"mention u-url"
|
"mention u-url"
|
||||||
])
|
])
|
||||||
|
|
||||||
Meta.allow_tag_with_this_attribute_values("a", "rel", [
|
Meta.allow_tag_with_this_attribute_values(:a, "rel", [
|
||||||
"tag",
|
"tag",
|
||||||
"nofollow",
|
"nofollow",
|
||||||
"noopener",
|
"noopener",
|
||||||
|
@ -188,37 +188,37 @@ defmodule Pleroma.HTML.Scrubber.Default do
|
||||||
"ugc"
|
"ugc"
|
||||||
])
|
])
|
||||||
|
|
||||||
Meta.allow_tag_with_these_attributes("a", ["name", "title"])
|
Meta.allow_tag_with_these_attributes(:a, ["name", "title"])
|
||||||
|
|
||||||
Meta.allow_tag_with_these_attributes("abbr", ["title"])
|
Meta.allow_tag_with_these_attributes(:abbr, ["title"])
|
||||||
|
|
||||||
Meta.allow_tag_with_these_attributes("b", [])
|
Meta.allow_tag_with_these_attributes(:b, [])
|
||||||
Meta.allow_tag_with_these_attributes("blockquote", [])
|
Meta.allow_tag_with_these_attributes(:blockquote, [])
|
||||||
Meta.allow_tag_with_these_attributes("br", [])
|
Meta.allow_tag_with_these_attributes(:br, [])
|
||||||
Meta.allow_tag_with_these_attributes("code", [])
|
Meta.allow_tag_with_these_attributes(:code, [])
|
||||||
Meta.allow_tag_with_these_attributes("del", [])
|
Meta.allow_tag_with_these_attributes(:del, [])
|
||||||
Meta.allow_tag_with_these_attributes("em", [])
|
Meta.allow_tag_with_these_attributes(:em, [])
|
||||||
Meta.allow_tag_with_these_attributes("i", [])
|
Meta.allow_tag_with_these_attributes(:i, [])
|
||||||
Meta.allow_tag_with_these_attributes("li", [])
|
Meta.allow_tag_with_these_attributes(:li, [])
|
||||||
Meta.allow_tag_with_these_attributes("ol", [])
|
Meta.allow_tag_with_these_attributes(:ol, [])
|
||||||
Meta.allow_tag_with_these_attributes("p", [])
|
Meta.allow_tag_with_these_attributes(:p, [])
|
||||||
Meta.allow_tag_with_these_attributes("pre", [])
|
Meta.allow_tag_with_these_attributes(:pre, [])
|
||||||
Meta.allow_tag_with_these_attributes("strong", [])
|
Meta.allow_tag_with_these_attributes(:strong, [])
|
||||||
Meta.allow_tag_with_these_attributes("sub", [])
|
Meta.allow_tag_with_these_attributes(:sub, [])
|
||||||
Meta.allow_tag_with_these_attributes("sup", [])
|
Meta.allow_tag_with_these_attributes(:sup, [])
|
||||||
Meta.allow_tag_with_these_attributes("u", [])
|
Meta.allow_tag_with_these_attributes(:u, [])
|
||||||
Meta.allow_tag_with_these_attributes("ul", [])
|
Meta.allow_tag_with_these_attributes(:ul, [])
|
||||||
|
|
||||||
Meta.allow_tag_with_this_attribute_values("span", "class", ["h-card"])
|
Meta.allow_tag_with_this_attribute_values(:span, "class", ["h-card"])
|
||||||
Meta.allow_tag_with_these_attributes("span", [])
|
Meta.allow_tag_with_these_attributes(:span, [])
|
||||||
|
|
||||||
@allow_inline_images Pleroma.Config.get([:markup, :allow_inline_images])
|
@allow_inline_images Pleroma.Config.get([:markup, :allow_inline_images])
|
||||||
|
|
||||||
if @allow_inline_images do
|
if @allow_inline_images do
|
||||||
# restrict img tags to http/https only, because of MediaProxy.
|
# restrict img tags to http/https only, because of MediaProxy.
|
||||||
Meta.allow_tag_with_uri_attributes("img", ["src"], ["http", "https"])
|
Meta.allow_tag_with_uri_attributes(:img, ["src"], ["http", "https"])
|
||||||
|
|
||||||
Meta.allow_tag_with_these_attributes("img", [
|
Meta.allow_tag_with_these_attributes(:img, [
|
||||||
"width",
|
"width",
|
||||||
"height",
|
"height",
|
||||||
"class",
|
"class",
|
||||||
|
@ -228,24 +228,24 @@ defmodule Pleroma.HTML.Scrubber.Default do
|
||||||
end
|
end
|
||||||
|
|
||||||
if Pleroma.Config.get([:markup, :allow_tables]) do
|
if Pleroma.Config.get([:markup, :allow_tables]) do
|
||||||
Meta.allow_tag_with_these_attributes("table", [])
|
Meta.allow_tag_with_these_attributes(:table, [])
|
||||||
Meta.allow_tag_with_these_attributes("tbody", [])
|
Meta.allow_tag_with_these_attributes(:tbody, [])
|
||||||
Meta.allow_tag_with_these_attributes("td", [])
|
Meta.allow_tag_with_these_attributes(:td, [])
|
||||||
Meta.allow_tag_with_these_attributes("th", [])
|
Meta.allow_tag_with_these_attributes(:th, [])
|
||||||
Meta.allow_tag_with_these_attributes("thead", [])
|
Meta.allow_tag_with_these_attributes(:thead, [])
|
||||||
Meta.allow_tag_with_these_attributes("tr", [])
|
Meta.allow_tag_with_these_attributes(:tr, [])
|
||||||
end
|
end
|
||||||
|
|
||||||
if Pleroma.Config.get([:markup, :allow_headings]) do
|
if Pleroma.Config.get([:markup, :allow_headings]) do
|
||||||
Meta.allow_tag_with_these_attributes("h1", [])
|
Meta.allow_tag_with_these_attributes(:h1, [])
|
||||||
Meta.allow_tag_with_these_attributes("h2", [])
|
Meta.allow_tag_with_these_attributes(:h2, [])
|
||||||
Meta.allow_tag_with_these_attributes("h3", [])
|
Meta.allow_tag_with_these_attributes(:h3, [])
|
||||||
Meta.allow_tag_with_these_attributes("h4", [])
|
Meta.allow_tag_with_these_attributes(:h4, [])
|
||||||
Meta.allow_tag_with_these_attributes("h5", [])
|
Meta.allow_tag_with_these_attributes(:h5, [])
|
||||||
end
|
end
|
||||||
|
|
||||||
if Pleroma.Config.get([:markup, :allow_fonts]) do
|
if Pleroma.Config.get([:markup, :allow_fonts]) do
|
||||||
Meta.allow_tag_with_these_attributes("font", ["face"])
|
Meta.allow_tag_with_these_attributes(:font, ["face"])
|
||||||
end
|
end
|
||||||
|
|
||||||
Meta.strip_everything_not_covered()
|
Meta.strip_everything_not_covered()
|
||||||
|
@ -258,7 +258,7 @@ defmodule Pleroma.HTML.Transform.MediaProxy do
|
||||||
|
|
||||||
def before_scrub(html), do: html
|
def before_scrub(html), do: html
|
||||||
|
|
||||||
def scrub_attribute("img", {"src", "http" <> target}) do
|
def scrub_attribute(:img, {"src", "http" <> target}) do
|
||||||
media_url =
|
media_url =
|
||||||
("http" <> target)
|
("http" <> target)
|
||||||
|> MediaProxy.url()
|
|> MediaProxy.url()
|
||||||
|
@ -268,16 +268,16 @@ def scrub_attribute("img", {"src", "http" <> target}) do
|
||||||
|
|
||||||
def scrub_attribute(_tag, attribute), do: attribute
|
def scrub_attribute(_tag, attribute), do: attribute
|
||||||
|
|
||||||
def scrub({"img", attributes, children}) do
|
def scrub({:img, attributes, children}) do
|
||||||
attributes =
|
attributes =
|
||||||
attributes
|
attributes
|
||||||
|> Enum.map(fn attr -> scrub_attribute("img", attr) end)
|
|> Enum.map(fn attr -> scrub_attribute(:img, attr) end)
|
||||||
|> Enum.reject(&is_nil(&1))
|
|> Enum.reject(&is_nil(&1))
|
||||||
|
|
||||||
{"img", attributes, children}
|
{:img, attributes, children}
|
||||||
end
|
end
|
||||||
|
|
||||||
def scrub({:comment, _children}), do: ""
|
def scrub({:comment, _text, _children}), do: ""
|
||||||
|
|
||||||
def scrub({tag, attributes, children}), do: {tag, attributes, children}
|
def scrub({tag, attributes, children}), do: {tag, attributes, children}
|
||||||
def scrub({_tag, children}), do: children
|
def scrub({_tag, children}), do: children
|
||||||
|
@ -291,16 +291,15 @@ defmodule Pleroma.HTML.Scrubber.LinksOnly do
|
||||||
|
|
||||||
@valid_schemes Pleroma.Config.get([:uri_schemes, :valid_schemes], [])
|
@valid_schemes Pleroma.Config.get([:uri_schemes, :valid_schemes], [])
|
||||||
|
|
||||||
require HtmlSanitizeEx.Scrubber.Meta
|
require FastSanitize.Sanitizer.Meta
|
||||||
alias HtmlSanitizeEx.Scrubber.Meta
|
alias FastSanitize.Sanitizer.Meta
|
||||||
|
|
||||||
Meta.remove_cdata_sections_before_scrub()
|
|
||||||
Meta.strip_comments()
|
Meta.strip_comments()
|
||||||
|
|
||||||
# links
|
# links
|
||||||
Meta.allow_tag_with_uri_attributes("a", ["href"], @valid_schemes)
|
Meta.allow_tag_with_uri_attributes(:a, ["href"], @valid_schemes)
|
||||||
|
|
||||||
Meta.allow_tag_with_this_attribute_values("a", "rel", [
|
Meta.allow_tag_with_this_attribute_values(:a, "rel", [
|
||||||
"tag",
|
"tag",
|
||||||
"nofollow",
|
"nofollow",
|
||||||
"noopener",
|
"noopener",
|
||||||
|
@ -309,6 +308,6 @@ defmodule Pleroma.HTML.Scrubber.LinksOnly do
|
||||||
"ugc"
|
"ugc"
|
||||||
])
|
])
|
||||||
|
|
||||||
Meta.allow_tag_with_these_attributes("a", ["name", "title"])
|
Meta.allow_tag_with_these_attributes(:a, ["name", "title"])
|
||||||
Meta.strip_everything_not_covered()
|
Meta.strip_everything_not_covered()
|
||||||
end
|
end
|
||||||
|
|
|
@ -369,6 +369,24 @@ def get_log_entry_message(%ModerationLog{
|
||||||
"@#{actor_nickname} created users: #{users_to_nicknames_string(subjects)}"
|
"@#{actor_nickname} created users: #{users_to_nicknames_string(subjects)}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@spec get_log_entry_message(ModerationLog) :: String.t()
|
||||||
|
def get_log_entry_message(%ModerationLog{
|
||||||
|
data: %{
|
||||||
|
"actor" => %{"nickname" => actor_nickname},
|
||||||
|
"action" => "activate",
|
||||||
|
"subject" => user
|
||||||
|
}
|
||||||
|
})
|
||||||
|
when is_map(user) do
|
||||||
|
get_log_entry_message(%ModerationLog{
|
||||||
|
data: %{
|
||||||
|
"actor" => %{"nickname" => actor_nickname},
|
||||||
|
"action" => "activate",
|
||||||
|
"subject" => [user]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
@spec get_log_entry_message(ModerationLog) :: String.t()
|
@spec get_log_entry_message(ModerationLog) :: String.t()
|
||||||
def get_log_entry_message(%ModerationLog{
|
def get_log_entry_message(%ModerationLog{
|
||||||
data: %{
|
data: %{
|
||||||
|
@ -380,6 +398,24 @@ def get_log_entry_message(%ModerationLog{
|
||||||
"@#{actor_nickname} activated users: #{users_to_nicknames_string(users)}"
|
"@#{actor_nickname} activated users: #{users_to_nicknames_string(users)}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@spec get_log_entry_message(ModerationLog) :: String.t()
|
||||||
|
def get_log_entry_message(%ModerationLog{
|
||||||
|
data: %{
|
||||||
|
"actor" => %{"nickname" => actor_nickname},
|
||||||
|
"action" => "deactivate",
|
||||||
|
"subject" => user
|
||||||
|
}
|
||||||
|
})
|
||||||
|
when is_map(user) do
|
||||||
|
get_log_entry_message(%ModerationLog{
|
||||||
|
data: %{
|
||||||
|
"actor" => %{"nickname" => actor_nickname},
|
||||||
|
"action" => "deactivate",
|
||||||
|
"subject" => [user]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
@spec get_log_entry_message(ModerationLog) :: String.t()
|
@spec get_log_entry_message(ModerationLog) :: String.t()
|
||||||
def get_log_entry_message(%ModerationLog{
|
def get_log_entry_message(%ModerationLog{
|
||||||
data: %{
|
data: %{
|
||||||
|
@ -419,6 +455,26 @@ def get_log_entry_message(%ModerationLog{
|
||||||
"@#{actor_nickname} removed tags: #{tags_string} from users: #{nicknames_to_string(nicknames)}"
|
"@#{actor_nickname} removed tags: #{tags_string} from users: #{nicknames_to_string(nicknames)}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@spec get_log_entry_message(ModerationLog) :: String.t()
|
||||||
|
def get_log_entry_message(%ModerationLog{
|
||||||
|
data: %{
|
||||||
|
"actor" => %{"nickname" => actor_nickname},
|
||||||
|
"action" => "grant",
|
||||||
|
"subject" => user,
|
||||||
|
"permission" => permission
|
||||||
|
}
|
||||||
|
})
|
||||||
|
when is_map(user) do
|
||||||
|
get_log_entry_message(%ModerationLog{
|
||||||
|
data: %{
|
||||||
|
"actor" => %{"nickname" => actor_nickname},
|
||||||
|
"action" => "grant",
|
||||||
|
"subject" => [user],
|
||||||
|
"permission" => permission
|
||||||
|
}
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
@spec get_log_entry_message(ModerationLog) :: String.t()
|
@spec get_log_entry_message(ModerationLog) :: String.t()
|
||||||
def get_log_entry_message(%ModerationLog{
|
def get_log_entry_message(%ModerationLog{
|
||||||
data: %{
|
data: %{
|
||||||
|
@ -431,6 +487,26 @@ def get_log_entry_message(%ModerationLog{
|
||||||
"@#{actor_nickname} made #{users_to_nicknames_string(users)} #{permission}"
|
"@#{actor_nickname} made #{users_to_nicknames_string(users)} #{permission}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@spec get_log_entry_message(ModerationLog) :: String.t()
|
||||||
|
def get_log_entry_message(%ModerationLog{
|
||||||
|
data: %{
|
||||||
|
"actor" => %{"nickname" => actor_nickname},
|
||||||
|
"action" => "revoke",
|
||||||
|
"subject" => user,
|
||||||
|
"permission" => permission
|
||||||
|
}
|
||||||
|
})
|
||||||
|
when is_map(user) do
|
||||||
|
get_log_entry_message(%ModerationLog{
|
||||||
|
data: %{
|
||||||
|
"actor" => %{"nickname" => actor_nickname},
|
||||||
|
"action" => "revoke",
|
||||||
|
"subject" => [user],
|
||||||
|
"permission" => permission
|
||||||
|
}
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
@spec get_log_entry_message(ModerationLog) :: String.t()
|
@spec get_log_entry_message(ModerationLog) :: String.t()
|
||||||
def get_log_entry_message(%ModerationLog{
|
def get_log_entry_message(%ModerationLog{
|
||||||
data: %{
|
data: %{
|
||||||
|
|
|
@ -1095,7 +1095,12 @@ def deactivate(users, status) when is_list(users) do
|
||||||
def deactivate(%User{} = user, status) do
|
def deactivate(%User{} = user, status) do
|
||||||
with {:ok, user} <- set_activation_status(user, status) do
|
with {:ok, user} <- set_activation_status(user, status) do
|
||||||
Enum.each(get_followers(user), &invalidate_cache/1)
|
Enum.each(get_followers(user), &invalidate_cache/1)
|
||||||
Enum.each(get_friends(user), &update_follower_count/1)
|
|
||||||
|
# Only update local user counts, remote will be update during the next pull.
|
||||||
|
user
|
||||||
|
|> get_friends()
|
||||||
|
|> Enum.filter(& &1.local)
|
||||||
|
|> Enum.each(&update_follower_count/1)
|
||||||
|
|
||||||
{:ok, user}
|
{:ok, user}
|
||||||
end
|
end
|
||||||
|
|
|
@ -175,6 +175,7 @@ defp compose_query({:recipients_from_activity, to}, query) do
|
||||||
[u, following: f, relationships: r],
|
[u, following: f, relationships: r],
|
||||||
u.ap_id in ^to or (f.follower_address in ^to and r.state == "accept")
|
u.ap_id in ^to or (f.follower_address in ^to and r.state == "accept")
|
||||||
)
|
)
|
||||||
|
|> distinct(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp compose_query({:order_by, key}, query) do
|
defp compose_query({:order_by, key}, query) do
|
||||||
|
|
|
@ -54,15 +54,7 @@ defp search_query(query_string, for_user, following) do
|
||||||
|> maybe_restrict_local(for_user)
|
|> maybe_restrict_local(for_user)
|
||||||
end
|
end
|
||||||
|
|
||||||
@nickname_regex ~r/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~\-@]+$/
|
|
||||||
defp fts_search(query, query_string) do
|
defp fts_search(query, query_string) do
|
||||||
{nickname_weight, name_weight} =
|
|
||||||
if String.match?(query_string, @nickname_regex) do
|
|
||||||
{"A", "B"}
|
|
||||||
else
|
|
||||||
{"B", "A"}
|
|
||||||
end
|
|
||||||
|
|
||||||
query_string = to_tsquery(query_string)
|
query_string = to_tsquery(query_string)
|
||||||
|
|
||||||
from(
|
from(
|
||||||
|
@ -70,12 +62,10 @@ defp fts_search(query, query_string) do
|
||||||
where:
|
where:
|
||||||
fragment(
|
fragment(
|
||||||
"""
|
"""
|
||||||
(setweight(to_tsvector('simple', ?), ?) || setweight(to_tsvector('simple', ?), ?)) @@ to_tsquery('simple', ?)
|
(to_tsvector('simple', ?) || to_tsvector('simple', ?)) @@ to_tsquery('simple', ?)
|
||||||
""",
|
""",
|
||||||
u.name,
|
u.name,
|
||||||
^name_weight,
|
|
||||||
u.nickname,
|
u.nickname,
|
||||||
^nickname_weight,
|
|
||||||
^query_string
|
^query_string
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -503,7 +503,8 @@ def flag(
|
||||||
|
|
||||||
with flag_data <- make_flag_data(params, additional),
|
with flag_data <- make_flag_data(params, additional),
|
||||||
{:ok, activity} <- insert(flag_data, local),
|
{:ok, activity} <- insert(flag_data, local),
|
||||||
:ok <- maybe_federate(activity) do
|
{:ok, stripped_activity} <- strip_report_status_data(activity),
|
||||||
|
:ok <- maybe_federate(stripped_activity) do
|
||||||
Enum.each(User.all_superusers(), fn superuser ->
|
Enum.each(User.all_superusers(), fn superuser ->
|
||||||
superuser
|
superuser
|
||||||
|> Pleroma.Emails.AdminEmail.report(actor, account, statuses, content)
|
|> Pleroma.Emails.AdminEmail.report(actor, account, statuses, content)
|
||||||
|
|
|
@ -11,13 +11,17 @@ defmodule Pleroma.Web.ActivityPub.Relay do
|
||||||
|
|
||||||
def get_actor do
|
def get_actor do
|
||||||
actor =
|
actor =
|
||||||
"#{Pleroma.Web.Endpoint.url()}/relay"
|
relay_ap_id()
|
||||||
|> User.get_or_create_service_actor_by_ap_id()
|
|> User.get_or_create_service_actor_by_ap_id()
|
||||||
|
|
||||||
{:ok, actor} = User.set_invisible(actor, true)
|
{:ok, actor} = User.set_invisible(actor, true)
|
||||||
actor
|
actor
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def relay_ap_id do
|
||||||
|
"#{Pleroma.Web.Endpoint.url()}/relay"
|
||||||
|
end
|
||||||
|
|
||||||
@spec follow(String.t()) :: {:ok, Activity.t()} | {:error, any()}
|
@spec follow(String.t()) :: {:ok, Activity.t()} | {:error, any()}
|
||||||
def follow(target_instance) do
|
def follow(target_instance) do
|
||||||
with %User{} = local_user <- get_actor(),
|
with %User{} = local_user <- get_actor(),
|
||||||
|
|
|
@ -12,6 +12,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web
|
alias Pleroma.Web
|
||||||
alias Pleroma.Web.ActivityPub.Visibility
|
alias Pleroma.Web.ActivityPub.Visibility
|
||||||
|
alias Pleroma.Web.AdminAPI.AccountView
|
||||||
alias Pleroma.Web.Endpoint
|
alias Pleroma.Web.Endpoint
|
||||||
alias Pleroma.Web.Router.Helpers
|
alias Pleroma.Web.Router.Helpers
|
||||||
|
|
||||||
|
@ -21,6 +22,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
||||||
require Pleroma.Constants
|
require Pleroma.Constants
|
||||||
|
|
||||||
@supported_object_types ["Article", "Note", "Video", "Page", "Question", "Answer", "Audio"]
|
@supported_object_types ["Article", "Note", "Video", "Page", "Question", "Answer", "Audio"]
|
||||||
|
@strip_status_report_states ~w(closed resolved)
|
||||||
@supported_report_states ~w(open closed resolved)
|
@supported_report_states ~w(open closed resolved)
|
||||||
@valid_visibilities ~w(public unlisted private direct)
|
@valid_visibilities ~w(public unlisted private direct)
|
||||||
|
|
||||||
|
@ -614,10 +616,24 @@ def make_flag_data(_, _), do: %{}
|
||||||
|
|
||||||
defp build_flag_object(%{account: account, statuses: statuses} = _) do
|
defp build_flag_object(%{account: account, statuses: statuses} = _) do
|
||||||
[account.ap_id] ++
|
[account.ap_id] ++
|
||||||
Enum.map(statuses || [], fn
|
Enum.map(statuses || [], fn act ->
|
||||||
%Activity{} = act -> act.data["id"]
|
id =
|
||||||
act when is_map(act) -> act["id"]
|
case act do
|
||||||
act when is_binary(act) -> act
|
%Activity{} = act -> act.data["id"]
|
||||||
|
act when is_map(act) -> act["id"]
|
||||||
|
act when is_binary(act) -> act
|
||||||
|
end
|
||||||
|
|
||||||
|
activity = Activity.get_by_ap_id_with_object(id)
|
||||||
|
actor = User.get_by_ap_id(activity.object.data["actor"])
|
||||||
|
|
||||||
|
%{
|
||||||
|
"type" => "Note",
|
||||||
|
"id" => activity.data["id"],
|
||||||
|
"content" => activity.object.data["content"],
|
||||||
|
"published" => activity.object.data["published"],
|
||||||
|
"actor" => AccountView.render("show.json", %{user: actor})
|
||||||
|
}
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -664,6 +680,20 @@ def fetch_ordered_collection(from, pages_left, acc \\ []) do
|
||||||
|
|
||||||
#### Report-related helpers
|
#### Report-related helpers
|
||||||
|
|
||||||
|
def update_report_state(%Activity{} = activity, state)
|
||||||
|
when state in @strip_status_report_states do
|
||||||
|
{:ok, stripped_activity} = strip_report_status_data(activity)
|
||||||
|
|
||||||
|
new_data =
|
||||||
|
activity.data
|
||||||
|
|> Map.put("state", state)
|
||||||
|
|> Map.put("object", stripped_activity.data["object"])
|
||||||
|
|
||||||
|
activity
|
||||||
|
|> Changeset.change(data: new_data)
|
||||||
|
|> Repo.update()
|
||||||
|
end
|
||||||
|
|
||||||
def update_report_state(%Activity{} = activity, state) when state in @supported_report_states do
|
def update_report_state(%Activity{} = activity, state) when state in @supported_report_states do
|
||||||
new_data = Map.put(activity.data, "state", state)
|
new_data = Map.put(activity.data, "state", state)
|
||||||
|
|
||||||
|
@ -674,6 +704,14 @@ def update_report_state(%Activity{} = activity, state) when state in @supported_
|
||||||
|
|
||||||
def update_report_state(_, _), do: {:error, "Unsupported state"}
|
def update_report_state(_, _), do: {:error, "Unsupported state"}
|
||||||
|
|
||||||
|
def strip_report_status_data(activity) do
|
||||||
|
[actor | reported_activities] = activity.data["object"]
|
||||||
|
stripped_activities = Enum.map(reported_activities, & &1["id"])
|
||||||
|
new_data = put_in(activity.data, ["object"], [actor | stripped_activities])
|
||||||
|
|
||||||
|
{:ok, %{activity | data: new_data}}
|
||||||
|
end
|
||||||
|
|
||||||
def update_activity_visibility(activity, visibility) when visibility in @valid_visibilities do
|
def update_activity_visibility(activity, visibility) when visibility in @valid_visibilities do
|
||||||
[to, cc, recipients] =
|
[to, cc, recipients] =
|
||||||
activity
|
activity
|
||||||
|
|
|
@ -334,6 +334,7 @@ def list_users(conn, params) do
|
||||||
}
|
}
|
||||||
|
|
||||||
with {:ok, users, count} <- Search.user(Map.merge(search_params, filters)),
|
with {:ok, users, count} <- Search.user(Map.merge(search_params, filters)),
|
||||||
|
{:ok, users, count} <- filter_relay_user(users, count),
|
||||||
do:
|
do:
|
||||||
conn
|
conn
|
||||||
|> json(
|
|> json(
|
||||||
|
@ -345,6 +346,17 @@ def list_users(conn, params) do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp filter_relay_user(users, count) do
|
||||||
|
filtered_users = Enum.reject(users, &relay_user?/1)
|
||||||
|
count = if Enum.any?(users, &relay_user?/1), do: length(filtered_users), else: count
|
||||||
|
|
||||||
|
{:ok, filtered_users, count}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp relay_user?(user) do
|
||||||
|
user.ap_id == Relay.relay_ap_id()
|
||||||
|
end
|
||||||
|
|
||||||
@filters ~w(local external active deactivated is_admin is_moderator)
|
@filters ~w(local external active deactivated is_admin is_moderator)
|
||||||
|
|
||||||
@spec maybe_parse_filters(String.t()) :: %{required(String.t()) => true} | %{}
|
@spec maybe_parse_filters(String.t()) :: %{required(String.t()) => true} | %{}
|
||||||
|
|
|
@ -13,8 +13,9 @@ def extract_report_info(
|
||||||
account = User.get_cached_by_ap_id(account_ap_id)
|
account = User.get_cached_by_ap_id(account_ap_id)
|
||||||
|
|
||||||
statuses =
|
statuses =
|
||||||
Enum.map(status_ap_ids, fn ap_id ->
|
Enum.map(status_ap_ids, fn
|
||||||
Activity.get_by_ap_id_with_object(ap_id)
|
act when is_map(act) -> Activity.get_by_ap_id_with_object(act["id"])
|
||||||
|
act when is_binary(act) -> Activity.get_by_ap_id_with_object(act)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
%{report: report, user: user, account: account, statuses: statuses}
|
%{report: report, user: user, account: account, statuses: statuses}
|
||||||
|
|
|
@ -34,7 +34,11 @@ def render("participation.json", %{participation: participation, for: user}) do
|
||||||
id: participation.id |> to_string(),
|
id: participation.id |> to_string(),
|
||||||
accounts: render(AccountView, "index.json", users: users, as: :user),
|
accounts: render(AccountView, "index.json", users: users, as: :user),
|
||||||
unread: !participation.read,
|
unread: !participation.read,
|
||||||
last_status: render(StatusView, "show.json", activity: activity, for: user)
|
last_status:
|
||||||
|
render(StatusView, "show.json",
|
||||||
|
activity: activity,
|
||||||
|
direct_conversation_id: participation.id
|
||||||
|
)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -243,7 +243,8 @@ def render("show.json", %{activity: %{data: %{"object" => _object}} = activity}
|
||||||
end
|
end
|
||||||
|
|
||||||
direct_conversation_id =
|
direct_conversation_id =
|
||||||
with {_, true} <- {:include_id, opts[:with_direct_conversation_id]},
|
with {_, nil} <- {:direct_conversation_id, opts[:direct_conversation_id]},
|
||||||
|
{_, true} <- {:include_id, opts[:with_direct_conversation_id]},
|
||||||
{_, %User{} = for_user} <- {:for_user, opts[:for]},
|
{_, %User{} = for_user} <- {:for_user, opts[:for]},
|
||||||
%{data: %{"context" => context}} when is_binary(context) <- activity,
|
%{data: %{"context" => context}} when is_binary(context) <- activity,
|
||||||
%Conversation{} = conversation <- Conversation.get_for_ap_id(context),
|
%Conversation{} = conversation <- Conversation.get_for_ap_id(context),
|
||||||
|
@ -251,6 +252,9 @@ def render("show.json", %{activity: %{data: %{"object" => _object}} = activity}
|
||||||
Participation.for_user_and_conversation(for_user, conversation) do
|
Participation.for_user_and_conversation(for_user, conversation) do
|
||||||
participation_id
|
participation_id
|
||||||
else
|
else
|
||||||
|
{:direct_conversation_id, participation_id} when is_integer(participation_id) ->
|
||||||
|
participation_id
|
||||||
|
|
||||||
_e ->
|
_e ->
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
|
@ -25,13 +25,13 @@ def parse(url) when is_binary(url) do
|
||||||
def parse(_), do: {:error, "No URL provided"}
|
def parse(_), do: {:error, "No URL provided"}
|
||||||
|
|
||||||
defp parse_url(url) do
|
defp parse_url(url) do
|
||||||
{:ok, %Tesla.Env{body: html}} = Pleroma.HTTP.get(url, [], adapter: @hackney_options)
|
with {:ok, %Tesla.Env{body: html, status: status}} when status in 200..299 <-
|
||||||
|
Pleroma.HTTP.get(url, [], adapter: @hackney_options),
|
||||||
data =
|
data <-
|
||||||
Floki.attribute(html, "link[rel~=me]", "href") ++
|
Floki.attribute(html, "link[rel~=me]", "href") ++
|
||||||
Floki.attribute(html, "a[rel~=me]", "href")
|
Floki.attribute(html, "a[rel~=me]", "href") do
|
||||||
|
{:ok, data}
|
||||||
{:ok, data}
|
end
|
||||||
rescue
|
rescue
|
||||||
e -> {:error, "Parsing error: #{inspect(e)}"}
|
e -> {:error, "Parsing error: #{inspect(e)}"}
|
||||||
end
|
end
|
||||||
|
|
|
@ -136,7 +136,7 @@ defp should_send?(%User{} = user, %Activity{} = item) do
|
||||||
recipients = MapSet.new(item.recipients)
|
recipients = MapSet.new(item.recipients)
|
||||||
domain_blocks = Pleroma.Web.ActivityPub.MRF.subdomains_regex(user.domain_blocks)
|
domain_blocks = Pleroma.Web.ActivityPub.MRF.subdomains_regex(user.domain_blocks)
|
||||||
|
|
||||||
with parent when not is_nil(parent) <- Object.normalize(item),
|
with parent <- Object.normalize(item) || item,
|
||||||
true <- Enum.all?([blocks, mutes, reblog_mutes], &(item.actor not in &1)),
|
true <- Enum.all?([blocks, mutes, reblog_mutes], &(item.actor not in &1)),
|
||||||
true <- Enum.all?([blocks, mutes], &(parent.data["actor"] not in &1)),
|
true <- Enum.all?([blocks, mutes], &(parent.data["actor"] not in &1)),
|
||||||
true <- MapSet.disjoint?(recipients, recipient_blocks),
|
true <- MapSet.disjoint?(recipients, recipient_blocks),
|
||||||
|
|
6
mix.exs
6
mix.exs
|
@ -63,7 +63,7 @@ def copy_nginx_config(%{path: target_path} = release) do
|
||||||
def application do
|
def application do
|
||||||
[
|
[
|
||||||
mod: {Pleroma.Application, []},
|
mod: {Pleroma.Application, []},
|
||||||
extra_applications: [:logger, :runtime_tools, :comeonin, :quack],
|
extra_applications: [:logger, :runtime_tools, :comeonin, :quack, :myhtmlex, :swarm],
|
||||||
included_applications: [:ex_syslogger]
|
included_applications: [:ex_syslogger]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
@ -108,7 +108,9 @@ defp deps do
|
||||||
{:comeonin, "~> 4.1.1"},
|
{:comeonin, "~> 4.1.1"},
|
||||||
{:pbkdf2_elixir, "~> 0.12.3"},
|
{:pbkdf2_elixir, "~> 0.12.3"},
|
||||||
{:trailing_format_plug, "~> 0.0.7"},
|
{:trailing_format_plug, "~> 0.0.7"},
|
||||||
{:html_sanitize_ex, "~> 1.3.0"},
|
{:fast_sanitize,
|
||||||
|
git: "https://git.pleroma.social/pleroma/fast_sanitize.git",
|
||||||
|
ref: "1af67547a02a104e26c99d03012383e8643bc4c2"},
|
||||||
{:html_entities, "~> 0.4"},
|
{:html_entities, "~> 0.4"},
|
||||||
{:phoenix_html, "~> 2.10"},
|
{:phoenix_html, "~> 2.10"},
|
||||||
{:calendar, "~> 0.17.4"},
|
{:calendar, "~> 0.17.4"},
|
||||||
|
|
49
mix.lock
49
mix.lock
|
@ -13,44 +13,45 @@
|
||||||
"comeonin": {:hex, :comeonin, "4.1.2", "3eb5620fd8e35508991664b4c2b04dd41e52f1620b36957be837c1d7784b7592", [:mix], [{:argon2_elixir, "~> 1.2", [hex: :argon2_elixir, repo: "hexpm", optional: true]}, {:bcrypt_elixir, "~> 0.12.1 or ~> 1.0", [hex: :bcrypt_elixir, repo: "hexpm", optional: true]}, {:pbkdf2_elixir, "~> 0.12", [hex: :pbkdf2_elixir, repo: "hexpm", optional: true]}], "hexpm"},
|
"comeonin": {:hex, :comeonin, "4.1.2", "3eb5620fd8e35508991664b4c2b04dd41e52f1620b36957be837c1d7784b7592", [:mix], [{:argon2_elixir, "~> 1.2", [hex: :argon2_elixir, repo: "hexpm", optional: true]}, {:bcrypt_elixir, "~> 0.12.1 or ~> 1.0", [hex: :bcrypt_elixir, repo: "hexpm", optional: true]}, {:pbkdf2_elixir, "~> 0.12", [hex: :pbkdf2_elixir, repo: "hexpm", optional: true]}], "hexpm"},
|
||||||
"connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm"},
|
"connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm"},
|
||||||
"cors_plug": {:hex, :cors_plug, "1.5.2", "72df63c87e4f94112f458ce9d25800900cc88608c1078f0e4faddf20933eda6e", [:mix], [{:plug, "~> 1.3 or ~> 1.4 or ~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
|
"cors_plug": {:hex, :cors_plug, "1.5.2", "72df63c87e4f94112f458ce9d25800900cc88608c1078f0e4faddf20933eda6e", [:mix], [{:plug, "~> 1.3 or ~> 1.4 or ~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"cowboy": {:hex, :cowboy, "2.6.3", "99aa50e94e685557cad82e704457336a453d4abcb77839ad22dbe71f311fcc06", [:rebar3], [{:cowlib, "~> 2.7.3", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"},
|
"cowboy": {:hex, :cowboy, "2.7.0", "91ed100138a764355f43316b1d23d7ff6bdb0de4ea618cb5d8677c93a7a2f115", [:rebar3], [{:cowlib, "~> 2.8.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"cowlib": {:hex, :cowlib, "2.7.3", "a7ffcd0917e6d50b4d5fb28e9e2085a0ceb3c97dea310505f7460ff5ed764ce9", [:rebar3], [], "hexpm"},
|
"cowlib": {:hex, :cowlib, "2.8.0", "fd0ff1787db84ac415b8211573e9a30a3ebe71b5cbff7f720089972b2319c8a4", [:rebar3], [], "hexpm"},
|
||||||
"credo": {:hex, :credo, "0.9.3", "76fa3e9e497ab282e0cf64b98a624aa11da702854c52c82db1bf24e54ab7c97a", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:poison, ">= 0.0.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"},
|
"credo": {:hex, :credo, "0.9.3", "76fa3e9e497ab282e0cf64b98a624aa11da702854c52c82db1bf24e54ab7c97a", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:poison, ">= 0.0.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"crontab": {:hex, :crontab, "1.1.7", "b9219f0bdc8678b94143655a8f229716c5810c0636a4489f98c0956137e53985", [:mix], [{:ecto, "~> 1.0 or ~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm"},
|
"crontab": {:hex, :crontab, "1.1.8", "2ce0e74777dfcadb28a1debbea707e58b879e6aa0ffbf9c9bb540887bce43617", [:mix], [{:ecto, "~> 1.0 or ~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm"},
|
||||||
"crypt": {:git, "https://github.com/msantos/crypt", "1f2b58927ab57e72910191a7ebaeff984382a1d3", [ref: "1f2b58927ab57e72910191a7ebaeff984382a1d3"]},
|
"crypt": {:git, "https://github.com/msantos/crypt", "1f2b58927ab57e72910191a7ebaeff984382a1d3", [ref: "1f2b58927ab57e72910191a7ebaeff984382a1d3"]},
|
||||||
"custom_base": {:hex, :custom_base, "0.2.1", "4a832a42ea0552299d81652aa0b1f775d462175293e99dfbe4d7dbaab785a706", [:mix], [], "hexpm"},
|
"custom_base": {:hex, :custom_base, "0.2.1", "4a832a42ea0552299d81652aa0b1f775d462175293e99dfbe4d7dbaab785a706", [:mix], [], "hexpm"},
|
||||||
"db_connection": {:hex, :db_connection, "2.1.1", "a51e8a2ee54ef2ae6ec41a668c85787ed40cb8944928c191280fe34c15b76ae5", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm"},
|
"db_connection": {:hex, :db_connection, "2.1.1", "a51e8a2ee54ef2ae6ec41a668c85787ed40cb8944928c191280fe34c15b76ae5", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"decimal": {:hex, :decimal, "1.8.0", "ca462e0d885f09a1c5a342dbd7c1dcf27ea63548c65a65e67334f4b61803822e", [:mix], [], "hexpm"},
|
"decimal": {:hex, :decimal, "1.8.0", "ca462e0d885f09a1c5a342dbd7c1dcf27ea63548c65a65e67334f4b61803822e", [:mix], [], "hexpm"},
|
||||||
"deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm"},
|
"deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm"},
|
||||||
"earmark": {:hex, :earmark, "1.3.6", "ce1d0675e10a5bb46b007549362bd3f5f08908843957687d8484fe7f37466b19", [:mix], [], "hexpm"},
|
"earmark": {:hex, :earmark, "1.4.2", "3aa0bd23bc4c61cf2f1e5d752d1bb470560a6f8539974f767a38923bb20e1d7f", [:mix], [], "hexpm"},
|
||||||
"ecto": {:hex, :ecto, "3.2.0", "940e2598813f205223d60c78d66e514afe1db5167ed8075510a59e496619cfb5", [:mix], [{:decimal, "~> 1.6", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"},
|
"ecto": {:hex, :ecto, "3.2.3", "51274df79862845b388733fddcf6f107d0c8c86e27abe7131fa98f8d30761bda", [:mix], [{:decimal, "~> 1.6", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"},
|
||||||
"ecto_sql": {:hex, :ecto_sql, "3.2.0", "751cea597e8deb616084894dd75cbabfdbe7255ff01e8c058ca13f0353a3921b", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.2.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.2.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
|
"ecto_sql": {:hex, :ecto_sql, "3.2.0", "751cea597e8deb616084894dd75cbabfdbe7255ff01e8c058ca13f0353a3921b", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.2.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.2.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"esshd": {:hex, :esshd, "0.1.0", "6f93a2062adb43637edad0ea7357db2702a4b80dd9683482fe00f5134e97f4c1", [:mix], [], "hexpm"},
|
"esshd": {:hex, :esshd, "0.1.0", "6f93a2062adb43637edad0ea7357db2702a4b80dd9683482fe00f5134e97f4c1", [:mix], [], "hexpm"},
|
||||||
"eternal": {:hex, :eternal, "1.2.0", "e2a6b6ce3b8c248f7dc31451aefca57e3bdf0e48d73ae5043229380a67614c41", [:mix], [], "hexpm"},
|
"eternal": {:hex, :eternal, "1.2.1", "d5b6b2499ba876c57be2581b5b999ee9bdf861c647401066d3eeed111d096bc4", [:mix], [], "hexpm"},
|
||||||
"ex2ms": {:hex, :ex2ms, "1.5.0", "19e27f9212be9a96093fed8cdfbef0a2b56c21237196d26760f11dfcfae58e97", [:mix], [], "hexpm"},
|
"ex2ms": {:hex, :ex2ms, "1.5.0", "19e27f9212be9a96093fed8cdfbef0a2b56c21237196d26760f11dfcfae58e97", [:mix], [], "hexpm"},
|
||||||
"ex_aws": {:hex, :ex_aws, "2.1.0", "b92651527d6c09c479f9013caa9c7331f19cba38a650590d82ebf2c6c16a1d8a", [:mix], [{:configparser_ex, "~> 2.0", [hex: :configparser_ex, repo: "hexpm", optional: true]}, {:hackney, "1.6.3 or 1.6.5 or 1.7.1 or 1.8.6 or ~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jsx, "~> 2.8", [hex: :jsx, repo: "hexpm", optional: true]}, {:poison, ">= 1.2.0", [hex: :poison, repo: "hexpm", optional: true]}, {:sweet_xml, "~> 0.6", [hex: :sweet_xml, repo: "hexpm", optional: true]}, {:xml_builder, "~> 0.1.0", [hex: :xml_builder, repo: "hexpm", optional: true]}], "hexpm"},
|
"ex_aws": {:hex, :ex_aws, "2.1.1", "1e4de2106cfbf4e837de41be41cd15813eabc722315e388f0d6bb3732cec47cd", [:mix], [{:configparser_ex, "~> 4.0", [hex: :configparser_ex, repo: "hexpm", optional: true]}, {:hackney, "1.6.3 or 1.6.5 or 1.7.1 or 1.8.6 or ~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jsx, "~> 2.8", [hex: :jsx, repo: "hexpm", optional: true]}, {:poison, ">= 1.2.0", [hex: :poison, repo: "hexpm", optional: true]}, {:sweet_xml, "~> 0.6", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm"},
|
||||||
"ex_aws_s3": {:hex, :ex_aws_s3, "2.0.1", "9e09366e77f25d3d88c5393824e613344631be8db0d1839faca49686e99b6704", [:mix], [{:ex_aws, "~> 2.0", [hex: :ex_aws, repo: "hexpm", optional: false]}, {:sweet_xml, ">= 0.0.0", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm"},
|
"ex_aws_s3": {:hex, :ex_aws_s3, "2.0.2", "c0258bbdfea55de4f98f0b2f0ca61fe402cc696f573815134beb1866e778f47b", [:mix], [{:ex_aws, "~> 2.0", [hex: :ex_aws, repo: "hexpm", optional: false]}, {:sweet_xml, ">= 0.0.0", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm"},
|
||||||
"ex_const": {:hex, :ex_const, "0.2.4", "d06e540c9d834865b012a17407761455efa71d0ce91e5831e86881b9c9d82448", [:mix], [], "hexpm"},
|
"ex_const": {:hex, :ex_const, "0.2.4", "d06e540c9d834865b012a17407761455efa71d0ce91e5831e86881b9c9d82448", [:mix], [], "hexpm"},
|
||||||
"ex_doc": {:hex, :ex_doc, "0.21.2", "caca5bc28ed7b3bdc0b662f8afe2bee1eedb5c3cf7b322feeeb7c6ebbde089d6", [:mix], [{:earmark, "~> 1.3.3 or ~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"},
|
"ex_doc": {:hex, :ex_doc, "0.21.2", "caca5bc28ed7b3bdc0b662f8afe2bee1eedb5c3cf7b322feeeb7c6ebbde089d6", [:mix], [{:earmark, "~> 1.3.3 or ~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"ex_machina": {:hex, :ex_machina, "2.3.0", "92a5ad0a8b10ea6314b876a99c8c9e3f25f4dde71a2a835845b136b9adaf199a", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm"},
|
"ex_machina": {:hex, :ex_machina, "2.3.0", "92a5ad0a8b10ea6314b876a99c8c9e3f25f4dde71a2a835845b136b9adaf199a", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm"},
|
||||||
"ex_rated": {:hex, :ex_rated, "1.3.3", "30ecbdabe91f7eaa9d37fa4e81c85ba420f371babeb9d1910adbcd79ec798d27", [:mix], [{:ex2ms, "~> 1.5", [hex: :ex2ms, repo: "hexpm", optional: false]}], "hexpm"},
|
"ex_rated": {:hex, :ex_rated, "1.3.3", "30ecbdabe91f7eaa9d37fa4e81c85ba420f371babeb9d1910adbcd79ec798d27", [:mix], [{:ex2ms, "~> 1.5", [hex: :ex2ms, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"ex_syslogger": {:git, "https://github.com/slashmili/ex_syslogger.git", "f3963399047af17e038897c69e20d552e6899e1d", [tag: "1.4.0"]},
|
"ex_syslogger": {:git, "https://github.com/slashmili/ex_syslogger.git", "f3963399047af17e038897c69e20d552e6899e1d", [tag: "1.4.0"]},
|
||||||
"excoveralls": {:hex, :excoveralls, "0.11.1", "dd677fbdd49114fdbdbf445540ec735808250d56b011077798316505064edb2c", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"},
|
"excoveralls": {:hex, :excoveralls, "0.11.2", "0c6f2c8db7683b0caa9d490fb8125709c54580b4255ffa7ad35f3264b075a643", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
|
"fast_sanitize": {:git, "https://git.pleroma.social/pleroma/fast_sanitize.git", "1af67547a02a104e26c99d03012383e8643bc4c2", [ref: "1af67547a02a104e26c99d03012383e8643bc4c2"]},
|
||||||
"flake_id": {:hex, :flake_id, "0.1.0", "7716b086d2e405d09b647121a166498a0d93d1a623bead243e1f74216079ccb3", [:mix], [{:base62, "~> 1.2", [hex: :base62, repo: "hexpm", optional: false]}, {:ecto, ">= 2.0.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm"},
|
"flake_id": {:hex, :flake_id, "0.1.0", "7716b086d2e405d09b647121a166498a0d93d1a623bead243e1f74216079ccb3", [:mix], [{:base62, "~> 1.2", [hex: :base62, repo: "hexpm", optional: false]}, {:ecto, ">= 2.0.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm"},
|
||||||
"floki": {:hex, :floki, "0.23.0", "956ab6dba828c96e732454809fb0bd8d43ce0979b75f34de6322e73d4c917829", [:mix], [{:html_entities, "~> 0.4.0", [hex: :html_entities, repo: "hexpm", optional: false]}], "hexpm"},
|
"floki": {:hex, :floki, "0.23.0", "956ab6dba828c96e732454809fb0bd8d43ce0979b75f34de6322e73d4c917829", [:mix], [{:html_entities, "~> 0.4.0", [hex: :html_entities, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"gen_smtp": {:hex, :gen_smtp, "0.14.0", "39846a03522456077c6429b4badfd1d55e5e7d0fdfb65e935b7c5e38549d9202", [:rebar3], [], "hexpm"},
|
"gen_smtp": {:hex, :gen_smtp, "0.15.0", "9f51960c17769b26833b50df0b96123605a8024738b62db747fece14eb2fbfcc", [:rebar3], [], "hexpm"},
|
||||||
"gen_stage": {:hex, :gen_stage, "0.14.2", "6a2a578a510c5bfca8a45e6b27552f613b41cf584b58210f017088d3d17d0b14", [:mix], [], "hexpm"},
|
"gen_stage": {:hex, :gen_stage, "0.14.3", "d0c66f1c87faa301c1a85a809a3ee9097a4264b2edf7644bf5c123237ef732bf", [:mix], [], "hexpm"},
|
||||||
"gen_state_machine": {:hex, :gen_state_machine, "2.0.5", "9ac15ec6e66acac994cc442dcc2c6f9796cf380ec4b08267223014be1c728a95", [:mix], [], "hexpm"},
|
"gen_state_machine": {:hex, :gen_state_machine, "2.0.5", "9ac15ec6e66acac994cc442dcc2c6f9796cf380ec4b08267223014be1c728a95", [:mix], [], "hexpm"},
|
||||||
"gettext": {:hex, :gettext, "0.17.0", "abe21542c831887a2b16f4c94556db9c421ab301aee417b7c4fbde7fbdbe01ec", [:mix], [], "hexpm"},
|
"gettext": {:hex, :gettext, "0.17.1", "8baab33482df4907b3eae22f719da492cee3981a26e649b9c2be1c0192616962", [:mix], [], "hexpm"},
|
||||||
"hackney": {:hex, :hackney, "1.15.2", "07e33c794f8f8964ee86cebec1a8ed88db5070e52e904b8f12209773c1036085", [:rebar3], [{:certifi, "2.5.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.5", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"},
|
"hackney": {:hex, :hackney, "1.15.2", "07e33c794f8f8964ee86cebec1a8ed88db5070e52e904b8f12209773c1036085", [:rebar3], [{:certifi, "2.5.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.5", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"html_entities": {:hex, :html_entities, "0.4.0", "f2fee876858cf6aaa9db608820a3209e45a087c5177332799592142b50e89a6b", [:mix], [], "hexpm"},
|
"html_entities": {:hex, :html_entities, "0.4.0", "f2fee876858cf6aaa9db608820a3209e45a087c5177332799592142b50e89a6b", [:mix], [], "hexpm"},
|
||||||
"html_sanitize_ex": {:hex, :html_sanitize_ex, "1.3.0", "f005ad692b717691203f940c686208aa3d8ffd9dd4bb3699240096a51fa9564e", [:mix], [{:mochiweb, "~> 2.15", [hex: :mochiweb, repo: "hexpm", optional: false]}], "hexpm"},
|
"html_sanitize_ex": {:hex, :html_sanitize_ex, "1.3.0", "f005ad692b717691203f940c686208aa3d8ffd9dd4bb3699240096a51fa9564e", [:mix], [{:mochiweb, "~> 2.15", [hex: :mochiweb, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"http_signatures": {:git, "https://git.pleroma.social/pleroma/http_signatures.git", "293d77bb6f4a67ac8bde1428735c3b42f22cbb30", [ref: "293d77bb6f4a67ac8bde1428735c3b42f22cbb30"]},
|
"http_signatures": {:git, "https://git.pleroma.social/pleroma/http_signatures.git", "293d77bb6f4a67ac8bde1428735c3b42f22cbb30", [ref: "293d77bb6f4a67ac8bde1428735c3b42f22cbb30"]},
|
||||||
"httpoison": {:hex, :httpoison, "1.2.0", "2702ed3da5fd7a8130fc34b11965c8cfa21ade2f232c00b42d96d4967c39a3a3", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
|
"httpoison": {:hex, :httpoison, "1.6.1", "2ce5bf6e535cd0ab02e905ba8c276580bab80052c5c549f53ddea52d72e81f33", [:mix], [{:hackney, "~> 1.15 and >= 1.15.2", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"},
|
"idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"inet_cidr": {:hex, :inet_cidr, "1.0.4", "a05744ab7c221ca8e395c926c3919a821eb512e8f36547c062f62c4ca0cf3d6e", [:mix], [], "hexpm"},
|
"inet_cidr": {:hex, :inet_cidr, "1.0.4", "a05744ab7c221ca8e395c926c3919a821eb512e8f36547c062f62c4ca0cf3d6e", [:mix], [], "hexpm"},
|
||||||
"jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"},
|
"jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"},
|
||||||
"joken": {:hex, :joken, "2.0.1", "ec9ab31bf660f343380da033b3316855197c8d4c6ef597fa3fcb451b326beb14", [:mix], [{:jose, "~> 1.9", [hex: :jose, repo: "hexpm", optional: false]}], "hexpm"},
|
"joken": {:hex, :joken, "2.1.0", "bf21a73105d82649f617c5e59a7f8919aa47013d2519ebcc39d998d8d12adda9", [:mix], [{:jose, "~> 1.9", [hex: :jose, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"jose": {:hex, :jose, "1.9.0", "4167c5f6d06ffaebffd15cdb8da61a108445ef5e85ab8f5a7ad926fdf3ada154", [:mix, :rebar3], [{:base64url, "~> 0.0.1", [hex: :base64url, repo: "hexpm", optional: false]}], "hexpm"},
|
"jose": {:hex, :jose, "1.9.0", "4167c5f6d06ffaebffd15cdb8da61a108445ef5e85ab8f5a7ad926fdf3ada154", [:mix, :rebar3], [{:base64url, "~> 0.0.1", [hex: :base64url, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"libring": {:hex, :libring, "1.4.0", "41246ba2f3fbc76b3971f6bce83119dfec1eee17e977a48d8a9cfaaf58c2a8d6", [:mix], [], "hexpm"},
|
"libring": {:hex, :libring, "1.4.0", "41246ba2f3fbc76b3971f6bce83119dfec1eee17e977a48d8a9cfaaf58c2a8d6", [:mix], [], "hexpm"},
|
||||||
"makeup": {:hex, :makeup, "1.0.0", "671df94cf5a594b739ce03b0d0316aa64312cee2574b6a44becb83cd90fb05dc", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"},
|
"makeup": {:hex, :makeup, "1.0.0", "671df94cf5a594b739ce03b0d0316aa64312cee2574b6a44becb83cd90fb05dc", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
|
@ -63,16 +64,18 @@
|
||||||
"mock": {:hex, :mock, "0.3.3", "42a433794b1291a9cf1525c6d26b38e039e0d3a360732b5e467bfc77ef26c914", [:mix], [{:meck, "~> 0.8.13", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm"},
|
"mock": {:hex, :mock, "0.3.3", "42a433794b1291a9cf1525c6d26b38e039e0d3a360732b5e467bfc77ef26c914", [:mix], [{:meck, "~> 0.8.13", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"mogrify": {:hex, :mogrify, "0.6.1", "de1b527514f2d95a7bbe9642eb556061afb337e220cf97adbf3a4e6438ed70af", [:mix], [], "hexpm"},
|
"mogrify": {:hex, :mogrify, "0.6.1", "de1b527514f2d95a7bbe9642eb556061afb337e220cf97adbf3a4e6438ed70af", [:mix], [], "hexpm"},
|
||||||
"mox": {:hex, :mox, "0.5.1", "f86bb36026aac1e6f924a4b6d024b05e9adbed5c63e8daa069bd66fb3292165b", [:mix], [], "hexpm"},
|
"mox": {:hex, :mox, "0.5.1", "f86bb36026aac1e6f924a4b6d024b05e9adbed5c63e8daa069bd66fb3292165b", [:mix], [], "hexpm"},
|
||||||
|
"myhtmlex": {:git, "https://git.pleroma.social/pleroma/myhtmlex.git", "ad0097e2f61d4953bfef20fb6abddf23b87111e6", [ref: "ad0097e2f61d4953bfef20fb6abddf23b87111e6", submodules: true]},
|
||||||
"nimble_parsec": {:hex, :nimble_parsec, "0.5.1", "c90796ecee0289dbb5ad16d3ad06f957b0cd1199769641c961cfe0b97db190e0", [:mix], [], "hexpm"},
|
"nimble_parsec": {:hex, :nimble_parsec, "0.5.1", "c90796ecee0289dbb5ad16d3ad06f957b0cd1199769641c961cfe0b97db190e0", [:mix], [], "hexpm"},
|
||||||
|
"nodex": {:git, "https://git.pleroma.social/pleroma/nodex", "cb6730f943cfc6aad674c92161be23a8411f15d1", [ref: "cb6730f943cfc6aad674c92161be23a8411f15d1"]},
|
||||||
"oban": {:hex, :oban, "0.8.1", "4bbf62eb1829f856d69aeb5069ac7036afe07db8221a17de2a9169cc7a58a318", [:mix], [{:ecto_sql, "~> 3.1", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.14", [hex: :postgrex, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
|
"oban": {:hex, :oban, "0.8.1", "4bbf62eb1829f856d69aeb5069ac7036afe07db8221a17de2a9169cc7a58a318", [:mix], [{:ecto_sql, "~> 3.1", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.14", [hex: :postgrex, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm"},
|
"parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm"},
|
||||||
"pbkdf2_elixir": {:hex, :pbkdf2_elixir, "0.12.3", "6706a148809a29c306062862c803406e88f048277f6e85b68faf73291e820b84", [:mix], [], "hexpm"},
|
"pbkdf2_elixir": {:hex, :pbkdf2_elixir, "0.12.4", "8dd29ed783f2e12195d7e0a4640effc0a7c37e6537da491f1db01839eee6d053", [:mix], [], "hexpm"},
|
||||||
"phoenix": {:hex, :phoenix, "1.4.9", "746d098e10741c334d88143d3c94cab1756435f94387a63441792e66ec0ee974", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.8.1 or ~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
|
"phoenix": {:hex, :phoenix, "1.4.10", "619e4a545505f562cd294df52294372d012823f4fd9d34a6657a8b242898c255", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.8.1 or ~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"phoenix_ecto": {:hex, :phoenix_ecto, "4.0.0", "c43117a136e7399ea04ecaac73f8f23ee0ffe3e07acfcb8062fe5f4c9f0f6531", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.9", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
|
"phoenix_ecto": {:hex, :phoenix_ecto, "4.0.0", "c43117a136e7399ea04ecaac73f8f23ee0ffe3e07acfcb8062fe5f4c9f0f6531", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.9", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"phoenix_html": {:hex, :phoenix_html, "2.13.1", "fa8f034b5328e2dfa0e4131b5569379003f34bc1fafdaa84985b0b9d2f12e68b", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
|
"phoenix_html": {:hex, :phoenix_html, "2.13.3", "850e292ff6e204257f5f9c4c54a8cb1f6fbc16ed53d360c2b780a3d0ba333867", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"phoenix_pubsub": {:hex, :phoenix_pubsub, "1.1.2", "496c303bdf1b2e98a9d26e89af5bba3ab487ba3a3735f74bf1f4064d2a845a3e", [:mix], [], "hexpm"},
|
"phoenix_pubsub": {:hex, :phoenix_pubsub, "1.1.2", "496c303bdf1b2e98a9d26e89af5bba3ab487ba3a3735f74bf1f4064d2a845a3e", [:mix], [], "hexpm"},
|
||||||
"phoenix_swoosh": {:hex, :phoenix_swoosh, "0.2.0", "a7e0b32077cd6d2323ae15198839b05d9caddfa20663fd85787479e81f89520e", [:mix], [{:phoenix, "~> 1.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.2", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:swoosh, "~> 0.1", [hex: :swoosh, repo: "hexpm", optional: false]}], "hexpm"},
|
"phoenix_swoosh": {:hex, :phoenix_swoosh, "0.2.0", "a7e0b32077cd6d2323ae15198839b05d9caddfa20663fd85787479e81f89520e", [:mix], [{:phoenix, "~> 1.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.2", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:swoosh, "~> 0.1", [hex: :swoosh, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"plug": {:hex, :plug, "1.8.2", "0bcce1daa420f189a6491f3940cc77ea7fb1919761175c9c3b59800d897440fc", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm"},
|
"plug": {:hex, :plug, "1.8.3", "12d5f9796dc72e8ac9614e94bda5e51c4c028d0d428e9297650d09e15a684478", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm"},
|
||||||
"plug_cowboy": {:hex, :plug_cowboy, "2.1.0", "b75768153c3a8a9e8039d4b25bb9b14efbc58e9c4a6e6a270abff1cd30cbe320", [:mix], [{:cowboy, "~> 2.5", [hex: :cowboy, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
|
"plug_cowboy": {:hex, :plug_cowboy, "2.1.0", "b75768153c3a8a9e8039d4b25bb9b14efbc58e9c4a6e6a270abff1cd30cbe320", [:mix], [{:cowboy, "~> 2.5", [hex: :cowboy, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"plug_crypto": {:hex, :plug_crypto, "1.0.0", "18e49317d3fa343f24620ed22795ec29d4a5e602d52d1513ccea0b07d8ea7d4d", [:mix], [], "hexpm"},
|
"plug_crypto": {:hex, :plug_crypto, "1.0.0", "18e49317d3fa343f24620ed22795ec29d4a5e602d52d1513ccea0b07d8ea7d4d", [:mix], [], "hexpm"},
|
||||||
"plug_static_index_html": {:hex, :plug_static_index_html, "1.0.0", "840123d4d3975585133485ea86af73cb2600afd7f2a976f9f5fd8b3808e636a0", [:mix], [{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
|
"plug_static_index_html": {:hex, :plug_static_index_html, "1.0.0", "840123d4d3975585133485ea86af73cb2600afd7f2a976f9f5fd8b3808e636a0", [:mix], [{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
|
@ -80,7 +83,7 @@
|
||||||
"poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm"},
|
"poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm"},
|
||||||
"postgrex": {:hex, :postgrex, "0.15.1", "23ce3417de70f4c0e9e7419ad85bdabcc6860a6925fe2c6f3b1b5b1e8e47bf2f", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"},
|
"postgrex": {:hex, :postgrex, "0.15.1", "23ce3417de70f4c0e9e7419ad85bdabcc6860a6925fe2c6f3b1b5b1e8e47bf2f", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"},
|
||||||
"prometheus": {:hex, :prometheus, "4.4.1", "1e96073b3ed7788053768fea779cbc896ddc3bdd9ba60687f2ad50b252ac87d6", [:mix, :rebar3], [], "hexpm"},
|
"prometheus": {:hex, :prometheus, "4.4.1", "1e96073b3ed7788053768fea779cbc896ddc3bdd9ba60687f2ad50b252ac87d6", [:mix, :rebar3], [], "hexpm"},
|
||||||
"prometheus_ecto": {:hex, :prometheus_ecto, "1.4.1", "6c768ea9654de871e5b32fab2eac348467b3021604ebebbcbd8bcbe806a65ed5", [:mix], [{:ecto, "~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:prometheus_ex, "~> 1.1 or ~> 2.0 or ~> 3.0", [hex: :prometheus_ex, repo: "hexpm", optional: false]}], "hexpm"},
|
"prometheus_ecto": {:hex, :prometheus_ecto, "1.4.3", "3dd4da1812b8e0dbee81ea58bb3b62ed7588f2eae0c9e97e434c46807ff82311", [:mix], [{:ecto, "~> 2.0 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:prometheus_ex, "~> 1.1 or ~> 2.0 or ~> 3.0", [hex: :prometheus_ex, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"prometheus_ex": {:hex, :prometheus_ex, "3.0.5", "fa58cfd983487fc5ead331e9a3e0aa622c67232b3ec71710ced122c4c453a02f", [:mix], [{:prometheus, "~> 4.0", [hex: :prometheus, repo: "hexpm", optional: false]}], "hexpm"},
|
"prometheus_ex": {:hex, :prometheus_ex, "3.0.5", "fa58cfd983487fc5ead331e9a3e0aa622c67232b3ec71710ced122c4c453a02f", [:mix], [{:prometheus, "~> 4.0", [hex: :prometheus, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"prometheus_phoenix": {:hex, :prometheus_phoenix, "1.3.0", "c4b527e0b3a9ef1af26bdcfbfad3998f37795b9185d475ca610fe4388fdd3bb5", [:mix], [{:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}, {:prometheus_ex, "~> 1.3 or ~> 2.0 or ~> 3.0", [hex: :prometheus_ex, repo: "hexpm", optional: false]}], "hexpm"},
|
"prometheus_phoenix": {:hex, :prometheus_phoenix, "1.3.0", "c4b527e0b3a9ef1af26bdcfbfad3998f37795b9185d475ca610fe4388fdd3bb5", [:mix], [{:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}, {:prometheus_ex, "~> 1.3 or ~> 2.0 or ~> 3.0", [hex: :prometheus_ex, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"prometheus_plugs": {:hex, :prometheus_plugs, "1.1.5", "25933d48f8af3a5941dd7b621c889749894d8a1082a6ff7c67cc99dec26377c5", [:mix], [{:accept, "~> 0.1", [hex: :accept, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}, {:prometheus_ex, "~> 1.1 or ~> 2.0 or ~> 3.0", [hex: :prometheus_ex, repo: "hexpm", optional: false]}, {:prometheus_process_collector, "~> 1.1", [hex: :prometheus_process_collector, repo: "hexpm", optional: true]}], "hexpm"},
|
"prometheus_plugs": {:hex, :prometheus_plugs, "1.1.5", "25933d48f8af3a5941dd7b621c889749894d8a1082a6ff7c67cc99dec26377c5", [:mix], [{:accept, "~> 0.1", [hex: :accept, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}, {:prometheus_ex, "~> 1.1 or ~> 2.0 or ~> 3.0", [hex: :prometheus_ex, repo: "hexpm", optional: false]}, {:prometheus_process_collector, "~> 1.1", [hex: :prometheus_process_collector, repo: "hexpm", optional: true]}], "hexpm"},
|
||||||
|
@ -92,16 +95,16 @@
|
||||||
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.5", "6eaf7ad16cb568bb01753dbbd7a95ff8b91c7979482b95f38443fe2c8852a79b", [:make, :mix, :rebar3], [], "hexpm"},
|
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.5", "6eaf7ad16cb568bb01753dbbd7a95ff8b91c7979482b95f38443fe2c8852a79b", [:make, :mix, :rebar3], [], "hexpm"},
|
||||||
"swarm": {:hex, :swarm, "3.4.0", "64f8b30055d74640d2186c66354b33b999438692a91be275bb89cdc7e401f448", [:mix], [{:gen_state_machine, "~> 2.0", [hex: :gen_state_machine, repo: "hexpm", optional: false]}, {:libring, "~> 1.0", [hex: :libring, repo: "hexpm", optional: false]}], "hexpm"},
|
"swarm": {:hex, :swarm, "3.4.0", "64f8b30055d74640d2186c66354b33b999438692a91be275bb89cdc7e401f448", [:mix], [{:gen_state_machine, "~> 2.0", [hex: :gen_state_machine, repo: "hexpm", optional: false]}, {:libring, "~> 1.0", [hex: :libring, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"sweet_xml": {:hex, :sweet_xml, "0.6.6", "fc3e91ec5dd7c787b6195757fbcf0abc670cee1e4172687b45183032221b66b8", [:mix], [], "hexpm"},
|
"sweet_xml": {:hex, :sweet_xml, "0.6.6", "fc3e91ec5dd7c787b6195757fbcf0abc670cee1e4172687b45183032221b66b8", [:mix], [], "hexpm"},
|
||||||
"swoosh": {:hex, :swoosh, "0.23.2", "7dda95ff0bf54a2298328d6899c74dae1223777b43563ccebebb4b5d2b61df38", [:mix], [{:cowboy, "~> 1.0.1 or ~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm"},
|
"swoosh": {:hex, :swoosh, "0.23.5", "bfd9404bbf5069b1be2ffd317923ce57e58b332e25dbca2a35dedd7820dfee5a", [:mix], [{:cowboy, "~> 1.0.1 or ~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm"},
|
||||||
"syslog": {:git, "https://github.com/Vagabond/erlang-syslog.git", "4a6c6f2c996483e86c1320e9553f91d337bcb6aa", [tag: "1.0.5"]},
|
"syslog": {:git, "https://github.com/Vagabond/erlang-syslog.git", "4a6c6f2c996483e86c1320e9553f91d337bcb6aa", [tag: "1.0.5"]},
|
||||||
"telemetry": {:hex, :telemetry, "0.4.0", "8339bee3fa8b91cb84d14c2935f8ecf399ccd87301ad6da6b71c09553834b2ab", [:rebar3], [], "hexpm"},
|
"telemetry": {:hex, :telemetry, "0.4.0", "8339bee3fa8b91cb84d14c2935f8ecf399ccd87301ad6da6b71c09553834b2ab", [:rebar3], [], "hexpm"},
|
||||||
"tesla": {:hex, :tesla, "1.3.0", "f35d72f029e608f9cdc6f6d6fcc7c66cf6d6512a70cfef9206b21b8bd0203a30", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, "~> 1.3", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "~> 4.4.0", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 0.4", [hex: :mint, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.3", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm"},
|
"tesla": {:hex, :tesla, "1.3.0", "f35d72f029e608f9cdc6f6d6fcc7c66cf6d6512a70cfef9206b21b8bd0203a30", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, "~> 1.3", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "~> 4.4.0", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 0.4", [hex: :mint, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.3", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm"},
|
||||||
"timex": {:hex, :timex, "3.6.1", "efdf56d0e67a6b956cc57774353b0329c8ab7726766a11547e529357ffdc1d56", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 0.1.8 or ~> 0.5 or ~> 1.0.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm"},
|
"timex": {:hex, :timex, "3.6.1", "efdf56d0e67a6b956cc57774353b0329c8ab7726766a11547e529357ffdc1d56", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 0.1.8 or ~> 0.5 or ~> 1.0.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"trailing_format_plug": {:hex, :trailing_format_plug, "0.0.7", "64b877f912cf7273bed03379936df39894149e35137ac9509117e59866e10e45", [:mix], [{:plug, "> 0.12.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
|
"trailing_format_plug": {:hex, :trailing_format_plug, "0.0.7", "64b877f912cf7273bed03379936df39894149e35137ac9509117e59866e10e45", [:mix], [{:plug, "> 0.12.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"tzdata": {:hex, :tzdata, "0.5.21", "8cbf3607fcce69636c672d5be2bbb08687fe26639a62bdcc283d267277db7cf0", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
|
"tzdata": {:hex, :tzdata, "0.5.22", "f2ba9105117ee0360eae2eca389783ef7db36d533899b2e84559404dbc77ebb8", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"ueberauth": {:hex, :ueberauth, "0.6.1", "9e90d3337dddf38b1ca2753aca9b1e53d8a52b890191cdc55240247c89230412", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
|
"ueberauth": {:hex, :ueberauth, "0.6.2", "25a31111249d60bad8b65438b2306a4dc91f3208faa62f5a8c33e8713989b2e8", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm"},
|
"unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm"},
|
||||||
"unsafe": {:hex, :unsafe, "1.0.1", "a27e1874f72ee49312e0a9ec2e0b27924214a05e3ddac90e91727bc76f8613d8", [:mix], [], "hexpm"},
|
"unsafe": {:hex, :unsafe, "1.0.1", "a27e1874f72ee49312e0a9ec2e0b27924214a05e3ddac90e91727bc76f8613d8", [:mix], [], "hexpm"},
|
||||||
"web_push_encryption": {:hex, :web_push_encryption, "0.2.1", "d42cecf73420d9dc0053ba3299cc8c8d6ff2be2487d67ca2a57265868e4d9a98", [:mix], [{:httpoison, "~> 1.0", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jose, "~> 1.8", [hex: :jose, repo: "hexpm", optional: false]}, {:poison, "~> 3.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"},
|
"web_push_encryption": {:hex, :web_push_encryption, "0.2.3", "a0ceab85a805a30852f143d22d71c434046fbdbafbc7292e7887cec500826a80", [:mix], [{:httpoison, "~> 1.0", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jose, "~> 1.8", [hex: :jose, repo: "hexpm", optional: false]}, {:poison, "~> 3.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"websocket_client": {:git, "https://github.com/jeremyong/websocket_client.git", "9a6f65d05ebf2725d62fb19262b21f1805a59fbf", []},
|
"websocket_client": {:git, "https://github.com/jeremyong/websocket_client.git", "9a6f65d05ebf2725d62fb19262b21f1805a59fbf", []},
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,10 @@ defmodule Pleroma.Repo.Migrations.MigrateOldBookmarks do
|
||||||
|
|
||||||
def up do
|
def up do
|
||||||
query =
|
query =
|
||||||
from(u in User,
|
from(u in "users",
|
||||||
where: u.local == true,
|
where: u.local == true,
|
||||||
where: fragment("array_length(bookmarks, 1)") > 0,
|
where: fragment("array_length(?, 1)", u.bookmarks) > 0,
|
||||||
select: %{id: u.id, bookmarks: fragment("bookmarks")}
|
select: %{id: u.id, bookmarks: u.bookmarks}
|
||||||
)
|
)
|
||||||
|
|
||||||
Repo.stream(query)
|
Repo.stream(query)
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
defmodule Pleroma.Repo.Migrations.AddDefaultsToTables do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def up do
|
||||||
|
execute("ALTER TABLE activities
|
||||||
|
ALTER COLUMN recipients SET DEFAULT ARRAY[]::character varying[]")
|
||||||
|
|
||||||
|
execute("ALTER TABLE filters
|
||||||
|
ALTER COLUMN whole_word SET DEFAULT true")
|
||||||
|
|
||||||
|
execute("ALTER TABLE push_subscriptions
|
||||||
|
ALTER COLUMN data SET DEFAULT '{}'::jsonb")
|
||||||
|
|
||||||
|
execute(~s(ALTER TABLE users
|
||||||
|
ALTER COLUMN tags SET DEFAULT ARRAY[]::character varying[],
|
||||||
|
ALTER COLUMN notification_settings SET DEFAULT
|
||||||
|
'{"followers": true, "follows": true, "non_follows": true, "non_followers": true}'::jsonb))
|
||||||
|
|
||||||
|
# irreversible updates
|
||||||
|
|
||||||
|
execute(
|
||||||
|
"UPDATE activities SET recipients = ARRAY[]::character varying[] WHERE recipients IS NULL"
|
||||||
|
)
|
||||||
|
|
||||||
|
execute("UPDATE filters SET whole_word = true WHERE whole_word IS NULL")
|
||||||
|
|
||||||
|
execute("UPDATE push_subscriptions SET data = '{}'::jsonb WHERE data IS NULL")
|
||||||
|
|
||||||
|
execute("UPDATE users SET source_data = '{}'::jsonb where source_data IS NULL")
|
||||||
|
execute("UPDATE users SET note_count = 0 where note_count IS NULL")
|
||||||
|
execute("UPDATE users SET background = '{}'::jsonb where background IS NULL")
|
||||||
|
execute("UPDATE users SET follower_count = 0 where follower_count IS NULL")
|
||||||
|
|
||||||
|
execute(
|
||||||
|
"UPDATE users SET unread_conversation_count = 0 where unread_conversation_count IS NULL"
|
||||||
|
)
|
||||||
|
|
||||||
|
execute(
|
||||||
|
~s(UPDATE users SET email_notifications = '{"digest": false}'::jsonb where email_notifications IS NULL)
|
||||||
|
)
|
||||||
|
|
||||||
|
execute("UPDATE users SET default_scope = 'public' where default_scope IS NULL")
|
||||||
|
|
||||||
|
execute(
|
||||||
|
"UPDATE users SET pleroma_settings_store = '{}'::jsonb where pleroma_settings_store IS NULL"
|
||||||
|
)
|
||||||
|
|
||||||
|
execute("UPDATE users SET tags = ARRAY[]::character varying[] WHERE tags IS NULL")
|
||||||
|
execute(~s(UPDATE users SET notification_settings =
|
||||||
|
'{"followers": true, "follows": true, "non_follows": true, "non_followers": true}'::jsonb
|
||||||
|
WHERE notification_settings = '{}'::jsonb))
|
||||||
|
end
|
||||||
|
|
||||||
|
def down do
|
||||||
|
execute("ALTER TABLE activities
|
||||||
|
ALTER COLUMN recipients DROP DEFAULT")
|
||||||
|
|
||||||
|
execute("ALTER TABLE filters
|
||||||
|
ALTER COLUMN whole_word DROP DEFAULT")
|
||||||
|
|
||||||
|
execute("ALTER TABLE push_subscriptions
|
||||||
|
ALTER COLUMN data DROP DEFAULT")
|
||||||
|
|
||||||
|
execute("ALTER TABLE users
|
||||||
|
ALTER COLUMN tags DROP DEFAULT,
|
||||||
|
ALTER COLUMN notification_settings SET DEFAULT '{}'::jsonb")
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,4 +1,4 @@
|
||||||
defmodule Pleroma.Repo.Migrations.MigrateFollowingRelationships do
|
defmodule Pleroma.Repo.Migrations.MigrateMissingFollowingRelationships do
|
||||||
use Ecto.Migration
|
use Ecto.Migration
|
||||||
|
|
||||||
def change do
|
def change do
|
||||||
|
|
112
priv/repo/migrations/20191029172832_fix_blocked_follows.exs
Normal file
112
priv/repo/migrations/20191029172832_fix_blocked_follows.exs
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
defmodule Pleroma.Repo.Migrations.FixBlockedFollows do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
import Ecto.Query
|
||||||
|
alias Pleroma.Config
|
||||||
|
alias Pleroma.Repo
|
||||||
|
|
||||||
|
def up do
|
||||||
|
unfollow_blocked = Config.get([:activitypub, :unfollow_blocked])
|
||||||
|
|
||||||
|
if unfollow_blocked do
|
||||||
|
"activities"
|
||||||
|
|> where([activity], fragment("? ->> 'type' = 'Block'", activity.data))
|
||||||
|
|> distinct([activity], [
|
||||||
|
activity.actor,
|
||||||
|
fragment(
|
||||||
|
"coalesce((?)->'object'->>'id', (?)->>'object')",
|
||||||
|
activity.data,
|
||||||
|
activity.data
|
||||||
|
)
|
||||||
|
])
|
||||||
|
|> order_by([activity], [fragment("? desc nulls last", activity.id)])
|
||||||
|
|> select([activity], %{
|
||||||
|
blocker: activity.actor,
|
||||||
|
blocked:
|
||||||
|
fragment("coalesce((?)->'object'->>'id', (?)->>'object')", activity.data, activity.data),
|
||||||
|
created_at: activity.id
|
||||||
|
})
|
||||||
|
|> Repo.stream()
|
||||||
|
|> Enum.map(&unfollow_if_blocked/1)
|
||||||
|
|> Enum.uniq()
|
||||||
|
|> Enum.each(&update_follower_count/1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def down do
|
||||||
|
end
|
||||||
|
|
||||||
|
def unfollow_if_blocked(%{blocker: blocker_id, blocked: blocked_id, created_at: blocked_at}) do
|
||||||
|
query =
|
||||||
|
from(
|
||||||
|
activity in "activities",
|
||||||
|
where: fragment("? ->> 'type' = 'Follow'", activity.data),
|
||||||
|
where: activity.actor == ^blocked_id,
|
||||||
|
# this is to use the index
|
||||||
|
where:
|
||||||
|
fragment(
|
||||||
|
"coalesce((?)->'object'->>'id', (?)->>'object') = ?",
|
||||||
|
activity.data,
|
||||||
|
activity.data,
|
||||||
|
^blocker_id
|
||||||
|
),
|
||||||
|
where: activity.id > ^blocked_at,
|
||||||
|
where: fragment("(?)->>'state' = 'accept'", activity.data),
|
||||||
|
order_by: [fragment("? desc nulls last", activity.id)]
|
||||||
|
)
|
||||||
|
|
||||||
|
unless Repo.exists?(query) do
|
||||||
|
blocker = "users" |> select([:id, :local]) |> Repo.get_by(ap_id: blocker_id)
|
||||||
|
blocked = "users" |> select([:id]) |> Repo.get_by(ap_id: blocked_id)
|
||||||
|
|
||||||
|
if !is_nil(blocker) && !is_nil(blocked) do
|
||||||
|
unfollow(blocked, blocker)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def unfollow(%{id: follower_id}, %{id: followed_id} = followed) do
|
||||||
|
following_relationship =
|
||||||
|
"following_relationships"
|
||||||
|
|> where(follower_id: ^follower_id, following_id: ^followed_id, state: "accept")
|
||||||
|
|> select([:id])
|
||||||
|
|> Repo.one()
|
||||||
|
|
||||||
|
case following_relationship do
|
||||||
|
nil ->
|
||||||
|
{:ok, nil}
|
||||||
|
|
||||||
|
%{id: following_relationship_id} ->
|
||||||
|
"following_relationships"
|
||||||
|
|> where(id: ^following_relationship_id)
|
||||||
|
|> Repo.delete_all()
|
||||||
|
|
||||||
|
followed
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_follower_count(%{id: user_id} = user) do
|
||||||
|
if user.local or !Pleroma.Config.get([:instance, :external_user_synchronization]) do
|
||||||
|
follower_count_query =
|
||||||
|
"users"
|
||||||
|
|> where([u], u.id != ^user_id)
|
||||||
|
|> where([u], u.deactivated != ^true)
|
||||||
|
|> join(:inner, [u], r in "following_relationships",
|
||||||
|
as: :relationships,
|
||||||
|
on: r.following_id == ^user_id and r.follower_id == u.id
|
||||||
|
)
|
||||||
|
|> where([relationships: r], r.state == "accept")
|
||||||
|
|> select([u], %{count: count(u.id)})
|
||||||
|
|
||||||
|
"users"
|
||||||
|
|> where(id: ^user_id)
|
||||||
|
|> join(:inner, [u], s in subquery(follower_count_query))
|
||||||
|
|> update([u, s],
|
||||||
|
set: [follower_count: s.count]
|
||||||
|
)
|
||||||
|
|> Repo.update_all([])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_follower_count(_), do: :noop
|
||||||
|
end
|
|
@ -12,7 +12,7 @@ test "it adds cool emoji" do
|
||||||
text = "I love :firefox:"
|
text = "I love :firefox:"
|
||||||
|
|
||||||
expected_result =
|
expected_result =
|
||||||
"I love <img class=\"emoji\" alt=\"firefox\" title=\"firefox\" src=\"/emoji/Firefox.gif\" />"
|
"I love <img class=\"emoji\" alt=\"firefox\" title=\"firefox\" src=\"/emoji/Firefox.gif\"/>"
|
||||||
|
|
||||||
assert Formatter.emojify(text) == expected_result
|
assert Formatter.emojify(text) == expected_result
|
||||||
end
|
end
|
||||||
|
@ -28,10 +28,7 @@ test "it does not add XSS emoji" do
|
||||||
}
|
}
|
||||||
|> Pleroma.Emoji.build()
|
|> Pleroma.Emoji.build()
|
||||||
|
|
||||||
expected_result =
|
refute Formatter.emojify(text, [{custom_emoji.code, custom_emoji}]) =~ text
|
||||||
"I love <img class=\"emoji\" alt=\"\" title=\"\" src=\"https://placehold.it/1x1\" />"
|
|
||||||
|
|
||||||
assert Formatter.emojify(text, [{custom_emoji.code, custom_emoji}]) == expected_result
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -21,31 +21,31 @@ defmodule Pleroma.HTMLTest do
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@html_onerror_sample """
|
@html_onerror_sample """
|
||||||
<img src="http://example.com/image.jpg" onerror="alert('hacked')">
|
<img src="http://example.com/image.jpg" onerror="alert('hacked')">
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@html_span_class_sample """
|
@html_span_class_sample """
|
||||||
<span class="animate-spin">hi</span>
|
<span class="animate-spin">hi</span>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@html_span_microformats_sample """
|
@html_span_microformats_sample """
|
||||||
<span class="h-card"><a class="u-url mention">@<span>foo</span></a></span>
|
<span class="h-card"><a class="u-url mention">@<span>foo</span></a></span>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@html_span_invalid_microformats_sample """
|
@html_span_invalid_microformats_sample """
|
||||||
<span class="h-card"><a class="u-url mention animate-spin">@<span>foo</span></a></span>
|
<span class="h-card"><a class="u-url mention animate-spin">@<span>foo</span></a></span>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
describe "StripTags scrubber" do
|
describe "StripTags scrubber" do
|
||||||
test "works as expected" do
|
test "works as expected" do
|
||||||
expected = """
|
expected = """
|
||||||
this is in bold
|
this is in bold
|
||||||
this is a paragraph
|
this is a paragraph
|
||||||
this is a linebreak
|
this is a linebreak
|
||||||
this is a link with allowed "rel" attribute: example.com
|
this is a link with allowed "rel" attribute: example.com
|
||||||
this is a link with not allowed "rel" attribute: example.com
|
this is a link with not allowed "rel" attribute: example.com
|
||||||
this is an image:
|
this is an image:
|
||||||
alert('hacked')
|
alert('hacked')
|
||||||
"""
|
"""
|
||||||
|
|
||||||
assert expected == HTML.strip_tags(@html_sample)
|
assert expected == HTML.strip_tags(@html_sample)
|
||||||
|
@ -61,13 +61,13 @@ test "does not allow attribute-based XSS" do
|
||||||
describe "TwitterText scrubber" do
|
describe "TwitterText scrubber" do
|
||||||
test "normalizes HTML as expected" do
|
test "normalizes HTML as expected" do
|
||||||
expected = """
|
expected = """
|
||||||
this is in bold
|
this is in bold
|
||||||
<p>this is a paragraph</p>
|
<p>this is a paragraph</p>
|
||||||
this is a linebreak<br />
|
this is a linebreak<br/>
|
||||||
this is a link with allowed "rel" attribute: <a href="http://example.com/" rel="tag">example.com</a>
|
this is a link with allowed "rel" attribute: <a href="http://example.com/" rel="tag">example.com</a>
|
||||||
this is a link with not allowed "rel" attribute: <a href="http://example.com/">example.com</a>
|
this is a link with not allowed "rel" attribute: <a href="http://example.com/">example.com</a>
|
||||||
this is an image: <img src="http://example.com/image.jpg" /><br />
|
this is an image: <img src="http://example.com/image.jpg"/><br/>
|
||||||
alert('hacked')
|
alert('hacked')
|
||||||
"""
|
"""
|
||||||
|
|
||||||
assert expected == HTML.filter_tags(@html_sample, Pleroma.HTML.Scrubber.TwitterText)
|
assert expected == HTML.filter_tags(@html_sample, Pleroma.HTML.Scrubber.TwitterText)
|
||||||
|
@ -75,7 +75,7 @@ test "normalizes HTML as expected" do
|
||||||
|
|
||||||
test "does not allow attribute-based XSS" do
|
test "does not allow attribute-based XSS" do
|
||||||
expected = """
|
expected = """
|
||||||
<img src="http://example.com/image.jpg" />
|
<img src="http://example.com/image.jpg"/>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
assert expected == HTML.filter_tags(@html_onerror_sample, Pleroma.HTML.Scrubber.TwitterText)
|
assert expected == HTML.filter_tags(@html_onerror_sample, Pleroma.HTML.Scrubber.TwitterText)
|
||||||
|
@ -115,13 +115,13 @@ test "filters invalid microformats markup" do
|
||||||
describe "default scrubber" do
|
describe "default scrubber" do
|
||||||
test "normalizes HTML as expected" do
|
test "normalizes HTML as expected" do
|
||||||
expected = """
|
expected = """
|
||||||
<b>this is in bold</b>
|
<b>this is in bold</b>
|
||||||
<p>this is a paragraph</p>
|
<p>this is a paragraph</p>
|
||||||
this is a linebreak<br />
|
this is a linebreak<br/>
|
||||||
this is a link with allowed "rel" attribute: <a href="http://example.com/" rel="tag">example.com</a>
|
this is a link with allowed "rel" attribute: <a href="http://example.com/" rel="tag">example.com</a>
|
||||||
this is a link with not allowed "rel" attribute: <a href="http://example.com/">example.com</a>
|
this is a link with not allowed "rel" attribute: <a href="http://example.com/">example.com</a>
|
||||||
this is an image: <img src="http://example.com/image.jpg" /><br />
|
this is an image: <img src="http://example.com/image.jpg"/><br/>
|
||||||
alert('hacked')
|
alert('hacked')
|
||||||
"""
|
"""
|
||||||
|
|
||||||
assert expected == HTML.filter_tags(@html_sample, Pleroma.HTML.Scrubber.Default)
|
assert expected == HTML.filter_tags(@html_sample, Pleroma.HTML.Scrubber.Default)
|
||||||
|
@ -129,7 +129,7 @@ test "normalizes HTML as expected" do
|
||||||
|
|
||||||
test "does not allow attribute-based XSS" do
|
test "does not allow attribute-based XSS" do
|
||||||
expected = """
|
expected = """
|
||||||
<img src="http://example.com/image.jpg" />
|
<img src="http://example.com/image.jpg"/>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
assert expected == HTML.filter_tags(@html_onerror_sample, Pleroma.HTML.Scrubber.Default)
|
assert expected == HTML.filter_tags(@html_onerror_sample, Pleroma.HTML.Scrubber.Default)
|
||||||
|
|
|
@ -1183,6 +1183,30 @@ def get("https://mstdn.jp/.well-known/webfinger?resource=acct:kpherox@mstdn.jp",
|
||||||
}}
|
}}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def get("https://10.111.10.1/notice/9kCP7V", _, _, _) do
|
||||||
|
{:ok, %Tesla.Env{status: 200, body: ""}}
|
||||||
|
end
|
||||||
|
|
||||||
|
def get("https://172.16.32.40/notice/9kCP7V", _, _, _) do
|
||||||
|
{:ok, %Tesla.Env{status: 200, body: ""}}
|
||||||
|
end
|
||||||
|
|
||||||
|
def get("https://192.168.10.40/notice/9kCP7V", _, _, _) do
|
||||||
|
{:ok, %Tesla.Env{status: 200, body: ""}}
|
||||||
|
end
|
||||||
|
|
||||||
|
def get("https://www.patreon.com/posts/mastodon-2-9-and-28121681", _, _, _) do
|
||||||
|
{:ok, %Tesla.Env{status: 200, body: ""}}
|
||||||
|
end
|
||||||
|
|
||||||
|
def get("http://mastodon.example.org/@admin/99541947525187367", _, _, _) do
|
||||||
|
{:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/mastodon-post-activity.json")}}
|
||||||
|
end
|
||||||
|
|
||||||
|
def get("https://info.pleroma.site/activity4.json", _, _, _) do
|
||||||
|
{:ok, %Tesla.Env{status: 500, body: "Error occurred"}}
|
||||||
|
end
|
||||||
|
|
||||||
def get("http://example.com/rel_me/anchor", _, _, _) do
|
def get("http://example.com/rel_me/anchor", _, _, _) do
|
||||||
{:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/rel_me_anchor.html")}}
|
{:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/rel_me_anchor.html")}}
|
||||||
end
|
end
|
||||||
|
@ -1215,6 +1239,10 @@ def get("https://patch.cx/users/rin", _, _, _) do
|
||||||
{:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/rin.json")}}
|
{:ok, %Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/rin.json")}}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def get("http://example.com/rel_me/error", _, _, _) do
|
||||||
|
{:ok, %Tesla.Env{status: 404, body: ""}}
|
||||||
|
end
|
||||||
|
|
||||||
def get(url, query, body, headers) do
|
def get(url, query, body, headers) do
|
||||||
{:error,
|
{:error,
|
||||||
"Mock response not implemented for GET #{inspect(url)}, #{query}, #{inspect(body)}, #{
|
"Mock response not implemented for GET #{inspect(url)}, #{query}, #{inspect(body)}, #{
|
||||||
|
|
|
@ -51,13 +51,6 @@ test "finds a user by full or partial name" do
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "finds users, preferring nickname matches over name matches" do
|
|
||||||
u1 = insert(:user, %{name: "lain", nickname: "nick1"})
|
|
||||||
u2 = insert(:user, %{nickname: "lain", name: "nick1"})
|
|
||||||
|
|
||||||
assert [u2.id, u1.id] == Enum.map(User.search("lain"), & &1.id)
|
|
||||||
end
|
|
||||||
|
|
||||||
test "finds users, considering density of matched tokens" do
|
test "finds users, considering density of matched tokens" do
|
||||||
u1 = insert(:user, %{name: "Bar Bar plus Word Word"})
|
u1 = insert(:user, %{name: "Bar Bar plus Word Word"})
|
||||||
u2 = insert(:user, %{name: "Word Word Bar Bar Bar"})
|
u2 = insert(:user, %{name: "Word Word Bar Bar Bar"})
|
||||||
|
|
|
@ -878,27 +878,50 @@ test "it imports user blocks from list" do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "get recipients from activity" do
|
describe "get_recipients_from_activity" do
|
||||||
actor = insert(:user)
|
test "get recipients" do
|
||||||
user = insert(:user, local: true)
|
actor = insert(:user)
|
||||||
user_two = insert(:user, local: false)
|
user = insert(:user, local: true)
|
||||||
addressed = insert(:user, local: true)
|
user_two = insert(:user, local: false)
|
||||||
addressed_remote = insert(:user, local: false)
|
addressed = insert(:user, local: true)
|
||||||
|
addressed_remote = insert(:user, local: false)
|
||||||
|
|
||||||
{:ok, activity} =
|
{:ok, activity} =
|
||||||
CommonAPI.post(actor, %{
|
CommonAPI.post(actor, %{
|
||||||
"status" => "hey @#{addressed.nickname} @#{addressed_remote.nickname}"
|
"status" => "hey @#{addressed.nickname} @#{addressed_remote.nickname}"
|
||||||
})
|
})
|
||||||
|
|
||||||
assert Enum.map([actor, addressed], & &1.ap_id) --
|
assert Enum.map([actor, addressed], & &1.ap_id) --
|
||||||
Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
|
Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
|
||||||
|
|
||||||
{:ok, user} = User.follow(user, actor)
|
{:ok, user} = User.follow(user, actor)
|
||||||
{:ok, _user_two} = User.follow(user_two, actor)
|
{:ok, _user_two} = User.follow(user_two, actor)
|
||||||
recipients = User.get_recipients_from_activity(activity)
|
recipients = User.get_recipients_from_activity(activity)
|
||||||
assert length(recipients) == 3
|
assert length(recipients) == 3
|
||||||
assert user in recipients
|
assert user in recipients
|
||||||
assert addressed in recipients
|
assert addressed in recipients
|
||||||
|
end
|
||||||
|
|
||||||
|
test "has following" do
|
||||||
|
actor = insert(:user)
|
||||||
|
user = insert(:user)
|
||||||
|
user_two = insert(:user)
|
||||||
|
addressed = insert(:user, local: true)
|
||||||
|
|
||||||
|
{:ok, activity} =
|
||||||
|
CommonAPI.post(actor, %{
|
||||||
|
"status" => "hey @#{addressed.nickname}"
|
||||||
|
})
|
||||||
|
|
||||||
|
assert Enum.map([actor, addressed], & &1.ap_id) --
|
||||||
|
Enum.map(User.get_recipients_from_activity(activity), & &1.ap_id) == []
|
||||||
|
|
||||||
|
{:ok, _actor} = User.follow(actor, user)
|
||||||
|
{:ok, _actor} = User.follow(actor, user_two)
|
||||||
|
recipients = User.get_recipients_from_activity(activity)
|
||||||
|
assert length(recipients) == 2
|
||||||
|
assert addressed in recipients
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe ".deactivate" do
|
describe ".deactivate" do
|
||||||
|
|
|
@ -10,6 +10,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
alias Pleroma.Web.ActivityPub.Utils
|
alias Pleroma.Web.ActivityPub.Utils
|
||||||
|
alias Pleroma.Web.AdminAPI.AccountView
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
|
|
||||||
import Pleroma.Factory
|
import Pleroma.Factory
|
||||||
|
@ -1281,35 +1282,99 @@ test "returned pinned statuses" do
|
||||||
assert 3 = length(activities)
|
assert 3 = length(activities)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it can create a Flag activity" do
|
describe "flag/1" do
|
||||||
reporter = insert(:user)
|
setup do
|
||||||
target_account = insert(:user)
|
reporter = insert(:user)
|
||||||
{:ok, activity} = CommonAPI.post(target_account, %{"status" => "foobar"})
|
target_account = insert(:user)
|
||||||
context = Utils.generate_context_id()
|
content = "foobar"
|
||||||
content = "foobar"
|
{:ok, activity} = CommonAPI.post(target_account, %{"status" => content})
|
||||||
|
context = Utils.generate_context_id()
|
||||||
|
|
||||||
reporter_ap_id = reporter.ap_id
|
reporter_ap_id = reporter.ap_id
|
||||||
target_ap_id = target_account.ap_id
|
target_ap_id = target_account.ap_id
|
||||||
activity_ap_id = activity.data["id"]
|
activity_ap_id = activity.data["id"]
|
||||||
|
|
||||||
assert {:ok, activity} =
|
activity_with_object = Activity.get_by_ap_id_with_object(activity_ap_id)
|
||||||
ActivityPub.flag(%{
|
|
||||||
actor: reporter,
|
|
||||||
context: context,
|
|
||||||
account: target_account,
|
|
||||||
statuses: [activity],
|
|
||||||
content: content
|
|
||||||
})
|
|
||||||
|
|
||||||
assert %Activity{
|
{:ok,
|
||||||
actor: ^reporter_ap_id,
|
%{
|
||||||
data: %{
|
reporter: reporter,
|
||||||
"type" => "Flag",
|
context: context,
|
||||||
"content" => ^content,
|
target_account: target_account,
|
||||||
"context" => ^context,
|
reported_activity: activity,
|
||||||
"object" => [^target_ap_id, ^activity_ap_id]
|
content: content,
|
||||||
}
|
activity_ap_id: activity_ap_id,
|
||||||
} = activity
|
activity_with_object: activity_with_object,
|
||||||
|
reporter_ap_id: reporter_ap_id,
|
||||||
|
target_ap_id: target_ap_id
|
||||||
|
}}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it can create a Flag activity",
|
||||||
|
%{
|
||||||
|
reporter: reporter,
|
||||||
|
context: context,
|
||||||
|
target_account: target_account,
|
||||||
|
reported_activity: reported_activity,
|
||||||
|
content: content,
|
||||||
|
activity_ap_id: activity_ap_id,
|
||||||
|
activity_with_object: activity_with_object,
|
||||||
|
reporter_ap_id: reporter_ap_id,
|
||||||
|
target_ap_id: target_ap_id
|
||||||
|
} do
|
||||||
|
assert {:ok, activity} =
|
||||||
|
ActivityPub.flag(%{
|
||||||
|
actor: reporter,
|
||||||
|
context: context,
|
||||||
|
account: target_account,
|
||||||
|
statuses: [reported_activity],
|
||||||
|
content: content
|
||||||
|
})
|
||||||
|
|
||||||
|
note_obj = %{
|
||||||
|
"type" => "Note",
|
||||||
|
"id" => activity_ap_id,
|
||||||
|
"content" => content,
|
||||||
|
"published" => activity_with_object.object.data["published"],
|
||||||
|
"actor" => AccountView.render("show.json", %{user: target_account})
|
||||||
|
}
|
||||||
|
|
||||||
|
assert %Activity{
|
||||||
|
actor: ^reporter_ap_id,
|
||||||
|
data: %{
|
||||||
|
"type" => "Flag",
|
||||||
|
"content" => ^content,
|
||||||
|
"context" => ^context,
|
||||||
|
"object" => [^target_ap_id, ^note_obj]
|
||||||
|
}
|
||||||
|
} = activity
|
||||||
|
end
|
||||||
|
|
||||||
|
test_with_mock "strips status data from Flag, before federating it",
|
||||||
|
%{
|
||||||
|
reporter: reporter,
|
||||||
|
context: context,
|
||||||
|
target_account: target_account,
|
||||||
|
reported_activity: reported_activity,
|
||||||
|
content: content
|
||||||
|
},
|
||||||
|
Utils,
|
||||||
|
[:passthrough],
|
||||||
|
[] do
|
||||||
|
{:ok, activity} =
|
||||||
|
ActivityPub.flag(%{
|
||||||
|
actor: reporter,
|
||||||
|
context: context,
|
||||||
|
account: target_account,
|
||||||
|
statuses: [reported_activity],
|
||||||
|
content: content
|
||||||
|
})
|
||||||
|
|
||||||
|
new_data =
|
||||||
|
put_in(activity.data, ["object"], [target_account.ap_id, reported_activity.data["id"]])
|
||||||
|
|
||||||
|
assert_called(Utils.maybe_federate(%{activity | data: new_data}))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "fetch_activities/2 returns activities addressed to a list " do
|
test "fetch_activities/2 returns activities addressed to a list " do
|
||||||
|
|
|
@ -20,11 +20,11 @@ test "it filter html tags" do
|
||||||
expected = """
|
expected = """
|
||||||
<b>this is in bold</b>
|
<b>this is in bold</b>
|
||||||
<p>this is a paragraph</p>
|
<p>this is a paragraph</p>
|
||||||
this is a linebreak<br />
|
this is a linebreak<br/>
|
||||||
this is a link with allowed "rel" attribute: <a href="http://example.com/" rel="tag">example.com</a>
|
this is a link with allowed "rel" attribute: <a href="http://example.com/" rel="tag">example.com</a>
|
||||||
this is a link with not allowed "rel" attribute: <a href="http://example.com/">example.com</a>
|
this is a link with not allowed "rel" attribute: <a href="http://example.com/">example.com</a>
|
||||||
this is an image: <img src="http://example.com/image.jpg" /><br />
|
this is an image: <img src="http://example.com/image.jpg"/><br/>
|
||||||
alert('hacked')
|
alert('hacked')
|
||||||
"""
|
"""
|
||||||
|
|
||||||
message = %{"type" => "Create", "object" => %{"content" => @html_sample}}
|
message = %{"type" => "Create", "object" => %{"content" => @html_sample}}
|
||||||
|
|
|
@ -11,6 +11,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||||
|
alias Pleroma.Web.AdminAPI.AccountView
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
|
|
||||||
import Mock
|
import Mock
|
||||||
|
@ -746,7 +747,10 @@ test "it fails for incoming user deletes with spoofed origin" do
|
||||||
|> Poison.decode!()
|
|> Poison.decode!()
|
||||||
|> Map.put("actor", ap_id)
|
|> Map.put("actor", ap_id)
|
||||||
|
|
||||||
assert :error == Transmogrifier.handle_incoming(data)
|
assert capture_log(fn ->
|
||||||
|
assert :error == Transmogrifier.handle_incoming(data)
|
||||||
|
end) =~ "Object containment failed"
|
||||||
|
|
||||||
assert User.get_cached_by_ap_id(ap_id)
|
assert User.get_cached_by_ap_id(ap_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1109,10 +1113,18 @@ test "it accepts Flag activities" do
|
||||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
|
{:ok, activity} = CommonAPI.post(user, %{"status" => "test post"})
|
||||||
object = Object.normalize(activity)
|
object = Object.normalize(activity)
|
||||||
|
|
||||||
|
note_obj = %{
|
||||||
|
"type" => "Note",
|
||||||
|
"id" => activity.data["id"],
|
||||||
|
"content" => "test post",
|
||||||
|
"published" => object.data["published"],
|
||||||
|
"actor" => AccountView.render("show.json", %{user: user})
|
||||||
|
}
|
||||||
|
|
||||||
message = %{
|
message = %{
|
||||||
"@context" => "https://www.w3.org/ns/activitystreams",
|
"@context" => "https://www.w3.org/ns/activitystreams",
|
||||||
"cc" => [user.ap_id],
|
"cc" => [user.ap_id],
|
||||||
"object" => [user.ap_id, object.data["id"]],
|
"object" => [user.ap_id, activity.data["id"]],
|
||||||
"type" => "Flag",
|
"type" => "Flag",
|
||||||
"content" => "blocked AND reported!!!",
|
"content" => "blocked AND reported!!!",
|
||||||
"actor" => other_user.ap_id
|
"actor" => other_user.ap_id
|
||||||
|
@ -1120,7 +1132,7 @@ test "it accepts Flag activities" do
|
||||||
|
|
||||||
assert {:ok, activity} = Transmogrifier.handle_incoming(message)
|
assert {:ok, activity} = Transmogrifier.handle_incoming(message)
|
||||||
|
|
||||||
assert activity.data["object"] == [user.ap_id, object.data["id"]]
|
assert activity.data["object"] == [user.ap_id, note_obj]
|
||||||
assert activity.data["content"] == "blocked AND reported!!!"
|
assert activity.data["content"] == "blocked AND reported!!!"
|
||||||
assert activity.data["actor"] == other_user.ap_id
|
assert activity.data["actor"] == other_user.ap_id
|
||||||
assert activity.data["cc"] == [user.ap_id]
|
assert activity.data["cc"] == [user.ap_id]
|
||||||
|
@ -1428,7 +1440,9 @@ test "it rejects activities which reference objects with bogus origins" do
|
||||||
"type" => "Announce"
|
"type" => "Announce"
|
||||||
}
|
}
|
||||||
|
|
||||||
:error = Transmogrifier.handle_incoming(data)
|
assert capture_log(fn ->
|
||||||
|
:error = Transmogrifier.handle_incoming(data)
|
||||||
|
end) =~ "Object containment failed"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it rejects activities which reference objects that have an incorrect attribution (variant 1)" do
|
test "it rejects activities which reference objects that have an incorrect attribution (variant 1)" do
|
||||||
|
@ -1441,7 +1455,9 @@ test "it rejects activities which reference objects that have an incorrect attri
|
||||||
"type" => "Announce"
|
"type" => "Announce"
|
||||||
}
|
}
|
||||||
|
|
||||||
:error = Transmogrifier.handle_incoming(data)
|
assert capture_log(fn ->
|
||||||
|
:error = Transmogrifier.handle_incoming(data)
|
||||||
|
end) =~ "Object containment failed"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it rejects activities which reference objects that have an incorrect attribution (variant 2)" do
|
test "it rejects activities which reference objects that have an incorrect attribution (variant 2)" do
|
||||||
|
@ -1454,7 +1470,9 @@ test "it rejects activities which reference objects that have an incorrect attri
|
||||||
"type" => "Announce"
|
"type" => "Announce"
|
||||||
}
|
}
|
||||||
|
|
||||||
:error = Transmogrifier.handle_incoming(data)
|
assert capture_log(fn ->
|
||||||
|
:error = Transmogrifier.handle_incoming(data)
|
||||||
|
end) =~ "Object containment failed"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1757,7 +1775,9 @@ test "retunrs not modified object" do
|
||||||
|
|
||||||
describe "get_obj_helper/2" do
|
describe "get_obj_helper/2" do
|
||||||
test "returns nil when cannot normalize object" do
|
test "returns nil when cannot normalize object" do
|
||||||
refute Transmogrifier.get_obj_helper("test-obj-id")
|
assert capture_log(fn ->
|
||||||
|
refute Transmogrifier.get_obj_helper("test-obj-id")
|
||||||
|
end) =~ "Unsupported URI scheme"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "returns {:ok, %Object{}} for success case" do
|
test "returns {:ok, %Object{}} for success case" do
|
||||||
|
|
|
@ -10,6 +10,7 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
alias Pleroma.Web.ActivityPub.Utils
|
alias Pleroma.Web.ActivityPub.Utils
|
||||||
|
alias Pleroma.Web.AdminAPI.AccountView
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
|
|
||||||
import Pleroma.Factory
|
import Pleroma.Factory
|
||||||
|
@ -581,11 +582,19 @@ test "returns map with Flag object" do
|
||||||
%{}
|
%{}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
note_obj = %{
|
||||||
|
"type" => "Note",
|
||||||
|
"id" => activity_ap_id,
|
||||||
|
"content" => content,
|
||||||
|
"published" => activity.object.data["published"],
|
||||||
|
"actor" => AccountView.render("show.json", %{user: target_account})
|
||||||
|
}
|
||||||
|
|
||||||
assert %{
|
assert %{
|
||||||
"type" => "Flag",
|
"type" => "Flag",
|
||||||
"content" => ^content,
|
"content" => ^content,
|
||||||
"context" => ^context,
|
"context" => ^context,
|
||||||
"object" => [^target_ap_id, ^activity_ap_id],
|
"object" => [^target_ap_id, ^note_obj],
|
||||||
"state" => "open"
|
"state" => "open"
|
||||||
} = res
|
} = res
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,6 +13,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
|
||||||
alias Pleroma.Tests.ObanHelpers
|
alias Pleroma.Tests.ObanHelpers
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.UserInviteToken
|
alias Pleroma.UserInviteToken
|
||||||
|
alias Pleroma.Web.ActivityPub.Relay
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
alias Pleroma.Web.MediaProxy
|
alias Pleroma.Web.MediaProxy
|
||||||
import Pleroma.Factory
|
import Pleroma.Factory
|
||||||
|
@ -1044,6 +1045,32 @@ test "it works with multiple filters" do
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "it omits relay user", %{admin: admin} do
|
||||||
|
assert %User{} = Relay.get_actor()
|
||||||
|
|
||||||
|
conn =
|
||||||
|
build_conn()
|
||||||
|
|> assign(:user, admin)
|
||||||
|
|> get("/api/pleroma/admin/users")
|
||||||
|
|
||||||
|
assert json_response(conn, 200) == %{
|
||||||
|
"count" => 1,
|
||||||
|
"page_size" => 50,
|
||||||
|
"users" => [
|
||||||
|
%{
|
||||||
|
"deactivated" => admin.deactivated,
|
||||||
|
"id" => admin.id,
|
||||||
|
"nickname" => admin.nickname,
|
||||||
|
"roles" => %{"admin" => true, "moderator" => false},
|
||||||
|
"local" => true,
|
||||||
|
"tags" => [],
|
||||||
|
"avatar" => User.avatar_url(admin) |> MediaProxy.url(),
|
||||||
|
"display_name" => HTML.strip_tags(admin.name || admin.nickname)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "PATCH /api/pleroma/admin/users/activate" do
|
test "PATCH /api/pleroma/admin/users/activate" do
|
||||||
|
|
|
@ -10,6 +10,7 @@ defmodule Pleroma.Web.CommonAPITest do
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
alias Pleroma.Web.ActivityPub.Visibility
|
alias Pleroma.Web.ActivityPub.Visibility
|
||||||
|
alias Pleroma.Web.AdminAPI.AccountView
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
|
|
||||||
import Pleroma.Factory
|
import Pleroma.Factory
|
||||||
|
@ -140,7 +141,7 @@ test "it filters out obviously bad tags when accepting a post as HTML" do
|
||||||
|
|
||||||
object = Object.normalize(activity)
|
object = Object.normalize(activity)
|
||||||
|
|
||||||
assert object.data["content"] == "<p><b>2hu</b></p>alert('xss')"
|
assert object.data["content"] == "<p><b>2hu</b></p>alert('xss')"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it filters out obviously bad tags when accepting a post as Markdown" do
|
test "it filters out obviously bad tags when accepting a post as Markdown" do
|
||||||
|
@ -156,7 +157,7 @@ test "it filters out obviously bad tags when accepting a post as Markdown" do
|
||||||
|
|
||||||
object = Object.normalize(activity)
|
object = Object.normalize(activity)
|
||||||
|
|
||||||
assert object.data["content"] == "<p><b>2hu</b></p>alert('xss')"
|
assert object.data["content"] == "<p><b>2hu</b></p>alert('xss')"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it does not allow replies to direct messages that are not direct messages themselves" do
|
test "it does not allow replies to direct messages that are not direct messages themselves" do
|
||||||
|
@ -385,6 +386,14 @@ test "creates a report" do
|
||||||
"status_ids" => [activity.id]
|
"status_ids" => [activity.id]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
note_obj = %{
|
||||||
|
"type" => "Note",
|
||||||
|
"id" => activity_ap_id,
|
||||||
|
"content" => "foobar",
|
||||||
|
"published" => activity.object.data["published"],
|
||||||
|
"actor" => AccountView.render("show.json", %{user: target_user})
|
||||||
|
}
|
||||||
|
|
||||||
assert {:ok, flag_activity} = CommonAPI.report(reporter, report_data)
|
assert {:ok, flag_activity} = CommonAPI.report(reporter, report_data)
|
||||||
|
|
||||||
assert %Activity{
|
assert %Activity{
|
||||||
|
@ -392,7 +401,7 @@ test "creates a report" do
|
||||||
data: %{
|
data: %{
|
||||||
"type" => "Flag",
|
"type" => "Flag",
|
||||||
"content" => ^comment,
|
"content" => ^comment,
|
||||||
"object" => [^target_ap_id, ^activity_ap_id],
|
"object" => [^target_ap_id, ^note_obj],
|
||||||
"state" => "open"
|
"state" => "open"
|
||||||
}
|
}
|
||||||
} = flag_activity
|
} = flag_activity
|
||||||
|
@ -412,6 +421,11 @@ test "updates report state" do
|
||||||
{:ok, report} = CommonAPI.update_report_state(report_id, "resolved")
|
{:ok, report} = CommonAPI.update_report_state(report_id, "resolved")
|
||||||
|
|
||||||
assert report.data["state"] == "resolved"
|
assert report.data["state"] == "resolved"
|
||||||
|
|
||||||
|
[reported_user, activity_id] = report.data["object"]
|
||||||
|
|
||||||
|
assert reported_user == target_user.ap_id
|
||||||
|
assert activity_id == activity.data["id"]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "does not update report state when state is unsupported" do
|
test "does not update report state when state is unsupported" do
|
||||||
|
|
|
@ -30,5 +30,6 @@ test "represents a Mastodon Conversation entity" do
|
||||||
|
|
||||||
assert [account] = conversation.accounts
|
assert [account] = conversation.accounts
|
||||||
assert account.id == other_user.id
|
assert account.id == other_user.id
|
||||||
|
assert conversation.last_status.pleroma.direct_conversation_id == participation.id
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,6 +7,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
||||||
|
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
alias Pleroma.Bookmark
|
alias Pleroma.Bookmark
|
||||||
|
alias Pleroma.Conversation.Participation
|
||||||
|
alias Pleroma.HTML
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
alias Pleroma.Repo
|
alias Pleroma.Repo
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
|
@ -22,10 +24,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
|
||||||
:ok
|
:ok
|
||||||
end
|
end
|
||||||
|
|
||||||
test "returns the direct conversation id when given the `with_conversation_id` option" do
|
test "loads and returns the direct conversation id when given the `with_direct_conversation_id` option" do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
||||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!", "visibility" => "direct"})
|
{:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!", "visibility" => "direct"})
|
||||||
|
[participation] = Participation.for_user(user)
|
||||||
|
|
||||||
status =
|
status =
|
||||||
StatusView.render("show.json",
|
StatusView.render("show.json",
|
||||||
|
@ -34,7 +37,26 @@ test "returns the direct conversation id when given the `with_conversation_id` o
|
||||||
for: user
|
for: user
|
||||||
)
|
)
|
||||||
|
|
||||||
assert status[:pleroma][:direct_conversation_id]
|
assert status[:pleroma][:direct_conversation_id] == participation.id
|
||||||
|
|
||||||
|
status = StatusView.render("show.json", activity: activity, for: user)
|
||||||
|
assert status[:pleroma][:direct_conversation_id] == nil
|
||||||
|
end
|
||||||
|
|
||||||
|
test "returns the direct conversation id when given the `direct_conversation_id` option" do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
{:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!", "visibility" => "direct"})
|
||||||
|
[participation] = Participation.for_user(user)
|
||||||
|
|
||||||
|
status =
|
||||||
|
StatusView.render("show.json",
|
||||||
|
activity: activity,
|
||||||
|
direct_conversation_id: participation.id,
|
||||||
|
for: user
|
||||||
|
)
|
||||||
|
|
||||||
|
assert status[:pleroma][:direct_conversation_id] == participation.id
|
||||||
end
|
end
|
||||||
|
|
||||||
test "returns a temporary ap_id based user for activities missing db users" do
|
test "returns a temporary ap_id based user for activities missing db users" do
|
||||||
|
@ -107,7 +129,7 @@ test "a note activity" do
|
||||||
in_reply_to_account_id: nil,
|
in_reply_to_account_id: nil,
|
||||||
card: nil,
|
card: nil,
|
||||||
reblog: nil,
|
reblog: nil,
|
||||||
content: HtmlSanitizeEx.basic_html(object_data["content"]),
|
content: HTML.filter_tags(object_data["content"]),
|
||||||
created_at: created_at,
|
created_at: created_at,
|
||||||
reblogs_count: 0,
|
reblogs_count: 0,
|
||||||
replies_count: 0,
|
replies_count: 0,
|
||||||
|
@ -119,7 +141,7 @@ test "a note activity" do
|
||||||
pinned: false,
|
pinned: false,
|
||||||
sensitive: false,
|
sensitive: false,
|
||||||
poll: nil,
|
poll: nil,
|
||||||
spoiler_text: HtmlSanitizeEx.basic_html(object_data["summary"]),
|
spoiler_text: HTML.filter_tags(object_data["summary"]),
|
||||||
visibility: "public",
|
visibility: "public",
|
||||||
media_attachments: [],
|
media_attachments: [],
|
||||||
mentions: [],
|
mentions: [],
|
||||||
|
@ -146,8 +168,8 @@ test "a note activity" do
|
||||||
local: true,
|
local: true,
|
||||||
conversation_id: convo_id,
|
conversation_id: convo_id,
|
||||||
in_reply_to_account_acct: nil,
|
in_reply_to_account_acct: nil,
|
||||||
content: %{"text/plain" => HtmlSanitizeEx.strip_tags(object_data["content"])},
|
content: %{"text/plain" => HTML.strip_tags(object_data["content"])},
|
||||||
spoiler_text: %{"text/plain" => HtmlSanitizeEx.strip_tags(object_data["summary"])},
|
spoiler_text: %{"text/plain" => HTML.strip_tags(object_data["summary"])},
|
||||||
expires_at: nil,
|
expires_at: nil,
|
||||||
direct_conversation_id: nil,
|
direct_conversation_id: nil,
|
||||||
thread_muted: false
|
thread_muted: false
|
||||||
|
|
|
@ -14,7 +14,9 @@ test "parse/1" do
|
||||||
hrefs = ["https://social.example.org/users/lain"]
|
hrefs = ["https://social.example.org/users/lain"]
|
||||||
|
|
||||||
assert Pleroma.Web.RelMe.parse("http://example.com/rel_me/null") == {:ok, []}
|
assert Pleroma.Web.RelMe.parse("http://example.com/rel_me/null") == {:ok, []}
|
||||||
assert {:error, _} = Pleroma.Web.RelMe.parse("http://example.com/rel_me/error")
|
|
||||||
|
assert {:ok, %Tesla.Env{status: 404}} =
|
||||||
|
Pleroma.Web.RelMe.parse("http://example.com/rel_me/error")
|
||||||
|
|
||||||
assert Pleroma.Web.RelMe.parse("http://example.com/rel_me/link") == {:ok, hrefs}
|
assert Pleroma.Web.RelMe.parse("http://example.com/rel_me/link") == {:ok, hrefs}
|
||||||
assert Pleroma.Web.RelMe.parse("http://example.com/rel_me/anchor") == {:ok, hrefs}
|
assert Pleroma.Web.RelMe.parse("http://example.com/rel_me/anchor") == {:ok, hrefs}
|
||||||
|
|
|
@ -7,6 +7,7 @@ defmodule Pleroma.Web.StreamerTest do
|
||||||
|
|
||||||
import Pleroma.Factory
|
import Pleroma.Factory
|
||||||
|
|
||||||
|
alias Pleroma.Conversation.Participation
|
||||||
alias Pleroma.List
|
alias Pleroma.List
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
|
@ -110,6 +111,24 @@ test "it doesn't send notify to the 'user:notification' stream' when a domain is
|
||||||
Streamer.stream("user:notification", notif)
|
Streamer.stream("user:notification", notif)
|
||||||
Task.await(task)
|
Task.await(task)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "it sends follow activities to the 'user:notification' stream", %{
|
||||||
|
user: user
|
||||||
|
} do
|
||||||
|
user2 = insert(:user)
|
||||||
|
task = Task.async(fn -> assert_receive {:text, _}, 4_000 end)
|
||||||
|
|
||||||
|
Streamer.add_socket(
|
||||||
|
"user:notification",
|
||||||
|
%{transport_pid: task.pid, assigns: %{user: user}}
|
||||||
|
)
|
||||||
|
|
||||||
|
{:ok, _follower, _followed, _activity} = CommonAPI.follow(user2, user)
|
||||||
|
|
||||||
|
# We don't directly pipe the notification to the streamer as it's already
|
||||||
|
# generated as a side effect of CommonAPI.follow().
|
||||||
|
Task.await(task)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it sends to public" do
|
test "it sends to public" do
|
||||||
|
@ -463,7 +482,14 @@ test "it sends conversation update to the 'direct' stream", %{} do
|
||||||
|
|
||||||
task =
|
task =
|
||||||
Task.async(fn ->
|
Task.async(fn ->
|
||||||
assert_receive {:text, _received_event}, 4_000
|
assert_receive {:text, received_event}, 4_000
|
||||||
|
|
||||||
|
assert %{"event" => "conversation", "payload" => received_payload} =
|
||||||
|
Jason.decode!(received_event)
|
||||||
|
|
||||||
|
assert %{"last_status" => last_status} = Jason.decode!(received_payload)
|
||||||
|
[participation] = Participation.for_user(user)
|
||||||
|
assert last_status["pleroma"]["direct_conversation_id"] == participation.id
|
||||||
end)
|
end)
|
||||||
|
|
||||||
Streamer.add_socket(
|
Streamer.add_socket(
|
||||||
|
@ -480,7 +506,7 @@ test "it sends conversation update to the 'direct' stream", %{} do
|
||||||
Task.await(task)
|
Task.await(task)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it doesn't send conversation update to the 'direct' streamj when the last message in the conversation is deleted" do
|
test "it doesn't send conversation update to the 'direct' stream when the last message in the conversation is deleted" do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
another_user = insert(:user)
|
another_user = insert(:user)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue