aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorRoman Chvanikov <chvanikoff@pm.me>2020-07-09 16:56:06 +0300
committerRoman Chvanikov <chvanikoff@pm.me>2020-07-09 16:56:06 +0300
commit17a2ff57ac589b6fb996583f38f542b365b01ccf (patch)
treedd19dc053927147c5b28742b1b2fbb743bcbb650 /lib
parent3ce21ff4e8cc0d3c1a7481082fe574e1f9ff6466 (diff)
parent8ca1f3e8c61b906387e9cb6fb8993d2ad496ab3d (diff)
downloadpleroma-17a2ff57ac589b6fb996583f38f542b365b01ccf.tar.gz
merge develop
Diffstat (limited to 'lib')
-rw-r--r--lib/pleroma/config/loader.ex8
-rw-r--r--lib/pleroma/filter.ex42
-rw-r--r--lib/pleroma/instances/instance.ex48
-rw-r--r--lib/pleroma/migration_helper/notification_backfill.ex16
-rw-r--r--lib/pleroma/notification.ex43
-rw-r--r--lib/pleroma/plugs/static_fe_plug.ex13
-rw-r--r--lib/pleroma/upload.ex9
-rw-r--r--lib/pleroma/user.ex15
-rw-r--r--lib/pleroma/user/search.ex5
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub.ex46
-rw-r--r--lib/pleroma/web/activity_pub/builder.ex13
-rw-r--r--lib/pleroma/web/activity_pub/object_validator.ex11
-rw-r--r--lib/pleroma/web/activity_pub/object_validators/follow_validator.ex44
-rw-r--r--lib/pleroma/web/activity_pub/relay.ex2
-rw-r--r--lib/pleroma/web/activity_pub/side_effects.ex85
-rw-r--r--lib/pleroma/web/activity_pub/transmogrifier.ex96
-rw-r--r--lib/pleroma/web/api_spec/operations/account_operation.ex38
-rw-r--r--lib/pleroma/web/api_spec/operations/pleroma_account_operation.ex91
-rw-r--r--lib/pleroma/web/api_spec/operations/status_operation.ex2
-rw-r--r--lib/pleroma/web/api_spec/schemas/account.ex6
-rw-r--r--lib/pleroma/web/api_spec/schemas/status.ex5
-rw-r--r--lib/pleroma/web/common_api/activity_draft.ex1
-rw-r--r--lib/pleroma/web/common_api/common_api.ex10
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/account_controller.ex23
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/search_controller.ex1
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/status_controller.ex13
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex46
-rw-r--r--lib/pleroma/web/mastodon_api/views/account_view.ex15
-rw-r--r--lib/pleroma/web/mastodon_api/views/instance_view.ex15
-rw-r--r--lib/pleroma/web/mastodon_api/views/status_view.ex1
-rw-r--r--lib/pleroma/web/oauth/mfa_controller.ex3
-rw-r--r--lib/pleroma/web/oauth/mfa_view.ex9
-rw-r--r--lib/pleroma/web/oauth/oauth_controller.ex16
-rw-r--r--lib/pleroma/web/oauth/oauth_view.ex22
-rw-r--r--lib/pleroma/web/oauth/token/response.ex45
-rw-r--r--lib/pleroma/web/pleroma_api/controllers/account_controller.ex62
-rw-r--r--lib/pleroma/web/preload/status_net.ex25
-rw-r--r--lib/pleroma/web/rich_media/parser.ex5
-rw-r--r--lib/pleroma/web/router.ex8
-rw-r--r--lib/pleroma/web/streamer/streamer.ex12
-rw-r--r--lib/pleroma/web/twitter_api/controllers/util_controller.ex74
41 files changed, 547 insertions, 497 deletions
diff --git a/lib/pleroma/config/loader.ex b/lib/pleroma/config/loader.ex
index 0f3ecf1ed..64e7de6df 100644
--- a/lib/pleroma/config/loader.ex
+++ b/lib/pleroma/config/loader.ex
@@ -12,6 +12,11 @@ defmodule Pleroma.Config.Loader do
:swarm
]
+ @reject_groups [
+ :postgrex,
+ :tesla
+ ]
+
if Code.ensure_loaded?(Config.Reader) do
@reader Config.Reader
@@ -47,7 +52,8 @@ defmodule Pleroma.Config.Loader do
@spec filter_group(atom(), keyword()) :: keyword()
def filter_group(group, configs) do
Enum.reject(configs[group], fn {key, _v} ->
- key in @reject_keys or (group == :phoenix and key == :serve_endpoints) or group == :postgrex
+ key in @reject_keys or group in @reject_groups or
+ (group == :phoenix and key == :serve_endpoints)
end)
end
end
diff --git a/lib/pleroma/filter.ex b/lib/pleroma/filter.ex
index 4d61b3650..5d6df9530 100644
--- a/lib/pleroma/filter.ex
+++ b/lib/pleroma/filter.ex
@@ -34,10 +34,18 @@ defmodule Pleroma.Filter do
Repo.one(query)
end
- def get_filters(%User{id: user_id} = _user) do
+ def get_active(query) do
+ from(f in query, where: is_nil(f.expires_at) or f.expires_at > ^NaiveDateTime.utc_now())
+ end
+
+ def get_irreversible(query) do
+ from(f in query, where: f.hide)
+ end
+
+ def get_filters(query \\ __MODULE__, %User{id: user_id}) do
query =
from(
- f in Pleroma.Filter,
+ f in query,
where: f.user_id == ^user_id,
order_by: [desc: :id]
)
@@ -95,4 +103,34 @@ defmodule Pleroma.Filter do
|> validate_required([:phrase, :context])
|> Repo.update()
end
+
+ def compose_regex(user_or_filters, format \\ :postgres)
+
+ def compose_regex(%User{} = user, format) do
+ __MODULE__
+ |> get_active()
+ |> get_irreversible()
+ |> get_filters(user)
+ |> compose_regex(format)
+ end
+
+ def compose_regex([_ | _] = filters, format) do
+ phrases =
+ filters
+ |> Enum.map(& &1.phrase)
+ |> Enum.join("|")
+
+ case format do
+ :postgres ->
+ "\\y(#{phrases})\\y"
+
+ :re ->
+ ~r/\b#{phrases}\b/i
+
+ _ ->
+ nil
+ end
+ end
+
+ def compose_regex(_, _), do: nil
end
diff --git a/lib/pleroma/instances/instance.ex b/lib/pleroma/instances/instance.ex
index 74458c09a..a1f935232 100644
--- a/lib/pleroma/instances/instance.ex
+++ b/lib/pleroma/instances/instance.ex
@@ -17,6 +17,8 @@ defmodule Pleroma.Instances.Instance do
schema "instances" do
field(:host, :string)
field(:unreachable_since, :naive_datetime_usec)
+ field(:favicon, :string)
+ field(:favicon_updated_at, :naive_datetime)
timestamps()
end
@@ -25,7 +27,7 @@ defmodule Pleroma.Instances.Instance do
def changeset(struct, params \\ %{}) do
struct
- |> cast(params, [:host, :unreachable_since])
+ |> cast(params, [:host, :unreachable_since, :favicon, :favicon_updated_at])
|> validate_required([:host])
|> unique_constraint(:host)
end
@@ -120,4 +122,48 @@ defmodule Pleroma.Instances.Instance do
end
defp parse_datetime(datetime), do: datetime
+
+ def get_or_update_favicon(%URI{host: host} = instance_uri) do
+ existing_record = Repo.get_by(Instance, %{host: host})
+ now = NaiveDateTime.utc_now()
+
+ if existing_record && existing_record.favicon_updated_at &&
+ NaiveDateTime.diff(now, existing_record.favicon_updated_at) < 86_400 do
+ existing_record.favicon
+ else
+ favicon = scrape_favicon(instance_uri)
+
+ if existing_record do
+ existing_record
+ |> changeset(%{favicon: favicon, favicon_updated_at: now})
+ |> Repo.update()
+ else
+ %Instance{}
+ |> changeset(%{host: host, favicon: favicon, favicon_updated_at: now})
+ |> Repo.insert()
+ end
+
+ favicon
+ end
+ end
+
+ defp scrape_favicon(%URI{} = instance_uri) do
+ try do
+ with {:ok, %Tesla.Env{body: html}} <-
+ Pleroma.HTTP.get(to_string(instance_uri), [{:Accept, "text/html"}]),
+ favicon_rel <-
+ html
+ |> Floki.parse_document!()
+ |> Floki.attribute("link[rel=icon]", "href")
+ |> List.first(),
+ favicon <- URI.merge(instance_uri, favicon_rel) |> to_string(),
+ true <- is_binary(favicon) do
+ favicon
+ else
+ _ -> nil
+ end
+ rescue
+ _ -> nil
+ end
+ end
end
diff --git a/lib/pleroma/migration_helper/notification_backfill.ex b/lib/pleroma/migration_helper/notification_backfill.ex
index b3770307a..d260e62ca 100644
--- a/lib/pleroma/migration_helper/notification_backfill.ex
+++ b/lib/pleroma/migration_helper/notification_backfill.ex
@@ -3,7 +3,6 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.MigrationHelper.NotificationBackfill do
- alias Pleroma.Notification
alias Pleroma.Object
alias Pleroma.Repo
alias Pleroma.User
@@ -25,18 +24,27 @@ defmodule Pleroma.MigrationHelper.NotificationBackfill do
|> type_from_activity()
notification
- |> Notification.changeset(%{type: type})
+ |> Ecto.Changeset.change(%{type: type})
|> Repo.update()
end)
end
+ defp get_by_ap_id(ap_id) do
+ q =
+ from(u in User,
+ select: u.id
+ )
+
+ Repo.get_by(q, ap_id: ap_id)
+ end
+
# This is copied over from Notifications to keep this stable.
defp type_from_activity(%{data: %{"type" => type}} = activity) do
case type do
"Follow" ->
accepted_function = fn activity ->
- with %User{} = follower <- User.get_by_ap_id(activity.data["actor"]),
- %User{} = followed <- User.get_by_ap_id(activity.data["object"]) do
+ with %User{} = follower <- get_by_ap_id(activity.data["actor"]),
+ %User{} = followed <- get_by_ap_id(activity.data["object"]) do
Pleroma.FollowingRelationship.following?(follower, followed)
end
end
diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex
index 2ef1a80c5..32bcfcaba 100644
--- a/lib/pleroma/notification.ex
+++ b/lib/pleroma/notification.ex
@@ -130,6 +130,7 @@ defmodule Pleroma.Notification do
|> preload([n, a, o], activity: {a, object: o})
|> exclude_notification_muted(user, exclude_notification_muted_opts)
|> exclude_blocked(user, exclude_blocked_opts)
+ |> exclude_filtered(user)
|> exclude_visibility(opts)
end
@@ -158,6 +159,20 @@ defmodule Pleroma.Notification do
|> where([n, a, o, tm], is_nil(tm.user_id))
end
+ defp exclude_filtered(query, user) do
+ case Pleroma.Filter.compose_regex(user) do
+ nil ->
+ query
+
+ regex ->
+ from([_n, a, o] in query,
+ where:
+ fragment("not(?->>'content' ~* ?)", o.data, ^regex) or
+ fragment("?->>'actor' = ?", o.data, ^user.ap_id)
+ )
+ end
+ end
+
@valid_visibilities ~w[direct unlisted public private]
defp exclude_visibility(query, %{exclude_visibilities: visibility})
@@ -337,6 +352,7 @@ defmodule Pleroma.Notification do
end
end
+ @spec create_notifications(Activity.t(), keyword()) :: {:ok, [Notification.t()] | []}
def create_notifications(activity, options \\ [])
def create_notifications(%Activity{data: %{"to" => _, "type" => "Create"}} = activity, options) do
@@ -481,6 +497,10 @@ defmodule Pleroma.Notification do
end
end
+ def get_potential_receiver_ap_ids(%{data: %{"type" => "Follow", "object" => object_id}}) do
+ [object_id]
+ end
+
def get_potential_receiver_ap_ids(activity) do
[]
|> Utils.maybe_notify_to_recipients(activity)
@@ -555,7 +575,8 @@ defmodule Pleroma.Notification do
:follows,
:non_followers,
:non_follows,
- :recently_followed
+ :recently_followed,
+ :filtered
]
|> Enum.find(&skip?(&1, activity, user))
end
@@ -624,6 +645,26 @@ defmodule Pleroma.Notification do
end)
end
+ def skip?(:filtered, %{data: %{"type" => type}}, _) when type in ["Follow", "Move"], do: false
+
+ def skip?(:filtered, activity, user) do
+ object = Object.normalize(activity)
+
+ cond do
+ is_nil(object) ->
+ false
+
+ object.data["actor"] == user.ap_id ->
+ false
+
+ not is_nil(regex = Pleroma.Filter.compose_regex(user, :re)) ->
+ Regex.match?(regex, object.data["content"])
+
+ true ->
+ false
+ end
+ end
+
def skip?(_, _, _), do: false
def for_user_and_activity(user, activity) do
diff --git a/lib/pleroma/plugs/static_fe_plug.ex b/lib/pleroma/plugs/static_fe_plug.ex
index c12776f4d..d3ae08835 100644
--- a/lib/pleroma/plugs/static_fe_plug.ex
+++ b/lib/pleroma/plugs/static_fe_plug.ex
@@ -10,8 +10,7 @@ defmodule Pleroma.Plugs.StaticFEPlug do
def call(%{private: %{frontend: %{static: true}}} = conn, _) do
action = Phoenix.Controller.action_name(conn)
- if accepts_html?(conn) and
- function_exported?(Pleroma.Web.Frontend.StaticController, action, 2) do
+ if requires_html?(conn) and has_action?(action) do
conn
|> Pleroma.Web.FrontendController.call(action)
|> halt()
@@ -22,10 +21,8 @@ defmodule Pleroma.Plugs.StaticFEPlug do
def call(conn, _), do: conn
- defp accepts_html?(conn) do
- case get_req_header(conn, "accept") do
- [accept | _] -> String.contains?(accept, "text/html")
- _ -> false
- end
- end
+ defp requires_html?(conn), do: Phoenix.Controller.get_format(conn) == "html"
+
+ defp has_action?(action),
+ do: function_exported?(Pleroma.Web.Frontend.StaticController, action, 2)
end
diff --git a/lib/pleroma/upload.ex b/lib/pleroma/upload.ex
index 797555bff..0fa6b89dc 100644
--- a/lib/pleroma/upload.ex
+++ b/lib/pleroma/upload.ex
@@ -63,6 +63,10 @@ defmodule Pleroma.Upload do
with {:ok, upload} <- prepare_upload(upload, opts),
upload = %__MODULE__{upload | path: upload.path || "#{upload.id}/#{upload.name}"},
{:ok, upload} <- Pleroma.Upload.Filter.filter(opts.filters, upload),
+ description = Map.get(opts, :description) || upload.name,
+ {_, true} <-
+ {:description_limit,
+ String.length(description) <= Pleroma.Config.get([:instance, :description_limit])},
{:ok, url_spec} <- Pleroma.Uploaders.Uploader.put_file(opts.uploader, upload) do
{:ok,
%{
@@ -75,9 +79,12 @@ defmodule Pleroma.Upload do
"href" => url_from_spec(upload, opts.base_url, url_spec)
}
],
- "name" => Map.get(opts, :description) || upload.name
+ "name" => description
}}
else
+ {:description_limit, _} ->
+ {:error, :description_too_long}
+
{:error, error} ->
Logger.error(
"#{__MODULE__} store (using #{inspect(opts.uploader)}) failed: #{inspect(error)}"
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 8a54546d6..9d1314f81 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -89,7 +89,7 @@ defmodule Pleroma.User do
field(:keys, :string)
field(:public_key, :string)
field(:ap_id, :string)
- field(:avatar, :map)
+ field(:avatar, :map, default: %{})
field(:local, :boolean, default: true)
field(:follower_address, :string)
field(:following_address, :string)
@@ -539,14 +539,11 @@ defmodule Pleroma.User do
end
defp put_change_if_present(changeset, map_field, value_function) do
- if value = get_change(changeset, map_field) do
- with {:ok, new_value} <- value_function.(value) do
- put_change(changeset, map_field, new_value)
- else
- _ -> changeset
- end
+ with {:ok, value} <- fetch_change(changeset, map_field),
+ {:ok, new_value} <- value_function.(value) do
+ put_change(changeset, map_field, new_value)
else
- changeset
+ _ -> changeset
end
end
@@ -1546,7 +1543,7 @@ defmodule Pleroma.User do
fn followed_identifier ->
with {:ok, %User{} = followed} <- get_or_fetch(followed_identifier),
{:ok, follower} <- maybe_direct_follow(follower, followed),
- {:ok, _} <- ActivityPub.follow(follower, followed) do
+ {:ok, _, _, _} <- CommonAPI.follow(follower, followed) do
followed
else
err ->
diff --git a/lib/pleroma/user/search.ex b/lib/pleroma/user/search.ex
index cec59c372..42ff1de78 100644
--- a/lib/pleroma/user/search.ex
+++ b/lib/pleroma/user/search.ex
@@ -52,6 +52,7 @@ defmodule Pleroma.User.Search do
|> base_query(following)
|> filter_blocked_user(for_user)
|> filter_invisible_users()
+ |> filter_internal_users()
|> filter_blocked_domains(for_user)
|> fts_search(query_string)
|> trigram_rank(query_string)
@@ -109,6 +110,10 @@ defmodule Pleroma.User.Search do
from(q in query, where: q.invisible == false)
end
+ defp filter_internal_users(query) do
+ from(q in query, where: q.actor_type != "Application")
+ end
+
defp filter_blocked_user(query, %User{} = blocker) do
query
|> join(:left, [u], b in Pleroma.UserRelationship,
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index 94117202c..1c2908805 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -10,6 +10,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
alias Pleroma.Constants
alias Pleroma.Conversation
alias Pleroma.Conversation.Participation
+ alias Pleroma.Filter
alias Pleroma.Maps
alias Pleroma.Notification
alias Pleroma.Object
@@ -321,28 +322,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
end
end
- @spec follow(User.t(), User.t(), String.t() | nil, boolean(), keyword()) ::
- {:ok, Activity.t()} | {:error, any()}
- def follow(follower, followed, activity_id \\ nil, local \\ true, opts \\ []) do
- with {:ok, result} <-
- Repo.transaction(fn -> do_follow(follower, followed, activity_id, local, opts) end) do
- result
- end
- end
-
- defp do_follow(follower, followed, activity_id, local, opts) do
- skip_notify_and_stream = Keyword.get(opts, :skip_notify_and_stream, false)
- data = make_follow_data(follower, followed, activity_id)
-
- with {:ok, activity} <- insert(data, local),
- _ <- skip_notify_and_stream || notify_and_stream(activity),
- :ok <- maybe_federate(activity) do
- {:ok, activity}
- else
- {:error, error} -> Repo.rollback(error)
- end
- end
-
@spec unfollow(User.t(), User.t(), String.t() | nil, boolean()) ::
{:ok, Activity.t()} | nil | {:error, any()}
def unfollow(follower, followed, activity_id \\ nil, local \\ true) do
@@ -446,6 +425,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|> maybe_set_thread_muted_field(opts)
|> restrict_blocked(opts)
|> restrict_recipients(recipients, opts[:user])
+ |> restrict_filtered(opts)
|> where(
[activity],
fragment(
@@ -961,6 +941,26 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
defp restrict_instance(query, _), do: query
+ defp restrict_filtered(query, %{user: %User{} = user}) do
+ case Filter.compose_regex(user) do
+ nil ->
+ query
+
+ regex ->
+ from([activity, object] in query,
+ where:
+ fragment("not(?->>'content' ~* ?)", object.data, ^regex) or
+ activity.actor == ^user.ap_id
+ )
+ end
+ end
+
+ defp restrict_filtered(query, %{blocking_user: %User{} = user}) do
+ restrict_filtered(query, %{user: user})
+ end
+
+ defp restrict_filtered(query, _), do: query
+
defp exclude_poll_votes(query, %{include_poll_votes: true}), do: query
defp exclude_poll_votes(query, _) do
@@ -1091,6 +1091,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|> restrict_favorited_by(opts)
|> restrict_blocked(restrict_blocked_opts)
|> restrict_muted(restrict_muted_opts)
+ |> restrict_filtered(opts)
|> restrict_media(opts)
|> restrict_visibility(opts)
|> restrict_thread_visibility(opts, config)
@@ -1099,6 +1100,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|> restrict_muted_reblogs(restrict_muted_reblogs_opts)
|> restrict_instance(opts)
|> restrict_announce_object_actor(opts)
+ |> restrict_filtered(opts)
|> Activity.restrict_deactivated_users()
|> exclude_poll_votes(opts)
|> exclude_chat_messages(opts)
diff --git a/lib/pleroma/web/activity_pub/builder.ex b/lib/pleroma/web/activity_pub/builder.ex
index cabc28de9..d5f3610ed 100644
--- a/lib/pleroma/web/activity_pub/builder.ex
+++ b/lib/pleroma/web/activity_pub/builder.ex
@@ -14,6 +14,19 @@ defmodule Pleroma.Web.ActivityPub.Builder do
require Pleroma.Constants
+ @spec follow(User.t(), User.t()) :: {:ok, map(), keyword()}
+ def follow(follower, followed) do
+ data = %{
+ "id" => Utils.generate_activity_id(),
+ "actor" => follower.ap_id,
+ "type" => "Follow",
+ "object" => followed.ap_id,
+ "to" => [followed.ap_id]
+ }
+
+ {:ok, data, []}
+ end
+
@spec emoji_react(User.t(), Object.t(), String.t()) :: {:ok, map(), keyword()}
def emoji_react(actor, object, emoji) do
with {:ok, data, meta} <- object_action(actor, object) do
diff --git a/lib/pleroma/web/activity_pub/object_validator.ex b/lib/pleroma/web/activity_pub/object_validator.ex
index bb6324460..df926829c 100644
--- a/lib/pleroma/web/activity_pub/object_validator.ex
+++ b/lib/pleroma/web/activity_pub/object_validator.ex
@@ -18,6 +18,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
alias Pleroma.Web.ActivityPub.ObjectValidators.CreateChatMessageValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.DeleteValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator
+ alias Pleroma.Web.ActivityPub.ObjectValidators.FollowValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.LikeValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.UndoValidator
alias Pleroma.Web.ActivityPub.ObjectValidators.UpdateValidator
@@ -25,6 +26,16 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
@spec validate(map(), keyword()) :: {:ok, map(), keyword()} | {:error, any()}
def validate(object, meta)
+ def validate(%{"type" => "Follow"} = object, meta) do
+ with {:ok, object} <-
+ object
+ |> FollowValidator.cast_and_validate()
+ |> Ecto.Changeset.apply_action(:insert) do
+ object = stringify_keys(object)
+ {:ok, object, meta}
+ end
+ end
+
def validate(%{"type" => "Block"} = block_activity, meta) do
with {:ok, block_activity} <-
block_activity
diff --git a/lib/pleroma/web/activity_pub/object_validators/follow_validator.ex b/lib/pleroma/web/activity_pub/object_validators/follow_validator.ex
new file mode 100644
index 000000000..ca2724616
--- /dev/null
+++ b/lib/pleroma/web/activity_pub/object_validators/follow_validator.ex
@@ -0,0 +1,44 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.ActivityPub.ObjectValidators.FollowValidator do
+ use Ecto.Schema
+
+ alias Pleroma.EctoType.ActivityPub.ObjectValidators
+
+ import Ecto.Changeset
+ import Pleroma.Web.ActivityPub.ObjectValidators.CommonValidations
+
+ @primary_key false
+
+ embedded_schema do
+ field(:id, ObjectValidators.ObjectID, primary_key: true)
+ field(:type, :string)
+ field(:actor, ObjectValidators.ObjectID)
+ field(:to, ObjectValidators.Recipients, default: [])
+ field(:cc, ObjectValidators.Recipients, default: [])
+ field(:object, ObjectValidators.ObjectID)
+ field(:state, :string, default: "pending")
+ end
+
+ def cast_data(data) do
+ %__MODULE__{}
+ |> cast(data, __schema__(:fields))
+ end
+
+ def validate_data(cng) do
+ cng
+ |> validate_required([:id, :type, :actor, :to, :cc, :object])
+ |> validate_inclusion(:type, ["Follow"])
+ |> validate_inclusion(:state, ~w{pending reject accept})
+ |> validate_actor_presence()
+ |> validate_actor_presence(field_name: :object)
+ end
+
+ def cast_and_validate(data) do
+ data
+ |> cast_data
+ |> validate_data
+ end
+end
diff --git a/lib/pleroma/web/activity_pub/relay.ex b/lib/pleroma/web/activity_pub/relay.ex
index 484178edd..b09764d2b 100644
--- a/lib/pleroma/web/activity_pub/relay.ex
+++ b/lib/pleroma/web/activity_pub/relay.ex
@@ -28,7 +28,7 @@ defmodule Pleroma.Web.ActivityPub.Relay do
def follow(target_instance) do
with %User{} = local_user <- get_actor(),
{:ok, %User{} = target_user} <- User.get_or_fetch_by_ap_id(target_instance),
- {:ok, activity} <- ActivityPub.follow(local_user, target_user) do
+ {:ok, _, _, activity} <- CommonAPI.follow(local_user, target_user) do
Logger.info("relay: followed instance: #{target_instance}; id=#{activity.data["id"]}")
{:ok, activity}
else
diff --git a/lib/pleroma/web/activity_pub/side_effects.ex b/lib/pleroma/web/activity_pub/side_effects.ex
index 61feeae4d..1d2c296a5 100644
--- a/lib/pleroma/web/activity_pub/side_effects.ex
+++ b/lib/pleroma/web/activity_pub/side_effects.ex
@@ -9,6 +9,7 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
alias Pleroma.Activity.Ir.Topics
alias Pleroma.Chat
alias Pleroma.Chat.MessageReference
+ alias Pleroma.FollowingRelationship
alias Pleroma.Notification
alias Pleroma.Object
alias Pleroma.Repo
@@ -21,6 +22,69 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
def handle(object, meta \\ [])
+ # Tasks this handle
+ # - Follows if possible
+ # - Sends a notification
+ # - Generates accept or reject if appropriate
+ def handle(
+ %{
+ data: %{
+ "id" => follow_id,
+ "type" => "Follow",
+ "object" => followed_user,
+ "actor" => following_user
+ }
+ } = object,
+ meta
+ ) do
+ with %User{} = follower <- User.get_cached_by_ap_id(following_user),
+ %User{} = followed <- User.get_cached_by_ap_id(followed_user),
+ {_, {:ok, _}, _, _} <-
+ {:following, User.follow(follower, followed, :follow_pending), follower, followed} do
+ if followed.local && !followed.locked do
+ Utils.update_follow_state_for_all(object, "accept")
+ FollowingRelationship.update(follower, followed, :follow_accept)
+ User.update_follower_count(followed)
+ User.update_following_count(follower)
+
+ %{
+ to: [following_user],
+ actor: followed,
+ object: follow_id,
+ local: true
+ }
+ |> ActivityPub.accept()
+ end
+ else
+ {:following, {:error, _}, follower, followed} ->
+ Utils.update_follow_state_for_all(object, "reject")
+ FollowingRelationship.update(follower, followed, :follow_reject)
+
+ if followed.local do
+ %{
+ to: [follower.ap_id],
+ actor: followed,
+ object: follow_id,
+ local: true
+ }
+ |> ActivityPub.reject()
+ end
+
+ _ ->
+ nil
+ end
+
+ {:ok, notifications} = Notification.create_notifications(object, do_send: false)
+
+ meta =
+ meta
+ |> add_notifications(notifications)
+
+ updated_object = Activity.get_by_ap_id(follow_id)
+
+ {:ok, updated_object, meta}
+ end
+
# Tasks this handles:
# - Unfollow and block
def handle(
@@ -209,14 +273,20 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
{:ok, object}
end
- def handle_undoing(%{data: %{"type" => "Like"}} = object) do
- with %Object{} = liked_object <- Object.get_by_ap_id(object.data["object"]),
- {:ok, _} <- Utils.remove_like_from_object(object, liked_object),
- {:ok, _} <- Repo.delete(object) do
- :ok
+ defp undo_like(nil, object), do: delete_object(object)
+
+ defp undo_like(%Object{} = liked_object, object) do
+ with {:ok, _} <- Utils.remove_like_from_object(object, liked_object) do
+ delete_object(object)
end
end
+ def handle_undoing(%{data: %{"type" => "Like"}} = object) do
+ object.data["object"]
+ |> Object.get_by_ap_id()
+ |> undo_like(object)
+ end
+
def handle_undoing(%{data: %{"type" => "EmojiReact"}} = object) do
with %Object{} = reacted_object <- Object.get_by_ap_id(object.data["object"]),
{:ok, _} <- Utils.remove_emoji_reaction_from_object(object, reacted_object),
@@ -246,6 +316,11 @@ defmodule Pleroma.Web.ActivityPub.SideEffects do
def handle_undoing(object), do: {:error, ["don't know how to handle", object]}
+ @spec delete_object(Object.t()) :: :ok | {:error, Ecto.Changeset.t()}
+ defp delete_object(object) do
+ with {:ok, _} <- Repo.delete(object), do: :ok
+ end
+
defp send_notifications(meta) do
Keyword.get(meta, :notifications, [])
|> Enum.each(fn notification ->
diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
index bc6fc4bd8..884646ceb 100644
--- a/lib/pleroma/web/activity_pub/transmogrifier.ex
+++ b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -233,18 +233,24 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
is_map(url) && is_binary(url["href"]) -> url["href"]
is_binary(data["url"]) -> data["url"]
is_binary(data["href"]) -> data["href"]
+ true -> nil
end
- attachment_url =
- %{"href" => href}
- |> Maps.put_if_present("mediaType", media_type)
- |> Maps.put_if_present("type", Map.get(url || %{}, "type"))
+ if href do
+ attachment_url =
+ %{"href" => href}
+ |> Maps.put_if_present("mediaType", media_type)
+ |> Maps.put_if_present("type", Map.get(url || %{}, "type"))
- %{"url" => [attachment_url]}
- |> Maps.put_if_present("mediaType", media_type)
- |> Maps.put_if_present("type", data["type"])
- |> Maps.put_if_present("name", data["name"])
+ %{"url" => [attachment_url]}
+ |> Maps.put_if_present("mediaType", media_type)
+ |> Maps.put_if_present("type", data["type"])
+ |> Maps.put_if_present("name", data["name"])
+ else
+ nil
+ end
end)
+ |> Enum.filter(& &1)
Map.put(object, "attachment", attachments)
end
@@ -263,12 +269,18 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
def fix_url(%{"type" => object_type, "url" => url} = object)
when object_type in ["Video", "Audio"] and is_list(url) do
- first_element = Enum.at(url, 0)
+ attachment =
+ Enum.find(url, fn x ->
+ media_type = x["mediaType"] || x["mimeType"] || ""
- link_element = Enum.find(url, fn x -> is_map(x) and x["mimeType"] == "text/html" end)
+ is_map(x) and String.starts_with?(media_type, ["audio/", "video/"])
+ end)
+
+ link_element =
+ Enum.find(url, fn x -> is_map(x) and (x["mediaType"] || x["mimeType"]) == "text/html" end)
object
- |> Map.put("attachment", [first_element])
+ |> Map.put("attachment", [attachment])
|> Map.put("url", link_element["href"])
end
@@ -518,66 +530,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end
def handle_incoming(
- %{"type" => "Follow", "object" => followed, "actor" => follower, "id" => id} = data,
- _options
- ) do
- with %User{local: true} = followed <-
- User.get_cached_by_ap_id(Containment.get_actor(%{"actor" => followed})),
- {:ok, %User{} = follower} <-
- User.get_or_fetch_by_ap_id(Containment.get_actor(%{"actor" => follower})),
- {:ok, activity} <-
- ActivityPub.follow(follower, followed, id, false, skip_notify_and_stream: true) do
- with deny_follow_blocked <- Pleroma.Config.get([:user, :deny_follow_blocked]),
- {_, false} <- {:user_blocked, User.blocks?(followed, follower) && deny_follow_blocked},
- {_, false} <- {:user_locked, User.locked?(followed)},
- {_, {:ok, follower}} <- {:follow, User.follow(follower, followed)},
- {_, {:ok, _}} <-
- {:follow_state_update, Utils.update_follow_state_for_all(activity, "accept")},
- {:ok, _relationship} <-
- FollowingRelationship.update(follower, followed, :follow_accept) do
- ActivityPub.accept(%{
- to: [follower.ap_id],
- actor: followed,
- object: data,
- local: true
- })
- else
- {:user_blocked, true} ->
- {:ok, _} = Utils.update_follow_state_for_all(activity, "reject")
- {:ok, _relationship} = FollowingRelationship.update(follower, followed, :follow_reject)
-
- ActivityPub.reject(%{
- to: [follower.ap_id],
- actor: followed,
- object: data,
- local: true
- })
-
- {:follow, {:error, _}} ->
- {:ok, _} = Utils.update_follow_state_for_all(activity, "reject")
- {:ok, _relationship} = FollowingRelationship.update(follower, followed, :follow_reject)
-
- ActivityPub.reject(%{
- to: [follower.ap_id],
- actor: followed,
- object: data,
- local: true
- })
-
- {:user_locked, true} ->
- {:ok, _relationship} = FollowingRelationship.update(follower, followed, :follow_pending)
- :noop
- end
-
- ActivityPub.notify_and_stream(activity)
- {:ok, activity}
- else
- _e ->
- :error
- end
- end
-
- def handle_incoming(
%{"type" => "Accept", "object" => follow_object, "actor" => _actor, "id" => id} = data,
_options
) do
@@ -684,7 +636,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
%{"type" => type} = data,
_options
)
- when type in ~w{Update Block} do
+ when type in ~w{Update Block Follow} do
with {:ok, %User{}} <- ObjectValidator.fetch_actor(data),
{:ok, activity, _} <- Pipeline.common_pipeline(data, local: false) do
{:ok, activity}
diff --git a/lib/pleroma/web/api_spec/operations/account_operation.ex b/lib/pleroma/web/api_spec/operations/account_operation.ex
index 9bde8fc0d..b8c527606 100644
--- a/lib/pleroma/web/api_spec/operations/account_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/account_operation.ex
@@ -203,14 +203,23 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
security: [%{"oAuth" => ["follow", "write:follows"]}],
description: "Follow the given account",
parameters: [
- %Reference{"$ref": "#/components/parameters/accountIdOrNickname"},
- Operation.parameter(
- :reblogs,
- :query,
- BooleanLike,
- "Receive this account's reblogs in home timeline? Defaults to true."
- )
+ %Reference{"$ref": "#/components/parameters/accountIdOrNickname"}
],
+ requestBody:
+ request_body(
+ "Parameters",
+ %Schema{
+ type: :object,
+ properties: %{
+ reblogs: %Schema{
+ type: :boolean,
+ description: "Receive this account's reblogs in home timeline? Defaults to true.",
+ default: true
+ }
+ }
+ },
+ required: false
+ ),
responses: %{
200 => Operation.response("Relationship", "application/json", AccountRelationship),
400 => Operation.response("Error", "application/json", ApiError),
@@ -438,6 +447,7 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
}
end
+ # TODO: This is actually a token respone, but there's no oauth operation file yet.
defp create_response do
%Schema{
title: "AccountCreateResponse",
@@ -446,14 +456,20 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
properties: %{
token_type: %Schema{type: :string},
access_token: %Schema{type: :string},
- scope: %Schema{type: :array, items: %Schema{type: :string}},
- created_at: %Schema{type: :integer, format: :"date-time"}
+ refresh_token: %Schema{type: :string},
+ scope: %Schema{type: :string},
+ created_at: %Schema{type: :integer, format: :"date-time"},
+ me: %Schema{type: :string},
+ expires_in: %Schema{type: :integer}
},
example: %{
+ "token_type" => "Bearer",
"access_token" => "i9hAVVzGld86Pl5JtLtizKoXVvtTlSCJvwaugCxvZzk",
+ "refresh_token" => "i9hAVVzGld86Pl5JtLtizKoXVvtTlSCJvwaugCxvZzz",
"created_at" => 1_585_918_714,
- "scope" => ["read", "write", "follow", "push"],
- "token_type" => "Bearer"
+ "expires_in" => 600,
+ "scope" => "read write follow push",
+ "me" => "https://gensokyo.2hu/users/raymoo"
}
}
end
diff --git a/lib/pleroma/web/api_spec/operations/pleroma_account_operation.ex b/lib/pleroma/web/api_spec/operations/pleroma_account_operation.ex
index 90922c064..97836b2eb 100644
--- a/lib/pleroma/web/api_spec/operations/pleroma_account_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/pleroma_account_operation.ex
@@ -4,7 +4,6 @@
defmodule Pleroma.Web.ApiSpec.PleromaAccountOperation do
alias OpenApiSpex.Operation
- alias OpenApiSpex.Schema
alias Pleroma.Web.ApiSpec.Schemas.AccountRelationship
alias Pleroma.Web.ApiSpec.Schemas.ApiError
alias Pleroma.Web.ApiSpec.Schemas.FlakeID
@@ -40,48 +39,6 @@ defmodule Pleroma.Web.ApiSpec.PleromaAccountOperation do
}
end
- def update_avatar_operation do
- %Operation{
- tags: ["Accounts"],
- summary: "Set/clear user avatar image",
- operationId: "PleromaAPI.AccountController.update_avatar",
- requestBody:
- request_body("Parameters", update_avatar_or_background_request(), required: true),
- security: [%{"oAuth" => ["write:accounts"]}],
- responses: %{
- 200 => update_response(),
- 403 => Operation.response("Forbidden", "application/json", ApiError)
- }
- }
- end
-
- def update_banner_operation do
- %Operation{
- tags: ["Accounts"],
- summary: "Set/clear user banner image",
- operationId: "PleromaAPI.AccountController.update_banner",
- requestBody: request_body("Parameters", update_banner_request(), required: true),
- security: [%{"oAuth" => ["write:accounts"]}],
- responses: %{
- 200 => update_response()
- }
- }
- end
-
- def update_background_operation do
- %Operation{
- tags: ["Accounts"],
- summary: "Set/clear user background image",
- operationId: "PleromaAPI.AccountController.update_background",
- security: [%{"oAuth" => ["write:accounts"]}],
- requestBody:
- request_body("Parameters", update_avatar_or_background_request(), required: true),
- responses: %{
- 200 => update_response()
- }
- }
- end
-
def favourites_operation do
%Operation{
tags: ["Accounts"],
@@ -136,52 +93,4 @@ defmodule Pleroma.Web.ApiSpec.PleromaAccountOperation do
required: true
)
end
-
- defp update_avatar_or_background_request do
- %Schema{
- title: "PleromaAccountUpdateAvatarOrBackgroundRequest",
- type: :object,
- properties: %{
- img: %Schema{
- nullable: true,
- type: :string,
- format: :binary,
- description: "Image encoded using `multipart/form-data` or an empty string to clear"
- }
- }
- }
- end
-
- defp update_banner_request do
- %Schema{
- title: "PleromaAccountUpdateBannerRequest",
- type: :object,
- properties: %{
- banner: %Schema{
- type: :string,
- nullable: true,
- format: :binary,
- description: "Image encoded using `multipart/form-data` or an empty string to clear"
- }
- }
- }
- end
-
- defp update_response do
- Operation.response("PleromaAccountUpdateResponse", "application/json", %Schema{
- type: :object,
- properties: %{
- url: %Schema{
- type: :string,
- format: :uri,
- nullable: true,
- description: "Image URL"
- }
- },
- example: %{
- "url" =>
- "https://cofe.party/media/9d0add56-bcb6-4c0f-8225-cbbd0b6dd773/13eadb6972c9ccd3f4ffa3b8196f0e0d38b4d2f27594457c52e52946c054cd9a.gif"
- }
- })
- end
end
diff --git a/lib/pleroma/web/api_spec/operations/status_operation.ex b/lib/pleroma/web/api_spec/operations/status_operation.ex
index 0b7fad793..5bd4619d5 100644
--- a/lib/pleroma/web/api_spec/operations/status_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/status_operation.ex
@@ -84,7 +84,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
operationId: "StatusController.delete",
parameters: [id_param()],
responses: %{
- 200 => empty_object_response(),
+ 200 => status_response(),
403 => Operation.response("Forbidden", "application/json", ApiError),
404 => Operation.response("Not Found", "application/json", ApiError)
}
diff --git a/lib/pleroma/web/api_spec/schemas/account.ex b/lib/pleroma/web/api_spec/schemas/account.ex
index 84f18f1b6..e6f163cb7 100644
--- a/lib/pleroma/web/api_spec/schemas/account.ex
+++ b/lib/pleroma/web/api_spec/schemas/account.ex
@@ -102,6 +102,12 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do
type: :object,
description:
"A generic map of settings for frontends. Opaque to the backend. Only returned in `verify_credentials` and `update_credentials`"
+ },
+ favicon: %Schema{
+ type: :string,
+ format: :uri,
+ nullable: true,
+ description: "Favicon image of the user's instance"
}
}
},
diff --git a/lib/pleroma/web/api_spec/schemas/status.ex b/lib/pleroma/web/api_spec/schemas/status.ex
index 28cde963e..947e42890 100644
--- a/lib/pleroma/web/api_spec/schemas/status.ex
+++ b/lib/pleroma/web/api_spec/schemas/status.ex
@@ -62,6 +62,11 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do
}
},
content: %Schema{type: :string, format: :html, description: "HTML-encoded status content"},
+ text: %Schema{
+ type: :string,
+ description: "Original unformatted content in plain text",
+ nullable: true
+ },
created_at: %Schema{
type: :string,
format: "date-time",
diff --git a/lib/pleroma/web/common_api/activity_draft.ex b/lib/pleroma/web/common_api/activity_draft.ex
index 9bcb9f587..f849b2e01 100644
--- a/lib/pleroma/web/common_api/activity_draft.ex
+++ b/lib/pleroma/web/common_api/activity_draft.ex
@@ -186,6 +186,7 @@ defmodule Pleroma.Web.CommonAPI.ActivityDraft do
draft.poll
)
|> Map.put("emoji", emoji)
+ |> Map.put("source", draft.status)
%__MODULE__{draft | object: object}
end
diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex
index fd7149079..4d5b0decf 100644
--- a/lib/pleroma/web/common_api/common_api.ex
+++ b/lib/pleroma/web/common_api/common_api.ex
@@ -101,10 +101,14 @@ defmodule Pleroma.Web.CommonAPI do
def follow(follower, followed) do
timeout = Pleroma.Config.get([:activitypub, :follow_handshake_timeout])
- with {:ok, follower} <- User.maybe_direct_follow(follower, followed),
- {:ok, activity} <- ActivityPub.follow(follower, followed),
+ with {:ok, follow_data, _} <- Builder.follow(follower, followed),
+ {:ok, activity, _} <- Pipeline.common_pipeline(follow_data, local: true),
{:ok, follower, followed} <- User.wait_and_refresh(timeout, follower, followed) do
- {:ok, follower, followed, activity}
+ if activity.data["state"] == "reject" do
+ {:error, :rejected}
+ else
+ {:ok, follower, followed, activity}
+ end
end
end
diff --git a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
index b5008d69b..743442855 100644
--- a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex
@@ -27,6 +27,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
alias Pleroma.Web.MastodonAPI.MastodonAPI
alias Pleroma.Web.MastodonAPI.MastodonAPIController
alias Pleroma.Web.MastodonAPI.StatusView
+ alias Pleroma.Web.OAuth.OAuthView
alias Pleroma.Web.OAuth.Token
alias Pleroma.Web.TwitterAPI.TwitterAPI
@@ -101,12 +102,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
:ok <- TwitterAPI.validate_captcha(app, params),
{:ok, user} <- TwitterAPI.register_user(params, need_confirmation: true),
{:ok, token} <- Token.create_token(app, user, %{scopes: app.scopes}) do
- json(conn, %{
- token_type: "Bearer",
- access_token: token.token,
- scope: app.scopes,
- created_at: Token.Utils.format_created_at(token)
- })
+ json(conn, OAuthView.render("token.json", %{user: user, token: token}))
else
{:error, error} -> json_response(conn, :bad_request, %{error: error})
end
@@ -148,6 +144,13 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|> Enum.filter(fn {_, value} -> not is_nil(value) end)
|> Enum.into(%{})
+ # We use an empty string as a special value to reset
+ # avatars, banners, backgrounds
+ user_image_value = fn
+ "" -> {:ok, nil}
+ value -> {:ok, value}
+ end
+
user_params =
[
:no_rich_text,
@@ -168,9 +171,9 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|> Maps.put_if_present(:name, params[:display_name])
|> Maps.put_if_present(:bio, params[:note])
|> Maps.put_if_present(:raw_bio, params[:note])
- |> Maps.put_if_present(:avatar, params[:avatar])
- |> Maps.put_if_present(:banner, params[:header])
- |> Maps.put_if_present(:background, params[:pleroma_background_image])
+ |> Maps.put_if_present(:avatar, params[:avatar], user_image_value)
+ |> Maps.put_if_present(:banner, params[:header], user_image_value)
+ |> Maps.put_if_present(:background, params[:pleroma_background_image], user_image_value)
|> Maps.put_if_present(
:raw_fields,
params[:fields_attributes],
@@ -346,7 +349,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
{:error, "Can not follow yourself"}
end
- def follow(%{assigns: %{user: follower, account: followed}} = conn, params) do
+ def follow(%{body_params: params, assigns: %{user: follower, account: followed}} = conn, _) do
with {:ok, follower} <- MastodonAPI.follow(follower, followed, params) do
render(conn, "relationship.json", user: follower, target: followed)
else
diff --git a/lib/pleroma/web/mastodon_api/controllers/search_controller.ex b/lib/pleroma/web/mastodon_api/controllers/search_controller.ex
index e50980122..29affa7d5 100644
--- a/lib/pleroma/web/mastodon_api/controllers/search_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/search_controller.ex
@@ -44,6 +44,7 @@ defmodule Pleroma.Web.MastodonAPI.SearchController do
def search(conn, params), do: do_search(:v1, conn, params)
defp do_search(version, %{assigns: %{user: user}} = conn, %{q: query} = params) do
+ query = String.trim(query)
options = search_options(params, user)
timeout = Keyword.get(Repo.config(), :timeout, 15_000)
default_values = %{"statuses" => [], "accounts" => [], "hashtags" => []}
diff --git a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex
index 468b44b67..12be530c9 100644
--- a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex
@@ -200,11 +200,16 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
@doc "DELETE /api/v1/statuses/:id"
def delete(%{assigns: %{user: user}} = conn, %{id: id}) do
- with {:ok, %Activity{}} <- CommonAPI.delete(id, user) do
- json(conn, %{})
+ with %Activity{} = activity <- Activity.get_by_id_with_object(id),
+ {:ok, %Activity{}} <- CommonAPI.delete(id, user) do
+ try_render(conn, "show.json",
+ activity: activity,
+ for: user,
+ with_direct_conversation_id: true,
+ with_source: true
+ )
else
- {:error, :not_found} = e -> e
- _e -> render_error(conn, :forbidden, "Can't delete this post")
+ _e -> {:error, :not_found}
end
end
diff --git a/lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex b/lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex
index 4bdd46d7e..ab7b1d6aa 100644
--- a/lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex
@@ -88,21 +88,20 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do
)
end
+ defp restrict_unauthenticated?(true = _local_only) do
+ Pleroma.Config.get([:restrict_unauthenticated, :timelines, :local])
+ end
+
+ defp restrict_unauthenticated?(_) do
+ Pleroma.Config.get([:restrict_unauthenticated, :timelines, :federated])
+ end
+
# GET /api/v1/timelines/public
def public(%{assigns: %{user: user}} = conn, params) do
local_only = params[:local]
- cfg_key =
- if local_only do
- :local
- else
- :federated
- end
-
- restrict? = Pleroma.Config.get([:restrict_unauthenticated, :timelines, cfg_key])
-
- if restrict? and is_nil(user) do
- render_error(conn, :unauthorized, "authorization required for timeline view")
+ if is_nil(user) and restrict_unauthenticated?(local_only) do
+ fail_on_bad_auth(conn)
else
activities =
params
@@ -123,6 +122,10 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do
end
end
+ defp fail_on_bad_auth(conn) do
+ render_error(conn, :unauthorized, "authorization required for timeline view")
+ end
+
defp hashtag_fetching(params, user, local_only) do
tags =
[params[:tag], params[:any]]
@@ -157,15 +160,20 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do
# GET /api/v1/timelines/tag/:tag
def hashtag(%{assigns: %{user: user}} = conn, params) do
local_only = params[:local]
- activities = hashtag_fetching(params, user, local_only)
- conn
- |> add_link_headers(activities, %{"local" => local_only})
- |> render("index.json",
- activities: activities,
- for: user,
- as: :activity
- )
+ if is_nil(user) and restrict_unauthenticated?(local_only) do
+ fail_on_bad_auth(conn)
+ else
+ activities = hashtag_fetching(params, user, local_only)
+
+ conn
+ |> add_link_headers(activities, %{"local" => local_only})
+ |> render("index.json",
+ activities: activities,
+ for: user,
+ as: :activity
+ )
+ end
end
# GET /api/v1/timelines/list/:list_id
diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex
index a6e64b4ab..2feba4778 100644
--- a/lib/pleroma/web/mastodon_api/views/account_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/account_view.ex
@@ -204,6 +204,18 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
%{}
end
+ favicon =
+ if Pleroma.Config.get([:instances_favicons, :enabled]) do
+ user
+ |> Map.get(:ap_id, "")
+ |> URI.parse()
+ |> URI.merge("/")
+ |> Pleroma.Instances.Instance.get_or_update_favicon()
+ |> MediaProxy.url()
+ else
+ nil
+ end
+
%{
id: to_string(user.id),
username: username_from_nickname(user.nickname),
@@ -245,7 +257,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
hide_favorites: user.hide_favorites,
relationship: relationship,
skip_thread_containment: user.skip_thread_containment,
- background_image: image_url(user.background) |> MediaProxy.url()
+ background_image: image_url(user.background) |> MediaProxy.url(),
+ favicon: favicon
}
}
|> maybe_put_role(user, opts[:for])
diff --git a/lib/pleroma/web/mastodon_api/views/instance_view.ex b/lib/pleroma/web/mastodon_api/views/instance_view.ex
index 35c2fc25c..5deb0d7ed 100644
--- a/lib/pleroma/web/mastodon_api/views/instance_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/instance_view.ex
@@ -34,10 +34,14 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do
background_upload_limit: Keyword.get(instance, :background_upload_limit),
banner_upload_limit: Keyword.get(instance, :banner_upload_limit),
background_image: Keyword.get(instance, :background_image),
+ chat_limit: Keyword.get(instance, :chat_limit),
+ description_limit: Keyword.get(instance, :description_limit),
pleroma: %{
metadata: %{
+ account_activation_required: Keyword.get(instance, :account_activation_required),
features: features(),
- federation: federation()
+ federation: federation(),
+ fields_limits: fields_limits()
},
vapid_public_key: Keyword.get(Pleroma.Web.Push.vapid_config(), :public_key)
}
@@ -88,4 +92,13 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do
end
|> Map.put(:enabled, Config.get([:instance, :federating]))
end
+
+ def fields_limits do
+ %{
+ max_fields: Config.get([:instance, :max_account_fields]),
+ max_remote_fields: Config.get([:instance, :max_remote_account_fields]),
+ name_length: Config.get([:instance, :account_field_name_length]),
+ value_length: Config.get([:instance, :account_field_value_length])
+ }
+ end
end
diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex
index 6ee17f4dd..fa9d695f3 100644
--- a/lib/pleroma/web/mastodon_api/views/status_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/status_view.ex
@@ -333,6 +333,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
reblog: nil,
card: card,
content: content_html,
+ text: opts[:with_source] && object.data["source"],
created_at: created_at,
reblogs_count: announcement_count,
replies_count: object.data["repliesCount"] || 0,
diff --git a/lib/pleroma/web/oauth/mfa_controller.ex b/lib/pleroma/web/oauth/mfa_controller.ex
index 53e19f82e..f102c93e7 100644
--- a/lib/pleroma/web/oauth/mfa_controller.ex
+++ b/lib/pleroma/web/oauth/mfa_controller.ex
@@ -13,6 +13,7 @@ defmodule Pleroma.Web.OAuth.MFAController do
alias Pleroma.Web.Auth.TOTPAuthenticator
alias Pleroma.Web.OAuth.MFAView, as: View
alias Pleroma.Web.OAuth.OAuthController
+ alias Pleroma.Web.OAuth.OAuthView
alias Pleroma.Web.OAuth.Token
plug(:fetch_session when action in [:show, :verify])
@@ -74,7 +75,7 @@ defmodule Pleroma.Web.OAuth.MFAController do
{:ok, %{user: user, authorization: auth}} <- MFA.Token.validate(mfa_token),
{:ok, _} <- validates_challenge(user, params),
{:ok, token} <- Token.exchange_token(app, auth) do
- json(conn, Token.Response.build(user, token))
+ json(conn, OAuthView.render("token.json", %{user: user, token: token}))
else
_error ->
conn
diff --git a/lib/pleroma/web/oauth/mfa_view.ex b/lib/pleroma/web/oauth/mfa_view.ex
index 41d5578dc..5d87db268 100644
--- a/lib/pleroma/web/oauth/mfa_view.ex
+++ b/lib/pleroma/web/oauth/mfa_view.ex
@@ -5,4 +5,13 @@
defmodule Pleroma.Web.OAuth.MFAView do
use Pleroma.Web, :view
import Phoenix.HTML.Form
+ alias Pleroma.MFA
+
+ def render("mfa_response.json", %{token: token, user: user}) do
+ %{
+ error: "mfa_required",
+ mfa_token: token.token,
+ supported_challenge_types: MFA.supported_methods(user)
+ }
+ end
end
diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex
index c557778ca..7683589cf 100644
--- a/lib/pleroma/web/oauth/oauth_controller.ex
+++ b/lib/pleroma/web/oauth/oauth_controller.ex
@@ -17,6 +17,8 @@ defmodule Pleroma.Web.OAuth.OAuthController do
alias Pleroma.Web.OAuth.App
alias Pleroma.Web.OAuth.Authorization
alias Pleroma.Web.OAuth.MFAController
+ alias Pleroma.Web.OAuth.MFAView
+ alias Pleroma.Web.OAuth.OAuthView
alias Pleroma.Web.OAuth.Scopes
alias Pleroma.Web.OAuth.Token
alias Pleroma.Web.OAuth.Token.Strategy.RefreshToken
@@ -233,9 +235,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do
with {:ok, app} <- Token.Utils.fetch_app(conn),
{:ok, %{user: user} = token} <- Token.get_by_refresh_token(app, token),
{:ok, token} <- RefreshToken.grant(token) do
- response_attrs = %{created_at: Token.Utils.format_created_at(token)}
-
- json(conn, Token.Response.build(user, token, response_attrs))
+ json(conn, OAuthView.render("token.json", %{user: user, token: token}))
else
_error -> render_invalid_credentials_error(conn)
end
@@ -247,9 +247,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do
{:ok, auth} <- Authorization.get_by_token(app, fixed_token),
%User{} = user <- User.get_cached_by_id(auth.user_id),
{:ok, token} <- Token.exchange_token(app, auth) do
- response_attrs = %{created_at: Token.Utils.format_created_at(token)}
-
- json(conn, Token.Response.build(user, token, response_attrs))
+ json(conn, OAuthView.render("token.json", %{user: user, token: token}))
else
error ->
handle_token_exchange_error(conn, error)
@@ -267,7 +265,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do
{:ok, auth} <- Authorization.create_authorization(app, user, scopes),
{:mfa_required, _, _, false} <- {:mfa_required, user, auth, MFA.require?(user)},
{:ok, token} <- Token.exchange_token(app, auth) do
- json(conn, Token.Response.build(user, token))
+ json(conn, OAuthView.render("token.json", %{user: user, token: token}))
else
error ->
handle_token_exchange_error(conn, error)
@@ -290,7 +288,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do
with {:ok, app} <- Token.Utils.fetch_app(conn),
{:ok, auth} <- Authorization.create_authorization(app, %User{}),
{:ok, token} <- Token.exchange_token(app, auth) do
- json(conn, Token.Response.build_for_client_credentials(token))
+ json(conn, OAuthView.render("token.json", %{token: token}))
else
_error ->
handle_token_exchange_error(conn, :invalid_credentails)
@@ -548,7 +546,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do
defp build_and_response_mfa_token(user, auth) do
with {:ok, token} <- MFA.Token.create_token(user, auth) do
- Token.Response.build_for_mfa_token(user, token)
+ MFAView.render("mfa_response.json", %{token: token, user: user})
end
end
diff --git a/lib/pleroma/web/oauth/oauth_view.ex b/lib/pleroma/web/oauth/oauth_view.ex
index 94ddaf913..f55247ebd 100644
--- a/lib/pleroma/web/oauth/oauth_view.ex
+++ b/lib/pleroma/web/oauth/oauth_view.ex
@@ -5,4 +5,26 @@
defmodule Pleroma.Web.OAuth.OAuthView do
use Pleroma.Web, :view
import Phoenix.HTML.Form
+
+ alias Pleroma.Web.OAuth.Token.Utils
+
+ def render("token.json", %{token: token} = opts) do
+ response = %{
+ token_type: "Bearer",
+ access_token: token.token,
+ refresh_token: token.refresh_token,
+ expires_in: expires_in(),
+ scope: Enum.join(token.scopes, " "),
+ created_at: Utils.format_created_at(token)
+ }
+
+ if user = opts[:user] do
+ response
+ |> Map.put(:me, user.ap_id)
+ else
+ response
+ end
+ end
+
+ defp expires_in, do: Pleroma.Config.get([:oauth2, :token_expires_in], 600)
end
diff --git a/lib/pleroma/web/oauth/token/response.ex b/lib/pleroma/web/oauth/token/response.ex
deleted file mode 100644
index 0e72c31e9..000000000
--- a/lib/pleroma/web/oauth/token/response.ex
+++ /dev/null
@@ -1,45 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.OAuth.Token.Response do
- @moduledoc false
-
- alias Pleroma.MFA
- alias Pleroma.User
- alias Pleroma.Web.OAuth.Token.Utils
-
- @doc false
- def build(%User{} = user, token, opts \\ %{}) do
- %{
- token_type: "Bearer",
- access_token: token.token,
- refresh_token: token.refresh_token,
- expires_in: expires_in(),
- scope: Enum.join(token.scopes, " "),
- me: user.ap_id
- }
- |> Map.merge(opts)
- end
-
- def build_for_client_credentials(token) do
- %{
- token_type: "Bearer",
- access_token: token.token,
- refresh_token: token.refresh_token,
- created_at: Utils.format_created_at(token),
- expires_in: expires_in(),
- scope: Enum.join(token.scopes, " ")
- }
- end
-
- def build_for_mfa_token(user, mfa_token) do
- %{
- error: "mfa_required",
- mfa_token: mfa_token.token,
- supported_challenge_types: MFA.supported_methods(user)
- }
- end
-
- defp expires_in, do: Pleroma.Config.get([:oauth2, :token_expires_in], 600)
-end
diff --git a/lib/pleroma/web/pleroma_api/controllers/account_controller.ex b/lib/pleroma/web/pleroma_api/controllers/account_controller.ex
index f3554d919..563edded7 100644
--- a/lib/pleroma/web/pleroma_api/controllers/account_controller.ex
+++ b/lib/pleroma/web/pleroma_api/controllers/account_controller.ex
@@ -8,7 +8,6 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do
import Pleroma.Web.ControllerHelper,
only: [json_response: 3, add_link_headers: 2, assign_account_by_id: 2]
- alias Ecto.Changeset
alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
alias Pleroma.Plugs.OAuthScopesPlug
alias Pleroma.Plugs.RateLimiter
@@ -37,17 +36,6 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do
plug(
OAuthScopesPlug,
- %{scopes: ["write:accounts"]}
- # Note: the following actions are not permission-secured in Mastodon:
- when action in [
- :update_avatar,
- :update_banner,
- :update_background
- ]
- )
-
- plug(
- OAuthScopesPlug,
%{scopes: ["read:favourites"], fallback: :proceed_unauthenticated} when action == :favourites
)
@@ -68,56 +56,6 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do
end
end
- @doc "PATCH /api/v1/pleroma/accounts/update_avatar"
- def update_avatar(%{assigns: %{user: user}, body_params: %{img: ""}} = conn, _) do
- {:ok, _user} =
- user
- |> Changeset.change(%{avatar: nil})
- |> User.update_and_set_cache()
-
- json(conn, %{url: nil})
- end
-
- def update_avatar(%{assigns: %{user: user}, body_params: params} = conn, _params) do
- {:ok, %{data: data}} = ActivityPub.upload(params, type: :avatar)
- {:ok, _user} = user |> Changeset.change(%{avatar: data}) |> User.update_and_set_cache()
- %{"url" => [%{"href" => href} | _]} = data
-
- json(conn, %{url: href})
- end
-
- @doc "PATCH /api/v1/pleroma/accounts/update_banner"
- def update_banner(%{assigns: %{user: user}, body_params: %{banner: ""}} = conn, _) do
- with {:ok, _user} <- User.update_banner(user, %{}) do
- json(conn, %{url: nil})
- end
- end
-
- def update_banner(%{assigns: %{user: user}, body_params: params} = conn, _) do
- with {:ok, object} <- ActivityPub.upload(%{img: params[:banner]}, type: :banner),
- {:ok, _user} <- User.update_banner(user, object.data) do
- %{"url" => [%{"href" => href} | _]} = object.data
-
- json(conn, %{url: href})
- end
- end
-
- @doc "PATCH /api/v1/pleroma/accounts/update_background"
- def update_background(%{assigns: %{user: user}, body_params: %{img: ""}} = conn, _) do
- with {:ok, _user} <- User.update_background(user, %{}) do
- json(conn, %{url: nil})
- end
- end
-
- def update_background(%{assigns: %{user: user}, body_params: params} = conn, _) do
- with {:ok, object} <- ActivityPub.upload(params, type: :background),
- {:ok, _user} <- User.update_background(user, object.data) do
- %{"url" => [%{"href" => href} | _]} = object.data
-
- json(conn, %{url: href})
- end
- end
-
@doc "GET /api/v1/pleroma/accounts/:id/favourites"
def favourites(%{assigns: %{account: %{hide_favorites: true}}} = conn, _params) do
render_error(conn, :forbidden, "Can't get favorites")
diff --git a/lib/pleroma/web/preload/status_net.ex b/lib/pleroma/web/preload/status_net.ex
deleted file mode 100644
index 9b62f87a2..000000000
--- a/lib/pleroma/web/preload/status_net.ex
+++ /dev/null
@@ -1,25 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.Preload.Providers.StatusNet do
- alias Pleroma.Web.Preload.Providers.Provider
- alias Pleroma.Web.TwitterAPI.UtilController
-
- @behaviour Provider
- @config_url "/api/statusnet/config.json"
-
- @impl Provider
- def generate_terms(_params) do
- %{}
- |> build_config_tag()
- end
-
- defp build_config_tag(acc) do
- resp =
- Plug.Test.conn(:get, @config_url |> to_string())
- |> UtilController.config(nil)
-
- Map.put(acc, @config_url, resp.resp_body)
- end
-end
diff --git a/lib/pleroma/web/rich_media/parser.ex b/lib/pleroma/web/rich_media/parser.ex
index ef5ead2da..c8a767935 100644
--- a/lib/pleroma/web/rich_media/parser.ex
+++ b/lib/pleroma/web/rich_media/parser.ex
@@ -86,7 +86,10 @@ defmodule Pleroma.Web.RichMedia.Parser do
end
try do
- {:ok, %Tesla.Env{body: html}} = Pleroma.HTTP.get(url, [], adapter: opts)
+ rich_media_agent = Pleroma.Application.user_agent() <> "; Bot"
+
+ {:ok, %Tesla.Env{body: html}} =
+ Pleroma.HTTP.get(url, [{"user-agent", rich_media_agent}], adapter: opts)
html
|> parse_html()
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index c837e83fe..e25ffd317 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -328,10 +328,6 @@ defmodule Pleroma.Web.Router do
delete("/statuses/:id/reactions/:emoji", EmojiReactionController, :delete)
post("/notifications/read", NotificationController, :mark_as_read)
- patch("/accounts/update_avatar", AccountController, :update_avatar)
- patch("/accounts/update_banner", AccountController, :update_banner)
- patch("/accounts/update_background", AccountController, :update_background)
-
get("/mascot", MascotController, :show)
put("/mascot", MascotController, :update)
@@ -517,10 +513,6 @@ defmodule Pleroma.Web.Router do
scope "/api", Pleroma.Web do
pipe_through(:config)
- get("/help/test", TwitterAPI.UtilController, :help_test)
- post("/help/test", TwitterAPI.UtilController, :help_test)
- get("/statusnet/config", TwitterAPI.UtilController, :config)
- get("/statusnet/version", TwitterAPI.UtilController, :version)
get("/pleroma/frontend_configurations", TwitterAPI.UtilController, :frontend_configurations)
end
diff --git a/lib/pleroma/web/streamer/streamer.ex b/lib/pleroma/web/streamer/streamer.ex
index 73ee3e1e1..d1d70e556 100644
--- a/lib/pleroma/web/streamer/streamer.ex
+++ b/lib/pleroma/web/streamer/streamer.ex
@@ -104,7 +104,9 @@ defmodule Pleroma.Web.Streamer do
:ok
end
- def filtered_by_user?(%User{} = user, %Activity{} = item) do
+ def filtered_by_user?(user, item, streamed_type \\ :activity)
+
+ def filtered_by_user?(%User{} = user, %Activity{} = item, streamed_type) do
%{block: blocked_ap_ids, mute: muted_ap_ids, reblog_mute: reblog_muted_ap_ids} =
User.outgoing_relationships_ap_ids(user, [:block, :mute, :reblog_mute])
@@ -116,7 +118,9 @@ defmodule Pleroma.Web.Streamer do
true <-
Enum.all?([blocked_ap_ids, muted_ap_ids], &(item.actor not in &1)),
true <- item.data["type"] != "Announce" || item.actor not in reblog_muted_ap_ids,
- true <- !(item.data["type"] == "Announce" && parent.data["actor"] == user.ap_id),
+ true <-
+ !(streamed_type == :activity && item.data["type"] == "Announce" &&
+ parent.data["actor"] == user.ap_id),
true <- Enum.all?([blocked_ap_ids, muted_ap_ids], &(parent.data["actor"] not in &1)),
true <- MapSet.disjoint?(recipients, recipient_blocks),
%{host: item_host} <- URI.parse(item.actor),
@@ -131,8 +135,8 @@ defmodule Pleroma.Web.Streamer do
end
end
- def filtered_by_user?(%User{} = user, %Notification{activity: activity}) do
- filtered_by_user?(user, activity)
+ def filtered_by_user?(%User{} = user, %Notification{activity: activity}, _) do
+ filtered_by_user?(user, activity, :notification)
end
defp do_stream("direct", item) do
diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex
index aaca182ec..8314e75b4 100644
--- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex
+++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex
@@ -13,9 +13,7 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
alias Pleroma.Notification
alias Pleroma.Plugs.OAuthScopesPlug
alias Pleroma.User
- alias Pleroma.Web
alias Pleroma.Web.CommonAPI
- alias Pleroma.Web.TwitterAPI.UtilView
alias Pleroma.Web.WebFinger
plug(Pleroma.Web.FederatingPlug when action == :remote_subscribe)
@@ -42,12 +40,6 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
plug(OAuthScopesPlug, %{scopes: ["write:notifications"]} when action == :notifications_read)
- plug(Pleroma.Plugs.SetFormatPlug when action in [:config, :version])
-
- def help_test(conn, _params) do
- json(conn, "ok")
- end
-
def remote_subscribe(conn, %{"nickname" => nick, "profile" => _}) do
with %User{} = user <- User.get_cached_by_nickname(nick),
avatar = User.avatar_url(user) do
@@ -89,60 +81,6 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
end
end
- def config(%{assigns: %{format: "xml"}} = conn, _params) do
- instance = Pleroma.Config.get(:instance)
- response = UtilView.status_net_config(instance)
-
- conn
- |> put_resp_content_type("application/xml")
- |> send_resp(200, response)
- end
-
- def config(conn, _params) do
- instance = Pleroma.Config.get(:instance)
-
- vapid_public_key = Keyword.get(Pleroma.Web.Push.vapid_config(), :public_key)
-
- uploadlimit = %{
- uploadlimit: to_string(Keyword.get(instance, :upload_limit)),
- avatarlimit: to_string(Keyword.get(instance, :avatar_upload_limit)),
- backgroundlimit: to_string(Keyword.get(instance, :background_upload_limit)),
- bannerlimit: to_string(Keyword.get(instance, :banner_upload_limit))
- }
-
- data = %{
- name: Keyword.get(instance, :name),
- description: Keyword.get(instance, :description),
- server: Web.base_url(),
- textlimit: to_string(Keyword.get(instance, :limit)),
- uploadlimit: uploadlimit,
- closed: bool_to_val(Keyword.get(instance, :registrations_open), "0", "1"),
- private: bool_to_val(Keyword.get(instance, :public, true), "0", "1"),
- vapidPublicKey: vapid_public_key,
- accountActivationRequired:
- bool_to_val(Keyword.get(instance, :account_activation_required, false)),
- invitesEnabled: bool_to_val(Keyword.get(instance, :invites_enabled, false)),
- safeDMMentionsEnabled: bool_to_val(Pleroma.Config.get([:instance, :safe_dm_mentions]))
- }
-
- managed_config = Keyword.get(instance, :managed_config)
-
- data =
- if managed_config do
- pleroma_fe = Pleroma.Config.get([:frontend_configurations, :pleroma_fe])
- Map.put(data, "pleromafe", pleroma_fe)
- else
- data
- end
-
- json(conn, %{site: data})
- end
-
- defp bool_to_val(true), do: "1"
- defp bool_to_val(_), do: "0"
- defp bool_to_val(true, val, _), do: val
- defp bool_to_val(_, _, val), do: val
-
def frontend_configurations(conn, _params) do
config =
Pleroma.Config.get(:frontend_configurations, %{})
@@ -151,18 +89,6 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
json(conn, config)
end
- def version(%{assigns: %{format: "xml"}} = conn, _params) do
- version = Pleroma.Application.named_version()
-
- conn
- |> put_resp_content_type("application/xml")
- |> send_resp(200, "<version>#{version}</version>")
- end
-
- def version(conn, _params) do
- json(conn, Pleroma.Application.named_version())
- end
-
def emoji(conn, _params) do
emoji =
Enum.reduce(Emoji.get_all(), %{}, fn {code, %Emoji{file: file, tags: tags}}, acc ->