aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/mix/tasks/pleroma/instance.ex17
-rw-r--r--lib/mix/tasks/pleroma/sample_config.eex2
-rw-r--r--lib/pleroma/activity.ex60
-rw-r--r--lib/pleroma/emails/admin_email.ex9
-rw-r--r--lib/pleroma/emails/mailer.ex2
-rw-r--r--lib/pleroma/emails/user_email.ex5
-rw-r--r--lib/pleroma/formatter.ex42
-rw-r--r--lib/pleroma/notification.ex11
-rw-r--r--lib/pleroma/pagination.ex6
-rw-r--r--lib/pleroma/user.ex6
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub.ex52
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub_controller.ex7
-rw-r--r--lib/pleroma/web/activity_pub/transmogrifier.ex3
-rw-r--r--lib/pleroma/web/activity_pub/utils.ex7
-rw-r--r--lib/pleroma/web/admin_api/admin_api_controller.ex9
-rw-r--r--lib/pleroma/web/common_api/utils.ex6
-rw-r--r--lib/pleroma/web/endpoint.ex13
-rw-r--r--lib/pleroma/web/mastodon_api/mastodon_api_controller.ex59
-rw-r--r--lib/pleroma/web/mastodon_api/views/status_view.ex20
-rw-r--r--lib/pleroma/web/rel_me.ex3
-rw-r--r--lib/pleroma/web/rich_media/parser.ex3
-rw-r--r--lib/pleroma/web/router.ex4
-rw-r--r--lib/pleroma/web/templates/layout/app.html.eex11
-rw-r--r--lib/pleroma/web/templates/twitter_api/util/password_reset.html.eex19
-rw-r--r--lib/pleroma/web/twitter_api/controllers/util_controller.ex7
-rw-r--r--lib/pleroma/web/twitter_api/twitter_api.ex4
-rw-r--r--lib/pleroma/web/twitter_api/views/activity_view.ex2
27 files changed, 250 insertions, 139 deletions
diff --git a/lib/mix/tasks/pleroma/instance.ex b/lib/mix/tasks/pleroma/instance.ex
index 8f8d86a11..6cee8d630 100644
--- a/lib/mix/tasks/pleroma/instance.ex
+++ b/lib/mix/tasks/pleroma/instance.ex
@@ -24,10 +24,12 @@ defmodule Mix.Tasks.Pleroma.Instance do
- `--domain DOMAIN` - the domain of your instance
- `--instance-name INSTANCE_NAME` - the name of your instance
- `--admin-email ADMIN_EMAIL` - the email address of the instance admin
+ - `--notify-email NOTIFY_EMAIL` - email address for notifications
- `--dbhost HOSTNAME` - the hostname of the PostgreSQL database to use
- `--dbname DBNAME` - the name of the database to use
- `--dbuser DBUSER` - the user (aka role) to use for the database connection
- `--dbpass DBPASS` - the password to use for the database connection
+ - `--indexable Y/N` - Allow/disallow indexing site by search engines
"""
def run(["gen" | rest]) do
@@ -41,10 +43,12 @@ defmodule Mix.Tasks.Pleroma.Instance do
domain: :string,
instance_name: :string,
admin_email: :string,
+ notify_email: :string,
dbhost: :string,
dbname: :string,
dbuser: :string,
- dbpass: :string
+ dbpass: :string,
+ indexable: :string
],
aliases: [
o: :output,
@@ -61,7 +65,7 @@ defmodule Mix.Tasks.Pleroma.Instance do
will_overwrite = Enum.filter(paths, &File.exists?/1)
proceed? = Enum.empty?(will_overwrite) or Keyword.get(options, :force, false)
- unless not proceed? do
+ if proceed? do
[domain, port | _] =
String.split(
Common.get_option(
@@ -81,6 +85,14 @@ defmodule Mix.Tasks.Pleroma.Instance do
email = Common.get_option(options, :admin_email, "What is your admin email address?")
+ notify_email =
+ Common.get_option(
+ options,
+ :notify_email,
+ "What email address do you want to use for sending email notifications?",
+ email
+ )
+
indexable =
Common.get_option(
options,
@@ -122,6 +134,7 @@ defmodule Mix.Tasks.Pleroma.Instance do
domain: domain,
port: port,
email: email,
+ notify_email: notify_email,
name: name,
dbhost: dbhost,
dbname: dbname,
diff --git a/lib/mix/tasks/pleroma/sample_config.eex b/lib/mix/tasks/pleroma/sample_config.eex
index 1c935c0d8..52bd57cb7 100644
--- a/lib/mix/tasks/pleroma/sample_config.eex
+++ b/lib/mix/tasks/pleroma/sample_config.eex
@@ -13,6 +13,7 @@ config :pleroma, Pleroma.Web.Endpoint,
config :pleroma, :instance,
name: "<%= name %>",
email: "<%= email %>",
+ notify_email: "<%= notify_email %>",
limit: 5000,
registrations_open: true,
dedupe_media: false
@@ -75,4 +76,3 @@ config :web_push_encryption, :vapid_details,
# storage_url: "https://swift-endpoint.prodider.com/v1/AUTH_<tenant>/<container>",
# object_url: "https://cdn-endpoint.provider.com/<container>"
#
-
diff --git a/lib/pleroma/activity.ex b/lib/pleroma/activity.ex
index ab8861b27..e6507e5ca 100644
--- a/lib/pleroma/activity.ex
+++ b/lib/pleroma/activity.ex
@@ -246,20 +246,22 @@ defmodule Pleroma.Activity do
|> Repo.all()
end
- def increase_replies_count(id) do
- Activity
- |> where(id: ^id)
- |> update([a],
- set: [
- data:
- fragment(
- """
- jsonb_set(?, '{object, repliesCount}',
- (coalesce((?->'object'->>'repliesCount')::int, 0) + 1)::varchar::jsonb, true)
- """,
- a.data,
- a.data
- )
+ def increase_replies_count(nil), do: nil
+
+ def increase_replies_count(object_ap_id) do
+ from(a in create_by_object_ap_id(object_ap_id),
+ update: [
+ set: [
+ data:
+ fragment(
+ """
+ jsonb_set(?, '{object, repliesCount}',
+ (coalesce((?->'object'->>'repliesCount')::int, 0) + 1)::varchar::jsonb, true)
+ """,
+ a.data,
+ a.data
+ )
+ ]
]
)
|> Repo.update_all([])
@@ -269,20 +271,22 @@ defmodule Pleroma.Activity do
end
end
- def decrease_replies_count(id) do
- Activity
- |> where(id: ^id)
- |> update([a],
- set: [
- data:
- fragment(
- """
- jsonb_set(?, '{object, repliesCount}',
- (greatest(0, (?->'object'->>'repliesCount')::int - 1))::varchar::jsonb, true)
- """,
- a.data,
- a.data
- )
+ def decrease_replies_count(nil), do: nil
+
+ def decrease_replies_count(object_ap_id) do
+ from(a in create_by_object_ap_id(object_ap_id),
+ update: [
+ set: [
+ data:
+ fragment(
+ """
+ jsonb_set(?, '{object, repliesCount}',
+ (greatest(0, (?->'object'->>'repliesCount')::int - 1))::varchar::jsonb, true)
+ """,
+ a.data,
+ a.data
+ )
+ ]
]
)
|> Repo.update_all([])
diff --git a/lib/pleroma/emails/admin_email.ex b/lib/pleroma/emails/admin_email.ex
index afefccec5..df0f72f96 100644
--- a/lib/pleroma/emails/admin_email.ex
+++ b/lib/pleroma/emails/admin_email.ex
@@ -2,7 +2,7 @@
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
-defmodule Pleroma.AdminEmail do
+defmodule Pleroma.Emails.AdminEmail do
@moduledoc "Admin emails"
import Swoosh.Email
@@ -11,7 +11,10 @@ defmodule Pleroma.AdminEmail do
defp instance_config, do: Pleroma.Config.get(:instance)
defp instance_name, do: instance_config()[:name]
- defp instance_email, do: instance_config()[:email]
+
+ defp instance_notify_email do
+ Keyword.get(instance_config(), :notify_email, instance_config()[:email])
+ end
defp user_url(user) do
Helpers.o_status_url(Pleroma.Web.Endpoint, :feed_redirect, user.nickname)
@@ -59,7 +62,7 @@ defmodule Pleroma.AdminEmail do
new()
|> to({to.name, to.email})
- |> from({instance_name(), instance_email()})
+ |> from({instance_name(), instance_notify_email()})
|> reply_to({reporter.name, reporter.email})
|> subject("#{instance_name()} Report")
|> html_body(html_body)
diff --git a/lib/pleroma/emails/mailer.ex b/lib/pleroma/emails/mailer.ex
index b384e6fec..53f5a661c 100644
--- a/lib/pleroma/emails/mailer.ex
+++ b/lib/pleroma/emails/mailer.ex
@@ -2,7 +2,7 @@
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
-defmodule Pleroma.Mailer do
+defmodule Pleroma.Emails.Mailer do
use Swoosh.Mailer, otp_app: :pleroma
def deliver_async(email, config \\ []) do
diff --git a/lib/pleroma/emails/user_email.ex b/lib/pleroma/emails/user_email.ex
index a3a09e96c..8502a0d0c 100644
--- a/lib/pleroma/emails/user_email.ex
+++ b/lib/pleroma/emails/user_email.ex
@@ -2,7 +2,7 @@
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
-defmodule Pleroma.UserEmail do
+defmodule Pleroma.Emails.UserEmail do
@moduledoc "User emails"
import Swoosh.Email
@@ -15,7 +15,8 @@ defmodule Pleroma.UserEmail do
defp instance_name, do: instance_config()[:name]
defp sender do
- {instance_name(), instance_config()[:email]}
+ email = Keyword.get(instance_config(), :notify_email, instance_config()[:email])
+ {instance_name(), email}
end
defp recipient(email, nil), do: email
diff --git a/lib/pleroma/formatter.ex b/lib/pleroma/formatter.ex
index 8ea9dbd38..dab8910c1 100644
--- a/lib/pleroma/formatter.ex
+++ b/lib/pleroma/formatter.ex
@@ -9,20 +9,31 @@ defmodule Pleroma.Formatter do
alias Pleroma.Web.MediaProxy
@safe_mention_regex ~r/^(\s*(?<mentions>@.+?\s+)+)(?<rest>.*)/
+ @link_regex ~r"((?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~%:/?#[\]@!\$&'\(\)\*\+,;=.]+)|[0-9a-z+\-\.]+:[0-9a-z$-_.+!*'(),]+"ui
@markdown_characters_regex ~r/(`|\*|_|{|}|[|]|\(|\)|#|\+|-|\.|!)/
- @link_regex ~r{((?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~%:/?#[\]@!\$&'\(\)\*\+,;=.]+)|[0-9a-z+\-\.]+:[0-9a-z$-_.+!*'(),]+}ui
- # credo:disable-for-previous-line Credo.Check.Readability.MaxLineLength
@auto_linker_config hashtag: true,
hashtag_handler: &Pleroma.Formatter.hashtag_handler/4,
mention: true,
mention_handler: &Pleroma.Formatter.mention_handler/4
+ def escape_mention_handler("@" <> nickname = mention, buffer, _, _) do
+ case User.get_cached_by_nickname(nickname) do
+ %User{} ->
+ # escape markdown characters with `\\`
+ # (we don't want something like @user__name to be parsed by markdown)
+ String.replace(mention, @markdown_characters_regex, "\\\\\\1")
+
+ _ ->
+ buffer
+ end
+ end
+
def mention_handler("@" <> nickname, buffer, opts, acc) do
case User.get_cached_by_nickname(nickname) do
%User{id: id} = user ->
ap_id = get_ap_id(user)
- nickname_text = get_nickname_text(nickname, opts) |> maybe_escape(opts)
+ nickname_text = get_nickname_text(nickname, opts)
link =
"<span class='h-card'><a data-user='#{id}' class='u-url mention' href='#{ap_id}'>@<span>#{
@@ -70,6 +81,25 @@ defmodule Pleroma.Formatter do
end
end
+ @doc """
+ Escapes a special characters in mention names.
+ """
+ def mentions_escape(text, options \\ []) do
+ options =
+ Keyword.merge(options,
+ mention: true,
+ url: false,
+ mention_handler: &Pleroma.Formatter.escape_mention_handler/4
+ )
+
+ if options[:safe_mention] && Regex.named_captures(@safe_mention_regex, text) do
+ %{"mentions" => mentions, "rest" => rest} = Regex.named_captures(@safe_mention_regex, text)
+ AutoLinker.link(mentions, options) <> AutoLinker.link(rest, options)
+ else
+ AutoLinker.link(text, options)
+ end
+ end
+
def emojify(text) do
emojify(text, Emoji.get_all())
end
@@ -140,10 +170,4 @@ defmodule Pleroma.Formatter do
defp get_nickname_text(nickname, %{mentions_format: :full}), do: User.full_nickname(nickname)
defp get_nickname_text(nickname, _), do: User.local_nickname(nickname)
-
- defp maybe_escape(str, %{mentions_escape: true}) do
- String.replace(str, @markdown_characters_regex, "\\\\\\1")
- end
-
- defp maybe_escape(str, _), do: str
end
diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex
index 15789907a..b357d5399 100644
--- a/lib/pleroma/notification.ex
+++ b/lib/pleroma/notification.ex
@@ -98,6 +98,14 @@ defmodule Pleroma.Notification do
|> Repo.delete_all()
end
+ def destroy_multiple(%{id: user_id} = _user, ids) do
+ from(n in Notification,
+ where: n.id in ^ids,
+ where: n.user_id == ^user_id
+ )
+ |> Repo.delete_all()
+ end
+
def dismiss(%{id: user_id} = _user, id) do
notification = Repo.get(Notification, id)
@@ -173,8 +181,7 @@ defmodule Pleroma.Notification do
def skip?(:muted, activity, user) do
actor = activity.data["actor"]
- User.mutes?(user, %{ap_id: actor}) or
- CommonAPI.thread_muted?(user, activity)
+ User.mutes?(user, %{ap_id: actor}) or CommonAPI.thread_muted?(user, activity)
end
def skip?(
diff --git a/lib/pleroma/pagination.ex b/lib/pleroma/pagination.ex
index 7c864deef..f435e5c9c 100644
--- a/lib/pleroma/pagination.ex
+++ b/lib/pleroma/pagination.ex
@@ -36,6 +36,12 @@ defmodule Pleroma.Pagination do
limit: :integer
}
+ params =
+ Enum.reduce(params, %{}, fn
+ {key, _value}, acc when is_atom(key) -> Map.drop(acc, [key])
+ {key, value}, acc -> Map.put(acc, key, value)
+ end)
+
changeset = cast({%{}, param_types}, params, Map.keys(param_types))
changeset.changes
end
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 6e2269aff..78eb29ddd 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -279,8 +279,10 @@ defmodule Pleroma.User do
if user.info.confirmation_pending &&
Pleroma.Config.get([:instance, :account_activation_required]) do
user
- |> Pleroma.UserEmail.account_confirmation_email()
- |> Pleroma.Mailer.deliver_async()
+ |> Pleroma.Emails.UserEmail.account_confirmation_email()
+ |> Pleroma.Emails.Mailer.deliver_async()
+
+ {:ok, :enqueued}
else
{:ok, :noop}
end
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index f217e7bac..cb88ba308 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
alias Pleroma.Instances
alias Pleroma.Notification
alias Pleroma.Object
+ alias Pleroma.Pagination
alias Pleroma.Repo
alias Pleroma.Upload
alias Pleroma.User
@@ -90,12 +91,11 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
end
def increase_replies_count_if_reply(%{
- "object" =>
- %{"inReplyTo" => reply_ap_id, "inReplyToStatusId" => reply_status_id} = object,
+ "object" => %{"inReplyTo" => reply_ap_id} = object,
"type" => "Create"
}) do
if is_public?(object) do
- Activity.increase_replies_count(reply_status_id)
+ Activity.increase_replies_count(reply_ap_id)
Object.increase_replies_count(reply_ap_id)
end
end
@@ -103,10 +103,10 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
def increase_replies_count_if_reply(_create_data), do: :noop
def decrease_replies_count_if_reply(%Object{
- data: %{"inReplyTo" => reply_ap_id, "inReplyToStatusId" => reply_status_id} = object
+ data: %{"inReplyTo" => reply_ap_id} = object
}) do
if is_public?(object) do
- Activity.decrease_replies_count(reply_status_id)
+ Activity.decrease_replies_count(reply_ap_id)
Object.decrease_replies_count(reply_ap_id)
end
end
@@ -449,8 +449,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
:ok <- maybe_federate(activity) do
Enum.each(User.all_superusers(), fn superuser ->
superuser
- |> Pleroma.AdminEmail.report(actor, account, statuses, content)
- |> Pleroma.Mailer.deliver_async()
+ |> Pleroma.Emails.AdminEmail.report(actor, account, statuses, content)
+ |> Pleroma.Emails.Mailer.deliver_async()
end)
{:ok, activity}
@@ -493,7 +493,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
q
|> restrict_unlisted()
- |> Repo.all()
+ |> Pagination.fetch_paginated(opts)
|> Enum.reverse()
end
@@ -636,26 +636,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
)
end
- defp restrict_limit(query, %{"limit" => limit}) do
- from(activity in query, limit: ^limit)
- end
-
- defp restrict_limit(query, _), do: query
-
defp restrict_local(query, %{"local_only" => true}) do
from(activity in query, where: activity.local == true)
end
defp restrict_local(query, _), do: query
- defp restrict_max(query, %{"max_id" => ""}), do: query
-
- defp restrict_max(query, %{"max_id" => max_id}) do
- from(activity in query, where: activity.id < ^max_id)
- end
-
- defp restrict_max(query, _), do: query
-
defp restrict_actor(query, %{"actor_id" => actor_id}) do
from(activity in query, where: activity.actor == ^actor_id)
end
@@ -726,7 +712,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
from(
activity in query,
where: fragment("not (? = ANY(?))", activity.actor, ^blocks),
- where: fragment("not (?->'to' \\?| ?)", activity.data, ^blocks),
+ where: fragment("not (? && ?)", activity.recipients, ^blocks),
+ where:
+ fragment(
+ "not (?->>'type' = 'Announce' and ?->'to' \\?| ?)",
+ activity.data,
+ activity.data,
+ ^blocks
+ ),
where: fragment("not (split_part(?, '/', 3) = ANY(?))", activity.actor, ^domain_blocks)
)
end
@@ -776,12 +769,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
end
def fetch_activities_query(recipients, opts \\ %{}) do
- base_query =
- from(
- activity in Activity,
- limit: 20,
- order_by: [fragment("? desc nulls last", activity.id)]
- )
+ base_query = from(activity in Activity)
base_query
|> maybe_preload_objects(opts)
@@ -791,8 +779,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|> restrict_tag_all(opts)
|> restrict_since(opts)
|> restrict_local(opts)
- |> restrict_limit(opts)
- |> restrict_max(opts)
|> restrict_actor(opts)
|> restrict_type(opts)
|> restrict_favorited_by(opts)
@@ -808,14 +794,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
def fetch_activities(recipients, opts \\ %{}) do
fetch_activities_query(recipients, opts)
- |> Repo.all()
+ |> Pagination.fetch_paginated(opts)
|> Enum.reverse()
end
def fetch_activities_bounded(recipients_to, recipients_cc, opts \\ %{}) do
fetch_activities_query([], opts)
|> restrict_to_cc(recipients_to, recipients_cc)
- |> Repo.all()
+ |> Pagination.fetch_paginated(opts)
|> Enum.reverse()
end
diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
index 7091d6927..3331ebebd 100644
--- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
@@ -153,9 +153,10 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
end
def inbox(%{assigns: %{valid_signature: true}} = conn, %{"nickname" => nickname} = params) do
- with %User{} = user <- User.get_cached_by_nickname(nickname),
- true <- Utils.recipient_in_message(user.ap_id, params),
- params <- Utils.maybe_splice_recipient(user.ap_id, params) do
+ with %User{} = recipient <- User.get_cached_by_nickname(nickname),
+ %User{} = actor <- User.get_or_fetch_by_ap_id(params["actor"]),
+ true <- Utils.recipient_in_message(recipient, actor, params),
+ params <- Utils.maybe_splice_recipient(recipient.ap_id, params) do
Federator.incoming_ap_doc(params)
json(conn, "ok")
end
diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
index 49ea73204..39cd31921 100644
--- a/lib/pleroma/web/activity_pub/transmogrifier.ex
+++ b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -225,12 +225,11 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
case fetch_obj_helper(in_reply_to_id) do
{:ok, replied_object} ->
- with %Activity{} = activity <-
+ with %Activity{} = _activity <-
Activity.get_create_by_object_ap_id(replied_object.data["id"]) do
object
|> Map.put("inReplyTo", replied_object.data["id"])
|> Map.put("inReplyToAtomUri", object["inReplyToAtomUri"] || in_reply_to_id)
- |> Map.put("inReplyToStatusId", activity.id)
|> Map.put("conversation", replied_object.data["context"] || object["conversation"])
|> Map.put("context", replied_object.data["context"] || object["conversation"])
else
diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex
index 0b53f71c3..ccc9da7c6 100644
--- a/lib/pleroma/web/activity_pub/utils.ex
+++ b/lib/pleroma/web/activity_pub/utils.ex
@@ -52,7 +52,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
defp recipient_in_collection(ap_id, coll) when is_list(coll), do: ap_id in coll
defp recipient_in_collection(_, _), do: false
- def recipient_in_message(ap_id, params) do
+ def recipient_in_message(%User{ap_id: ap_id} = recipient, %User{} = actor, params) do
cond do
recipient_in_collection(ap_id, params["to"]) ->
true
@@ -71,6 +71,11 @@ defmodule Pleroma.Web.ActivityPub.Utils do
!params["to"] && !params["cc"] && !params["bto"] && !params["bcc"] ->
true
+ # if the message is sent from somebody the user is following, then assume it
+ # is addressed to the recipient
+ User.following?(recipient, actor) ->
+ true
+
true ->
false
end
diff --git a/lib/pleroma/web/admin_api/admin_api_controller.ex b/lib/pleroma/web/admin_api/admin_api_controller.ex
index 70a5b5c5d..c436715d5 100644
--- a/lib/pleroma/web/admin_api/admin_api_controller.ex
+++ b/lib/pleroma/web/admin_api/admin_api_controller.ex
@@ -238,8 +238,13 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
!Pleroma.Config.get([:instance, :registrations_open]),
{:ok, invite_token} <- UserInviteToken.create_invite(),
email <-
- Pleroma.UserEmail.user_invitation_email(user, invite_token, email, params["name"]),
- {:ok, _} <- Pleroma.Mailer.deliver(email) do
+ Pleroma.Emails.UserEmail.user_invitation_email(
+ user,
+ invite_token,
+ email,
+ params["name"]
+ ),
+ {:ok, _} <- Pleroma.Emails.Mailer.deliver(email) do
json_response(conn, :no_content, "")
end
end
diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex
index 7b9f0ea06..185292878 100644
--- a/lib/pleroma/web/common_api/utils.ex
+++ b/lib/pleroma/web/common_api/utils.ex
@@ -195,11 +195,10 @@ defmodule Pleroma.Web.CommonAPI.Utils do
Formatting text to markdown.
"""
def format_input(text, "text/markdown", options) do
- options = Keyword.put(options, :mentions_escape, true)
-
text
+ |> Formatter.mentions_escape(options)
+ |> Earmark.as_html!()
|> Formatter.linkify(options)
- |> (fn {text, mentions, tags} -> {Earmark.as_html!(text), mentions, tags} end).()
|> Formatter.html_escape("text/html")
end
@@ -229,7 +228,6 @@ defmodule Pleroma.Web.CommonAPI.Utils do
if inReplyTo do
object
|> Map.put("inReplyTo", inReplyTo.data["object"]["id"])
- |> Map.put("inReplyToStatusId", inReplyTo.id)
else
object
end
diff --git a/lib/pleroma/web/endpoint.ex b/lib/pleroma/web/endpoint.ex
index 1633477c3..7f939991d 100644
--- a/lib/pleroma/web/endpoint.ex
+++ b/lib/pleroma/web/endpoint.ex
@@ -58,14 +58,9 @@ defmodule Pleroma.Web.Endpoint do
do: "__Host-pleroma_key",
else: "pleroma_key"
- same_site =
- if Pleroma.Config.oauth_consumer_enabled?() do
- # Note: "SameSite=Strict" prevents sign in with external OAuth provider
- # (there would be no cookies during callback request from OAuth provider)
- "SameSite=Lax"
- else
- "SameSite=Strict"
- end
+ extra =
+ Pleroma.Config.get([__MODULE__, :extra_cookie_attrs])
+ |> Enum.join(";")
# The session will be stored in the cookie and signed,
# this means its contents can be read but not tampered with.
@@ -77,7 +72,7 @@ defmodule Pleroma.Web.Endpoint do
signing_salt: {Pleroma.Config, :get, [[__MODULE__, :signing_salt], "CqaoopA2"]},
http_only: true,
secure: secure_cookies,
- extra: same_site
+ extra: extra
)
# Note: the plug and its configuration is compile-time this can't be upstreamed yet
diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
index ed082abdf..63fadce38 100644
--- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
+++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
@@ -11,6 +11,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
alias Pleroma.Filter
alias Pleroma.Notification
alias Pleroma.Object
+ alias Pleroma.Pagination
alias Pleroma.Repo
alias Pleroma.ScheduledActivity
alias Pleroma.Stats
@@ -202,15 +203,29 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
defp add_link_headers(conn, method, activities, param \\ nil, params \\ %{}) do
params =
conn.params
- |> Map.drop(["since_id", "max_id"])
+ |> Map.drop(["since_id", "max_id", "min_id"])
|> Map.merge(params)
last = List.last(activities)
- first = List.first(activities)
if last do
- min = last.id
- max = first.id
+ max_id = last.id
+
+ limit =
+ params
+ |> Map.get("limit", "20")
+ |> String.to_integer()
+
+ min_id =
+ if length(activities) <= limit do
+ activities
+ |> List.first()
+ |> Map.get(:id)
+ else
+ activities
+ |> Enum.at(limit * -1)
+ |> Map.get(:id)
+ end
{next_url, prev_url} =
if param do
@@ -219,13 +234,13 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
Pleroma.Web.Endpoint,
method,
param,
- Map.merge(params, %{max_id: min})
+ Map.merge(params, %{max_id: max_id})
),
mastodon_api_url(
Pleroma.Web.Endpoint,
method,
param,
- Map.merge(params, %{since_id: max})
+ Map.merge(params, %{min_id: min_id})
)
}
else
@@ -233,12 +248,12 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
mastodon_api_url(
Pleroma.Web.Endpoint,
method,
- Map.merge(params, %{max_id: min})
+ Map.merge(params, %{max_id: max_id})
),
mastodon_api_url(
Pleroma.Web.Endpoint,
method,
- Map.merge(params, %{since_id: max})
+ Map.merge(params, %{min_id: min_id})
)
}
end
@@ -314,7 +329,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
activities =
[user.ap_id]
|> ActivityPub.fetch_activities_query(params)
- |> Repo.all()
+ |> Pagination.fetch_paginated(params)
conn
|> add_link_headers(:dm_timeline, activities)
@@ -612,6 +627,11 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
end
end
+ def destroy_multiple(%{assigns: %{user: user}} = conn, %{"ids" => ids} = _params) do
+ Notification.destroy_multiple(user, ids)
+ json(conn, %{})
+ end
+
def relationships(%{assigns: %{user: user}} = conn, %{"id" => id}) do
id = List.wrap(id)
q = from(u in User, where: u.id in ^id)
@@ -795,13 +815,17 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
end
def follow(%{assigns: %{user: follower}} = conn, %{"id" => id}) do
- with %User{} = followed <- User.get_by_id(id),
+ with {_, %User{} = followed} <- {:followed, User.get_cached_by_id(id)},
+ {_, true} <- {:followed, follower.id != followed.id},
false <- User.following?(follower, followed),
{:ok, follower, followed, _} <- CommonAPI.follow(follower, followed) do
conn
|> put_view(AccountView)
|> render("relationship.json", %{user: follower, target: followed})
else
+ {:followed, _} ->
+ {:error, :not_found}
+
true ->
followed = User.get_cached_by_id(id)
@@ -823,12 +847,16 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
end
def follow(%{assigns: %{user: follower}} = conn, %{"uri" => uri}) do
- with %User{} = followed <- User.get_by_nickname(uri),
+ with {_, %User{} = followed} <- {:followed, User.get_cached_by_nickname(uri)},
+ {_, true} <- {:followed, follower.id != followed.id},
{:ok, follower, followed, _} <- CommonAPI.follow(follower, followed) do
conn
|> put_view(AccountView)
|> render("account.json", %{user: followed, for: follower})
else
+ {:followed, _} ->
+ {:error, :not_found}
+
{:error, message} ->
conn
|> put_resp_content_type("application/json")
@@ -837,11 +865,18 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
end
def unfollow(%{assigns: %{user: follower}} = conn, %{"id" => id}) do
- with %User{} = followed <- User.get_by_id(id),
+ with {_, %User{} = followed} <- {:followed, User.get_cached_by_id(id)},
+ {_, true} <- {:followed, follower.id != followed.id},
{:ok, follower} <- CommonAPI.unfollow(follower, followed) do
conn
|> put_view(AccountView)
|> render("relationship.json", %{user: follower, target: followed})
+ else
+ {:followed, _} ->
+ {:error, :not_found}
+
+ error ->
+ error
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 d4a8e4fff..a9f607aa5 100644
--- a/lib/pleroma/web/mastodon_api/views/status_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/status_view.ex
@@ -54,6 +54,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
defp get_context_id(_), do: nil
+ defp reblogged?(activity, user) do
+ object = activity.data["object"] || %{}
+ present?(user && user.ap_id in (object["announcements"] || []))
+ end
+
def render("index.json", opts) do
replied_to_activities = get_replied_to_activities(opts.activities)
@@ -72,8 +77,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
user = get_user(activity.data["actor"])
created_at = Utils.to_masto_date(activity.data["published"])
- reblogged = Activity.get_create_by_object_ap_id(object)
- reblogged = render("status.json", Map.put(opts, :activity, reblogged))
+ reblogged_activity = Activity.get_create_by_object_ap_id(object)
+ reblogged = render("status.json", Map.put(opts, :activity, reblogged_activity))
mentions =
activity.recipients
@@ -94,7 +99,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
reblogs_count: 0,
replies_count: 0,
favourites_count: 0,
- reblogged: false,
+ reblogged: reblogged?(reblogged_activity, opts[:for]),
favourited: false,
bookmarked: false,
muted: false,
@@ -132,7 +137,6 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|> Enum.filter(& &1)
|> Enum.map(fn user -> AccountView.render("mention.json", %{user: user}) end)
- repeated = opts[:for] && opts[:for].ap_id in (object["announcements"] || [])
favorited = opts[:for] && opts[:for].ap_id in (object["likes"] || [])
bookmarked = opts[:for] && object["id"] in opts[:for].bookmarks
@@ -203,7 +207,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
reblogs_count: announcement_count,
replies_count: object["repliesCount"] || 0,
favourites_count: like_count,
- reblogged: present?(repeated),
+ reblogged: reblogged?(activity, opts[:for]),
favourited: present?(favorited),
bookmarked: present?(bookmarked),
muted: CommonAPI.thread_muted?(user, activity) || User.mutes?(opts[:for], user),
@@ -301,8 +305,10 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
end
def get_reply_to(activity, %{replied_to_activities: replied_to_activities}) do
- _id = activity.data["object"]["inReplyTo"]
- replied_to_activities[activity.data["object"]["inReplyTo"]]
+ with nil <- replied_to_activities[activity.data["object"]["inReplyTo"]] do
+ # If user didn't participate in the thread
+ Activity.get_in_reply_to_activity(activity)
+ end
end
def get_reply_to(%{data: %{"object" => object}}, _) do
diff --git a/lib/pleroma/web/rel_me.ex b/lib/pleroma/web/rel_me.ex
index eaca41132..26eb614a6 100644
--- a/lib/pleroma/web/rel_me.ex
+++ b/lib/pleroma/web/rel_me.ex
@@ -6,7 +6,8 @@ defmodule Pleroma.Web.RelMe do
@hackney_options [
pool: :media,
recv_timeout: 2_000,
- max_body: 2_000_000
+ max_body: 2_000_000,
+ with_body: true
]
if Mix.env() == :test do
diff --git a/lib/pleroma/web/rich_media/parser.ex b/lib/pleroma/web/rich_media/parser.ex
index 4bd271d8e..62e8fa610 100644
--- a/lib/pleroma/web/rich_media/parser.ex
+++ b/lib/pleroma/web/rich_media/parser.ex
@@ -12,7 +12,8 @@ defmodule Pleroma.Web.RichMedia.Parser do
@hackney_options [
pool: :media,
recv_timeout: 2_000,
- max_body: 2_000_000
+ max_body: 2_000_000,
+ with_body: true
]
def parse(nil), do: {:error, "No URL provided"}
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index 172f337db..8b665d61b 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -242,7 +242,6 @@ defmodule Pleroma.Web.Router do
get("/accounts/verify_credentials", MastodonAPIController, :verify_credentials)
get("/accounts/relationships", MastodonAPIController, :relationships)
- get("/accounts/search", MastodonAPIController, :account_search)
get("/accounts/:id/lists", MastodonAPIController, :account_lists)
get("/accounts/:id/identity_proofs", MastodonAPIController, :empty_array)
@@ -261,6 +260,7 @@ defmodule Pleroma.Web.Router do
post("/notifications/dismiss", MastodonAPIController, :dismiss_notification)
get("/notifications", MastodonAPIController, :notifications)
get("/notifications/:id", MastodonAPIController, :get_notification)
+ delete("/notifications/destroy_multiple", MastodonAPIController, :destroy_multiple)
get("/scheduled_statuses", MastodonAPIController, :scheduled_statuses)
get("/scheduled_statuses/:id", MastodonAPIController, :show_scheduled_status)
@@ -376,6 +376,8 @@ defmodule Pleroma.Web.Router do
get("/trends", MastodonAPIController, :empty_array)
+ get("/accounts/search", MastodonAPIController, :account_search)
+
scope [] do
pipe_through(:oauth_read_or_unauthenticated)
diff --git a/lib/pleroma/web/templates/layout/app.html.eex b/lib/pleroma/web/templates/layout/app.html.eex
index 8333bc921..3389c91cc 100644
--- a/lib/pleroma/web/templates/layout/app.html.eex
+++ b/lib/pleroma/web/templates/layout/app.html.eex
@@ -179,6 +179,17 @@
flex-basis: 50%;
}
}
+ .form-row {
+ display: flex;
+ }
+ .form-row > label {
+ text-align: left;
+ line-height: 47px;
+ flex: 1;
+ }
+ .form-row > input {
+ flex: 2;
+ }
</style>
</head>
<body>
diff --git a/lib/pleroma/web/templates/twitter_api/util/password_reset.html.eex b/lib/pleroma/web/templates/twitter_api/util/password_reset.html.eex
index 3c7960998..a3facf017 100644
--- a/lib/pleroma/web/templates/twitter_api/util/password_reset.html.eex
+++ b/lib/pleroma/web/templates/twitter_api/util/password_reset.html.eex
@@ -1,12 +1,13 @@
<h2>Password Reset for <%= @user.nickname %></h2>
<%= form_for @conn, util_path(@conn, :password_reset), [as: "data"], fn f -> %>
-<%= label f, :password, "Password" %>
-<%= password_input f, :password %>
-<br>
-
-<%= label f, :password_confirmation, "Confirmation" %>
-<%= password_input f, :password_confirmation %>
-<br>
-<%= hidden_input f, :token, value: @token.token %>
-<%= submit "Reset" %>
+ <div class="form-row">
+ <%= label f, :password, "Password" %>
+ <%= password_input f, :password %>
+ </div>
+ <div class="form-row">
+ <%= label f, :password_confirmation, "Confirmation" %>
+ <%= password_input f, :password_confirmation %>
+ </div>
+ <%= hidden_input f, :token, value: @token.token %>
+ <%= submit "Reset" %>
<% end %>
diff --git a/lib/pleroma/web/twitter_api/controllers/util_controller.ex b/lib/pleroma/web/twitter_api/controllers/util_controller.ex
index d066d35f5..ed45ca735 100644
--- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex
+++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex
@@ -304,7 +304,12 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
end
def follow_import(%{assigns: %{user: follower}} = conn, %{"list" => list}) do
- with followed_identifiers <- String.split(list),
+ with lines <- String.split(list, "\n"),
+ followed_identifiers <-
+ Enum.map(lines, fn line ->
+ String.split(line, ",") |> List.first()
+ end)
+ |> List.delete("Account address"),
{:ok, _} = Task.start(fn -> User.follow_import(follower, followed_identifiers) end) do
json(conn, "job started")
end
diff --git a/lib/pleroma/web/twitter_api/twitter_api.ex b/lib/pleroma/web/twitter_api/twitter_api.ex
index 9e9a46cf1..d6ce0a7c6 100644
--- a/lib/pleroma/web/twitter_api/twitter_api.ex
+++ b/lib/pleroma/web/twitter_api/twitter_api.ex
@@ -4,10 +4,10 @@
defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
alias Pleroma.Activity
- alias Pleroma.Mailer
+ alias Pleroma.Emails.Mailer
+ alias Pleroma.Emails.UserEmail
alias Pleroma.Repo
alias Pleroma.User
- alias Pleroma.UserEmail
alias Pleroma.UserInviteToken
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.CommonAPI
diff --git a/lib/pleroma/web/twitter_api/views/activity_view.ex b/lib/pleroma/web/twitter_api/views/activity_view.ex
index 433322eb8..ecb2b437b 100644
--- a/lib/pleroma/web/twitter_api/views/activity_view.ex
+++ b/lib/pleroma/web/twitter_api/views/activity_view.ex
@@ -291,7 +291,7 @@ defmodule Pleroma.Web.TwitterAPI.ActivityView do
"is_local" => activity.local,
"is_post_verb" => true,
"created_at" => created_at,
- "in_reply_to_status_id" => object["inReplyToStatusId"],
+ "in_reply_to_status_id" => reply_parent && reply_parent.id,
"in_reply_to_screen_name" => reply_user && reply_user.nickname,
"in_reply_to_profileurl" => User.profile_url(reply_user),
"in_reply_to_ostatus_uri" => reply_user && reply_user.ap_id,