Merge branch 'develop' of git.pleroma.social:pleroma/pleroma into feature/digest-email
This commit is contained in:
commit
0cd4b6024d
26 changed files with 221 additions and 86 deletions
91
CHANGELOG.md
Normal file
91
CHANGELOG.md
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
# Changelog
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
|
|
||||||
|
## [unreleased]
|
||||||
|
### Added
|
||||||
|
- LDAP authentication
|
||||||
|
- External OAuth provider authentication
|
||||||
|
- A [job queue](https://git.pleroma.social/pleroma/pleroma_job_queue) for federation, emails, web push, etc.
|
||||||
|
- [Prometheus](https://prometheus.io/) metrics
|
||||||
|
- Support for Mastodon's remote interaction
|
||||||
|
- Federation: Support for reports
|
||||||
|
- Configuration: `safe_dm_mentions` option
|
||||||
|
- Configuration: `link_name` option
|
||||||
|
- Configuration: `fetch_initial_posts` option
|
||||||
|
- Pleroma API: User subscribtions
|
||||||
|
- Admin API: Endpoints for listing/revoking invite tokens
|
||||||
|
- Admin API: Endpoints for making users follow/unfollow each other
|
||||||
|
- Mastodon API: [Scheduled statuses](https://docs.joinmastodon.org/api/rest/scheduled-statuses/)
|
||||||
|
- Mastodon API: `/api/v1/notifications/destroy_multiple` (glitch-soc extension)
|
||||||
|
- Mastodon API: [Reports](https://docs.joinmastodon.org/api/rest/reports/)
|
||||||
|
- ActivityPub C2S: OAuth endpoints
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- **Breaking:** Configuration: move from Pleroma.Mailer to Pleroma.Emails.Mailer
|
||||||
|
- Enforcement of OAuth scopes
|
||||||
|
- Add multiple use/time expiring invite token
|
||||||
|
- Restyled OAuth pages to fit with Pleroma's default theme
|
||||||
|
- Link/mention/hashtag detection is now handled by [auto_linker](https://git.pleroma.social/pleroma/auto_linker)
|
||||||
|
- NodeInfo: Return `safe_dm_mentions` feature flag
|
||||||
|
- Federation: Expand the audience of delete activities to all recipients of the deleted object
|
||||||
|
- Configuration: Dedupe enabled by default
|
||||||
|
- Pleroma API: Support for emoji tags in `/api/pleroma/emoji` resulting in a breaking API change
|
||||||
|
- Mastodon API: Support for `exclude_types`, `limit` and `min_id` in `/api/v1/notifications`
|
||||||
|
- Mastodon API: Add `languages` and `registrations` to `/api/v1/instance`
|
||||||
|
- Mastodon API: Provide plaintext versions of cw/content in the Status entity
|
||||||
|
- Mastodon API: Add `pleroma.conversation_id` field to the Status entity
|
||||||
|
- Mastodon API: Add `pleroma.tags`, `pleroma.relationship{}`, `pleroma.is_moderator`, `pleroma.is_admin`, `pleroma.confirmation_pending` fields to the User entity
|
||||||
|
- Mastodon API: Add `pleroma.is_seen` to the Notification entity
|
||||||
|
- Mastodon API: Add `pleroma.local` to the Status entity
|
||||||
|
- Mastodon API: Add `preview` parameter to `POST /api/v1/statuses`
|
||||||
|
- Mastodon API: Add `with_muted` parameter to timeline endpoints
|
||||||
|
- Mastodon API: Actual reblog hiding instead of a dummy
|
||||||
|
- Mastodon API: Remove attachment limit in the Status entity
|
||||||
|
- Deps: Updated Cowboy to 2.6
|
||||||
|
- Deps: Updated Ecto to 3.0.7
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Followers counter not being updated when a follower is blocked
|
||||||
|
- Deactivated users being able to request an access token
|
||||||
|
- Limit on request body in rich media/relme parsers being ignored resulting in a possible memory leak
|
||||||
|
- proper Twitter Card generation instead of a dummy
|
||||||
|
- NodeInfo: Include admins in `staffAccounts`
|
||||||
|
- ActivityPub: Crashing when requesting empty local user's outbox
|
||||||
|
- Federation: Handling of objects without `summary` property
|
||||||
|
- Federation: Add a language tag to activities as required by ActivityStreams 2.0
|
||||||
|
- Federation: Do not federate avatar/banner if set to default allowing other servers/clients to use their defaults
|
||||||
|
- Federation: Cope with missing or explicitly nulled address lists
|
||||||
|
- Federation: Explicitly ensure activities addressed to `as:Public` become addressed to the followers collection
|
||||||
|
- Federation: Better cope with actors which do not declare a followers collection and use `as:Public` with these semantics
|
||||||
|
- MediaProxy: Parse name from content disposition headers even for non-whitelisted types
|
||||||
|
- MediaProxy: S3 link encoding
|
||||||
|
- Rich Media: Reject any data which cannot be explicitly encoded into JSON
|
||||||
|
- Mastodon API: `/api/v1/favourites` serving only public activities
|
||||||
|
- Mastodon API: Reblogs having `in_reply_to_id` - `null` even when they are replies
|
||||||
|
- Mastodon API: Streaming API broadcasting wrong activity id
|
||||||
|
- Mastodon API: 500 errors when requesting a card for a private conversation
|
||||||
|
|
||||||
|
## [0.9.9999] - 2019-04-05
|
||||||
|
### Security
|
||||||
|
- Mastodon API: Fix content warnings skipping HTML sanitization
|
||||||
|
|
||||||
|
## [0.9.999] - 2019-03-13
|
||||||
|
Frontend changes only.
|
||||||
|
### Added
|
||||||
|
- Added floating action button for posting status on mobile
|
||||||
|
### Changed
|
||||||
|
- Changed user-settings icon to a pencil
|
||||||
|
### Fixed
|
||||||
|
- Keyboard shortcuts activating when typing a message
|
||||||
|
- Gaps when scrolling down on a timeline after showing new
|
||||||
|
|
||||||
|
## [0.9.99] - 2019-03-08
|
||||||
|
### Changed
|
||||||
|
- Update the frontend to the 0.9.99 tag
|
||||||
|
### Fixed
|
||||||
|
- Sign the date header in federation to fix Mastodon federation.
|
||||||
|
|
||||||
|
## [0.9.9] - 2019-02-22
|
||||||
|
This is our first stable release.
|
|
@ -413,7 +413,7 @@
|
||||||
|
|
||||||
config :pleroma, :auth, oauth_consumer_strategies: oauth_consumer_strategies
|
config :pleroma, :auth, oauth_consumer_strategies: oauth_consumer_strategies
|
||||||
|
|
||||||
config :pleroma, Pleroma.Mailer, adapter: Swoosh.Adapters.Sendmail
|
config :pleroma, Pleroma.Emails.Mailer, adapter: Swoosh.Adapters.Sendmail
|
||||||
|
|
||||||
config :prometheus, Pleroma.Web.Endpoint.MetricsExporter, path: "/api/pleroma/app_metrics"
|
config :prometheus, Pleroma.Web.Endpoint.MetricsExporter, path: "/api/pleroma/app_metrics"
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
watchers: [],
|
watchers: [],
|
||||||
secure_cookie_flag: false
|
secure_cookie_flag: false
|
||||||
|
|
||||||
config :pleroma, Pleroma.Mailer, adapter: Swoosh.Adapters.Local
|
config :pleroma, Pleroma.Emails.Mailer, adapter: Swoosh.Adapters.Local
|
||||||
|
|
||||||
# ## SSL Support
|
# ## SSL Support
|
||||||
#
|
#
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
config :pleroma, Pleroma.Uploaders.Local, uploads: "test/uploads"
|
config :pleroma, Pleroma.Uploaders.Local, uploads: "test/uploads"
|
||||||
|
|
||||||
config :pleroma, Pleroma.Mailer, adapter: Swoosh.Adapters.Test
|
config :pleroma, Pleroma.Emails.Mailer, adapter: Swoosh.Adapters.Test
|
||||||
|
|
||||||
# Configure your database
|
# Configure your database
|
||||||
config :pleroma, Pleroma.Repo,
|
config :pleroma, Pleroma.Repo,
|
||||||
|
|
|
@ -31,14 +31,14 @@ This filter replaces the filename (not the path) of an upload. For complete obfu
|
||||||
|
|
||||||
* `text`: Text to replace filenames in links. If empty, `{random}.extension` will be used.
|
* `text`: Text to replace filenames in links. If empty, `{random}.extension` will be used.
|
||||||
|
|
||||||
## Pleroma.Mailer
|
## Pleroma.Emails.Mailer
|
||||||
* `adapter`: one of the mail adapters listed in [Swoosh readme](https://github.com/swoosh/swoosh#adapters), or `Swoosh.Adapters.Local` for in-memory mailbox.
|
* `adapter`: one of the mail adapters listed in [Swoosh readme](https://github.com/swoosh/swoosh#adapters), or `Swoosh.Adapters.Local` for in-memory mailbox.
|
||||||
* `api_key` / `password` and / or other adapter-specific settings, per the above documentation.
|
* `api_key` / `password` and / or other adapter-specific settings, per the above documentation.
|
||||||
|
|
||||||
An example for Sendgrid adapter:
|
An example for Sendgrid adapter:
|
||||||
|
|
||||||
```exs
|
```exs
|
||||||
config :pleroma, Pleroma.Mailer,
|
config :pleroma, Pleroma.Emails.Mailer,
|
||||||
adapter: Swoosh.Adapters.Sendgrid,
|
adapter: Swoosh.Adapters.Sendgrid,
|
||||||
api_key: "YOUR_API_KEY"
|
api_key: "YOUR_API_KEY"
|
||||||
```
|
```
|
||||||
|
@ -46,7 +46,7 @@ config :pleroma, Pleroma.Mailer,
|
||||||
An example for SMTP adapter:
|
An example for SMTP adapter:
|
||||||
|
|
||||||
```exs
|
```exs
|
||||||
config :pleroma, Pleroma.Mailer,
|
config :pleroma, Pleroma.Emails.Mailer,
|
||||||
adapter: Swoosh.Adapters.SMTP,
|
adapter: Swoosh.Adapters.SMTP,
|
||||||
relay: "smtp.gmail.com",
|
relay: "smtp.gmail.com",
|
||||||
username: "YOUR_USERNAME@gmail.com",
|
username: "YOUR_USERNAME@gmail.com",
|
||||||
|
@ -317,7 +317,7 @@ Pleroma has the following queues:
|
||||||
|
|
||||||
* `federator_outgoing` - Outgoing federation
|
* `federator_outgoing` - Outgoing federation
|
||||||
* `federator_incoming` - Incoming federation
|
* `federator_incoming` - Incoming federation
|
||||||
* `mailer` - Email sender, see [`Pleroma.Mailer`](#pleroma-mailer)
|
* `mailer` - Email sender, see [`Pleroma.Emails.Mailer`](#pleroma-emails-mailer)
|
||||||
* `transmogrifier` - Transmogrifier
|
* `transmogrifier` - Transmogrifier
|
||||||
* `web_push` - Web push notifications
|
* `web_push` - Web push notifications
|
||||||
* `scheduled_activities` - Scheduled activities, see [`Pleroma.ScheduledActivities`](#pleromascheduledactivity)
|
* `scheduled_activities` - Scheduled activities, see [`Pleroma.ScheduledActivities`](#pleromascheduledactivity)
|
||||||
|
|
|
@ -7,7 +7,6 @@ This guide will assume that you have administrative rights, either as root or a
|
||||||
|
|
||||||
* `postgresql`
|
* `postgresql`
|
||||||
* `elixir`
|
* `elixir`
|
||||||
* `erlang-unixodbc`
|
|
||||||
* `git`
|
* `git`
|
||||||
* `base-devel`
|
* `base-devel`
|
||||||
|
|
||||||
|
@ -27,7 +26,7 @@ sudo pacman -Syu
|
||||||
* Install some of the above mentioned programs:
|
* Install some of the above mentioned programs:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
sudo pacman -S git base-devel elixir erlang-unixodbc
|
sudo pacman -S git base-devel elixir
|
||||||
```
|
```
|
||||||
|
|
||||||
### Install PostgreSQL
|
### Install PostgreSQL
|
||||||
|
|
|
@ -37,7 +37,7 @@ server {
|
||||||
listen [::]:443 ssl http2;
|
listen [::]:443 ssl http2;
|
||||||
ssl_session_timeout 5m;
|
ssl_session_timeout 5m;
|
||||||
|
|
||||||
ssl_trusted_certificate /etc/letsencrypt/live/example.tld/fullchain.pem;
|
ssl_trusted_certificate /etc/letsencrypt/live/example.tld/chain.pem;
|
||||||
ssl_certificate /etc/letsencrypt/live/example.tld/fullchain.pem;
|
ssl_certificate /etc/letsencrypt/live/example.tld/fullchain.pem;
|
||||||
ssl_certificate_key /etc/letsencrypt/live/example.tld/privkey.pem;
|
ssl_certificate_key /etc/letsencrypt/live/example.tld/privkey.pem;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
defmodule Pleroma.AdminEmail do
|
defmodule Pleroma.Emails.AdminEmail do
|
||||||
@moduledoc "Admin emails"
|
@moduledoc "Admin emails"
|
||||||
|
|
||||||
import Swoosh.Email
|
import Swoosh.Email
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
defmodule Pleroma.Mailer do
|
defmodule Pleroma.Emails.Mailer do
|
||||||
use Swoosh.Mailer, otp_app: :pleroma
|
use Swoosh.Mailer, otp_app: :pleroma
|
||||||
|
|
||||||
def deliver_async(email, config \\ []) do
|
def deliver_async(email, config \\ []) do
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
defmodule Pleroma.UserEmail do
|
defmodule Pleroma.Emails.UserEmail do
|
||||||
@moduledoc "User emails"
|
@moduledoc "User emails"
|
||||||
|
|
||||||
import Swoosh.Email
|
import Swoosh.Email
|
||||||
|
|
|
@ -9,20 +9,31 @@ defmodule Pleroma.Formatter do
|
||||||
alias Pleroma.Web.MediaProxy
|
alias Pleroma.Web.MediaProxy
|
||||||
|
|
||||||
@safe_mention_regex ~r/^(\s*(?<mentions>@.+?\s+)+)(?<rest>.*)/
|
@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/(`|\*|_|{|}|[|]|\(|\)|#|\+|-|\.|!)/
|
@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,
|
@auto_linker_config hashtag: true,
|
||||||
hashtag_handler: &Pleroma.Formatter.hashtag_handler/4,
|
hashtag_handler: &Pleroma.Formatter.hashtag_handler/4,
|
||||||
mention: true,
|
mention: true,
|
||||||
mention_handler: &Pleroma.Formatter.mention_handler/4
|
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
|
def mention_handler("@" <> nickname, buffer, opts, acc) do
|
||||||
case User.get_cached_by_nickname(nickname) do
|
case User.get_cached_by_nickname(nickname) do
|
||||||
%User{id: id} = user ->
|
%User{id: id} = user ->
|
||||||
ap_id = get_ap_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 =
|
link =
|
||||||
"<span class='h-card'><a data-user='#{id}' class='u-url mention' href='#{ap_id}'>@<span>#{
|
"<span class='h-card'><a data-user='#{id}' class='u-url mention' href='#{ap_id}'>@<span>#{
|
||||||
|
@ -70,6 +81,25 @@ def linkify(text, options \\ []) do
|
||||||
end
|
end
|
||||||
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
|
def emojify(text) do
|
||||||
emojify(text, Emoji.get_all())
|
emojify(text, Emoji.get_all())
|
||||||
end
|
end
|
||||||
|
@ -140,10 +170,4 @@ defp get_ap_id(%User{ap_id: ap_id}), do: ap_id
|
||||||
|
|
||||||
defp get_nickname_text(nickname, %{mentions_format: :full}), do: User.full_nickname(nickname)
|
defp get_nickname_text(nickname, %{mentions_format: :full}), do: User.full_nickname(nickname)
|
||||||
defp get_nickname_text(nickname, _), do: User.local_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
|
end
|
||||||
|
|
|
@ -36,6 +36,12 @@ defp cast_params(params) do
|
||||||
limit: :integer
|
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 = cast({%{}, param_types}, params, Map.keys(param_types))
|
||||||
changeset.changes
|
changeset.changes
|
||||||
end
|
end
|
||||||
|
|
|
@ -279,8 +279,8 @@ def try_send_confirmation_email(%User{} = user) do
|
||||||
if user.info.confirmation_pending &&
|
if user.info.confirmation_pending &&
|
||||||
Pleroma.Config.get([:instance, :account_activation_required]) do
|
Pleroma.Config.get([:instance, :account_activation_required]) do
|
||||||
user
|
user
|
||||||
|> Pleroma.UserEmail.account_confirmation_email()
|
|> Pleroma.Emails.UserEmail.account_confirmation_email()
|
||||||
|> Pleroma.Mailer.deliver_async()
|
|> Pleroma.Emails.Mailer.deliver_async()
|
||||||
else
|
else
|
||||||
{:ok, :noop}
|
{:ok, :noop}
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
||||||
alias Pleroma.Instances
|
alias Pleroma.Instances
|
||||||
alias Pleroma.Notification
|
alias Pleroma.Notification
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
|
alias Pleroma.Pagination
|
||||||
alias Pleroma.Repo
|
alias Pleroma.Repo
|
||||||
alias Pleroma.Upload
|
alias Pleroma.Upload
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
|
@ -449,8 +450,8 @@ def flag(
|
||||||
:ok <- maybe_federate(activity) do
|
:ok <- maybe_federate(activity) do
|
||||||
Enum.each(User.all_superusers(), fn superuser ->
|
Enum.each(User.all_superusers(), fn superuser ->
|
||||||
superuser
|
superuser
|
||||||
|> Pleroma.AdminEmail.report(actor, account, statuses, content)
|
|> Pleroma.Emails.AdminEmail.report(actor, account, statuses, content)
|
||||||
|> Pleroma.Mailer.deliver_async()
|
|> Pleroma.Emails.Mailer.deliver_async()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
{:ok, activity}
|
{:ok, activity}
|
||||||
|
@ -493,7 +494,7 @@ def fetch_public_activities(opts \\ %{}) do
|
||||||
|
|
||||||
q
|
q
|
||||||
|> restrict_unlisted()
|
|> restrict_unlisted()
|
||||||
|> Repo.all()
|
|> Pagination.fetch_paginated(opts)
|
||||||
|> Enum.reverse()
|
|> Enum.reverse()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -636,26 +637,12 @@ defp restrict_recipients(query, recipients, user) do
|
||||||
)
|
)
|
||||||
end
|
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
|
defp restrict_local(query, %{"local_only" => true}) do
|
||||||
from(activity in query, where: activity.local == true)
|
from(activity in query, where: activity.local == true)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp restrict_local(query, _), do: query
|
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
|
defp restrict_actor(query, %{"actor_id" => actor_id}) do
|
||||||
from(activity in query, where: activity.actor == ^actor_id)
|
from(activity in query, where: activity.actor == ^actor_id)
|
||||||
end
|
end
|
||||||
|
@ -776,12 +763,7 @@ defp maybe_preload_objects(query, _) do
|
||||||
end
|
end
|
||||||
|
|
||||||
def fetch_activities_query(recipients, opts \\ %{}) do
|
def fetch_activities_query(recipients, opts \\ %{}) do
|
||||||
base_query =
|
base_query = from(activity in Activity)
|
||||||
from(
|
|
||||||
activity in Activity,
|
|
||||||
limit: 20,
|
|
||||||
order_by: [fragment("? desc nulls last", activity.id)]
|
|
||||||
)
|
|
||||||
|
|
||||||
base_query
|
base_query
|
||||||
|> maybe_preload_objects(opts)
|
|> maybe_preload_objects(opts)
|
||||||
|
@ -791,8 +773,6 @@ def fetch_activities_query(recipients, opts \\ %{}) do
|
||||||
|> restrict_tag_all(opts)
|
|> restrict_tag_all(opts)
|
||||||
|> restrict_since(opts)
|
|> restrict_since(opts)
|
||||||
|> restrict_local(opts)
|
|> restrict_local(opts)
|
||||||
|> restrict_limit(opts)
|
|
||||||
|> restrict_max(opts)
|
|
||||||
|> restrict_actor(opts)
|
|> restrict_actor(opts)
|
||||||
|> restrict_type(opts)
|
|> restrict_type(opts)
|
||||||
|> restrict_favorited_by(opts)
|
|> restrict_favorited_by(opts)
|
||||||
|
@ -808,14 +788,14 @@ def fetch_activities_query(recipients, opts \\ %{}) do
|
||||||
|
|
||||||
def fetch_activities(recipients, opts \\ %{}) do
|
def fetch_activities(recipients, opts \\ %{}) do
|
||||||
fetch_activities_query(recipients, opts)
|
fetch_activities_query(recipients, opts)
|
||||||
|> Repo.all()
|
|> Pagination.fetch_paginated(opts)
|
||||||
|> Enum.reverse()
|
|> Enum.reverse()
|
||||||
end
|
end
|
||||||
|
|
||||||
def fetch_activities_bounded(recipients_to, recipients_cc, opts \\ %{}) do
|
def fetch_activities_bounded(recipients_to, recipients_cc, opts \\ %{}) do
|
||||||
fetch_activities_query([], opts)
|
fetch_activities_query([], opts)
|
||||||
|> restrict_to_cc(recipients_to, recipients_cc)
|
|> restrict_to_cc(recipients_to, recipients_cc)
|
||||||
|> Repo.all()
|
|> Pagination.fetch_paginated(opts)
|
||||||
|> Enum.reverse()
|
|> Enum.reverse()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -238,8 +238,13 @@ def email_invite(%{assigns: %{user: user}} = conn, %{"email" => email} = params)
|
||||||
!Pleroma.Config.get([:instance, :registrations_open]),
|
!Pleroma.Config.get([:instance, :registrations_open]),
|
||||||
{:ok, invite_token} <- UserInviteToken.create_invite(),
|
{:ok, invite_token} <- UserInviteToken.create_invite(),
|
||||||
email <-
|
email <-
|
||||||
Pleroma.UserEmail.user_invitation_email(user, invite_token, email, params["name"]),
|
Pleroma.Emails.UserEmail.user_invitation_email(
|
||||||
{:ok, _} <- Pleroma.Mailer.deliver(email) do
|
user,
|
||||||
|
invite_token,
|
||||||
|
email,
|
||||||
|
params["name"]
|
||||||
|
),
|
||||||
|
{:ok, _} <- Pleroma.Emails.Mailer.deliver(email) do
|
||||||
json_response(conn, :no_content, "")
|
json_response(conn, :no_content, "")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -195,11 +195,10 @@ def format_input(text, "text/html", options) do
|
||||||
Formatting text to markdown.
|
Formatting text to markdown.
|
||||||
"""
|
"""
|
||||||
def format_input(text, "text/markdown", options) do
|
def format_input(text, "text/markdown", options) do
|
||||||
options = Keyword.put(options, :mentions_escape, true)
|
|
||||||
|
|
||||||
text
|
text
|
||||||
|
|> Formatter.mentions_escape(options)
|
||||||
|
|> Earmark.as_html!()
|
||||||
|> Formatter.linkify(options)
|
|> Formatter.linkify(options)
|
||||||
|> (fn {text, mentions, tags} -> {Earmark.as_html!(text), mentions, tags} end).()
|
|
||||||
|> Formatter.html_escape("text/html")
|
|> Formatter.html_escape("text/html")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
||||||
alias Pleroma.Filter
|
alias Pleroma.Filter
|
||||||
alias Pleroma.Notification
|
alias Pleroma.Notification
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
|
alias Pleroma.Pagination
|
||||||
alias Pleroma.Repo
|
alias Pleroma.Repo
|
||||||
alias Pleroma.ScheduledActivity
|
alias Pleroma.ScheduledActivity
|
||||||
alias Pleroma.Stats
|
alias Pleroma.Stats
|
||||||
|
@ -202,15 +203,29 @@ def custom_emojis(conn, _params) do
|
||||||
defp add_link_headers(conn, method, activities, param \\ nil, params \\ %{}) do
|
defp add_link_headers(conn, method, activities, param \\ nil, params \\ %{}) do
|
||||||
params =
|
params =
|
||||||
conn.params
|
conn.params
|
||||||
|> Map.drop(["since_id", "max_id"])
|
|> Map.drop(["since_id", "max_id", "min_id"])
|
||||||
|> Map.merge(params)
|
|> Map.merge(params)
|
||||||
|
|
||||||
last = List.last(activities)
|
last = List.last(activities)
|
||||||
first = List.first(activities)
|
|
||||||
|
|
||||||
if last do
|
if last do
|
||||||
min = last.id
|
max_id = last.id
|
||||||
max = first.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} =
|
{next_url, prev_url} =
|
||||||
if param do
|
if param do
|
||||||
|
@ -219,13 +234,13 @@ defp add_link_headers(conn, method, activities, param \\ nil, params \\ %{}) do
|
||||||
Pleroma.Web.Endpoint,
|
Pleroma.Web.Endpoint,
|
||||||
method,
|
method,
|
||||||
param,
|
param,
|
||||||
Map.merge(params, %{max_id: min})
|
Map.merge(params, %{max_id: max_id})
|
||||||
),
|
),
|
||||||
mastodon_api_url(
|
mastodon_api_url(
|
||||||
Pleroma.Web.Endpoint,
|
Pleroma.Web.Endpoint,
|
||||||
method,
|
method,
|
||||||
param,
|
param,
|
||||||
Map.merge(params, %{since_id: max})
|
Map.merge(params, %{min_id: min_id})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -233,12 +248,12 @@ defp add_link_headers(conn, method, activities, param \\ nil, params \\ %{}) do
|
||||||
mastodon_api_url(
|
mastodon_api_url(
|
||||||
Pleroma.Web.Endpoint,
|
Pleroma.Web.Endpoint,
|
||||||
method,
|
method,
|
||||||
Map.merge(params, %{max_id: min})
|
Map.merge(params, %{max_id: max_id})
|
||||||
),
|
),
|
||||||
mastodon_api_url(
|
mastodon_api_url(
|
||||||
Pleroma.Web.Endpoint,
|
Pleroma.Web.Endpoint,
|
||||||
method,
|
method,
|
||||||
Map.merge(params, %{since_id: max})
|
Map.merge(params, %{min_id: min_id})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
@ -314,7 +329,7 @@ def dm_timeline(%{assigns: %{user: user}} = conn, params) do
|
||||||
activities =
|
activities =
|
||||||
[user.ap_id]
|
[user.ap_id]
|
||||||
|> ActivityPub.fetch_activities_query(params)
|
|> ActivityPub.fetch_activities_query(params)
|
||||||
|> Repo.all()
|
|> Pagination.fetch_paginated(params)
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> add_link_headers(:dm_timeline, activities)
|
|> add_link_headers(:dm_timeline, activities)
|
||||||
|
|
|
@ -179,6 +179,17 @@
|
||||||
flex-basis: 50%;
|
flex-basis: 50%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.form-row {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.form-row > label {
|
||||||
|
text-align: left;
|
||||||
|
line-height: 47px;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.form-row > input {
|
||||||
|
flex: 2;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
<h2>Password Reset for <%= @user.nickname %></h2>
|
<h2>Password Reset for <%= @user.nickname %></h2>
|
||||||
<%= form_for @conn, util_path(@conn, :password_reset), [as: "data"], fn f -> %>
|
<%= form_for @conn, util_path(@conn, :password_reset), [as: "data"], fn f -> %>
|
||||||
<%= label f, :password, "Password" %>
|
<div class="form-row">
|
||||||
<%= password_input f, :password %>
|
<%= label f, :password, "Password" %>
|
||||||
<br>
|
<%= password_input f, :password %>
|
||||||
|
</div>
|
||||||
<%= label f, :password_confirmation, "Confirmation" %>
|
<div class="form-row">
|
||||||
<%= password_input f, :password_confirmation %>
|
<%= label f, :password_confirmation, "Confirmation" %>
|
||||||
<br>
|
<%= password_input f, :password_confirmation %>
|
||||||
<%= hidden_input f, :token, value: @token.token %>
|
</div>
|
||||||
<%= submit "Reset" %>
|
<%= hidden_input f, :token, value: @token.token %>
|
||||||
|
<%= submit "Reset" %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -4,10 +4,10 @@
|
||||||
|
|
||||||
defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
|
defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
alias Pleroma.Mailer
|
alias Pleroma.Emails.Mailer
|
||||||
|
alias Pleroma.Emails.UserEmail
|
||||||
alias Pleroma.Repo
|
alias Pleroma.Repo
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.UserEmail
|
|
||||||
alias Pleroma.UserInviteToken
|
alias Pleroma.UserInviteToken
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
|
|
4
mix.exs
4
mix.exs
|
@ -22,7 +22,7 @@ def project do
|
||||||
homepage_url: "https://pleroma.social/",
|
homepage_url: "https://pleroma.social/",
|
||||||
docs: [
|
docs: [
|
||||||
logo: "priv/static/static/logo.png",
|
logo: "priv/static/static/logo.png",
|
||||||
extras: ["README.md" | Path.wildcard("docs/**/*.md")],
|
extras: ["README.md", "CHANGELOG.md"] ++ Path.wildcard("docs/**/*.md"),
|
||||||
groups_for_extras: [
|
groups_for_extras: [
|
||||||
"Installation manuals": Path.wildcard("docs/installation/*.md"),
|
"Installation manuals": Path.wildcard("docs/installation/*.md"),
|
||||||
Configuration: Path.wildcard("docs/config/*.md"),
|
Configuration: Path.wildcard("docs/config/*.md"),
|
||||||
|
@ -101,7 +101,7 @@ defp deps do
|
||||||
{:ueberauth, "~> 0.4"},
|
{:ueberauth, "~> 0.4"},
|
||||||
{:auto_linker,
|
{:auto_linker,
|
||||||
git: "https://git.pleroma.social/pleroma/auto_linker.git",
|
git: "https://git.pleroma.social/pleroma/auto_linker.git",
|
||||||
ref: "479dd343f4e563ff91215c8275f3b5c67e032850"},
|
ref: "90613b4bae875a3610c275b7056b61ffdd53210d"},
|
||||||
{:pleroma_job_queue, "~> 0.2.0"},
|
{:pleroma_job_queue, "~> 0.2.0"},
|
||||||
{:telemetry, "~> 0.3"},
|
{:telemetry, "~> 0.3"},
|
||||||
{:prometheus_ex, "~> 3.0"},
|
{:prometheus_ex, "~> 3.0"},
|
||||||
|
|
2
mix.lock
2
mix.lock
|
@ -1,6 +1,6 @@
|
||||||
%{
|
%{
|
||||||
"accept": {:hex, :accept, "0.3.5", "b33b127abca7cc948bbe6caa4c263369abf1347cfa9d8e699c6d214660f10cd1", [:rebar3], [], "hexpm"},
|
"accept": {:hex, :accept, "0.3.5", "b33b127abca7cc948bbe6caa4c263369abf1347cfa9d8e699c6d214660f10cd1", [:rebar3], [], "hexpm"},
|
||||||
"auto_linker": {:git, "https://git.pleroma.social/pleroma/auto_linker.git", "479dd343f4e563ff91215c8275f3b5c67e032850", [ref: "479dd343f4e563ff91215c8275f3b5c67e032850"]},
|
"auto_linker": {:git, "https://git.pleroma.social/pleroma/auto_linker.git", "90613b4bae875a3610c275b7056b61ffdd53210d", [ref: "90613b4bae875a3610c275b7056b61ffdd53210d"]},
|
||||||
"base64url": {:hex, :base64url, "0.0.1", "36a90125f5948e3afd7be97662a1504b934dd5dac78451ca6e9abf85a10286be", [:rebar], [], "hexpm"},
|
"base64url": {:hex, :base64url, "0.0.1", "36a90125f5948e3afd7be97662a1504b934dd5dac78451ca6e9abf85a10286be", [:rebar], [], "hexpm"},
|
||||||
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"},
|
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"},
|
||||||
"cachex": {:hex, :cachex, "3.0.2", "1351caa4e26e29f7d7ec1d29b53d6013f0447630bbf382b4fb5d5bad0209f203", [:mix], [{:eternal, "~> 1.2", [hex: :eternal, repo: "hexpm", optional: false]}, {:unsafe, "~> 1.0", [hex: :unsafe, repo: "hexpm", optional: false]}], "hexpm"},
|
"cachex": {:hex, :cachex, "3.0.2", "1351caa4e26e29f7d7ec1d29b53d6013f0447630bbf382b4fb5d5bad0209f203", [:mix], [{:eternal, "~> 1.2", [hex: :eternal, repo: "hexpm", optional: false]}, {:unsafe, "~> 1.0", [hex: :unsafe, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
|
|
|
@ -318,7 +318,7 @@ test "sends invitation and returns 204", %{conn: conn, user: user} do
|
||||||
refute token_record.used
|
refute token_record.used
|
||||||
|
|
||||||
Swoosh.TestAssertions.assert_email_sent(
|
Swoosh.TestAssertions.assert_email_sent(
|
||||||
Pleroma.UserEmail.user_invitation_email(
|
Pleroma.Emails.UserEmail.user_invitation_email(
|
||||||
user,
|
user,
|
||||||
token_record,
|
token_record,
|
||||||
recipient_email,
|
recipient_email,
|
||||||
|
|
|
@ -1473,7 +1473,7 @@ test "getting followers, pagination", %{conn: conn} do
|
||||||
assert id2 == follower2.id
|
assert id2 == follower2.id
|
||||||
|
|
||||||
assert [link_header] = get_resp_header(res_conn, "link")
|
assert [link_header] = get_resp_header(res_conn, "link")
|
||||||
assert link_header =~ ~r/since_id=#{follower2.id}/
|
assert link_header =~ ~r/min_id=#{follower2.id}/
|
||||||
assert link_header =~ ~r/max_id=#{follower2.id}/
|
assert link_header =~ ~r/max_id=#{follower2.id}/
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1552,7 +1552,7 @@ test "getting following, pagination", %{conn: conn} do
|
||||||
assert id2 == following2.id
|
assert id2 == following2.id
|
||||||
|
|
||||||
assert [link_header] = get_resp_header(res_conn, "link")
|
assert [link_header] = get_resp_header(res_conn, "link")
|
||||||
assert link_header =~ ~r/since_id=#{following2.id}/
|
assert link_header =~ ~r/min_id=#{following2.id}/
|
||||||
assert link_header =~ ~r/max_id=#{following2.id}/
|
assert link_header =~ ~r/max_id=#{following2.id}/
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -2382,7 +2382,7 @@ test "preserves parameters in link headers", %{conn: conn} do
|
||||||
|
|
||||||
assert [link_header] = get_resp_header(conn, "link")
|
assert [link_header] = get_resp_header(conn, "link")
|
||||||
assert link_header =~ ~r/media_only=true/
|
assert link_header =~ ~r/media_only=true/
|
||||||
assert link_header =~ ~r/since_id=#{notification2.id}/
|
assert link_header =~ ~r/min_id=#{notification2.id}/
|
||||||
assert link_header =~ ~r/max_id=#{notification1.id}/
|
assert link_header =~ ~r/max_id=#{notification1.id}/
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1064,7 +1064,7 @@ test "it sends an email to user", %{user: user} do
|
||||||
token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
|
token_record = Repo.get_by(Pleroma.PasswordResetToken, user_id: user.id)
|
||||||
|
|
||||||
Swoosh.TestAssertions.assert_email_sent(
|
Swoosh.TestAssertions.assert_email_sent(
|
||||||
Pleroma.UserEmail.password_reset_email(user, token_record.token)
|
Pleroma.Emails.UserEmail.password_reset_email(user, token_record.token)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1163,7 +1163,9 @@ test "it sends confirmation email", %{conn: conn, user: user} do
|
||||||
|> assign(:user, user)
|
|> assign(:user, user)
|
||||||
|> post("/api/account/resend_confirmation_email?email=#{user.email}")
|
|> post("/api/account/resend_confirmation_email?email=#{user.email}")
|
||||||
|
|
||||||
Swoosh.TestAssertions.assert_email_sent(Pleroma.UserEmail.account_confirmation_email(user))
|
Swoosh.TestAssertions.assert_email_sent(
|
||||||
|
Pleroma.Emails.UserEmail.account_confirmation_email(user)
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -325,7 +325,9 @@ test "it sends confirmation email if :account_activation_required is specified i
|
||||||
|
|
||||||
assert user.info.confirmation_pending
|
assert user.info.confirmation_pending
|
||||||
|
|
||||||
Swoosh.TestAssertions.assert_email_sent(Pleroma.UserEmail.account_confirmation_email(user))
|
Swoosh.TestAssertions.assert_email_sent(
|
||||||
|
Pleroma.Emails.UserEmail.account_confirmation_email(user)
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it registers a new user and parses mentions in the bio" do
|
test "it registers a new user and parses mentions in the bio" do
|
||||||
|
|
Loading…
Reference in a new issue