Merge remote-tracking branch 'pleroma/develop' into feature/addressable-lists
This commit is contained in:
commit
9ce928d823
103 changed files with 3064 additions and 721 deletions
|
|
@ -29,13 +29,13 @@ defmodule Pleroma.Healthcheck do
|
|||
end
|
||||
|
||||
defp assign_db_info(healthcheck) do
|
||||
database = Application.get_env(:pleroma, Repo)[:database]
|
||||
database = Pleroma.Config.get([Repo, :database])
|
||||
|
||||
query =
|
||||
"select state, count(pid) from pg_stat_activity where datname = '#{database}' group by state;"
|
||||
|
||||
result = Repo.query!(query)
|
||||
pool_size = Application.get_env(:pleroma, Repo)[:pool_size]
|
||||
pool_size = Pleroma.Config.get([Repo, :pool_size])
|
||||
|
||||
db_info =
|
||||
Enum.reduce(result.rows, %{active: 0, idle: 0}, fn [state, cnt], states ->
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ defmodule Pleroma.Conversation do
|
|||
with true <- Pleroma.Web.ActivityPub.Visibility.is_direct?(activity),
|
||||
"Create" <- activity.data["type"],
|
||||
object <- Pleroma.Object.normalize(activity),
|
||||
"Note" <- object.data["type"],
|
||||
true <- object.data["type"] in ["Note", "Question"],
|
||||
ap_id when is_binary(ap_id) and byte_size(ap_id) > 0 <- object.data["context"] do
|
||||
{:ok, conversation} = create_for_ap_id(ap_id)
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ defmodule Pleroma.Emoji do
|
|||
|
||||
@ets __MODULE__.Ets
|
||||
@ets_options [:ordered_set, :protected, :named_table, {:read_concurrency, true}]
|
||||
@groups Application.get_env(:pleroma, :emoji)[:groups]
|
||||
@groups Pleroma.Config.get([:emoji, :groups])
|
||||
|
||||
@doc false
|
||||
def start_link do
|
||||
|
|
@ -112,7 +112,7 @@ defmodule Pleroma.Emoji do
|
|||
|
||||
# Compat thing for old custom emoji handling & default emoji,
|
||||
# it should run even if there are no emoji packs
|
||||
shortcode_globs = Application.get_env(:pleroma, :emoji)[:shortcode_globs] || []
|
||||
shortcode_globs = Pleroma.Config.get([:emoji, :shortcode_globs], [])
|
||||
|
||||
emojis =
|
||||
(load_from_file("config/emoji.txt") ++
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ defmodule Pleroma.Formatter do
|
|||
alias Pleroma.User
|
||||
alias Pleroma.Web.MediaProxy
|
||||
|
||||
@safe_mention_regex ~r/^(\s*(?<mentions>@.+?\s+)+)(?<rest>.*)/s
|
||||
@safe_mention_regex ~r/^(\s*(?<mentions>(@.+?\s+){1,})+)(?<rest>.*)/s
|
||||
@link_regex ~r"((?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~%:/?#[\]@!\$&'\(\)\*\+,;=.]+)|[0-9a-z+\-\.]+:[0-9a-z$-_.+!*'(),]+"ui
|
||||
@markdown_characters_regex ~r/(`|\*|_|{|}|[|]|\(|\)|#|\+|-|\.|!)/
|
||||
|
||||
|
|
|
|||
|
|
@ -104,7 +104,6 @@ defmodule Pleroma.HTML.Scrubber.TwitterText do
|
|||
paragraphs, breaks and links are allowed through the filter.
|
||||
"""
|
||||
|
||||
@markup Application.get_env(:pleroma, :markup)
|
||||
@valid_schemes Pleroma.Config.get([:uri_schemes, :valid_schemes], [])
|
||||
|
||||
require HtmlSanitizeEx.Scrubber.Meta
|
||||
|
|
@ -142,9 +141,7 @@ defmodule Pleroma.HTML.Scrubber.TwitterText do
|
|||
Meta.allow_tag_with_these_attributes("span", [])
|
||||
|
||||
# allow inline images for custom emoji
|
||||
@allow_inline_images Keyword.get(@markup, :allow_inline_images)
|
||||
|
||||
if @allow_inline_images do
|
||||
if Pleroma.Config.get([:markup, :allow_inline_images]) do
|
||||
# restrict img tags to http/https only, because of MediaProxy.
|
||||
Meta.allow_tag_with_uri_attributes("img", ["src"], ["http", "https"])
|
||||
|
||||
|
|
@ -168,7 +165,6 @@ defmodule Pleroma.HTML.Scrubber.Default do
|
|||
# credo:disable-for-previous-line
|
||||
# No idea how to fix this one…
|
||||
|
||||
@markup Application.get_env(:pleroma, :markup)
|
||||
@valid_schemes Pleroma.Config.get([:uri_schemes, :valid_schemes], [])
|
||||
|
||||
Meta.remove_cdata_sections_before_scrub()
|
||||
|
|
@ -213,7 +209,7 @@ defmodule Pleroma.HTML.Scrubber.Default do
|
|||
Meta.allow_tag_with_this_attribute_values("span", "class", ["h-card"])
|
||||
Meta.allow_tag_with_these_attributes("span", [])
|
||||
|
||||
@allow_inline_images Keyword.get(@markup, :allow_inline_images)
|
||||
@allow_inline_images Pleroma.Config.get([:markup, :allow_inline_images])
|
||||
|
||||
if @allow_inline_images do
|
||||
# restrict img tags to http/https only, because of MediaProxy.
|
||||
|
|
@ -228,9 +224,7 @@ defmodule Pleroma.HTML.Scrubber.Default do
|
|||
])
|
||||
end
|
||||
|
||||
@allow_tables Keyword.get(@markup, :allow_tables)
|
||||
|
||||
if @allow_tables do
|
||||
if Pleroma.Config.get([:markup, :allow_tables]) do
|
||||
Meta.allow_tag_with_these_attributes("table", [])
|
||||
Meta.allow_tag_with_these_attributes("tbody", [])
|
||||
Meta.allow_tag_with_these_attributes("td", [])
|
||||
|
|
@ -239,9 +233,7 @@ defmodule Pleroma.HTML.Scrubber.Default do
|
|||
Meta.allow_tag_with_these_attributes("tr", [])
|
||||
end
|
||||
|
||||
@allow_headings Keyword.get(@markup, :allow_headings)
|
||||
|
||||
if @allow_headings do
|
||||
if Pleroma.Config.get([:markup, :allow_headings]) do
|
||||
Meta.allow_tag_with_these_attributes("h1", [])
|
||||
Meta.allow_tag_with_these_attributes("h2", [])
|
||||
Meta.allow_tag_with_these_attributes("h3", [])
|
||||
|
|
@ -249,9 +241,7 @@ defmodule Pleroma.HTML.Scrubber.Default do
|
|||
Meta.allow_tag_with_these_attributes("h5", [])
|
||||
end
|
||||
|
||||
@allow_fonts Keyword.get(@markup, :allow_fonts)
|
||||
|
||||
if @allow_fonts do
|
||||
if Pleroma.Config.get([:markup, :allow_fonts]) do
|
||||
Meta.allow_tag_with_these_attributes("font", ["face"])
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -32,9 +32,11 @@ defmodule Pleroma.HTTP.Connection do
|
|||
defp hackney_options(opts) do
|
||||
options = Keyword.get(opts, :adapter, [])
|
||||
adapter_options = Pleroma.Config.get([:http, :adapter], [])
|
||||
proxy_url = Pleroma.Config.get([:http, :proxy_url], nil)
|
||||
|
||||
@hackney_options
|
||||
|> Keyword.merge(adapter_options)
|
||||
|> Keyword.merge(options)
|
||||
|> Keyword.merge(proxy: proxy_url)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -65,12 +65,9 @@ defmodule Pleroma.HTTP do
|
|||
end
|
||||
|
||||
def process_request_options(options) do
|
||||
config = Application.get_env(:pleroma, :http, [])
|
||||
proxy = Keyword.get(config, :proxy_url, nil)
|
||||
|
||||
case proxy do
|
||||
case Pleroma.Config.get([:http, :proxy_url]) do
|
||||
nil -> options
|
||||
_ -> options ++ [proxy: proxy]
|
||||
proxy -> options ++ [proxy: proxy]
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -127,10 +127,15 @@ defmodule Pleroma.Notification do
|
|||
|
||||
def create_notifications(%Activity{data: %{"to" => _, "type" => type}} = activity)
|
||||
when type in ["Create", "Like", "Announce", "Follow"] do
|
||||
users = get_notified_from_activity(activity)
|
||||
object = Object.normalize(activity)
|
||||
|
||||
notifications = Enum.map(users, fn user -> create_notification(activity, user) end)
|
||||
{:ok, notifications}
|
||||
unless object && object.data["type"] == "Answer" do
|
||||
users = get_notified_from_activity(activity)
|
||||
notifications = Enum.map(users, fn user -> create_notification(activity, user) end)
|
||||
{:ok, notifications}
|
||||
else
|
||||
{:ok, []}
|
||||
end
|
||||
end
|
||||
|
||||
def create_notifications(_), do: {:ok, []}
|
||||
|
|
@ -166,7 +171,16 @@ defmodule Pleroma.Notification do
|
|||
def get_notified_from_activity(_, _local_only), do: []
|
||||
|
||||
def skip?(activity, user) do
|
||||
[:self, :blocked, :local, :muted, :followers, :follows, :recently_followed]
|
||||
[
|
||||
:self,
|
||||
:blocked,
|
||||
:muted,
|
||||
:followers,
|
||||
:follows,
|
||||
:non_followers,
|
||||
:non_follows,
|
||||
:recently_followed
|
||||
]
|
||||
|> Enum.any?(&skip?(&1, activity, user))
|
||||
end
|
||||
|
||||
|
|
@ -179,12 +193,6 @@ defmodule Pleroma.Notification do
|
|||
User.blocks?(user, %{ap_id: actor})
|
||||
end
|
||||
|
||||
def skip?(:local, %{local: true}, %{info: %{notification_settings: %{"local" => false}}}),
|
||||
do: true
|
||||
|
||||
def skip?(:local, %{local: false}, %{info: %{notification_settings: %{"remote" => false}}}),
|
||||
do: true
|
||||
|
||||
def skip?(:muted, activity, user) do
|
||||
actor = activity.data["actor"]
|
||||
|
||||
|
|
@ -201,12 +209,32 @@ defmodule Pleroma.Notification do
|
|||
User.following?(follower, user)
|
||||
end
|
||||
|
||||
def skip?(
|
||||
:non_followers,
|
||||
activity,
|
||||
%{info: %{notification_settings: %{"non_followers" => false}}} = user
|
||||
) do
|
||||
actor = activity.data["actor"]
|
||||
follower = User.get_cached_by_ap_id(actor)
|
||||
!User.following?(follower, user)
|
||||
end
|
||||
|
||||
def skip?(:follows, activity, %{info: %{notification_settings: %{"follows" => false}}} = user) do
|
||||
actor = activity.data["actor"]
|
||||
followed = User.get_cached_by_ap_id(actor)
|
||||
User.following?(user, followed)
|
||||
end
|
||||
|
||||
def skip?(
|
||||
:non_follows,
|
||||
activity,
|
||||
%{info: %{notification_settings: %{"non_follows" => false}}} = user
|
||||
) do
|
||||
actor = activity.data["actor"]
|
||||
followed = User.get_cached_by_ap_id(actor)
|
||||
!User.following?(user, followed)
|
||||
end
|
||||
|
||||
def skip?(:recently_followed, %{data: %{"type" => "Follow"}} = activity, user) do
|
||||
actor = activity.data["actor"]
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,9 @@ defmodule Pleroma.Object do
|
|||
|> unique_constraint(:ap_id, name: :objects_unique_apid_index)
|
||||
end
|
||||
|
||||
def get_by_id(nil), do: nil
|
||||
def get_by_id(id), do: Repo.get(Object, id)
|
||||
|
||||
def get_by_ap_id(nil), do: nil
|
||||
|
||||
def get_by_ap_id(ap_id) do
|
||||
|
|
@ -195,4 +198,34 @@ defmodule Pleroma.Object do
|
|||
_ -> {:error, "Not found"}
|
||||
end
|
||||
end
|
||||
|
||||
def increase_vote_count(ap_id, name) do
|
||||
with %Object{} = object <- Object.normalize(ap_id),
|
||||
"Question" <- object.data["type"] do
|
||||
multiple = Map.has_key?(object.data, "anyOf")
|
||||
|
||||
options =
|
||||
(object.data["anyOf"] || object.data["oneOf"] || [])
|
||||
|> Enum.map(fn
|
||||
%{"name" => ^name} = option ->
|
||||
Kernel.update_in(option["replies"]["totalItems"], &(&1 + 1))
|
||||
|
||||
option ->
|
||||
option
|
||||
end)
|
||||
|
||||
data =
|
||||
if multiple do
|
||||
Map.put(object.data, "anyOf", options)
|
||||
else
|
||||
Map.put(object.data, "oneOf", options)
|
||||
end
|
||||
|
||||
object
|
||||
|> Object.change(%{data: data})
|
||||
|> update_and_set_cache()
|
||||
else
|
||||
_ -> :noop
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
defmodule Pleroma.Object.Fetcher do
|
||||
alias Pleroma.HTTP
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Object.Containment
|
||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||
|
|
@ -6,8 +7,6 @@ defmodule Pleroma.Object.Fetcher do
|
|||
|
||||
require Logger
|
||||
|
||||
@httpoison Application.get_env(:pleroma, :httpoison)
|
||||
|
||||
defp reinject_object(data) do
|
||||
Logger.debug("Reinjecting object #{data["id"]}")
|
||||
|
||||
|
|
@ -78,7 +77,7 @@ defmodule Pleroma.Object.Fetcher do
|
|||
|
||||
with true <- String.starts_with?(id, "http"),
|
||||
{:ok, %{body: body, status: code}} when code in 200..299 <-
|
||||
@httpoison.get(
|
||||
HTTP.get(
|
||||
id,
|
||||
[{:Accept, "application/activity+json"}]
|
||||
),
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ defmodule Pleroma.Web.FederatingPlug do
|
|||
end
|
||||
|
||||
def call(conn, _opts) do
|
||||
if Keyword.get(Application.get_env(:pleroma, :instance), :federating) do
|
||||
if Pleroma.Config.get([:instance, :federating]) do
|
||||
conn
|
||||
else
|
||||
conn
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.ReverseProxy do
|
||||
alias Pleroma.HTTP
|
||||
|
||||
@keep_req_headers ~w(accept user-agent accept-encoding cache-control if-modified-since) ++
|
||||
~w(if-unmodified-since if-none-match if-range range)
|
||||
@resp_cache_headers ~w(etag date last-modified cache-control)
|
||||
|
|
@ -59,9 +61,6 @@ defmodule Pleroma.ReverseProxy do
|
|||
* `http`: options for [hackney](https://github.com/benoitc/hackney).
|
||||
|
||||
"""
|
||||
@hackney Application.get_env(:pleroma, :hackney, :hackney)
|
||||
@httpoison Application.get_env(:pleroma, :httpoison, HTTPoison)
|
||||
|
||||
@default_hackney_options []
|
||||
|
||||
@inline_content_types [
|
||||
|
|
@ -97,7 +96,7 @@ defmodule Pleroma.ReverseProxy do
|
|||
hackney_opts =
|
||||
@default_hackney_options
|
||||
|> Keyword.merge(Keyword.get(opts, :http, []))
|
||||
|> @httpoison.process_request_options()
|
||||
|> HTTP.process_request_options()
|
||||
|
||||
req_headers = build_req_headers(conn.req_headers, opts)
|
||||
|
||||
|
|
@ -147,7 +146,7 @@ defmodule Pleroma.ReverseProxy do
|
|||
Logger.debug("#{__MODULE__} #{method} #{url} #{inspect(headers)}")
|
||||
method = method |> String.downcase() |> String.to_existing_atom()
|
||||
|
||||
case @hackney.request(method, url, headers, "", hackney_opts) do
|
||||
case :hackney.request(method, url, headers, "", hackney_opts) do
|
||||
{:ok, code, headers, client} when code in @valid_resp_codes ->
|
||||
{:ok, code, downcase_headers(headers), client}
|
||||
|
||||
|
|
@ -197,7 +196,7 @@ defmodule Pleroma.ReverseProxy do
|
|||
duration,
|
||||
Keyword.get(opts, :max_read_duration, @max_read_duration)
|
||||
),
|
||||
{:ok, data} <- @hackney.stream_body(client),
|
||||
{:ok, data} <- :hackney.stream_body(client),
|
||||
{:ok, duration} <- increase_read_duration(duration),
|
||||
sent_so_far = sent_so_far + byte_size(data),
|
||||
:ok <- body_size_constraint(sent_so_far, Keyword.get(opts, :max_body_size)),
|
||||
|
|
|
|||
|
|
@ -4,11 +4,10 @@
|
|||
|
||||
defmodule Pleroma.Uploaders.MDII do
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.HTTP
|
||||
|
||||
@behaviour Pleroma.Uploaders.Uploader
|
||||
|
||||
@httpoison Application.get_env(:pleroma, :httpoison)
|
||||
|
||||
# MDII-hosted images are never passed through the MediaPlug; only local media.
|
||||
# Delegate to Pleroma.Uploaders.Local
|
||||
def get_file(file) do
|
||||
|
|
@ -25,7 +24,7 @@ defmodule Pleroma.Uploaders.MDII do
|
|||
query = "#{cgi}?#{extension}"
|
||||
|
||||
with {:ok, %{status: 200, body: body}} <-
|
||||
@httpoison.post(query, file_data, [], adapter: [pool: :default]) do
|
||||
HTTP.post(query, file_data, [], adapter: [pool: :default]) do
|
||||
remote_file_name = String.split(body) |> List.first()
|
||||
public_url = "#{files}/#{remote_file_name}.#{extension}"
|
||||
{:ok, {:url, public_url}}
|
||||
|
|
|
|||
|
|
@ -366,9 +366,7 @@ defmodule Pleroma.User do
|
|||
end
|
||||
|
||||
def follow(%User{} = follower, %User{info: info} = followed) do
|
||||
user_config = Application.get_env(:pleroma, :user)
|
||||
deny_follow_blocked = Keyword.get(user_config, :deny_follow_blocked)
|
||||
|
||||
deny_follow_blocked = Pleroma.Config.get([:user, :deny_follow_blocked])
|
||||
ap_followers = followed.follower_address
|
||||
|
||||
cond do
|
||||
|
|
@ -760,7 +758,7 @@ defmodule Pleroma.User do
|
|||
|
||||
from(s in subquery(boost_search_rank_query(distinct_query, for_user)),
|
||||
order_by: [desc: s.search_rank],
|
||||
limit: 20
|
||||
limit: 40
|
||||
)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -42,12 +42,17 @@ defmodule Pleroma.User.Info do
|
|||
field(:hide_follows, :boolean, default: false)
|
||||
field(:hide_favorites, :boolean, default: true)
|
||||
field(:pinned_activities, {:array, :string}, default: [])
|
||||
field(:flavour, :string, default: nil)
|
||||
field(:mascot, :map, default: nil)
|
||||
field(:emoji, {:array, :map}, default: [])
|
||||
field(:pleroma_settings_store, :map, default: %{})
|
||||
|
||||
field(:notification_settings, :map,
|
||||
default: %{"remote" => true, "local" => true, "followers" => true, "follows" => true}
|
||||
default: %{
|
||||
"followers" => true,
|
||||
"follows" => true,
|
||||
"non_follows" => true,
|
||||
"non_followers" => true
|
||||
}
|
||||
)
|
||||
|
||||
# Found in the wild
|
||||
|
|
@ -68,10 +73,15 @@ defmodule Pleroma.User.Info do
|
|||
end
|
||||
|
||||
def update_notification_settings(info, settings) do
|
||||
settings =
|
||||
settings
|
||||
|> Enum.map(fn {k, v} -> {k, v in [true, "true", "True", "1"]} end)
|
||||
|> Map.new()
|
||||
|
||||
notification_settings =
|
||||
info.notification_settings
|
||||
|> Map.merge(settings)
|
||||
|> Map.take(["remote", "local", "followers", "follows"])
|
||||
|> Map.take(["followers", "follows", "non_follows", "non_followers"])
|
||||
|
||||
params = %{notification_settings: notification_settings}
|
||||
|
||||
|
|
@ -209,7 +219,8 @@ defmodule Pleroma.User.Info do
|
|||
:hide_followers,
|
||||
:hide_favorites,
|
||||
:background,
|
||||
:show_role
|
||||
:show_role,
|
||||
:pleroma_settings_store
|
||||
])
|
||||
end
|
||||
|
||||
|
|
@ -241,14 +252,6 @@ defmodule Pleroma.User.Info do
|
|||
|> validate_required([:settings])
|
||||
end
|
||||
|
||||
def mastodon_flavour_update(info, flavour) do
|
||||
params = %{flavour: flavour}
|
||||
|
||||
info
|
||||
|> cast(params, [:flavour])
|
||||
|> validate_required([:flavour])
|
||||
end
|
||||
|
||||
def mascot_update(info, url) do
|
||||
params = %{mascot: url}
|
||||
|
||||
|
|
|
|||
|
|
@ -107,6 +107,15 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
|
||||
def decrease_replies_count_if_reply(_object), do: :noop
|
||||
|
||||
def increase_poll_votes_if_vote(%{
|
||||
"object" => %{"inReplyTo" => reply_ap_id, "name" => name},
|
||||
"type" => "Create"
|
||||
}) do
|
||||
Object.increase_vote_count(reply_ap_id, name)
|
||||
end
|
||||
|
||||
def increase_poll_votes_if_vote(_create_data), do: :noop
|
||||
|
||||
def insert(map, local \\ true, fake \\ false) when is_map(map) do
|
||||
with nil <- Activity.normalize(map),
|
||||
map <- lazy_put_activity_defaults(map, fake),
|
||||
|
|
@ -182,40 +191,42 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
public = "https://www.w3.org/ns/activitystreams#Public"
|
||||
|
||||
if activity.data["type"] in ["Create", "Announce", "Delete"] do
|
||||
Pleroma.Web.Streamer.stream("user", activity)
|
||||
Pleroma.Web.Streamer.stream("list", activity)
|
||||
object = Object.normalize(activity)
|
||||
# Do not stream out poll replies
|
||||
unless object.data["type"] == "Answer" do
|
||||
Pleroma.Web.Streamer.stream("user", activity)
|
||||
Pleroma.Web.Streamer.stream("list", activity)
|
||||
|
||||
if Enum.member?(activity.data["to"], public) do
|
||||
Pleroma.Web.Streamer.stream("public", activity)
|
||||
if Enum.member?(activity.data["to"], public) do
|
||||
Pleroma.Web.Streamer.stream("public", activity)
|
||||
|
||||
if activity.local do
|
||||
Pleroma.Web.Streamer.stream("public:local", activity)
|
||||
end
|
||||
if activity.local do
|
||||
Pleroma.Web.Streamer.stream("public:local", activity)
|
||||
end
|
||||
|
||||
if activity.data["type"] in ["Create"] do
|
||||
object = Object.normalize(activity)
|
||||
if activity.data["type"] in ["Create"] do
|
||||
object.data
|
||||
|> Map.get("tag", [])
|
||||
|> Enum.filter(fn tag -> is_bitstring(tag) end)
|
||||
|> Enum.each(fn tag -> Pleroma.Web.Streamer.stream("hashtag:" <> tag, activity) end)
|
||||
|
||||
object.data
|
||||
|> Map.get("tag", [])
|
||||
|> Enum.filter(fn tag -> is_bitstring(tag) end)
|
||||
|> Enum.each(fn tag -> Pleroma.Web.Streamer.stream("hashtag:" <> tag, activity) end)
|
||||
if object.data["attachment"] != [] do
|
||||
Pleroma.Web.Streamer.stream("public:media", activity)
|
||||
|
||||
if object.data["attachment"] != [] do
|
||||
Pleroma.Web.Streamer.stream("public:media", activity)
|
||||
|
||||
if activity.local do
|
||||
Pleroma.Web.Streamer.stream("public:local:media", activity)
|
||||
if activity.local do
|
||||
Pleroma.Web.Streamer.stream("public:local:media", activity)
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
# TODO: Write test, replace with visibility test
|
||||
if !Enum.member?(activity.data["cc"] || [], public) &&
|
||||
!Enum.member?(
|
||||
activity.data["to"],
|
||||
User.get_cached_by_ap_id(activity.data["actor"]).follower_address
|
||||
),
|
||||
do: Pleroma.Web.Streamer.stream("direct", activity)
|
||||
end
|
||||
else
|
||||
# TODO: Write test, replace with visibility test
|
||||
if !Enum.member?(activity.data["cc"] || [], public) &&
|
||||
!Enum.member?(
|
||||
activity.data["to"],
|
||||
User.get_cached_by_ap_id(activity.data["actor"]).follower_address
|
||||
),
|
||||
do: Pleroma.Web.Streamer.stream("direct", activity)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -234,6 +245,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
{:ok, activity} <- insert(create_data, local, fake),
|
||||
{:fake, false, activity} <- {:fake, fake, activity},
|
||||
_ <- increase_replies_count_if_reply(create_data),
|
||||
_ <- increase_poll_votes_if_vote(create_data),
|
||||
# Changing note count prior to enqueuing federation task in order to avoid
|
||||
# race conditions on updating user.info
|
||||
{:ok, _actor} <- increase_note_count_if_public(actor, activity),
|
||||
|
|
@ -398,16 +410,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
end
|
||||
|
||||
def block(blocker, blocked, activity_id \\ nil, local \\ true) do
|
||||
ap_config = Application.get_env(:pleroma, :activitypub)
|
||||
unfollow_blocked = Keyword.get(ap_config, :unfollow_blocked)
|
||||
outgoing_blocks = Keyword.get(ap_config, :outgoing_blocks)
|
||||
outgoing_blocks = Pleroma.Config.get([:activitypub, :outgoing_blocks])
|
||||
unfollow_blocked = Pleroma.Config.get([:activitypub, :unfollow_blocked])
|
||||
|
||||
with true <- unfollow_blocked do
|
||||
if unfollow_blocked do
|
||||
follow_activity = fetch_latest_follow(blocker, blocked)
|
||||
|
||||
if follow_activity do
|
||||
unfollow(blocker, blocked, nil, local)
|
||||
end
|
||||
if follow_activity, do: unfollow(blocker, blocked, nil, local)
|
||||
end
|
||||
|
||||
with true <- outgoing_blocks,
|
||||
|
|
@ -479,6 +487,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
if opts["user"], do: [opts["user"].ap_id | opts["user"].following] ++ public, else: public
|
||||
|
||||
from(activity in Activity)
|
||||
|> maybe_preload_objects(opts)
|
||||
|> restrict_blocked(opts)
|
||||
|> restrict_recipients(recipients, opts["user"])
|
||||
|> where(
|
||||
|
|
@ -491,6 +500,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
^context
|
||||
)
|
||||
)
|
||||
|> exclude_poll_votes(opts)
|
||||
|> order_by([activity], desc: activity.id)
|
||||
end
|
||||
|
||||
|
|
@ -498,7 +508,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
def fetch_activities_for_context(context, opts \\ %{}) do
|
||||
context
|
||||
|> fetch_activities_for_context_query(opts)
|
||||
|> Activity.with_preloaded_object()
|
||||
|> Repo.all()
|
||||
end
|
||||
|
||||
|
|
@ -506,7 +515,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
Pleroma.FlakeId.t() | nil
|
||||
def fetch_latest_activity_id_for_context(context, opts \\ %{}) do
|
||||
context
|
||||
|> fetch_activities_for_context_query(opts)
|
||||
|> fetch_activities_for_context_query(Map.merge(%{"skip_preload" => true}, opts))
|
||||
|> limit(1)
|
||||
|> select([a], a.id)
|
||||
|> Repo.one()
|
||||
|
|
@ -652,20 +661,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
|
||||
defp restrict_tag(query, _), do: query
|
||||
|
||||
defp restrict_to_cc(query, recipients_to, recipients_cc) do
|
||||
from(
|
||||
activity in query,
|
||||
where:
|
||||
fragment(
|
||||
"(?->'to' \\?| ?) or (?->'cc' \\?| ?)",
|
||||
activity.data,
|
||||
^recipients_to,
|
||||
activity.data,
|
||||
^recipients_cc
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
defp restrict_recipients(query, [], _user), do: query
|
||||
|
||||
defp restrict_recipients(query, recipients, nil) do
|
||||
|
|
@ -819,6 +814,18 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
|
||||
defp restrict_muted_reblogs(query, _), do: query
|
||||
|
||||
defp exclude_poll_votes(query, %{"include_poll_votes" => "true"}), do: query
|
||||
|
||||
defp exclude_poll_votes(query, _) do
|
||||
if has_named_binding?(query, :object) do
|
||||
from([activity, object: o] in query,
|
||||
where: fragment("not(?->>'type' = ?)", o.data, "Answer")
|
||||
)
|
||||
else
|
||||
query
|
||||
end
|
||||
end
|
||||
|
||||
defp maybe_preload_objects(query, %{"skip_preload" => true}), do: query
|
||||
|
||||
defp maybe_preload_objects(query, _) do
|
||||
|
|
@ -878,6 +885,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
|> restrict_pinned(opts)
|
||||
|> restrict_muted_reblogs(opts)
|
||||
|> Activity.restrict_deactivated_users()
|
||||
|> exclude_poll_votes(opts)
|
||||
end
|
||||
|
||||
def fetch_activities(recipients, opts \\ %{}) do
|
||||
|
|
@ -906,9 +914,18 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
|
||||
defp maybe_update_cc(activities, _, _), do: activities
|
||||
|
||||
def fetch_activities_bounded(recipients_to, recipients_cc, opts \\ %{}) do
|
||||
def fetch_activities_bounded_query(query, recipients, recipients_with_public) do
|
||||
from(activity in query,
|
||||
where:
|
||||
fragment("? && ?", activity.recipients, ^recipients) or
|
||||
(fragment("? && ?", activity.recipients, ^recipients_with_public) and
|
||||
"https://www.w3.org/ns/activitystreams#Public" in activity.recipients)
|
||||
)
|
||||
end
|
||||
|
||||
def fetch_activities_bounded(recipients, recipients_with_public, opts \\ %{}) do
|
||||
fetch_activities_query([], opts)
|
||||
|> restrict_to_cc(recipients_to, recipients_cc)
|
||||
|> fetch_activities_bounded_query(recipients, recipients_with_public)
|
||||
|> Pagination.fetch_paginated(opts)
|
||||
|> Enum.reverse()
|
||||
end
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
|
|||
plug(:relay_active? when action in [:relay])
|
||||
|
||||
def relay_active?(conn, _) do
|
||||
if Keyword.get(Application.get_env(:pleroma, :instance), :allow_relay) do
|
||||
if Pleroma.Config.get([:instance, :allow_relay]) do
|
||||
conn
|
||||
else
|
||||
conn
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
defmodule Pleroma.Web.ActivityPub.MRF do
|
||||
@callback filter(Map.t()) :: {:ok | :reject, Map.t()}
|
||||
|
||||
def filter(object) do
|
||||
get_policies()
|
||||
def filter(policies, %{} = object) do
|
||||
policies
|
||||
|> Enum.reduce({:ok, object}, fn
|
||||
policy, {:ok, object} ->
|
||||
policy.filter(object)
|
||||
|
|
@ -16,10 +16,10 @@ defmodule Pleroma.Web.ActivityPub.MRF do
|
|||
end)
|
||||
end
|
||||
|
||||
def filter(%{} = object), do: get_policies() |> filter(object)
|
||||
|
||||
def get_policies do
|
||||
Application.get_env(:pleroma, :instance, [])
|
||||
|> Keyword.get(:rewrite_policy, [])
|
||||
|> get_policies()
|
||||
Pleroma.Config.get([:instance, :rewrite_policy], []) |> get_policies()
|
||||
end
|
||||
|
||||
defp get_policies(policy) when is_atom(policy), do: [policy]
|
||||
|
|
|
|||
|
|
@ -74,8 +74,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.SimplePolicy do
|
|||
actor_host
|
||||
),
|
||||
user <- User.get_cached_by_ap_id(object["actor"]),
|
||||
true <- "https://www.w3.org/ns/activitystreams#Public" in object["to"],
|
||||
true <- user.follower_address in object["cc"] do
|
||||
true <- "https://www.w3.org/ns/activitystreams#Public" in object["to"] do
|
||||
to =
|
||||
List.delete(object["to"], "https://www.w3.org/ns/activitystreams#Public") ++
|
||||
[user.follower_address]
|
||||
|
|
|
|||
40
lib/pleroma/web/activity_pub/mrf/subchain_policy.ex
Normal file
40
lib/pleroma/web/activity_pub/mrf/subchain_policy.ex
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ActivityPub.MRF.SubchainPolicy do
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.Web.ActivityPub.MRF
|
||||
|
||||
require Logger
|
||||
|
||||
@behaviour MRF
|
||||
|
||||
defp lookup_subchain(actor) do
|
||||
with matches <- Config.get([:mrf_subchain, :match_actor]),
|
||||
{match, subchain} <- Enum.find(matches, fn {k, _v} -> String.match?(actor, k) end) do
|
||||
{:ok, match, subchain}
|
||||
else
|
||||
_e -> {:error, :notfound}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(%{"actor" => actor} = message) do
|
||||
with {:ok, match, subchain} <- lookup_subchain(actor) do
|
||||
Logger.debug(
|
||||
"[SubchainPolicy] Matched #{actor} against #{inspect(match)} with subchain #{
|
||||
inspect(subchain)
|
||||
}"
|
||||
)
|
||||
|
||||
subchain
|
||||
|> MRF.filter(message)
|
||||
else
|
||||
_e -> {:ok, message}
|
||||
end
|
||||
end
|
||||
|
||||
@impl true
|
||||
def filter(message), do: {:ok, message}
|
||||
end
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
defmodule Pleroma.Web.ActivityPub.Publisher do
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.Config
|
||||
alias Pleroma.HTTP
|
||||
alias Pleroma.Instances
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.Relay
|
||||
|
|
@ -16,8 +17,6 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
|
|||
|
||||
require Logger
|
||||
|
||||
@httpoison Application.get_env(:pleroma, :httpoison)
|
||||
|
||||
@moduledoc """
|
||||
ActivityPub outgoing federation module.
|
||||
"""
|
||||
|
|
@ -63,7 +62,7 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
|
|||
|
||||
with {:ok, %{status: code}} when code in 200..299 <-
|
||||
result =
|
||||
@httpoison.post(
|
||||
HTTP.post(
|
||||
inbox,
|
||||
json,
|
||||
[
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
|> fix_likes
|
||||
|> fix_addressing
|
||||
|> fix_summary
|
||||
|> fix_type
|
||||
end
|
||||
|
||||
def fix_summary(%{"summary" => nil} = object) do
|
||||
|
|
@ -65,7 +66,11 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
end
|
||||
end
|
||||
|
||||
def fix_explicit_addressing(%{"to" => to, "cc" => cc} = object, explicit_mentions) do
|
||||
def fix_explicit_addressing(
|
||||
%{"to" => to, "cc" => cc} = object,
|
||||
explicit_mentions,
|
||||
follower_collection
|
||||
) do
|
||||
explicit_to =
|
||||
to
|
||||
|> Enum.filter(fn x -> x in explicit_mentions end)
|
||||
|
|
@ -76,6 +81,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
|
||||
final_cc =
|
||||
(cc ++ explicit_cc)
|
||||
|> Enum.reject(fn x -> String.ends_with?(x, "/followers") and x != follower_collection end)
|
||||
|> Enum.uniq()
|
||||
|
||||
object
|
||||
|
|
@ -83,7 +89,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
|> Map.put("cc", final_cc)
|
||||
end
|
||||
|
||||
def fix_explicit_addressing(object, _explicit_mentions), do: object
|
||||
def fix_explicit_addressing(object, _explicit_mentions, _followers_collection), do: object
|
||||
|
||||
# if directMessage flag is set to true, leave the addressing alone
|
||||
def fix_explicit_addressing(%{"directMessage" => true} = object), do: object
|
||||
|
|
@ -93,10 +99,12 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
object
|
||||
|> Utils.determine_explicit_mentions()
|
||||
|
||||
explicit_mentions = explicit_mentions ++ ["https://www.w3.org/ns/activitystreams#Public"]
|
||||
follower_collection = User.get_cached_by_ap_id(Containment.get_actor(object)).follower_address
|
||||
|
||||
object
|
||||
|> fix_explicit_addressing(explicit_mentions)
|
||||
explicit_mentions =
|
||||
explicit_mentions ++ ["https://www.w3.org/ns/activitystreams#Public", follower_collection]
|
||||
|
||||
fix_explicit_addressing(object, explicit_mentions, follower_collection)
|
||||
end
|
||||
|
||||
# if as:Public is addressed, then make sure the followers collection is also addressed
|
||||
|
|
@ -133,7 +141,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
|> fix_addressing_list("cc")
|
||||
|> fix_addressing_list("bto")
|
||||
|> fix_addressing_list("bcc")
|
||||
|> fix_explicit_addressing
|
||||
|> fix_explicit_addressing()
|
||||
|> fix_implicit_addressing(followers_collection)
|
||||
end
|
||||
|
||||
|
|
@ -328,6 +336,18 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
|
||||
def fix_content_map(object), do: object
|
||||
|
||||
def fix_type(%{"inReplyTo" => reply_id} = object) when is_binary(reply_id) do
|
||||
reply = Object.normalize(reply_id)
|
||||
|
||||
if reply.data["type"] == "Question" and object["name"] do
|
||||
Map.put(object, "type", "Answer")
|
||||
else
|
||||
object
|
||||
end
|
||||
end
|
||||
|
||||
def fix_type(object), do: object
|
||||
|
||||
defp mastodon_follow_hack(%{"id" => id, "actor" => follower_id}, followed) do
|
||||
with true <- id =~ "follows",
|
||||
%User{local: true} = follower <- User.get_cached_by_ap_id(follower_id),
|
||||
|
|
@ -398,7 +418,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
# - tags
|
||||
# - emoji
|
||||
def handle_incoming(%{"type" => "Create", "object" => %{"type" => objtype} = object} = data)
|
||||
when objtype in ["Article", "Note", "Video", "Page"] do
|
||||
when objtype in ["Article", "Note", "Video", "Page", "Question", "Answer"] do
|
||||
actor = Containment.get_actor(data)
|
||||
|
||||
data =
|
||||
|
|
@ -731,6 +751,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
|> set_reply_to_uri
|
||||
|> strip_internal_fields
|
||||
|> strip_internal_tags
|
||||
|> set_type
|
||||
end
|
||||
|
||||
# @doc
|
||||
|
|
@ -898,6 +919,12 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
Map.put(object, "sensitive", "nsfw" in tags)
|
||||
end
|
||||
|
||||
def set_type(%{"type" => "Answer"} = object) do
|
||||
Map.put(object, "type", "Note")
|
||||
end
|
||||
|
||||
def set_type(object), do: object
|
||||
|
||||
def add_attributed_to(object) do
|
||||
attributed_to = object["attributedTo"] || object["actor"]
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
|||
|
||||
require Logger
|
||||
|
||||
@supported_object_types ["Article", "Note", "Video", "Page"]
|
||||
@supported_object_types ["Article", "Note", "Video", "Page", "Question", "Answer"]
|
||||
@supported_report_states ~w(open closed resolved)
|
||||
@valid_visibilities ~w(public unlisted private direct)
|
||||
|
||||
|
|
@ -789,4 +789,21 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
|||
[to, cc, recipients]
|
||||
end
|
||||
end
|
||||
|
||||
def get_existing_votes(actor, %{data: %{"id" => id}}) do
|
||||
query =
|
||||
from(
|
||||
[activity, object: object] in Activity.with_preloaded_object(Activity),
|
||||
where: fragment("(?)->>'actor' = ?", activity.data, ^actor),
|
||||
where:
|
||||
fragment(
|
||||
"(?)->>'inReplyTo' = ?",
|
||||
object.data,
|
||||
^to_string(id)
|
||||
),
|
||||
where: fragment("(?)->>'type' = 'Answer'", object.data)
|
||||
)
|
||||
|
||||
Repo.all(query)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -66,6 +66,9 @@ defmodule Pleroma.Web.ActivityPub.Visibility do
|
|||
Enum.any?(to, &String.contains?(&1, "/followers")) ->
|
||||
"private"
|
||||
|
||||
object.data["directMessage"] == true ->
|
||||
"direct"
|
||||
|
||||
length(cc) > 0 ->
|
||||
"private"
|
||||
|
||||
|
|
|
|||
|
|
@ -119,6 +119,53 @@ defmodule Pleroma.Web.CommonAPI do
|
|||
end
|
||||
end
|
||||
|
||||
def vote(user, object, choices) do
|
||||
with "Question" <- object.data["type"],
|
||||
{:author, false} <- {:author, object.data["actor"] == user.ap_id},
|
||||
{:existing_votes, []} <- {:existing_votes, Utils.get_existing_votes(user.ap_id, object)},
|
||||
{options, max_count} <- get_options_and_max_count(object),
|
||||
option_count <- Enum.count(options),
|
||||
{:choice_check, {choices, true}} <-
|
||||
{:choice_check, normalize_and_validate_choice_indices(choices, option_count)},
|
||||
{:count_check, true} <- {:count_check, Enum.count(choices) <= max_count} do
|
||||
answer_activities =
|
||||
Enum.map(choices, fn index ->
|
||||
answer_data = make_answer_data(user, object, Enum.at(options, index)["name"])
|
||||
|
||||
ActivityPub.create(%{
|
||||
to: answer_data["to"],
|
||||
actor: user,
|
||||
context: object.data["context"],
|
||||
object: answer_data,
|
||||
additional: %{"cc" => answer_data["cc"]}
|
||||
})
|
||||
end)
|
||||
|
||||
object = Object.get_cached_by_ap_id(object.data["id"])
|
||||
{:ok, answer_activities, object}
|
||||
else
|
||||
{:author, _} -> {:error, "Poll's author can't vote"}
|
||||
{:existing_votes, _} -> {:error, "Already voted"}
|
||||
{:choice_check, {_, false}} -> {:error, "Invalid indices"}
|
||||
{:count_check, false} -> {:error, "Too many choices"}
|
||||
end
|
||||
end
|
||||
|
||||
defp get_options_and_max_count(object) do
|
||||
if Map.has_key?(object.data, "anyOf") do
|
||||
{object.data["anyOf"], Enum.count(object.data["anyOf"])}
|
||||
else
|
||||
{object.data["oneOf"], 1}
|
||||
end
|
||||
end
|
||||
|
||||
defp normalize_and_validate_choice_indices(choices, count) do
|
||||
Enum.map_reduce(choices, true, fn index, valid ->
|
||||
index = if is_binary(index), do: String.to_integer(index), else: index
|
||||
{index, if(valid, do: index < count, else: valid)}
|
||||
end)
|
||||
end
|
||||
|
||||
def get_visibility(%{"visibility" => visibility}, in_reply_to)
|
||||
when visibility in ~w{public unlisted private direct},
|
||||
do: {visibility, get_replied_to_visibility(in_reply_to)}
|
||||
|
|
@ -159,6 +206,7 @@ defmodule Pleroma.Web.CommonAPI do
|
|||
data,
|
||||
visibility
|
||||
),
|
||||
{poll, poll_emoji} <- make_poll_data(data),
|
||||
{to, cc} <- to_for_user_and_mentions(user, mentions, in_reply_to, visibility),
|
||||
bcc <- bcc_for_list(user, visibility),
|
||||
context <- make_context(in_reply_to),
|
||||
|
|
@ -177,13 +225,14 @@ defmodule Pleroma.Web.CommonAPI do
|
|||
tags,
|
||||
cw,
|
||||
cc,
|
||||
sensitive
|
||||
sensitive,
|
||||
poll
|
||||
),
|
||||
object <-
|
||||
Map.put(
|
||||
object,
|
||||
"emoji",
|
||||
Formatter.get_emoji_map(full_payload)
|
||||
Map.merge(Formatter.get_emoji_map(full_payload), poll_emoji)
|
||||
) do
|
||||
ActivityPub.create(
|
||||
%{
|
||||
|
|
|
|||
|
|
@ -111,6 +111,72 @@ defmodule Pleroma.Web.CommonAPI.Utils do
|
|||
|
||||
def bcc_for_list(_, _), do: []
|
||||
|
||||
def make_poll_data(%{"poll" => %{"options" => options, "expires_in" => expires_in}} = data)
|
||||
when is_list(options) do
|
||||
%{max_expiration: max_expiration, min_expiration: min_expiration} =
|
||||
limits = Pleroma.Config.get([:instance, :poll_limits])
|
||||
|
||||
# XXX: There is probably a cleaner way of doing this
|
||||
try do
|
||||
# In some cases mastofe sends out strings instead of integers
|
||||
expires_in = if is_binary(expires_in), do: String.to_integer(expires_in), else: expires_in
|
||||
|
||||
if Enum.count(options) > limits.max_options do
|
||||
raise ArgumentError, message: "Poll can't contain more than #{limits.max_options} options"
|
||||
end
|
||||
|
||||
{poll, emoji} =
|
||||
Enum.map_reduce(options, %{}, fn option, emoji ->
|
||||
if String.length(option) > limits.max_option_chars do
|
||||
raise ArgumentError,
|
||||
message:
|
||||
"Poll options cannot be longer than #{limits.max_option_chars} characters each"
|
||||
end
|
||||
|
||||
{%{
|
||||
"name" => option,
|
||||
"type" => "Note",
|
||||
"replies" => %{"type" => "Collection", "totalItems" => 0}
|
||||
}, Map.merge(emoji, Formatter.get_emoji_map(option))}
|
||||
end)
|
||||
|
||||
case expires_in do
|
||||
expires_in when expires_in > max_expiration ->
|
||||
raise ArgumentError, message: "Expiration date is too far in the future"
|
||||
|
||||
expires_in when expires_in < min_expiration ->
|
||||
raise ArgumentError, message: "Expiration date is too soon"
|
||||
|
||||
_ ->
|
||||
:noop
|
||||
end
|
||||
|
||||
end_time =
|
||||
NaiveDateTime.utc_now()
|
||||
|> NaiveDateTime.add(expires_in)
|
||||
|> NaiveDateTime.to_iso8601()
|
||||
|
||||
poll =
|
||||
if Pleroma.Web.ControllerHelper.truthy_param?(data["poll"]["multiple"]) do
|
||||
%{"type" => "Question", "anyOf" => poll, "closed" => end_time}
|
||||
else
|
||||
%{"type" => "Question", "oneOf" => poll, "closed" => end_time}
|
||||
end
|
||||
|
||||
{poll, emoji}
|
||||
rescue
|
||||
e in ArgumentError -> e.message
|
||||
end
|
||||
end
|
||||
|
||||
def make_poll_data(%{"poll" => poll}) when is_map(poll) do
|
||||
"Invalid poll"
|
||||
end
|
||||
|
||||
def make_poll_data(_data) do
|
||||
{%{}, %{}}
|
||||
end
|
||||
|
||||
def make_content_html(
|
||||
status,
|
||||
attachments,
|
||||
|
|
@ -233,7 +299,8 @@ defmodule Pleroma.Web.CommonAPI.Utils do
|
|||
tags,
|
||||
cw \\ nil,
|
||||
cc \\ [],
|
||||
sensitive \\ false
|
||||
sensitive \\ false,
|
||||
merge \\ %{}
|
||||
) do
|
||||
object = %{
|
||||
"type" => "Note",
|
||||
|
|
@ -248,12 +315,15 @@ defmodule Pleroma.Web.CommonAPI.Utils do
|
|||
"tag" => tags |> Enum.map(fn {_, tag} -> tag end) |> Enum.uniq()
|
||||
}
|
||||
|
||||
with false <- is_nil(in_reply_to),
|
||||
%Object{} = in_reply_to_object <- Object.normalize(in_reply_to) do
|
||||
Map.put(object, "inReplyTo", in_reply_to_object.data["id"])
|
||||
else
|
||||
_ -> object
|
||||
end
|
||||
object =
|
||||
with false <- is_nil(in_reply_to),
|
||||
%Object{} = in_reply_to_object <- Object.normalize(in_reply_to) do
|
||||
Map.put(object, "inReplyTo", in_reply_to_object.data["id"])
|
||||
else
|
||||
_ -> object
|
||||
end
|
||||
|
||||
Map.merge(object, merge)
|
||||
end
|
||||
|
||||
def format_naive_asctime(date) do
|
||||
|
|
@ -430,4 +500,15 @@ defmodule Pleroma.Web.CommonAPI.Utils do
|
|||
{:error, "No such conversation"}
|
||||
end
|
||||
end
|
||||
|
||||
def make_answer_data(%User{ap_id: ap_id}, object, name) do
|
||||
%{
|
||||
"type" => "Answer",
|
||||
"actor" => ap_id,
|
||||
"cc" => [object.data["actor"]],
|
||||
"to" => [],
|
||||
"name" => name,
|
||||
"inReplyTo" => object.data["id"]
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -16,17 +16,32 @@ defmodule Pleroma.Web.Endpoint do
|
|||
|
||||
plug(Pleroma.Plugs.UploadedMedia)
|
||||
|
||||
@static_cache_control "public, no-cache"
|
||||
|
||||
# InstanceStatic needs to be before Plug.Static to be able to override shipped-static files
|
||||
# If you're adding new paths to `only:` you'll need to configure them in InstanceStatic as well
|
||||
plug(Pleroma.Plugs.InstanceStatic, at: "/")
|
||||
# Cache-control headers are duplicated in case we turn off etags in the future
|
||||
plug(Pleroma.Plugs.InstanceStatic,
|
||||
at: "/",
|
||||
gzip: true,
|
||||
cache_control_for_etags: @static_cache_control,
|
||||
headers: %{
|
||||
"cache-control" => @static_cache_control
|
||||
}
|
||||
)
|
||||
|
||||
plug(
|
||||
Plug.Static,
|
||||
at: "/",
|
||||
from: :pleroma,
|
||||
only:
|
||||
~w(index.html robots.txt static finmoji emoji packs sounds images instance sw.js sw-pleroma.js favicon.png schemas doc)
|
||||
~w(index.html robots.txt static finmoji emoji packs sounds images instance sw.js sw-pleroma.js favicon.png schemas doc),
|
||||
# credo:disable-for-previous-line Credo.Check.Readability.MaxLineLength
|
||||
gzip: true,
|
||||
cache_control_for_etags: @static_cache_control,
|
||||
headers: %{
|
||||
"cache-control" => @static_cache_control
|
||||
}
|
||||
)
|
||||
|
||||
plug(Plug.Static.IndexHtml, at: "/pleroma/admin/")
|
||||
|
|
@ -51,7 +66,7 @@ defmodule Pleroma.Web.Endpoint do
|
|||
parsers: [:urlencoded, :multipart, :json],
|
||||
pass: ["*/*"],
|
||||
json_decoder: Jason,
|
||||
length: Application.get_env(:pleroma, :instance) |> Keyword.get(:upload_limit),
|
||||
length: Pleroma.Config.get([:instance, :upload_limit]),
|
||||
body_reader: {Pleroma.Web.Plugs.DigestPlug, :read_body, []}
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -11,13 +11,11 @@ defmodule Pleroma.Web.Federator do
|
|||
alias Pleroma.Web.ActivityPub.Utils
|
||||
alias Pleroma.Web.Federator.Publisher
|
||||
alias Pleroma.Web.Federator.RetryQueue
|
||||
alias Pleroma.Web.OStatus
|
||||
alias Pleroma.Web.Websub
|
||||
|
||||
require Logger
|
||||
|
||||
@websub Application.get_env(:pleroma, :websub)
|
||||
@ostatus Application.get_env(:pleroma, :ostatus)
|
||||
|
||||
def init do
|
||||
# 1 minute
|
||||
Process.sleep(1000 * 60)
|
||||
|
|
@ -87,12 +85,12 @@ defmodule Pleroma.Web.Federator do
|
|||
"Running WebSub verification for #{websub.id} (#{websub.topic}, #{websub.callback})"
|
||||
end)
|
||||
|
||||
@websub.verify(websub)
|
||||
Websub.verify(websub)
|
||||
end
|
||||
|
||||
def perform(:incoming_doc, doc) do
|
||||
Logger.info("Got document, trying to parse")
|
||||
@ostatus.handle_incoming(doc)
|
||||
OStatus.handle_incoming(doc)
|
||||
end
|
||||
|
||||
def perform(:incoming_ap_doc, params) do
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
alias Pleroma.Conversation.Participation
|
||||
alias Pleroma.Filter
|
||||
alias Pleroma.Formatter
|
||||
alias Pleroma.HTTP
|
||||
alias Pleroma.Notification
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Object.Fetcher
|
||||
|
|
@ -55,7 +56,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
when action in [:account_register]
|
||||
)
|
||||
|
||||
@httpoison Application.get_env(:pleroma, :httpoison)
|
||||
@local_mastodon_name "Mastodon-Local"
|
||||
|
||||
action_fallback(:errors)
|
||||
|
|
@ -124,6 +124,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
end)
|
||||
end)
|
||||
|> add_if_present(params, "default_scope", :default_scope)
|
||||
|> add_if_present(params, "pleroma_settings_store", :pleroma_settings_store, fn value ->
|
||||
{:ok, Map.merge(user.info.pleroma_settings_store, value)}
|
||||
end)
|
||||
|> add_if_present(params, "header", :banner, fn value ->
|
||||
with %Plug.Upload{} <- value,
|
||||
{:ok, object} <- ActivityPub.upload(value, type: :banner) do
|
||||
|
|
@ -143,7 +146,10 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
CommonAPI.update(user)
|
||||
end
|
||||
|
||||
json(conn, AccountView.render("account.json", %{user: user, for: user}))
|
||||
json(
|
||||
conn,
|
||||
AccountView.render("account.json", %{user: user, for: user, with_pleroma_settings: true})
|
||||
)
|
||||
else
|
||||
_e ->
|
||||
conn
|
||||
|
|
@ -153,7 +159,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
end
|
||||
|
||||
def verify_credentials(%{assigns: %{user: user}} = conn, _) do
|
||||
account = AccountView.render("account.json", %{user: user, for: user})
|
||||
account =
|
||||
AccountView.render("account.json", %{user: user, for: user, with_pleroma_settings: true})
|
||||
|
||||
json(conn, account)
|
||||
end
|
||||
|
||||
|
|
@ -197,7 +205,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
languages: ["en"],
|
||||
registrations: Pleroma.Config.get([:instance, :registrations_open]),
|
||||
# Extra (not present in Mastodon):
|
||||
max_toot_chars: Keyword.get(instance, :limit)
|
||||
max_toot_chars: Keyword.get(instance, :limit),
|
||||
poll_limits: Keyword.get(instance, :poll_limits)
|
||||
}
|
||||
|
||||
json(conn, response)
|
||||
|
|
@ -409,6 +418,53 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
end
|
||||
end
|
||||
|
||||
def get_poll(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||
with %Object{} = object <- Object.get_by_id(id),
|
||||
%Activity{} = activity <- Activity.get_create_by_object_ap_id(object.data["id"]),
|
||||
true <- Visibility.visible_for_user?(activity, user) do
|
||||
conn
|
||||
|> put_view(StatusView)
|
||||
|> try_render("poll.json", %{object: object, for: user})
|
||||
else
|
||||
nil ->
|
||||
conn
|
||||
|> put_status(404)
|
||||
|> json(%{error: "Record not found"})
|
||||
|
||||
false ->
|
||||
conn
|
||||
|> put_status(404)
|
||||
|> json(%{error: "Record not found"})
|
||||
end
|
||||
end
|
||||
|
||||
def poll_vote(%{assigns: %{user: user}} = conn, %{"id" => id, "choices" => choices}) do
|
||||
with %Object{} = object <- Object.get_by_id(id),
|
||||
true <- object.data["type"] == "Question",
|
||||
%Activity{} = activity <- Activity.get_create_by_object_ap_id(object.data["id"]),
|
||||
true <- Visibility.visible_for_user?(activity, user),
|
||||
{:ok, _activities, object} <- CommonAPI.vote(user, object, choices) do
|
||||
conn
|
||||
|> put_view(StatusView)
|
||||
|> try_render("poll.json", %{object: object, for: user})
|
||||
else
|
||||
nil ->
|
||||
conn
|
||||
|> put_status(404)
|
||||
|> json(%{error: "Record not found"})
|
||||
|
||||
false ->
|
||||
conn
|
||||
|> put_status(404)
|
||||
|> json(%{error: "Record not found"})
|
||||
|
||||
{:error, message} ->
|
||||
conn
|
||||
|> put_status(422)
|
||||
|> json(%{error: message})
|
||||
end
|
||||
end
|
||||
|
||||
def scheduled_statuses(%{assigns: %{user: user}} = conn, params) do
|
||||
with scheduled_activities <- MastodonAPI.get_scheduled_activities(user, params) do
|
||||
conn
|
||||
|
|
@ -472,12 +528,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
params
|
||||
|> Map.put("in_reply_to_status_id", params["in_reply_to_id"])
|
||||
|
||||
idempotency_key =
|
||||
case get_req_header(conn, "idempotency-key") do
|
||||
[key] -> key
|
||||
_ -> Ecto.UUID.generate()
|
||||
end
|
||||
|
||||
scheduled_at = params["scheduled_at"]
|
||||
|
||||
if scheduled_at && ScheduledActivity.far_enough?(scheduled_at) do
|
||||
|
|
@ -490,17 +540,40 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
else
|
||||
params = Map.drop(params, ["scheduled_at"])
|
||||
|
||||
{:ok, activity} =
|
||||
Cachex.fetch!(:idempotency_cache, idempotency_key, fn _ ->
|
||||
CommonAPI.post(user, params)
|
||||
end)
|
||||
case get_cached_status_or_post(conn, params) do
|
||||
{:ignore, message} ->
|
||||
conn
|
||||
|> put_status(422)
|
||||
|> json(%{error: message})
|
||||
|
||||
conn
|
||||
|> put_view(StatusView)
|
||||
|> try_render("status.json", %{activity: activity, for: user, as: :activity})
|
||||
{:error, message} ->
|
||||
conn
|
||||
|> put_status(422)
|
||||
|> json(%{error: message})
|
||||
|
||||
{_, activity} ->
|
||||
conn
|
||||
|> put_view(StatusView)
|
||||
|> try_render("status.json", %{activity: activity, for: user, as: :activity})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defp get_cached_status_or_post(%{assigns: %{user: user}} = conn, params) do
|
||||
idempotency_key =
|
||||
case get_req_header(conn, "idempotency-key") do
|
||||
[key] -> key
|
||||
_ -> Ecto.UUID.generate()
|
||||
end
|
||||
|
||||
Cachex.fetch(:idempotency_cache, idempotency_key, fn _ ->
|
||||
case CommonAPI.post(user, params) do
|
||||
{:ok, activity} -> activity
|
||||
{:error, message} -> {:ignore, message}
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
def delete_status(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||
with {:ok, %Activity{}} <- CommonAPI.delete(id, user) do
|
||||
json(conn, %{})
|
||||
|
|
@ -1084,7 +1157,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
from([a, o] in Activity.with_preloaded_object(Activity),
|
||||
where: fragment("?->>'type' = 'Create'", a.data),
|
||||
where: "https://www.w3.org/ns/activitystreams#Public" in a.recipients,
|
||||
limit: 20
|
||||
limit: 40
|
||||
)
|
||||
|
||||
q =
|
||||
|
|
@ -1346,8 +1419,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
accounts =
|
||||
Map.put(%{}, user.id, AccountView.render("account.json", %{user: user, for: user}))
|
||||
|
||||
flavour = get_user_flavour(user)
|
||||
|
||||
initial_state =
|
||||
%{
|
||||
meta: %{
|
||||
|
|
@ -1366,6 +1437,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
max_toot_chars: limit,
|
||||
mascot: User.get_mascot(user)["url"]
|
||||
},
|
||||
poll_limits: Config.get([:instance, :poll_limits]),
|
||||
rights: %{
|
||||
delete_others_notice: present?(user.info.is_moderator),
|
||||
admin: present?(user.info.is_admin)
|
||||
|
|
@ -1433,7 +1505,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
conn
|
||||
|> put_layout(false)
|
||||
|> put_view(MastodonView)
|
||||
|> render("index.html", %{initial_state: initial_state, flavour: flavour})
|
||||
|> render("index.html", %{initial_state: initial_state})
|
||||
else
|
||||
conn
|
||||
|> put_session(:return_to, conn.request_path)
|
||||
|
|
@ -1456,43 +1528,6 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
end
|
||||
end
|
||||
|
||||
@supported_flavours ["glitch", "vanilla"]
|
||||
|
||||
def set_flavour(%{assigns: %{user: user}} = conn, %{"flavour" => flavour} = _params)
|
||||
when flavour in @supported_flavours do
|
||||
flavour_cng = User.Info.mastodon_flavour_update(user.info, flavour)
|
||||
|
||||
with changeset <- Ecto.Changeset.change(user),
|
||||
changeset <- Ecto.Changeset.put_embed(changeset, :info, flavour_cng),
|
||||
{:ok, user} <- User.update_and_set_cache(changeset),
|
||||
flavour <- user.info.flavour do
|
||||
json(conn, flavour)
|
||||
else
|
||||
e ->
|
||||
conn
|
||||
|> put_resp_content_type("application/json")
|
||||
|> send_resp(500, Jason.encode!(%{"error" => inspect(e)}))
|
||||
end
|
||||
end
|
||||
|
||||
def set_flavour(conn, _params) do
|
||||
conn
|
||||
|> put_status(400)
|
||||
|> json(%{error: "Unsupported flavour"})
|
||||
end
|
||||
|
||||
def get_flavour(%{assigns: %{user: user}} = conn, _params) do
|
||||
json(conn, get_user_flavour(user))
|
||||
end
|
||||
|
||||
defp get_user_flavour(%User{info: %{flavour: flavour}}) when flavour in @supported_flavours do
|
||||
flavour
|
||||
end
|
||||
|
||||
defp get_user_flavour(_) do
|
||||
"glitch"
|
||||
end
|
||||
|
||||
def login(%{assigns: %{user: %User{}}} = conn, _params) do
|
||||
redirect(conn, to: local_mastodon_root_path(conn))
|
||||
end
|
||||
|
|
@ -1691,7 +1726,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
|> String.replace("{{user}}", user)
|
||||
|
||||
with {:ok, %{status: 200, body: body}} <-
|
||||
@httpoison.get(
|
||||
HTTP.get(
|
||||
url,
|
||||
[],
|
||||
adapter: [
|
||||
|
|
|
|||
|
|
@ -130,6 +130,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
|
|||
|> maybe_put_role(user, opts[:for])
|
||||
|> maybe_put_settings(user, opts[:for], user_info)
|
||||
|> maybe_put_notification_settings(user, opts[:for])
|
||||
|> maybe_put_settings_store(user, opts[:for], opts)
|
||||
end
|
||||
|
||||
defp username_from_nickname(string) when is_binary(string) do
|
||||
|
|
@ -152,6 +153,15 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
|
|||
|
||||
defp maybe_put_settings(data, _, _, _), do: data
|
||||
|
||||
defp maybe_put_settings_store(data, %User{info: info, id: id}, %User{id: id}, %{
|
||||
with_pleroma_settings: true
|
||||
}) do
|
||||
data
|
||||
|> Kernel.put_in([:pleroma, :settings_store], info.pleroma_settings_store)
|
||||
end
|
||||
|
||||
defp maybe_put_settings_store(data, _, _, _), do: data
|
||||
|
||||
defp maybe_put_role(data, %User{info: %{show_role: true}} = user, _) do
|
||||
data
|
||||
|> Kernel.put_in([:pleroma, :is_admin], user.info.is_admin)
|
||||
|
|
|
|||
|
|
@ -22,9 +22,14 @@ defmodule Pleroma.Web.MastodonAPI.ConversationView do
|
|||
|
||||
last_status = StatusView.render("status.json", %{activity: activity, for: user})
|
||||
|
||||
# Conversations return all users except the current user.
|
||||
users =
|
||||
participation.conversation.users
|
||||
|> Enum.reject(&(&1.id == user.id))
|
||||
|
||||
accounts =
|
||||
AccountView.render("accounts.json", %{
|
||||
users: participation.conversation.users,
|
||||
users: users,
|
||||
as: :user
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -240,6 +240,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
|||
spoiler_text: summary_html,
|
||||
visibility: get_visibility(object),
|
||||
media_attachments: attachments,
|
||||
poll: render("poll.json", %{object: object, for: opts[:for]}),
|
||||
mentions: mentions,
|
||||
tags: build_tags(tags),
|
||||
application: %{
|
||||
|
|
@ -290,8 +291,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
|||
provider_url: page_url_data.scheme <> "://" <> page_url_data.host,
|
||||
url: page_url,
|
||||
image: image_url |> MediaProxy.url(),
|
||||
title: rich_media[:title],
|
||||
description: rich_media[:description],
|
||||
title: rich_media[:title] || "",
|
||||
description: rich_media[:description] || "",
|
||||
pleroma: %{
|
||||
opengraph: rich_media
|
||||
}
|
||||
|
|
@ -329,6 +330,64 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
|||
}
|
||||
end
|
||||
|
||||
def render("poll.json", %{object: object} = opts) do
|
||||
{multiple, options} =
|
||||
case object.data do
|
||||
%{"anyOf" => options} when is_list(options) -> {true, options}
|
||||
%{"oneOf" => options} when is_list(options) -> {false, options}
|
||||
_ -> {nil, nil}
|
||||
end
|
||||
|
||||
if options do
|
||||
end_time =
|
||||
(object.data["closed"] || object.data["endTime"])
|
||||
|> NaiveDateTime.from_iso8601!()
|
||||
|
||||
expired =
|
||||
end_time
|
||||
|> NaiveDateTime.compare(NaiveDateTime.utc_now())
|
||||
|> case do
|
||||
:lt -> true
|
||||
_ -> false
|
||||
end
|
||||
|
||||
voted =
|
||||
if opts[:for] do
|
||||
existing_votes =
|
||||
Pleroma.Web.ActivityPub.Utils.get_existing_votes(opts[:for].ap_id, object)
|
||||
|
||||
existing_votes != [] or opts[:for].ap_id == object.data["actor"]
|
||||
else
|
||||
false
|
||||
end
|
||||
|
||||
{options, votes_count} =
|
||||
Enum.map_reduce(options, 0, fn %{"name" => name} = option, count ->
|
||||
current_count = option["replies"]["totalItems"] || 0
|
||||
|
||||
{%{
|
||||
title: HTML.strip_tags(name),
|
||||
votes_count: current_count
|
||||
}, current_count + count}
|
||||
end)
|
||||
|
||||
%{
|
||||
# Mastodon uses separate ids for polls, but an object can't have
|
||||
# more than one poll embedded so object id is fine
|
||||
id: object.id,
|
||||
expires_at: Utils.to_masto_date(end_time),
|
||||
expired: expired,
|
||||
multiple: multiple,
|
||||
votes_count: votes_count,
|
||||
options: options,
|
||||
voted: voted,
|
||||
emojis: build_emojis(object.data["emoji"])
|
||||
}
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def get_reply_to(activity, %{replied_to_activities: replied_to_activities}) do
|
||||
object = Object.normalize(activity)
|
||||
|
||||
|
|
|
|||
|
|
@ -12,25 +12,27 @@ defmodule Pleroma.Web.MediaProxy do
|
|||
def url("/" <> _ = url), do: url
|
||||
|
||||
def url(url) do
|
||||
config = Application.get_env(:pleroma, :media_proxy, [])
|
||||
domain = URI.parse(url).host
|
||||
|
||||
cond do
|
||||
!Keyword.get(config, :enabled, false) or String.starts_with?(url, Pleroma.Web.base_url()) ->
|
||||
url
|
||||
|
||||
Enum.any?(Pleroma.Config.get([:media_proxy, :whitelist]), fn pattern ->
|
||||
String.equivalent?(domain, pattern)
|
||||
end) ->
|
||||
url
|
||||
|
||||
true ->
|
||||
encode_url(url)
|
||||
if !enabled?() or local?(url) or whitelisted?(url) do
|
||||
url
|
||||
else
|
||||
encode_url(url)
|
||||
end
|
||||
end
|
||||
|
||||
defp enabled?, do: Pleroma.Config.get([:media_proxy, :enabled], false)
|
||||
|
||||
defp local?(url), do: String.starts_with?(url, Pleroma.Web.base_url())
|
||||
|
||||
defp whitelisted?(url) do
|
||||
%{host: domain} = URI.parse(url)
|
||||
|
||||
Enum.any?(Pleroma.Config.get([:media_proxy, :whitelist]), fn pattern ->
|
||||
String.equivalent?(domain, pattern)
|
||||
end)
|
||||
end
|
||||
|
||||
def encode_url(url) do
|
||||
secret = Application.get_env(:pleroma, Pleroma.Web.Endpoint)[:secret_key_base]
|
||||
secret = Pleroma.Config.get([Pleroma.Web.Endpoint, :secret_key_base])
|
||||
|
||||
# Must preserve `%2F` for compatibility with S3
|
||||
# https://git.pleroma.social/pleroma/pleroma/issues/580
|
||||
|
|
@ -52,7 +54,7 @@ defmodule Pleroma.Web.MediaProxy do
|
|||
end
|
||||
|
||||
def decode_url(sig, url) do
|
||||
secret = Application.get_env(:pleroma, Pleroma.Web.Endpoint)[:secret_key_base]
|
||||
secret = Pleroma.Config.get([Pleroma.Web.Endpoint, :secret_key_base])
|
||||
sig = Base.url_decode64!(sig, @base64_opts)
|
||||
local_sig = :crypto.hmac(:sha, secret, url)
|
||||
|
||||
|
|
|
|||
|
|
@ -12,8 +12,6 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do
|
|||
alias Pleroma.Web.ActivityPub.MRF
|
||||
alias Pleroma.Web.Federator.Publisher
|
||||
|
||||
plug(Pleroma.Web.FederatingPlug)
|
||||
|
||||
def schemas(conn, _params) do
|
||||
response = %{
|
||||
links: [
|
||||
|
|
@ -34,20 +32,15 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do
|
|||
# returns a nodeinfo 2.0 map, since 2.1 just adds a repository field
|
||||
# under software.
|
||||
def raw_nodeinfo do
|
||||
instance = Application.get_env(:pleroma, :instance)
|
||||
media_proxy = Application.get_env(:pleroma, :media_proxy)
|
||||
suggestions = Application.get_env(:pleroma, :suggestions)
|
||||
chat = Application.get_env(:pleroma, :chat)
|
||||
gopher = Application.get_env(:pleroma, :gopher)
|
||||
stats = Stats.get_stats()
|
||||
|
||||
mrf_simple =
|
||||
Application.get_env(:pleroma, :mrf_simple)
|
||||
Config.get(:mrf_simple)
|
||||
|> Enum.into(%{})
|
||||
|
||||
# This horror is needed to convert regex sigils to strings
|
||||
mrf_keyword =
|
||||
Application.get_env(:pleroma, :mrf_keyword, [])
|
||||
Config.get(:mrf_keyword, [])
|
||||
|> Enum.map(fn {key, value} ->
|
||||
{key,
|
||||
Enum.map(value, fn
|
||||
|
|
@ -76,14 +69,7 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do
|
|||
MRF.get_policies()
|
||||
|> Enum.map(fn policy -> to_string(policy) |> String.split(".") |> List.last() end)
|
||||
|
||||
quarantined = Keyword.get(instance, :quarantined_instances)
|
||||
|
||||
quarantined =
|
||||
if is_list(quarantined) do
|
||||
quarantined
|
||||
else
|
||||
[]
|
||||
end
|
||||
quarantined = Config.get([:instance, :quarantined_instances], [])
|
||||
|
||||
staff_accounts =
|
||||
User.all_superusers()
|
||||
|
|
@ -94,7 +80,7 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do
|
|||
|> Enum.into(%{}, fn {k, v} -> {k, length(v)} end)
|
||||
|
||||
federation_response =
|
||||
if Keyword.get(instance, :mrf_transparency) do
|
||||
if Config.get([:instance, :mrf_transparency]) do
|
||||
%{
|
||||
mrf_policies: mrf_policies,
|
||||
mrf_simple: mrf_simple,
|
||||
|
|
@ -111,22 +97,23 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do
|
|||
"pleroma_api",
|
||||
"mastodon_api",
|
||||
"mastodon_api_streaming",
|
||||
if Keyword.get(media_proxy, :enabled) do
|
||||
"polls",
|
||||
if Config.get([:media_proxy, :enabled]) do
|
||||
"media_proxy"
|
||||
end,
|
||||
if Keyword.get(gopher, :enabled) do
|
||||
if Config.get([:gopher, :enabled]) do
|
||||
"gopher"
|
||||
end,
|
||||
if Keyword.get(chat, :enabled) do
|
||||
if Config.get([:chat, :enabled]) do
|
||||
"chat"
|
||||
end,
|
||||
if Keyword.get(suggestions, :enabled) do
|
||||
if Config.get([:suggestions, :enabled]) do
|
||||
"suggestions"
|
||||
end,
|
||||
if Keyword.get(instance, :allow_relay) do
|
||||
if Config.get([:instance, :allow_relay]) do
|
||||
"relay"
|
||||
end,
|
||||
if Keyword.get(instance, :safe_dm_mentions) do
|
||||
if Config.get([:instance, :safe_dm_mentions]) do
|
||||
"safe_dm_mentions"
|
||||
end
|
||||
]
|
||||
|
|
@ -143,7 +130,7 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do
|
|||
inbound: [],
|
||||
outbound: []
|
||||
},
|
||||
openRegistrations: Keyword.get(instance, :registrations_open),
|
||||
openRegistrations: Config.get([:instance, :registrations_open]),
|
||||
usage: %{
|
||||
users: %{
|
||||
total: stats.user_count || 0
|
||||
|
|
@ -151,29 +138,30 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do
|
|||
localPosts: stats.status_count || 0
|
||||
},
|
||||
metadata: %{
|
||||
nodeName: Keyword.get(instance, :name),
|
||||
nodeDescription: Keyword.get(instance, :description),
|
||||
private: !Keyword.get(instance, :public, true),
|
||||
nodeName: Config.get([:instance, :name]),
|
||||
nodeDescription: Config.get([:instance, :description]),
|
||||
private: !Config.get([:instance, :public], true),
|
||||
suggestions: %{
|
||||
enabled: Keyword.get(suggestions, :enabled, false),
|
||||
thirdPartyEngine: Keyword.get(suggestions, :third_party_engine, ""),
|
||||
timeout: Keyword.get(suggestions, :timeout, 5000),
|
||||
limit: Keyword.get(suggestions, :limit, 23),
|
||||
web: Keyword.get(suggestions, :web, "")
|
||||
enabled: Config.get([:suggestions, :enabled], false),
|
||||
thirdPartyEngine: Config.get([:suggestions, :third_party_engine], ""),
|
||||
timeout: Config.get([:suggestions, :timeout], 5000),
|
||||
limit: Config.get([:suggestions, :limit], 23),
|
||||
web: Config.get([:suggestions, :web], "")
|
||||
},
|
||||
staffAccounts: staff_accounts,
|
||||
federation: federation_response,
|
||||
postFormats: Keyword.get(instance, :allowed_post_formats),
|
||||
pollLimits: Config.get([:instance, :poll_limits]),
|
||||
postFormats: Config.get([:instance, :allowed_post_formats]),
|
||||
uploadLimits: %{
|
||||
general: Keyword.get(instance, :upload_limit),
|
||||
avatar: Keyword.get(instance, :avatar_upload_limit),
|
||||
banner: Keyword.get(instance, :banner_upload_limit),
|
||||
background: Keyword.get(instance, :background_upload_limit)
|
||||
general: Config.get([:instance, :upload_limit]),
|
||||
avatar: Config.get([:instance, :avatar_upload_limit]),
|
||||
banner: Config.get([:instance, :banner_upload_limit]),
|
||||
background: Config.get([:instance, :background_upload_limit])
|
||||
},
|
||||
accountActivationRequired: Keyword.get(instance, :account_activation_required, false),
|
||||
invitesEnabled: Keyword.get(instance, :invites_enabled, false),
|
||||
accountActivationRequired: Config.get([:instance, :account_activation_required], false),
|
||||
invitesEnabled: Config.get([:instance, :invites_enabled], false),
|
||||
features: features,
|
||||
restrictedNicknames: Pleroma.Config.get([Pleroma.User, :restricted_nicknames])
|
||||
restrictedNicknames: Config.get([Pleroma.User, :restricted_nicknames])
|
||||
}
|
||||
}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,13 +3,12 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.OStatus do
|
||||
@httpoison Application.get_env(:pleroma, :httpoison)
|
||||
|
||||
import Ecto.Query
|
||||
import Pleroma.Web.XML
|
||||
require Logger
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.HTTP
|
||||
alias Pleroma.Object
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
|
|
@ -363,7 +362,7 @@ defmodule Pleroma.Web.OStatus do
|
|||
def fetch_activity_from_atom_url(url) do
|
||||
with true <- String.starts_with?(url, "http"),
|
||||
{:ok, %{body: body, status: code}} when code in 200..299 <-
|
||||
@httpoison.get(
|
||||
HTTP.get(
|
||||
url,
|
||||
[{:Accept, "application/atom+xml"}]
|
||||
) do
|
||||
|
|
@ -380,7 +379,7 @@ defmodule Pleroma.Web.OStatus do
|
|||
Logger.debug("Trying to fetch #{url}")
|
||||
|
||||
with true <- String.starts_with?(url, "http"),
|
||||
{:ok, %{body: body}} <- @httpoison.get(url, []),
|
||||
{:ok, %{body: body}} <- HTTP.get(url, []),
|
||||
{:ok, atom_url} <- get_atom_url(body) do
|
||||
fetch_activity_from_atom_url(atom_url)
|
||||
else
|
||||
|
|
|
|||
|
|
@ -37,7 +37,10 @@ defmodule Pleroma.Web.RichMedia.Parser do
|
|||
try do
|
||||
{:ok, %Tesla.Env{body: html}} = Pleroma.HTTP.get(url, [], adapter: @hackney_options)
|
||||
|
||||
html |> maybe_parse() |> clean_parsed_data() |> check_parsed_data()
|
||||
html
|
||||
|> maybe_parse()
|
||||
|> clean_parsed_data()
|
||||
|> check_parsed_data()
|
||||
rescue
|
||||
e ->
|
||||
{:error, "Parsing error: #{inspect(e)}"}
|
||||
|
|
|
|||
|
|
@ -309,8 +309,6 @@ defmodule Pleroma.Web.Router do
|
|||
post("/conversations/:id/read", MastodonAPIController, :conversation_read)
|
||||
|
||||
get("/endorsements", MastodonAPIController, :empty_array)
|
||||
|
||||
get("/pleroma/flavour", MastodonAPIController, :get_flavour)
|
||||
end
|
||||
|
||||
scope [] do
|
||||
|
|
@ -335,6 +333,8 @@ defmodule Pleroma.Web.Router do
|
|||
put("/scheduled_statuses/:id", MastodonAPIController, :update_scheduled_status)
|
||||
delete("/scheduled_statuses/:id", MastodonAPIController, :delete_scheduled_status)
|
||||
|
||||
post("/polls/:id/votes", MastodonAPIController, :poll_vote)
|
||||
|
||||
post("/media", MastodonAPIController, :upload)
|
||||
put("/media/:id", MastodonAPIController, :update_media)
|
||||
|
||||
|
|
@ -350,8 +350,6 @@ defmodule Pleroma.Web.Router do
|
|||
put("/filters/:id", MastodonAPIController, :update_filter)
|
||||
delete("/filters/:id", MastodonAPIController, :delete_filter)
|
||||
|
||||
post("/pleroma/flavour/:flavour", MastodonAPIController, :set_flavour)
|
||||
|
||||
get("/pleroma/mascot", MastodonAPIController, :get_mascot)
|
||||
put("/pleroma/mascot", MastodonAPIController, :set_mascot)
|
||||
|
||||
|
|
@ -426,6 +424,8 @@ defmodule Pleroma.Web.Router do
|
|||
get("/statuses/:id", MastodonAPIController, :get_status)
|
||||
get("/statuses/:id/context", MastodonAPIController, :get_context)
|
||||
|
||||
get("/polls/:id", MastodonAPIController, :get_poll)
|
||||
|
||||
get("/accounts/:id/statuses", MastodonAPIController, :user_statuses)
|
||||
get("/accounts/:id/followers", MastodonAPIController, :followers)
|
||||
get("/accounts/:id/following", MastodonAPIController, :following)
|
||||
|
|
|
|||
|
|
@ -5,11 +5,10 @@
|
|||
defmodule Pleroma.Web.Salmon do
|
||||
@behaviour Pleroma.Web.Federator.Publisher
|
||||
|
||||
@httpoison Application.get_env(:pleroma, :httpoison)
|
||||
|
||||
use Bitwise
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.HTTP
|
||||
alias Pleroma.Instances
|
||||
alias Pleroma.Keys
|
||||
alias Pleroma.User
|
||||
|
|
@ -153,7 +152,7 @@ defmodule Pleroma.Web.Salmon do
|
|||
|
||||
def publish_one(%{recipient: url, feed: feed} = params) when is_binary(url) do
|
||||
with {:ok, %{status: code}} when code in 200..299 <-
|
||||
@httpoison.post(
|
||||
HTTP.post(
|
||||
url,
|
||||
feed,
|
||||
[{"Content-Type", "application/magic-envelope+xml"}]
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,minimal-ui" />
|
||||
<title>
|
||||
<%= Application.get_env(:pleroma, :instance)[:name] %>
|
||||
<%= Pleroma.Config.get([:instance, :name]) %>
|
||||
</title>
|
||||
<style>
|
||||
body {
|
||||
|
|
@ -63,13 +63,14 @@
|
|||
|
||||
.scopes-input {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: 1em;
|
||||
text-align: left;
|
||||
color: #89898a;
|
||||
}
|
||||
|
||||
.scopes-input label:first-child {
|
||||
flex-basis: 40%;
|
||||
height: 2em;
|
||||
}
|
||||
|
||||
.scopes {
|
||||
|
|
@ -80,13 +81,22 @@
|
|||
}
|
||||
|
||||
.scope {
|
||||
flex-basis: 100%;
|
||||
display: flex;
|
||||
flex-basis: 100%;
|
||||
height: 2em;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.scope:before {
|
||||
color: #b9b9ba;
|
||||
content: "✔\fe0e";
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
[type="checkbox"] + label {
|
||||
display: none;
|
||||
cursor: pointer;
|
||||
margin: 0.5em;
|
||||
}
|
||||
|
||||
|
|
@ -95,10 +105,12 @@
|
|||
}
|
||||
|
||||
[type="checkbox"] + label:before {
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
color: white;
|
||||
background-color: #121a24;
|
||||
border: 4px solid #121a24;
|
||||
box-shadow: 0px 0px 1px 0 #d8a070;
|
||||
box-sizing: border-box;
|
||||
width: 1.2em;
|
||||
height: 1.2em;
|
||||
|
|
@ -128,7 +140,8 @@
|
|||
border-radius: 4px;
|
||||
border: none;
|
||||
padding: 10px;
|
||||
margin-top: 30px;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
text-transform: uppercase;
|
||||
font-size: 16px;
|
||||
box-shadow: 0px 0px 2px 0px black,
|
||||
|
|
@ -147,8 +160,8 @@
|
|||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
background-color: #931014;
|
||||
border: 1px solid #a06060;
|
||||
border-radius: 4px;
|
||||
border: none;
|
||||
padding: 10px;
|
||||
margin-top: 20px;
|
||||
font-weight: 500;
|
||||
|
|
@ -171,12 +184,27 @@
|
|||
margin-top: 0
|
||||
}
|
||||
|
||||
.scopes-input {
|
||||
flex-direction: column;
|
||||
.scope {
|
||||
flex-basis: 0%;
|
||||
}
|
||||
|
||||
.scope {
|
||||
flex-basis: 50%;
|
||||
.scope:before {
|
||||
content: "";
|
||||
margin-left: 0em;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
.scope:first-child:before {
|
||||
margin-left: 1em;
|
||||
content: "✔\fe0e";
|
||||
}
|
||||
|
||||
.scope:after {
|
||||
content: ",";
|
||||
}
|
||||
|
||||
.scope:last-child:after {
|
||||
content: "";
|
||||
}
|
||||
}
|
||||
.form-row {
|
||||
|
|
@ -194,7 +222,7 @@
|
|||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1><%= Application.get_env(:pleroma, :instance)[:name] %></h1>
|
||||
<h1><%= Pleroma.Config.get([:instance, :name]) %></h1>
|
||||
<%= render @view_module, @view_template, assigns %>
|
||||
</div>
|
||||
</body>
|
||||
|
|
|
|||
|
|
@ -4,11 +4,11 @@
|
|||
<meta charset='utf-8'>
|
||||
<meta content='width=device-width, initial-scale=1' name='viewport'>
|
||||
<title>
|
||||
<%= Application.get_env(:pleroma, :instance)[:name] %>
|
||||
<%= Pleroma.Config.get([:instance, :name]) %>
|
||||
</title>
|
||||
<link rel="icon" type="image/png" href="/favicon.png"/>
|
||||
<script crossorigin='anonymous' src="/packs/locales.js"></script>
|
||||
<script crossorigin='anonymous' src="/packs/locales/<%= @flavour %>/en.js"></script>
|
||||
<script crossorigin='anonymous' src="/packs/locales/glitch/en.js"></script>
|
||||
|
||||
<link rel='preload' as='script' crossorigin='anonymous' href='/packs/features/getting_started.js'>
|
||||
<link rel='preload' as='script' crossorigin='anonymous' href='/packs/features/compose.js'>
|
||||
|
|
@ -19,10 +19,10 @@
|
|||
<script src="/packs/core/common.js"></script>
|
||||
<link rel="stylesheet" media="all" href="/packs/core/common.css" />
|
||||
|
||||
<script src="/packs/flavours/<%= @flavour %>/common.js"></script>
|
||||
<link rel="stylesheet" media="all" href="/packs/flavours/<%= @flavour %>/common.css" />
|
||||
<script src="/packs/flavours/glitch/common.js"></script>
|
||||
<link rel="stylesheet" media="all" href="/packs/flavours/glitch/common.css" />
|
||||
|
||||
<script src="/packs/flavours/<%= @flavour %>/home.js"></script>
|
||||
<script src="/packs/flavours/glitch/home.js"></script>
|
||||
</head>
|
||||
<body class='app-body no-reduce-motion system-font'>
|
||||
<div class='app-holder' data-props='{"locale":"en"}' id='mastodon'>
|
||||
|
|
|
|||
|
|
@ -1,13 +1,19 @@
|
|||
<div class="scopes-input">
|
||||
<%= label @form, :scope, "Permissions" %>
|
||||
|
||||
<%= label @form, :scope, "The following permissions will be granted" %>
|
||||
<div class="scopes">
|
||||
<%= for scope <- @available_scopes do %>
|
||||
<%# Note: using hidden input with `unchecked_value` in order to distinguish user's empty selection from `scope` param being omitted %>
|
||||
<div class="scope">
|
||||
<%= if scope in @scopes do %>
|
||||
<div class="scope">
|
||||
<%= checkbox @form, :"scope_#{scope}", value: scope in @scopes && scope, checked_value: scope, unchecked_value: "", name: "authorization[scope][]" %>
|
||||
<%= label @form, :"scope_#{scope}", String.capitalize(scope) %>
|
||||
<%= if scope in @scopes && scope do %>
|
||||
<%= String.capitalize(scope) %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% else %>
|
||||
<%= checkbox @form, :"scope_#{scope}", value: scope in @scopes && scope, checked_value: scope, unchecked_value: "", name: "authorization[scope][]" %>
|
||||
<%= label @form, :"scope_#{scope}", String.capitalize(scope) %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
<h2>Sign in with external provider</h2>
|
||||
|
||||
<%= form_for @conn, o_auth_path(@conn, :prepare_request), [as: "authorization", method: "get"], fn f -> %>
|
||||
<%= render @view_module, "_scopes.html", Map.put(assigns, :form, f) %>
|
||||
<div style="display: none">
|
||||
<%= render @view_module, "_scopes.html", Map.merge(assigns, %{form: f}) %>
|
||||
</div>
|
||||
|
||||
<%= hidden_input f, :client_id, value: @client_id %>
|
||||
<%= hidden_input f, :redirect_uri, value: @redirect_uri %>
|
||||
|
|
|
|||
|
|
@ -6,26 +6,38 @@
|
|||
<% end %>
|
||||
|
||||
<h2>OAuth Authorization</h2>
|
||||
|
||||
<%= form_for @conn, o_auth_path(@conn, :authorize), [as: "authorization"], fn f -> %>
|
||||
<div class="input">
|
||||
<%= label f, :name, "Name or email" %>
|
||||
<%= text_input f, :name %>
|
||||
</div>
|
||||
<div class="input">
|
||||
<%= label f, :password, "Password" %>
|
||||
<%= password_input f, :password %>
|
||||
</div>
|
||||
|
||||
<%= render @view_module, "_scopes.html", Map.merge(assigns, %{form: f}) %>
|
||||
<%= if @params["registration"] in ["true", true] do %>
|
||||
<h3>This is the first time you visit! Please enter your Pleroma handle.</h3>
|
||||
<p>Choose carefully! You won't be able to change this later. You will be able to change your display name, though.</p>
|
||||
<div class="input">
|
||||
<%= label f, :nickname, "Pleroma Handle" %>
|
||||
<%= text_input f, :nickname, placeholder: "lain" %>
|
||||
</div>
|
||||
<%= hidden_input f, :name, value: @params["name"] %>
|
||||
<%= hidden_input f, :password, value: @params["password"] %>
|
||||
<br>
|
||||
<% else %>
|
||||
<div class="input">
|
||||
<%= label f, :name, "Username" %>
|
||||
<%= text_input f, :name %>
|
||||
</div>
|
||||
<div class="input">
|
||||
<%= label f, :password, "Password" %>
|
||||
<%= password_input f, :password %>
|
||||
</div>
|
||||
<%= submit "Log In" %>
|
||||
<%= render @view_module, "_scopes.html", Map.merge(assigns, %{form: f}) %>
|
||||
<% end %>
|
||||
|
||||
<%= hidden_input f, :client_id, value: @client_id %>
|
||||
<%= hidden_input f, :response_type, value: @response_type %>
|
||||
<%= hidden_input f, :redirect_uri, value: @redirect_uri %>
|
||||
<%= hidden_input f, :state, value: @state %>
|
||||
<%= submit "Authorize" %>
|
||||
<% end %>
|
||||
|
||||
<%= if Pleroma.Config.oauth_consumer_enabled?() do %>
|
||||
<%= render @view_module, Pleroma.Web.Auth.Authenticator.oauth_consumer_template(), assigns %>
|
||||
<% end %>
|
||||
|
||||
|
|
|
|||
|
|
@ -728,7 +728,7 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
|
|||
def only_if_public_instance(%{assigns: %{user: %User{}}} = conn, _), do: conn
|
||||
|
||||
def only_if_public_instance(conn, _) do
|
||||
if Keyword.get(Application.get_env(:pleroma, :instance), :public) do
|
||||
if Pleroma.Config.get([:instance, :public]) do
|
||||
conn
|
||||
else
|
||||
conn
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ defmodule Pleroma.Web.TwitterAPI.UserView do
|
|||
"tags" => user.tags
|
||||
}
|
||||
|> maybe_with_activation_status(user, for_user)
|
||||
|> with_notification_settings(user, for_user)
|
||||
}
|
||||
|> maybe_with_user_settings(user, for_user)
|
||||
|> maybe_with_role(user, for_user)
|
||||
|
|
@ -132,6 +133,12 @@ defmodule Pleroma.Web.TwitterAPI.UserView do
|
|||
end
|
||||
end
|
||||
|
||||
defp with_notification_settings(data, %User{id: user_id} = user, %User{id: user_id}) do
|
||||
Map.put(data, "notification_settings", user.info.notification_settings)
|
||||
end
|
||||
|
||||
defp with_notification_settings(data, _, _), do: data
|
||||
|
||||
defp maybe_with_activation_status(data, user, %User{info: %{is_admin: true}}) do
|
||||
Map.put(data, "deactivated", user.info.deactivated)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.WebFinger do
|
||||
@httpoison Application.get_env(:pleroma, :httpoison)
|
||||
|
||||
alias Pleroma.HTTP
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web
|
||||
alias Pleroma.Web.Federator.Publisher
|
||||
|
|
@ -176,11 +175,11 @@ defmodule Pleroma.Web.WebFinger do
|
|||
|
||||
def find_lrdd_template(domain) do
|
||||
with {:ok, %{status: status, body: body}} when status in 200..299 <-
|
||||
@httpoison.get("http://#{domain}/.well-known/host-meta", []) do
|
||||
HTTP.get("http://#{domain}/.well-known/host-meta", []) do
|
||||
get_template_from_xml(body)
|
||||
else
|
||||
_ ->
|
||||
with {:ok, %{body: body}} <- @httpoison.get("https://#{domain}/.well-known/host-meta", []) do
|
||||
with {:ok, %{body: body}} <- HTTP.get("https://#{domain}/.well-known/host-meta", []) do
|
||||
get_template_from_xml(body)
|
||||
else
|
||||
e -> {:error, "Can't find LRDD template: #{inspect(e)}"}
|
||||
|
|
@ -209,7 +208,7 @@ defmodule Pleroma.Web.WebFinger do
|
|||
end
|
||||
|
||||
with response <-
|
||||
@httpoison.get(
|
||||
HTTP.get(
|
||||
address,
|
||||
Accept: "application/xrd+xml,application/jrd+json"
|
||||
),
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
defmodule Pleroma.Web.Websub do
|
||||
alias Ecto.Changeset
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.HTTP
|
||||
alias Pleroma.Instances
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
|
|
@ -24,9 +25,7 @@ defmodule Pleroma.Web.Websub do
|
|||
|
||||
@behaviour Pleroma.Web.Federator.Publisher
|
||||
|
||||
@httpoison Application.get_env(:pleroma, :httpoison)
|
||||
|
||||
def verify(subscription, getter \\ &@httpoison.get/3) do
|
||||
def verify(subscription, getter \\ &HTTP.get/3) do
|
||||
challenge = Base.encode16(:crypto.strong_rand_bytes(8))
|
||||
lease_seconds = NaiveDateTime.diff(subscription.valid_until, subscription.updated_at)
|
||||
lease_seconds = lease_seconds |> to_string
|
||||
|
|
@ -207,7 +206,7 @@ defmodule Pleroma.Web.Websub do
|
|||
requester.(subscription)
|
||||
end
|
||||
|
||||
def gather_feed_data(topic, getter \\ &@httpoison.get/1) do
|
||||
def gather_feed_data(topic, getter \\ &HTTP.get/1) do
|
||||
with {:ok, response} <- getter.(topic),
|
||||
status when status in 200..299 <- response.status,
|
||||
body <- response.body,
|
||||
|
|
@ -236,7 +235,7 @@ defmodule Pleroma.Web.Websub do
|
|||
end
|
||||
end
|
||||
|
||||
def request_subscription(websub, poster \\ &@httpoison.post/3, timeout \\ 10_000) do
|
||||
def request_subscription(websub, poster \\ &HTTP.post/3, timeout \\ 10_000) do
|
||||
data = [
|
||||
"hub.mode": "subscribe",
|
||||
"hub.topic": websub.topic,
|
||||
|
|
@ -294,7 +293,7 @@ defmodule Pleroma.Web.Websub do
|
|||
Logger.info(fn -> "Pushing #{topic} to #{callback}" end)
|
||||
|
||||
with {:ok, %{status: code}} when code in 200..299 <-
|
||||
@httpoison.post(
|
||||
HTTP.post(
|
||||
callback,
|
||||
xml,
|
||||
[
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue