aboutsummaryrefslogtreecommitdiff
path: root/lib/pleroma
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pleroma')
-rw-r--r--lib/pleroma/plugs/http_security_plug.ex9
-rw-r--r--lib/pleroma/upload.ex8
-rw-r--r--lib/pleroma/user.ex47
-rw-r--r--lib/pleroma/web/activity_pub/utils.ex25
-rw-r--r--lib/pleroma/web/admin_api/admin_api_controller.ex22
-rw-r--r--lib/pleroma/web/common_api/common_api.ex13
-rw-r--r--lib/pleroma/web/mastodon_api/mastodon_api_controller.ex69
-rw-r--r--lib/pleroma/web/mastodon_api/subscription_controller.ex71
-rw-r--r--lib/pleroma/web/mastodon_api/views/push_subscription_view.ex5
-rw-r--r--lib/pleroma/web/metadata/utils.ex4
-rw-r--r--lib/pleroma/web/nodeinfo/nodeinfo_controller.ex4
-rw-r--r--lib/pleroma/web/push/impl.ex127
-rw-r--r--lib/pleroma/web/push/push.ex113
-rw-r--r--lib/pleroma/web/push/subscription.ex24
-rw-r--r--lib/pleroma/web/rel_me.ex3
-rw-r--r--lib/pleroma/web/rich_media/helpers.ex14
-rw-r--r--lib/pleroma/web/router.ex9
-rw-r--r--lib/pleroma/web/twitter_api/twitter_api.ex14
-rw-r--r--lib/pleroma/web/twitter_api/twitter_api_controller.ex15
19 files changed, 369 insertions, 227 deletions
diff --git a/lib/pleroma/plugs/http_security_plug.ex b/lib/pleroma/plugs/http_security_plug.ex
index 057553e24..f701aaaa5 100644
--- a/lib/pleroma/plugs/http_security_plug.ex
+++ b/lib/pleroma/plugs/http_security_plug.ex
@@ -34,13 +34,16 @@ defmodule Pleroma.Plugs.HTTPSecurityPlug do
defp csp_string do
scheme = Config.get([Pleroma.Web.Endpoint, :url])[:scheme]
- websocket_url = String.replace(Pleroma.Web.Endpoint.static_url(), "http", "ws")
+ static_url = Pleroma.Web.Endpoint.static_url()
+ websocket_url = String.replace(static_url, "http", "ws")
+
+ connect_src = "connect-src 'self' #{static_url} #{websocket_url}"
connect_src =
if Mix.env() == :dev do
- "connect-src 'self' http://localhost:3035/ " <> websocket_url
+ connect_src <> " http://localhost:3035/"
else
- "connect-src 'self' " <> websocket_url
+ connect_src
end
script_src =
diff --git a/lib/pleroma/upload.ex b/lib/pleroma/upload.ex
index 91a5db8c5..1a97e9fde 100644
--- a/lib/pleroma/upload.ex
+++ b/lib/pleroma/upload.ex
@@ -85,6 +85,10 @@ defmodule Pleroma.Upload do
end
end
+ def char_unescaped?(char) do
+ URI.char_unreserved?(char) or char == ?/
+ end
+
defp get_opts(opts) do
{size_limit, activity_type} =
case Keyword.get(opts, :type) do
@@ -218,9 +222,7 @@ defmodule Pleroma.Upload do
defp url_from_spec(base_url, {:file, path}) do
path =
path
- |> URI.encode()
- |> String.replace("?", "%3F")
- |> String.replace(":", "%3A")
+ |> URI.encode(&char_unescaped?/1)
[base_url, "media", path]
|> Path.join()
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 50e7e7ccd..3878e4efa 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -749,13 +749,41 @@ defmodule Pleroma.User do
Repo.all(query)
end
- @spec search_for_admin(binary(), %{
+ @spec search_for_admin(%{
+ local: boolean(),
+ page: number(),
+ page_size: number()
+ }) :: {:ok, [Pleroma.User.t()], number()}
+ def search_for_admin(%{query: nil, local: local, page: page, page_size: page_size}) do
+ query =
+ from(u in User, order_by: u.id)
+ |> maybe_local_user_query(local)
+
+ paginated_query =
+ query
+ |> paginate(page, page_size)
+
+ count =
+ query
+ |> Repo.aggregate(:count, :id)
+
+ {:ok, Repo.all(paginated_query), count}
+ end
+
+ @spec search_for_admin(%{
+ query: binary(),
admin: Pleroma.User.t(),
local: boolean(),
page: number(),
page_size: number()
}) :: {:ok, [Pleroma.User.t()], number()}
- def search_for_admin(term, %{admin: admin, local: local, page: page, page_size: page_size}) do
+ def search_for_admin(%{
+ query: term,
+ admin: admin,
+ local: local,
+ page: page,
+ page_size: page_size
+ }) do
term = String.trim_leading(term, "@")
local_paginated_query =
@@ -774,21 +802,6 @@ defmodule Pleroma.User do
{:ok, do_search(search_query, admin), count}
end
- @spec all_for_admin(number(), number()) :: {:ok, [Pleroma.User.t()], number()}
- def all_for_admin(page, page_size) do
- query = from(u in User, order_by: u.id)
-
- paginated_query =
- query
- |> paginate(page, page_size)
-
- count =
- query
- |> Repo.aggregate(:count, :id)
-
- {:ok, Repo.all(paginated_query), count}
- end
-
def search(query, resolve \\ false, for_user \\ nil) do
# Strip the beginning @ off if there is a query
query = String.trim_leading(query, "@")
diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex
index 88f4779c8..9e50789db 100644
--- a/lib/pleroma/web/activity_pub/utils.ex
+++ b/lib/pleroma/web/activity_pub/utils.ex
@@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
alias Pleroma.Web
alias Pleroma.Object
alias Pleroma.Activity
+ alias Pleroma.Web.ActivityPub.Visibility
alias Pleroma.User
alias Pleroma.Notification
alias Pleroma.Web.Router.Helpers
@@ -274,13 +275,31 @@ defmodule Pleroma.Web.ActivityPub.Utils do
Repo.all(query)
end
- def make_like_data(%User{ap_id: ap_id} = actor, %{data: %{"id" => id}} = object, activity_id) do
+ def make_like_data(
+ %User{ap_id: ap_id} = actor,
+ %{data: %{"actor" => object_actor_id, "id" => id}} = object,
+ activity_id
+ ) do
+ object_actor = User.get_cached_by_ap_id(object_actor_id)
+
+ to =
+ if Visibility.is_public?(object) do
+ [actor.follower_address, object.data["actor"]]
+ else
+ [object.data["actor"]]
+ end
+
+ cc =
+ (object.data["to"] ++ (object.data["cc"] || []))
+ |> List.delete(actor.ap_id)
+ |> List.delete(object_actor.follower_address)
+
data = %{
"type" => "Like",
"actor" => ap_id,
"object" => id,
- "to" => [actor.follower_address, object.data["actor"]],
- "cc" => ["https://www.w3.org/ns/activitystreams#Public"],
+ "to" => to,
+ "cc" => cc,
"context" => object.data["context"]
}
diff --git a/lib/pleroma/web/admin_api/admin_api_controller.ex b/lib/pleroma/web/admin_api/admin_api_controller.ex
index aae02cab8..75c2c6061 100644
--- a/lib/pleroma/web/admin_api/admin_api_controller.ex
+++ b/lib/pleroma/web/admin_api/admin_api_controller.ex
@@ -63,28 +63,14 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
do: json_response(conn, :no_content, "")
end
- def list_users(conn, params) do
- {page, page_size} = page_params(params)
-
- with {:ok, users, count} <- User.all_for_admin(page, page_size),
- do:
- conn
- |> json(
- AccountView.render("index.json",
- users: users,
- count: count,
- page_size: page_size
- )
- )
- end
-
- def search_users(%{assigns: %{user: admin}} = conn, %{"query" => query} = params) do
+ def list_users(%{assigns: %{user: admin}} = conn, params) do
{page, page_size} = page_params(params)
with {:ok, users, count} <-
- User.search_for_admin(query, %{
+ User.search_for_admin(%{
+ query: params["query"],
admin: admin,
- local: params["local"] == "true",
+ local: params["local_only"] == "true",
page: page,
page_size: page_size
}),
diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex
index 7114d6de6..55a9c2572 100644
--- a/lib/pleroma/web/common_api/common_api.ex
+++ b/lib/pleroma/web/common_api/common_api.ex
@@ -14,6 +14,19 @@ defmodule Pleroma.Web.CommonAPI do
import Pleroma.Web.CommonAPI.Utils
+ def follow(follower, followed) do
+ with {:ok, follower} <- User.maybe_direct_follow(follower, followed),
+ {:ok, activity} <- ActivityPub.follow(follower, followed),
+ {:ok, follower, followed} <-
+ User.wait_and_refresh(
+ Pleroma.Config.get([:activitypub, :follow_handshake_timeout]),
+ follower,
+ followed
+ ) do
+ {:ok, follower, followed, activity}
+ end
+ end
+
def delete(activity_id, user) do
with %Activity{data: %{"object" => %{"id" => object_id}}} <- Repo.get(Activity, activity_id),
%Object{} = object <- Object.normalize(object_id),
diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
index 056be49b0..8c58f4545 100644
--- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
+++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
@@ -15,14 +15,11 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
alias Pleroma.Web
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.MediaProxy
- alias Pleroma.Web.Push
- alias Push.Subscription
alias Pleroma.Web.MastodonAPI.AccountView
alias Pleroma.Web.MastodonAPI.FilterView
alias Pleroma.Web.MastodonAPI.ListView
alias Pleroma.Web.MastodonAPI.MastodonView
- alias Pleroma.Web.MastodonAPI.PushSubscriptionView
alias Pleroma.Web.MastodonAPI.StatusView
alias Pleroma.Web.MastodonAPI.ReportView
alias Pleroma.Web.ActivityPub.ActivityPub
@@ -193,6 +190,11 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
end
defp add_link_headers(conn, method, activities, param \\ nil, params \\ %{}) do
+ params =
+ conn.params
+ |> Map.drop(["since_id", "max_id"])
+ |> Map.merge(params)
+
last = List.last(activities)
first = List.first(activities)
@@ -292,13 +294,17 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
end
def dm_timeline(%{assigns: %{user: user}} = conn, params) do
- query =
- ActivityPub.fetch_activities_query(
- [user.ap_id],
- Map.merge(params, %{"type" => "Create", visibility: "direct"})
- )
+ params =
+ params
+ |> Map.put("type", "Create")
+ |> Map.put("blocking_user", user)
+ |> Map.put("user", user)
+ |> Map.put(:visibility, "direct")
- activities = Repo.all(query)
+ activities =
+ [user.ap_id]
+ |> ActivityPub.fetch_activities_query(params)
+ |> Repo.all()
conn
|> add_link_headers(:dm_timeline, activities)
@@ -733,14 +739,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
def follow(%{assigns: %{user: follower}} = conn, %{"id" => id}) do
with %User{} = followed <- Repo.get(User, id),
- {:ok, follower} <- User.maybe_direct_follow(follower, followed),
- {:ok, _activity} <- ActivityPub.follow(follower, followed),
- {:ok, follower, followed} <-
- User.wait_and_refresh(
- Config.get([:activitypub, :follow_handshake_timeout]),
- follower,
- followed
- ) do
+ {:ok, follower, followed, _} <- CommonAPI.follow(follower, followed) do
conn
|> put_view(AccountView)
|> render("relationship.json", %{user: follower, target: followed})
@@ -754,8 +753,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
def follow(%{assigns: %{user: follower}} = conn, %{"uri" => uri}) do
with %User{} = followed <- Repo.get_by(User, nickname: uri),
- {:ok, follower} <- User.maybe_direct_follow(follower, followed),
- {:ok, _activity} <- ActivityPub.follow(follower, followed) do
+ {:ok, follower, followed, _} <- CommonAPI.follow(follower, followed) do
conn
|> put_view(AccountView)
|> render("account.json", %{user: followed, for: follower})
@@ -1424,37 +1422,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
json(conn, %{})
end
- def create_push_subscription(%{assigns: %{user: user, token: token}} = conn, params) do
- true = Push.enabled()
- Subscription.delete_if_exists(user, token)
- {:ok, subscription} = Subscription.create(user, token, params)
- view = PushSubscriptionView.render("push_subscription.json", subscription: subscription)
- json(conn, view)
- end
-
- def get_push_subscription(%{assigns: %{user: user, token: token}} = conn, _params) do
- true = Push.enabled()
- subscription = Subscription.get(user, token)
- view = PushSubscriptionView.render("push_subscription.json", subscription: subscription)
- json(conn, view)
- end
-
- def update_push_subscription(
- %{assigns: %{user: user, token: token}} = conn,
- params
- ) do
- true = Push.enabled()
- {:ok, subscription} = Subscription.update(user, token, params)
- view = PushSubscriptionView.render("push_subscription.json", subscription: subscription)
- json(conn, view)
- end
-
- def delete_push_subscription(%{assigns: %{user: user, token: token}} = conn, _params) do
- true = Push.enabled()
- {:ok, _response} = Subscription.delete(user, token)
- json(conn, %{})
- end
-
+ # fallback action
+ #
def errors(conn, _) do
conn
|> put_status(500)
diff --git a/lib/pleroma/web/mastodon_api/subscription_controller.ex b/lib/pleroma/web/mastodon_api/subscription_controller.ex
new file mode 100644
index 000000000..b6c8ff808
--- /dev/null
+++ b/lib/pleroma/web/mastodon_api/subscription_controller.ex
@@ -0,0 +1,71 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.MastodonAPI.SubscriptionController do
+ @moduledoc "The module represents functions to manage user subscriptions."
+ use Pleroma.Web, :controller
+
+ alias Pleroma.Web.Push
+ alias Pleroma.Web.Push.Subscription
+ alias Pleroma.Web.MastodonAPI.PushSubscriptionView, as: View
+
+ action_fallback(:errors)
+
+ # Creates PushSubscription
+ # POST /api/v1/push/subscription
+ #
+ def create(%{assigns: %{user: user, token: token}} = conn, params) do
+ with true <- Push.enabled(),
+ {:ok, _} <- Subscription.delete_if_exists(user, token),
+ {:ok, subscription} <- Subscription.create(user, token, params) do
+ view = View.render("push_subscription.json", subscription: subscription)
+ json(conn, view)
+ end
+ end
+
+ # Gets PushSubscription
+ # GET /api/v1/push/subscription
+ #
+ def get(%{assigns: %{user: user, token: token}} = conn, _params) do
+ with true <- Push.enabled(),
+ {:ok, subscription} <- Subscription.get(user, token) do
+ view = View.render("push_subscription.json", subscription: subscription)
+ json(conn, view)
+ end
+ end
+
+ # Updates PushSubscription
+ # PUT /api/v1/push/subscription
+ #
+ def update(%{assigns: %{user: user, token: token}} = conn, params) do
+ with true <- Push.enabled(),
+ {:ok, subscription} <- Subscription.update(user, token, params) do
+ view = View.render("push_subscription.json", subscription: subscription)
+ json(conn, view)
+ end
+ end
+
+ # Deletes PushSubscription
+ # DELETE /api/v1/push/subscription
+ #
+ def delete(%{assigns: %{user: user, token: token}} = conn, _params) do
+ with true <- Push.enabled(),
+ {:ok, _response} <- Subscription.delete(user, token),
+ do: json(conn, %{})
+ end
+
+ # fallback action
+ #
+ def errors(conn, {:error, :not_found}) do
+ conn
+ |> put_status(404)
+ |> json("Not found")
+ end
+
+ def errors(conn, _) do
+ conn
+ |> put_status(500)
+ |> json("Something went wrong")
+ end
+end
diff --git a/lib/pleroma/web/mastodon_api/views/push_subscription_view.ex b/lib/pleroma/web/mastodon_api/views/push_subscription_view.ex
index e86b789c5..021489711 100644
--- a/lib/pleroma/web/mastodon_api/views/push_subscription_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/push_subscription_view.ex
@@ -4,6 +4,7 @@
defmodule Pleroma.Web.MastodonAPI.PushSubscriptionView do
use Pleroma.Web, :view
+ alias Pleroma.Web.Push
def render("push_subscription.json", %{subscription: subscription}) do
%{
@@ -14,7 +15,5 @@ defmodule Pleroma.Web.MastodonAPI.PushSubscriptionView do
}
end
- defp server_key do
- Keyword.get(Application.get_env(:web_push_encryption, :vapid_details), :public_key)
- end
+ defp server_key, do: Keyword.get(Push.vapid_config(), :public_key)
end
diff --git a/lib/pleroma/web/metadata/utils.ex b/lib/pleroma/web/metadata/utils.ex
index a166800d4..5fc9c9e7b 100644
--- a/lib/pleroma/web/metadata/utils.ex
+++ b/lib/pleroma/web/metadata/utils.ex
@@ -17,14 +17,14 @@ defmodule Pleroma.Web.Metadata.Utils do
|> Formatter.truncate()
end
- def scrub_html_and_truncate(content) when is_binary(content) do
+ def scrub_html_and_truncate(content, max_length \\ 200) when is_binary(content) do
content
# html content comes from DB already encoded, decode first and scrub after
|> HtmlEntities.decode()
|> String.replace(~r/<br\s?\/?>/, " ")
|> HTML.strip_tags()
|> Formatter.demojify()
- |> Formatter.truncate()
+ |> Formatter.truncate(max_length)
end
def attachment_url(url) do
diff --git a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex
index f4867d05b..8c775ce24 100644
--- a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex
+++ b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex
@@ -6,7 +6,6 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do
use Pleroma.Web, :controller
alias Pleroma.Config
- alias Pleroma.Repo
alias Pleroma.Stats
alias Pleroma.User
alias Pleroma.Web
@@ -86,8 +85,7 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do
end
staff_accounts =
- User.moderator_user_query()
- |> Repo.all()
+ User.all_superusers()
|> Enum.map(fn u -> u.ap_id end)
mrf_user_allowlist =
diff --git a/lib/pleroma/web/push/impl.ex b/lib/pleroma/web/push/impl.ex
new file mode 100644
index 000000000..33f912d34
--- /dev/null
+++ b/lib/pleroma/web/push/impl.ex
@@ -0,0 +1,127 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.Push.Impl do
+ @moduledoc "The module represents implementation push web notification"
+
+ alias Pleroma.Repo
+ alias Pleroma.User
+ alias Pleroma.Activity
+ alias Pleroma.Object
+ alias Pleroma.Web.Push.Subscription
+ alias Pleroma.Web.Metadata.Utils
+ alias Pleroma.Notification
+
+ require Logger
+ import Ecto.Query
+
+ @types ["Create", "Follow", "Announce", "Like"]
+
+ @doc "Performs sending notifications for user subscriptions"
+ @spec perform_send(Notification.t()) :: list(any)
+ def perform_send(%{activity: %{data: %{"type" => activity_type}}, user_id: user_id} = notif)
+ when activity_type in @types do
+ actor = User.get_cached_by_ap_id(notif.activity.data["actor"])
+
+ type = Activity.mastodon_notification_type(notif.activity)
+ gcm_api_key = Application.get_env(:web_push_encryption, :gcm_api_key)
+ avatar_url = User.avatar_url(actor)
+
+ for subscription <- fetch_subsriptions(user_id),
+ get_in(subscription.data, ["alerts", type]) do
+ %{
+ title: format_title(notif),
+ access_token: subscription.token.token,
+ body: format_body(notif, actor),
+ notification_id: notif.id,
+ notification_type: type,
+ icon: avatar_url,
+ preferred_locale: "en"
+ }
+ |> Jason.encode!()
+ |> push_message(build_sub(subscription), gcm_api_key, subscription)
+ end
+ end
+
+ def perform_send(_) do
+ Logger.warn("Unknown notification type")
+ :error
+ end
+
+ @doc "Push message to web"
+ def push_message(body, sub, api_key, subscription) do
+ case WebPushEncryption.send_web_push(body, sub, api_key) do
+ {:ok, %{status_code: code}} when 400 <= code and code < 500 ->
+ Logger.debug("Removing subscription record")
+ Repo.delete!(subscription)
+ :ok
+
+ {:ok, %{status_code: code}} when 200 <= code and code < 300 ->
+ :ok
+
+ {:ok, %{status_code: code}} ->
+ Logger.error("Web Push Notification failed with code: #{code}")
+ :error
+
+ _ ->
+ Logger.error("Web Push Notification failed with unknown error")
+ :error
+ end
+ end
+
+ @doc "Gets user subscriptions"
+ def fetch_subsriptions(user_id) do
+ Subscription
+ |> where(user_id: ^user_id)
+ |> preload(:token)
+ |> Repo.all()
+ end
+
+ def build_sub(subscription) do
+ %{
+ keys: %{
+ p256dh: subscription.key_p256dh,
+ auth: subscription.key_auth
+ },
+ endpoint: subscription.endpoint
+ }
+ end
+
+ def format_body(
+ %{activity: %{data: %{"type" => "Create", "object" => %{"content" => content}}}},
+ actor
+ ) do
+ "@#{actor.nickname}: #{Utils.scrub_html_and_truncate(content, 80)}"
+ end
+
+ def format_body(
+ %{activity: %{data: %{"type" => "Announce", "object" => activity_id}}},
+ actor
+ ) do
+ %Activity{data: %{"object" => %{"id" => object_id}}} = Activity.get_by_ap_id(activity_id)
+ %Object{data: %{"content" => content}} = Object.get_by_ap_id(object_id)
+
+ "@#{actor.nickname} repeated: #{Utils.scrub_html_and_truncate(content, 80)}"
+ end
+
+ def format_body(
+ %{activity: %{data: %{"type" => type}}},
+ actor
+ )
+ when type in ["Follow", "Like"] do
+ case type do
+ "Follow" -> "@#{actor.nickname} has followed you"
+ "Like" -> "@#{actor.nickname} has favorited your post"
+ end
+ end
+
+ def format_title(%{activity: %{data: %{"type" => type}}}) do
+ case type do
+ "Create" -> "New Mention"
+ "Follow" -> "New Follower"
+ "Announce" -> "New Repeat"
+ "Like" -> "New Favorite"
+ end
+ end
+end
diff --git a/lib/pleroma/web/push/push.ex b/lib/pleroma/web/push/push.ex
index ddd4fe037..951dab535 100644
--- a/lib/pleroma/web/push/push.ex
+++ b/lib/pleroma/web/push/push.ex
@@ -5,14 +5,13 @@
defmodule Pleroma.Web.Push do
use GenServer
- alias Pleroma.Repo
- alias Pleroma.User
- alias Pleroma.Web.Push.Subscription
+ alias Pleroma.Web.Push.Impl
require Logger
- import Ecto.Query
- @types ["Create", "Follow", "Announce", "Like"]
+ ##############
+ # Client API #
+ ##############
def start_link() do
GenServer.start_link(__MODULE__, :ok, name: __MODULE__)
@@ -30,14 +29,18 @@ defmodule Pleroma.Web.Push do
end
end
- def send(notification) do
- if enabled() do
- GenServer.cast(Pleroma.Web.Push, {:send, notification})
- end
- end
+ def send(notification),
+ do: GenServer.cast(__MODULE__, {:send, notification})
+
+ ####################
+ # Server Callbacks #
+ ####################
+ @impl true
def init(:ok) do
- if !enabled() do
+ if enabled() do
+ {:ok, nil}
+ else
Logger.warn("""
VAPID key pair is not found. If you wish to enabled web push, please run
@@ -47,93 +50,15 @@ defmodule Pleroma.Web.Push do
""")
:ignore
- else
- {:ok, nil}
end
end
- def handle_cast(
- {:send, %{activity: %{data: %{"type" => type}}, user_id: user_id} = notification},
- state
- )
- when type in @types do
- actor = User.get_cached_by_ap_id(notification.activity.data["actor"])
-
- type = Pleroma.Activity.mastodon_notification_type(notification.activity)
-
- Subscription
- |> where(user_id: ^user_id)
- |> preload(:token)
- |> Repo.all()
- |> Enum.filter(fn subscription ->
- get_in(subscription.data, ["alerts", type]) || false
- end)
- |> Enum.each(fn subscription ->
- sub = %{
- keys: %{
- p256dh: subscription.key_p256dh,
- auth: subscription.key_auth
- },
- endpoint: subscription.endpoint
- }
-
- body =
- Jason.encode!(%{
- title: format_title(notification),
- access_token: subscription.token.token,
- body: format_body(notification, actor),
- notification_id: notification.id,
- notification_type: type,
- icon: User.avatar_url(actor),
- preferred_locale: "en"
- })
-
- case WebPushEncryption.send_web_push(
- body,
- sub,
- Application.get_env(:web_push_encryption, :gcm_api_key)
- ) do
- {:ok, %{status_code: code}} when 400 <= code and code < 500 ->
- Logger.debug("Removing subscription record")
- Repo.delete!(subscription)
- :ok
-
- {:ok, %{status_code: code}} when 200 <= code and code < 300 ->
- :ok
-
- {:ok, %{status_code: code}} ->
- Logger.error("Web Push Notification failed with code: #{code}")
- :error
-
- _ ->
- Logger.error("Web Push Notification failed with unknown error")
- :error
- end
- end)
-
- {:noreply, state}
- end
-
- def handle_cast({:send, _}, state) do
- Logger.warn("Unknown notification type")
- {:noreply, state}
- end
-
- defp format_title(%{activity: %{data: %{"type" => type}}}) do
- case type do
- "Create" -> "New Mention"
- "Follow" -> "New Follower"
- "Announce" -> "New Repeat"
- "Like" -> "New Favorite"
+ @impl true
+ def handle_cast({:send, notification}, state) do
+ if enabled() do
+ Impl.perform_send(notification)
end
- end
- defp format_body(%{activity: %{data: %{"type" => type}}}, actor) do
- case type do
- "Create" -> "@#{actor.nickname} has mentioned you"
- "Follow" -> "@#{actor.nickname} has followed you"
- "Announce" -> "@#{actor.nickname} has repeated your post"
- "Like" -> "@#{actor.nickname} has favorited your post"
- end
+ {:noreply, state}
end
end
diff --git a/lib/pleroma/web/push/subscription.ex b/lib/pleroma/web/push/subscription.ex
index 242e30910..c90bd2bda 100644
--- a/lib/pleroma/web/push/subscription.ex
+++ b/lib/pleroma/web/push/subscription.ex
@@ -12,6 +12,8 @@ defmodule Pleroma.Web.Push.Subscription do
alias Pleroma.Web.OAuth.Token
alias Pleroma.Web.Push.Subscription
+ @type t :: %__MODULE__{}
+
schema "push_subscriptions" do
belongs_to(:user, User, type: Pleroma.FlakeId)
belongs_to(:token, Token)
@@ -50,24 +52,32 @@ defmodule Pleroma.Web.Push.Subscription do
})
end
+ @doc "Gets subsciption by user & token"
+ @spec get(User.t(), Token.t()) :: {:ok, t()} | {:error, :not_found}
def get(%User{id: user_id}, %Token{id: token_id}) do
- Repo.get_by(Subscription, user_id: user_id, token_id: token_id)
+ case Repo.get_by(Subscription, user_id: user_id, token_id: token_id) do
+ nil -> {:error, :not_found}
+ subscription -> {:ok, subscription}
+ end
end
def update(user, token, params) do
- get(user, token)
- |> change(data: alerts(params))
- |> Repo.update()
+ with {:ok, subscription} <- get(user, token) do
+ subscription
+ |> change(data: alerts(params))
+ |> Repo.update()
+ end
end
def delete(user, token) do
- Repo.delete(get(user, token))
+ with {:ok, subscription} <- get(user, token),
+ do: Repo.delete(subscription)
end
def delete_if_exists(user, token) do
case get(user, token) do
- nil -> {:ok, nil}
- sub -> Repo.delete(sub)
+ {:error, _} -> {:ok, nil}
+ {:ok, sub} -> Repo.delete(sub)
end
end
diff --git a/lib/pleroma/web/rel_me.ex b/lib/pleroma/web/rel_me.ex
index a07db966f..ab29a36e3 100644
--- a/lib/pleroma/web/rel_me.ex
+++ b/lib/pleroma/web/rel_me.ex
@@ -28,7 +28,8 @@ defmodule Pleroma.Web.RelMe do
{:ok, %Tesla.Env{body: html}} = Pleroma.HTTP.get(url, [], adapter: @hackney_options)
data =
- Floki.attribute(html, "link[rel=me]", "href") ++ Floki.attribute(html, "a[rel=me]", "href")
+ Floki.attribute(html, "link[rel~=me]", "href") ++
+ Floki.attribute(html, "a[rel~=me]", "href")
{:ok, data}
rescue
diff --git a/lib/pleroma/web/rich_media/helpers.ex b/lib/pleroma/web/rich_media/helpers.ex
index abb1cf7f2..8317a1162 100644
--- a/lib/pleroma/web/rich_media/helpers.ex
+++ b/lib/pleroma/web/rich_media/helpers.ex
@@ -8,10 +8,24 @@ defmodule Pleroma.Web.RichMedia.Helpers do
alias Pleroma.HTML
alias Pleroma.Web.RichMedia.Parser
+ defp validate_page_url(page_url) when is_binary(page_url) do
+ if AutoLinker.Parser.is_url?(page_url, true) do
+ URI.parse(page_url) |> validate_page_url
+ else
+ :error
+ end
+ end
+
+ defp validate_page_url(%URI{authority: nil}), do: :error
+ defp validate_page_url(%URI{scheme: nil}), do: :error
+ defp validate_page_url(%URI{}), do: :ok
+ defp validate_page_url(_), do: :error
+
def fetch_data_for_activity(%Activity{} = activity) do
with true <- Pleroma.Config.get([:rich_media, :enabled]),
%Object{} = object <- Object.normalize(activity.data["object"]),
{:ok, page_url} <- HTML.extract_first_external_url(object, object.data["content"]),
+ :ok <- validate_page_url(page_url),
{:ok, rich_media} <- Parser.parse(page_url) do
%{page_url: page_url, rich_media: rich_media}
else
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index 6fcb46878..65a90e31e 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -140,7 +140,6 @@ defmodule Pleroma.Web.Router do
pipe_through([:admin_api, :oauth_write])
get("/users", AdminAPIController, :list_users)
- get("/users/search", AdminAPIController, :search_users)
delete("/user", AdminAPIController, :user_delete)
patch("/users/:nickname/toggle_activation", AdminAPIController, :user_toggle_activation)
post("/user", AdminAPIController, :user_create)
@@ -304,10 +303,10 @@ defmodule Pleroma.Web.Router do
scope [] do
pipe_through(:oauth_push)
- post("/push/subscription", MastodonAPIController, :create_push_subscription)
- get("/push/subscription", MastodonAPIController, :get_push_subscription)
- put("/push/subscription", MastodonAPIController, :update_push_subscription)
- delete("/push/subscription", MastodonAPIController, :delete_push_subscription)
+ post("/push/subscription", SubscriptionController, :create)
+ get("/push/subscription", SubscriptionController, :get)
+ put("/push/subscription", SubscriptionController, :update)
+ delete("/push/subscription", SubscriptionController, :delete)
end
end
diff --git a/lib/pleroma/web/twitter_api/twitter_api.ex b/lib/pleroma/web/twitter_api/twitter_api.ex
index ab6470d78..dcb15b9a9 100644
--- a/lib/pleroma/web/twitter_api/twitter_api.ex
+++ b/lib/pleroma/web/twitter_api/twitter_api.ex
@@ -28,18 +28,8 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
end
def follow(%User{} = follower, params) do
- with {:ok, %User{} = followed} <- get_user(params),
- {:ok, follower} <- User.maybe_direct_follow(follower, followed),
- {:ok, activity} <- ActivityPub.follow(follower, followed),
- {:ok, follower, followed} <-
- User.wait_and_refresh(
- Pleroma.Config.get([:activitypub, :follow_handshake_timeout]),
- follower,
- followed
- ) do
- {:ok, follower, followed, activity}
- else
- err -> err
+ with {:ok, %User{} = followed} <- get_user(params) do
+ CommonAPI.follow(follower, followed)
end
end
diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex
index de7b9f24c..5e4ebb8e8 100644
--- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex
+++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex
@@ -177,13 +177,16 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
end
def dm_timeline(%{assigns: %{user: user}} = conn, params) do
- query =
- ActivityPub.fetch_activities_query(
- [user.ap_id],
- Map.merge(params, %{"type" => "Create", "user" => user, visibility: "direct"})
- )
+ params =
+ params
+ |> Map.put("type", "Create")
+ |> Map.put("blocking_user", user)
+ |> Map.put("user", user)
+ |> Map.put(:visibility, "direct")
- activities = Repo.all(query)
+ activities =
+ ActivityPub.fetch_activities_query([user.ap_id], params)
+ |> Repo.all()
conn
|> put_view(ActivityView)