Merge remote-tracking branch 'origin/develop' into shigusegubu
This commit is contained in:
commit
4e05e7a989
84 changed files with 965 additions and 320 deletions
12
CHANGELOG.md
12
CHANGELOG.md
|
@ -4,6 +4,18 @@ 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/).
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
|
|
||||||
|
## 2.7.1
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Accept `application/activity+json` for requests to `/.well-known/nodeinfo`
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Truncate remote user fields, avoids them getting rejected
|
||||||
|
- Improve the `FollowValidator` to successfully incoming activities with an errant `cc` field.
|
||||||
|
- Resolved edge case where the API can report you are following a user but the relationship is not fully established.
|
||||||
|
- The Swoosh email adapter for Mailgun was missing a new dependency on `:multipart`
|
||||||
|
- Fix Mastodon WebSocket authentication
|
||||||
|
|
||||||
## 2.7.0
|
## 2.7.0
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
1
changelog.d/activity-pub-metadata.add
Normal file
1
changelog.d/activity-pub-metadata.add
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Add metadata provider for ActivityPub alternate links
|
1
changelog.d/atom-tag.change
Normal file
1
changelog.d/atom-tag.change
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Metadata: Do not include .atom feed links for remote accounts
|
|
@ -1 +0,0 @@
|
||||||
Truncate remote user fields, avoids them getting rejected
|
|
1
changelog.d/bump-lexbor.change
Normal file
1
changelog.d/bump-lexbor.change
Normal file
|
@ -0,0 +1 @@
|
||||||
|
- Bumped `fast_html` to v2.3.0, which notably allows to use system-installed lexbor with passing `WITH_SYSTEM_LEXBOR=1` environment variable at build-time
|
1
changelog.d/debian-install-improve.skip
Normal file
1
changelog.d/debian-install-improve.skip
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Fixed a formatting issue that had a required commend embedded in a textblock, and change the language to make it a bit more idiomatic.
|
1
changelog.d/dedupe-sharding.change
Normal file
1
changelog.d/dedupe-sharding.change
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Dedupe upload filter now uses a three-level sharding directory structure
|
0
changelog.d/docs-vips.skip
Normal file
0
changelog.d/docs-vips.skip
Normal file
|
@ -1 +0,0 @@
|
||||||
Improve the FollowValidator to successfully incoming activities with an errant cc field.
|
|
|
@ -1 +0,0 @@
|
||||||
Resolved edge case where the API can report you are following a user but the relationship is not fully established.
|
|
0
changelog.d/freebsd-docs.skip
Normal file
0
changelog.d/freebsd-docs.skip
Normal file
1
changelog.d/hashtag-feeds-restricted.add
Normal file
1
changelog.d/hashtag-feeds-restricted.add
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Repesct :restrict_unauthenticated for hashtag rss/atom feeds
|
1
changelog.d/incoming-blocks.fix
Normal file
1
changelog.d/incoming-blocks.fix
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Fix incoming Block activities being rejected
|
1
changelog.d/ldap-password-change.add
Normal file
1
changelog.d/ldap-password-change.add
Normal file
|
@ -0,0 +1 @@
|
||||||
|
LDAP now supports users changing their passwords
|
|
@ -1 +0,0 @@
|
||||||
The Swoosh email adapter for Mailgun was missing a new dependency on :multipart
|
|
1
changelog.d/mediav2_status.fix
Normal file
1
changelog.d/mediav2_status.fix
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Fix /api/v2/media returning the wrong status code (202) for media processed synchronously
|
1
changelog.d/meilisearch-misc-fixes.fix
Normal file
1
changelog.d/meilisearch-misc-fixes.fix
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Miscellaneous fixes for Meilisearch support
|
1
changelog.d/module-search-in-pleroma-ctl.fix
Normal file
1
changelog.d/module-search-in-pleroma-ctl.fix
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Fix pleroma_ctl mix task calls sometimes not being found
|
1
changelog.d/poll-refresh.change
Normal file
1
changelog.d/poll-refresh.change
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Poll results refreshing is handled asynchronously and will not attempt to keep fetching updates to a closed poll.
|
1
changelog.d/release-tuning.change
Normal file
1
changelog.d/release-tuning.change
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Tuning for release builds to lower CPU usage.
|
1
changelog.d/remote-report-policy.add
Normal file
1
changelog.d/remote-report-policy.add
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Added RemoteReportPolicy from Rebased for handling bogus federated reports
|
1
changelog.d/se-opt-out.change
Normal file
1
changelog.d/se-opt-out.change
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Fix nonexisting user will not generate metadata for search engine opt-out
|
1
changelog.d/token-view-scopes.add
Normal file
1
changelog.d/token-view-scopes.add
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Include session scopes in TokenView
|
1
changelog.d/vapid_keyword_fallback.fix
Normal file
1
changelog.d/vapid_keyword_fallback.fix
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Make vapid_config return empty array, fixing preloading for instances without push notifications configured
|
|
@ -1 +0,0 @@
|
||||||
Accept application/activity+json for requests to .well-known/nodeinfo
|
|
|
@ -447,6 +447,11 @@ config :pleroma, :mrf_follow_bot, follower_nickname: nil
|
||||||
|
|
||||||
config :pleroma, :mrf_inline_quote, template: "<bdi>RT:</bdi> {url}"
|
config :pleroma, :mrf_inline_quote, template: "<bdi>RT:</bdi> {url}"
|
||||||
|
|
||||||
|
config :pleroma, :mrf_remote_report,
|
||||||
|
reject_all: false,
|
||||||
|
reject_anonymous: true,
|
||||||
|
reject_empty_message: true
|
||||||
|
|
||||||
config :pleroma, :mrf_force_mention,
|
config :pleroma, :mrf_force_mention,
|
||||||
mention_parent: true,
|
mention_parent: true,
|
||||||
mention_quoted: true
|
mention_quoted: true
|
||||||
|
|
|
@ -69,12 +69,18 @@ cd /opt/pleroma
|
||||||
sudo -Hu pleroma mix deps.get
|
sudo -Hu pleroma mix deps.get
|
||||||
```
|
```
|
||||||
|
|
||||||
* Generate the configuration: `sudo -Hu pleroma MIX_ENV=prod mix pleroma.instance gen`
|
* Generate the configuration:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
sudo -Hu pleroma MIX_ENV=prod mix pleroma.instance gen`
|
||||||
|
```
|
||||||
|
|
||||||
|
* During this process:
|
||||||
* Answer with `yes` if it asks you to install `rebar3`.
|
* Answer with `yes` if it asks you to install `rebar3`.
|
||||||
* This may take some time, because parts of pleroma get compiled first.
|
* This may take some time, because parts of pleroma get compiled first.
|
||||||
* After that it will ask you a few questions about your instance and generates a configuration file in `config/generated_config.exs`.
|
* After that it will ask you a few questions about your instance and generates a configuration file in `config/generated_config.exs`.
|
||||||
|
|
||||||
* Check the configuration and if all looks right, rename it, so Pleroma will load it (`prod.secret.exs` for productive instance, `dev.secret.exs` for development instances):
|
* Check the configuration and if all looks right, rename it, so Pleroma will load it (`prod.secret.exs` for production instances, `dev.secret.exs` for development instances):
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
sudo -Hu pleroma mv config/{generated_config.exs,prod.secret.exs}
|
sudo -Hu pleroma mv config/{generated_config.exs,prod.secret.exs}
|
||||||
|
|
|
@ -31,7 +31,7 @@ Setup the required services to automatically start at boot, using `sysrc(8)`.
|
||||||
### Install media / graphics packages (optional, see [`docs/installation/optional/media_graphics_packages.md`](../installation/optional/media_graphics_packages.md))
|
### Install media / graphics packages (optional, see [`docs/installation/optional/media_graphics_packages.md`](../installation/optional/media_graphics_packages.md))
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# pkg install imagemagick ffmpeg p5-Image-ExifTool
|
# pkg install imagemagick ffmpeg p5-Image-ExifTool vips
|
||||||
```
|
```
|
||||||
|
|
||||||
## Configuring Pleroma
|
## Configuring Pleroma
|
||||||
|
|
|
@ -12,7 +12,7 @@ For any additional information regarding commands and configuration files mentio
|
||||||
To install them, run the following command (with doas or as root):
|
To install them, run the following command (with doas or as root):
|
||||||
|
|
||||||
```
|
```
|
||||||
pkg_add elixir gmake git postgresql-server postgresql-contrib cmake ffmpeg ImageMagick
|
pkg_add elixir gmake git postgresql-server postgresql-contrib cmake ffmpeg ImageMagick libvips
|
||||||
```
|
```
|
||||||
|
|
||||||
Pleroma requires a reverse proxy, OpenBSD has relayd in base (and is used in this guide) and packages/ports are available for nginx (www/nginx) and apache (www/apache-httpd). Independently of the reverse proxy, [acme-client(1)](https://man.openbsd.org/acme-client) can be used to get a certificate from Let's Encrypt.
|
Pleroma requires a reverse proxy, OpenBSD has relayd in base (and is used in this guide) and packages/ports are available for nginx (www/nginx) and apache (www/apache-httpd). Independently of the reverse proxy, [acme-client(1)](https://man.openbsd.org/acme-client) can be used to get a certificate from Let's Encrypt.
|
||||||
|
|
|
@ -18,7 +18,7 @@ Matrix-kanava #pleroma:libera.chat ovat hyviä paikkoja löytää apua
|
||||||
|
|
||||||
Asenna tarvittava ohjelmisto:
|
Asenna tarvittava ohjelmisto:
|
||||||
|
|
||||||
`# pkg_add git elixir gmake postgresql-server-10.3 postgresql-contrib-10.3 cmake ffmpeg ImageMagick`
|
`# pkg_add git elixir gmake postgresql-server-10.3 postgresql-contrib-10.3 cmake ffmpeg ImageMagick libvips`
|
||||||
|
|
||||||
#### Optional software
|
#### Optional software
|
||||||
|
|
||||||
|
|
7
installation/openldap/pw_self_service.ldif
Normal file
7
installation/openldap/pw_self_service.ldif
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
dn: olcDatabase={1}mdb,cn=config
|
||||||
|
changetype: modify
|
||||||
|
add: olcAccess
|
||||||
|
olcAccess: {1}to attrs=userPassword
|
||||||
|
by self write
|
||||||
|
by anonymous auth
|
||||||
|
by * none
|
|
@ -9,7 +9,7 @@ defmodule Mix.Tasks.Pleroma.Search.Meilisearch do
|
||||||
import Ecto.Query
|
import Ecto.Query
|
||||||
|
|
||||||
import Pleroma.Search.Meilisearch,
|
import Pleroma.Search.Meilisearch,
|
||||||
only: [meili_post: 2, meili_put: 2, meili_get: 1, meili_delete: 1]
|
only: [meili_put: 2, meili_get: 1, meili_delete: 1]
|
||||||
|
|
||||||
def run(["index"]) do
|
def run(["index"]) do
|
||||||
start_pleroma()
|
start_pleroma()
|
||||||
|
@ -28,7 +28,7 @@ defmodule Mix.Tasks.Pleroma.Search.Meilisearch do
|
||||||
end
|
end
|
||||||
|
|
||||||
{:ok, _} =
|
{:ok, _} =
|
||||||
meili_post(
|
meili_put(
|
||||||
"/indexes/objects/settings/ranking-rules",
|
"/indexes/objects/settings/ranking-rules",
|
||||||
[
|
[
|
||||||
"published:desc",
|
"published:desc",
|
||||||
|
@ -42,7 +42,7 @@ defmodule Mix.Tasks.Pleroma.Search.Meilisearch do
|
||||||
)
|
)
|
||||||
|
|
||||||
{:ok, _} =
|
{:ok, _} =
|
||||||
meili_post(
|
meili_put(
|
||||||
"/indexes/objects/settings/searchable-attributes",
|
"/indexes/objects/settings/searchable-attributes",
|
||||||
[
|
[
|
||||||
"content"
|
"content"
|
||||||
|
|
|
@ -87,6 +87,7 @@ defmodule Pleroma.Constants do
|
||||||
|
|
||||||
const(activity_types,
|
const(activity_types,
|
||||||
do: [
|
do: [
|
||||||
|
"Block",
|
||||||
"Create",
|
"Create",
|
||||||
"Update",
|
"Update",
|
||||||
"Delete",
|
"Delete",
|
||||||
|
@ -115,6 +116,10 @@ defmodule Pleroma.Constants do
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const(object_types,
|
||||||
|
do: ~w[Event Question Answer Audio Video Image Article Note Page ChatMessage]
|
||||||
|
)
|
||||||
|
|
||||||
# basic regex, just there to weed out potential mistakes
|
# basic regex, just there to weed out potential mistakes
|
||||||
# https://datatracker.ietf.org/doc/html/rfc2045#section-5.1
|
# https://datatracker.ietf.org/doc/html/rfc2045#section-5.1
|
||||||
const(mime_regex,
|
const(mime_regex,
|
||||||
|
|
|
@ -74,11 +74,14 @@ defmodule Pleroma.Frontend do
|
||||||
|
|
||||||
new_file_path = Path.join(dest, path)
|
new_file_path = Path.join(dest, path)
|
||||||
|
|
||||||
new_file_path
|
path
|
||||||
|> Path.dirname()
|
|> Path.dirname()
|
||||||
|
|> then(&Path.join(dest, &1))
|
||||||
|> File.mkdir_p!()
|
|> File.mkdir_p!()
|
||||||
|
|
||||||
File.write!(new_file_path, data)
|
if not File.dir?(new_file_path) do
|
||||||
|
File.write!(new_file_path, data)
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -15,6 +15,14 @@ defmodule Pleroma.LDAP do
|
||||||
GenServer.start_link(__MODULE__, [], name: __MODULE__)
|
GenServer.start_link(__MODULE__, [], name: __MODULE__)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def bind_user(name, password) do
|
||||||
|
GenServer.call(__MODULE__, {:bind_user, name, password})
|
||||||
|
end
|
||||||
|
|
||||||
|
def change_password(name, password, new_password) do
|
||||||
|
GenServer.call(__MODULE__, {:change_password, name, password, new_password})
|
||||||
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def init(state) do
|
def init(state) do
|
||||||
case {Config.get(Pleroma.Web.Auth.Authenticator), Config.get([:ldap, :enabled])} do
|
case {Config.get(Pleroma.Web.Auth.Authenticator), Config.get([:ldap, :enabled])} do
|
||||||
|
@ -47,13 +55,42 @@ defmodule Pleroma.LDAP do
|
||||||
def handle_info(:connect, _state), do: do_handle_connect()
|
def handle_info(:connect, _state), do: do_handle_connect()
|
||||||
|
|
||||||
def handle_info({:bind_after_reconnect, name, password, from}, state) do
|
def handle_info({:bind_after_reconnect, name, password, from}, state) do
|
||||||
result = bind_user(state[:handle], name, password)
|
result = do_bind_user(state[:handle], name, password)
|
||||||
|
|
||||||
GenServer.reply(from, result)
|
GenServer.reply(from, result)
|
||||||
|
|
||||||
{:noreply, state}
|
{:noreply, state}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def handle_call({:bind_user, name, password}, from, state) do
|
||||||
|
case do_bind_user(state[:handle], name, password) do
|
||||||
|
:needs_reconnect ->
|
||||||
|
Process.send(self(), {:bind_after_reconnect, name, password, from}, [])
|
||||||
|
{:noreply, state, {:continue, :connect}}
|
||||||
|
|
||||||
|
result ->
|
||||||
|
{:reply, result, state, :hibernate}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_call({:change_password, name, password, new_password}, _from, state) do
|
||||||
|
result = change_password(state[:handle], name, password, new_password)
|
||||||
|
|
||||||
|
{:reply, result, state, :hibernate}
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def terminate(_, state) do
|
||||||
|
handle = Keyword.get(state, :handle)
|
||||||
|
|
||||||
|
if not is_nil(handle) do
|
||||||
|
:eldap.close(handle)
|
||||||
|
end
|
||||||
|
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
|
||||||
defp do_handle_connect do
|
defp do_handle_connect do
|
||||||
state =
|
state =
|
||||||
case connect() do
|
case connect() do
|
||||||
|
@ -71,33 +108,6 @@ defmodule Pleroma.LDAP do
|
||||||
{:noreply, state}
|
{:noreply, state}
|
||||||
end
|
end
|
||||||
|
|
||||||
@impl true
|
|
||||||
def handle_call({:bind_user, name, password}, from, state) do
|
|
||||||
case bind_user(state[:handle], name, password) do
|
|
||||||
:needs_reconnect ->
|
|
||||||
Process.send(self(), {:bind_after_reconnect, name, password, from}, [])
|
|
||||||
{:noreply, state, {:continue, :connect}}
|
|
||||||
|
|
||||||
result ->
|
|
||||||
{:reply, result, state, :hibernate}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
@impl true
|
|
||||||
def terminate(_, state) do
|
|
||||||
handle = Keyword.get(state, :handle)
|
|
||||||
|
|
||||||
if not is_nil(handle) do
|
|
||||||
:eldap.close(handle)
|
|
||||||
end
|
|
||||||
|
|
||||||
:ok
|
|
||||||
end
|
|
||||||
|
|
||||||
def bind_user(name, password) do
|
|
||||||
GenServer.call(__MODULE__, {:bind_user, name, password})
|
|
||||||
end
|
|
||||||
|
|
||||||
defp connect do
|
defp connect do
|
||||||
ldap = Config.get(:ldap, [])
|
ldap = Config.get(:ldap, [])
|
||||||
host = Keyword.get(ldap, :host, "localhost")
|
host = Keyword.get(ldap, :host, "localhost")
|
||||||
|
@ -161,18 +171,17 @@ defmodule Pleroma.LDAP do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp bind_user(handle, name, password) do
|
defp do_bind_user(handle, name, password) do
|
||||||
uid = Config.get([:ldap, :uid], "cn")
|
dn = make_dn(name)
|
||||||
base = Config.get([:ldap, :base])
|
|
||||||
|
|
||||||
case :eldap.simple_bind(handle, "#{uid}=#{name},#{base}", password) do
|
case :eldap.simple_bind(handle, dn, password) do
|
||||||
:ok ->
|
:ok ->
|
||||||
case fetch_user(name) do
|
case fetch_user(name) do
|
||||||
%User{} = user ->
|
%User{} = user ->
|
||||||
user
|
user
|
||||||
|
|
||||||
_ ->
|
_ ->
|
||||||
register_user(handle, base, uid, name)
|
register_user(handle, ldap_base(), ldap_uid(), name)
|
||||||
end
|
end
|
||||||
|
|
||||||
# eldap does not inform us of socket closure
|
# eldap does not inform us of socket closure
|
||||||
|
@ -231,6 +240,14 @@ defmodule Pleroma.LDAP do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp change_password(handle, name, password, new_password) do
|
||||||
|
dn = make_dn(name)
|
||||||
|
|
||||||
|
with :ok <- :eldap.simple_bind(handle, dn, password) do
|
||||||
|
:eldap.modify_password(handle, dn, to_charlist(new_password), to_charlist(password))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
defp decode_certfile(file) do
|
defp decode_certfile(file) do
|
||||||
with {:ok, data} <- File.read(file) do
|
with {:ok, data} <- File.read(file) do
|
||||||
data
|
data
|
||||||
|
@ -242,4 +259,13 @@ defmodule Pleroma.LDAP do
|
||||||
[]
|
[]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp ldap_uid, do: to_charlist(Config.get([:ldap, :uid], "cn"))
|
||||||
|
defp ldap_base, do: to_charlist(Config.get([:ldap, :base]))
|
||||||
|
|
||||||
|
defp make_dn(name) do
|
||||||
|
uid = ldap_uid()
|
||||||
|
base = ldap_base()
|
||||||
|
~c"#{uid}=#{name},#{base}"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -99,27 +99,6 @@ defmodule Pleroma.Object do
|
||||||
def get_by_id(nil), do: nil
|
def get_by_id(nil), do: nil
|
||||||
def get_by_id(id), do: Repo.get(Object, id)
|
def get_by_id(id), do: Repo.get(Object, id)
|
||||||
|
|
||||||
@spec get_by_id_and_maybe_refetch(integer(), list()) :: Object.t() | nil
|
|
||||||
def get_by_id_and_maybe_refetch(id, opts \\ []) do
|
|
||||||
with %Object{updated_at: updated_at} = object <- get_by_id(id) do
|
|
||||||
if opts[:interval] &&
|
|
||||||
NaiveDateTime.diff(NaiveDateTime.utc_now(), updated_at) > opts[:interval] do
|
|
||||||
case Fetcher.refetch_object(object) do
|
|
||||||
{:ok, %Object{} = object} ->
|
|
||||||
object
|
|
||||||
|
|
||||||
e ->
|
|
||||||
Logger.error("Couldn't refresh #{object.data["id"]}:\n#{inspect(e)}")
|
|
||||||
object
|
|
||||||
end
|
|
||||||
else
|
|
||||||
object
|
|
||||||
end
|
|
||||||
else
|
|
||||||
nil -> nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def get_by_ap_id(nil), do: nil
|
def get_by_ap_id(nil), do: nil
|
||||||
|
|
||||||
def get_by_ap_id(ap_id) do
|
def get_by_ap_id(ap_id) do
|
||||||
|
|
|
@ -16,17 +16,24 @@ defmodule Pleroma.ReleaseTasks do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def find_module(task) do
|
||||||
|
module_name =
|
||||||
|
task
|
||||||
|
|> String.split(".")
|
||||||
|
|> Enum.map(&String.capitalize/1)
|
||||||
|
|> then(fn x -> [Mix, Tasks, Pleroma] ++ x end)
|
||||||
|
|> Module.concat()
|
||||||
|
|
||||||
|
case Code.ensure_loaded(module_name) do
|
||||||
|
{:module, _} -> module_name
|
||||||
|
_ -> nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
defp mix_task(task, args) do
|
defp mix_task(task, args) do
|
||||||
Application.load(:pleroma)
|
Application.load(:pleroma)
|
||||||
{:ok, modules} = :application.get_key(:pleroma, :modules)
|
|
||||||
|
|
||||||
module =
|
module = find_module(task)
|
||||||
Enum.find(modules, fn module ->
|
|
||||||
module = Module.split(module)
|
|
||||||
|
|
||||||
match?(["Mix", "Tasks", "Pleroma" | _], module) and
|
|
||||||
String.downcase(List.last(module)) == task
|
|
||||||
end)
|
|
||||||
|
|
||||||
if module do
|
if module do
|
||||||
module.run(args)
|
module.run(args)
|
||||||
|
|
|
@ -122,6 +122,7 @@ defmodule Pleroma.Search.Meilisearch do
|
||||||
# Only index public or unlisted Notes
|
# Only index public or unlisted Notes
|
||||||
if not is_nil(object) and object.data["type"] == "Note" and
|
if not is_nil(object) and object.data["type"] == "Note" and
|
||||||
not is_nil(object.data["content"]) and
|
not is_nil(object.data["content"]) and
|
||||||
|
not is_nil(object.data["published"]) and
|
||||||
(Pleroma.Constants.as_public() in object.data["to"] or
|
(Pleroma.Constants.as_public() in object.data["to"] or
|
||||||
Pleroma.Constants.as_public() in object.data["cc"]) and
|
Pleroma.Constants.as_public() in object.data["cc"]) and
|
||||||
object.data["content"] not in ["", "."] do
|
object.data["content"] not in ["", "."] do
|
||||||
|
|
|
@ -17,8 +17,16 @@ defmodule Pleroma.Upload.Filter.Dedupe do
|
||||||
|> Base.encode16(case: :lower)
|
|> Base.encode16(case: :lower)
|
||||||
|
|
||||||
filename = shasum <> "." <> extension
|
filename = shasum <> "." <> extension
|
||||||
{:ok, :filtered, %Upload{upload | id: shasum, path: filename}}
|
|
||||||
|
{:ok, :filtered, %Upload{upload | id: shasum, path: shard_path(filename)}}
|
||||||
end
|
end
|
||||||
|
|
||||||
def filter(_), do: {:ok, :noop}
|
def filter(_), do: {:ok, :noop}
|
||||||
|
|
||||||
|
@spec shard_path(String.t()) :: String.t()
|
||||||
|
def shard_path(
|
||||||
|
<<a::binary-size(2), b::binary-size(2), c::binary-size(2), _::binary>> = filename
|
||||||
|
) do
|
||||||
|
Path.join([a, b, c, filename])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
118
lib/pleroma/web/activity_pub/mrf/remote_report_policy.ex
Normal file
118
lib/pleroma/web/activity_pub/mrf/remote_report_policy.ex
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
defmodule Pleroma.Web.ActivityPub.MRF.RemoteReportPolicy do
|
||||||
|
@moduledoc "Drop remote reports if they don't contain enough information."
|
||||||
|
@behaviour Pleroma.Web.ActivityPub.MRF.Policy
|
||||||
|
|
||||||
|
alias Pleroma.Config
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def filter(%{"type" => "Flag"} = object) do
|
||||||
|
with {_, false} <- {:local, local?(object)},
|
||||||
|
{:ok, _} <- maybe_reject_all(object),
|
||||||
|
{:ok, _} <- maybe_reject_anonymous(object),
|
||||||
|
{:ok, _} <- maybe_reject_third_party(object),
|
||||||
|
{:ok, _} <- maybe_reject_empty_message(object) do
|
||||||
|
{:ok, object}
|
||||||
|
else
|
||||||
|
{:local, true} -> {:ok, object}
|
||||||
|
{:reject, message} -> {:reject, message}
|
||||||
|
error -> {:reject, error}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def filter(object), do: {:ok, object}
|
||||||
|
|
||||||
|
defp maybe_reject_all(object) do
|
||||||
|
if Config.get([:mrf_remote_report, :reject_all]) do
|
||||||
|
{:reject, "[RemoteReportPolicy] Remote report"}
|
||||||
|
else
|
||||||
|
{:ok, object}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp maybe_reject_anonymous(%{"actor" => actor} = object) do
|
||||||
|
with true <- Config.get([:mrf_remote_report, :reject_anonymous]),
|
||||||
|
%URI{path: "/actor"} <- URI.parse(actor) do
|
||||||
|
{:reject, "[RemoteReportPolicy] Anonymous: #{actor}"}
|
||||||
|
else
|
||||||
|
_ -> {:ok, object}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp maybe_reject_third_party(%{"object" => objects} = object) do
|
||||||
|
{_, to} =
|
||||||
|
case objects do
|
||||||
|
[head | tail] when is_binary(head) -> {tail, head}
|
||||||
|
s when is_binary(s) -> {[], s}
|
||||||
|
_ -> {[], ""}
|
||||||
|
end
|
||||||
|
|
||||||
|
with true <- Config.get([:mrf_remote_report, :reject_third_party]),
|
||||||
|
false <- String.starts_with?(to, Pleroma.Web.Endpoint.url()) do
|
||||||
|
{:reject, "[RemoteReportPolicy] Third-party: #{to}"}
|
||||||
|
else
|
||||||
|
_ -> {:ok, object}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp maybe_reject_empty_message(%{"content" => content} = object)
|
||||||
|
when is_binary(content) and content != "" do
|
||||||
|
{:ok, object}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp maybe_reject_empty_message(object) do
|
||||||
|
if Config.get([:mrf_remote_report, :reject_empty_message]) do
|
||||||
|
{:reject, ["RemoteReportPolicy] No content"]}
|
||||||
|
else
|
||||||
|
{:ok, object}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp local?(%{"actor" => actor}) do
|
||||||
|
String.starts_with?(actor, Pleroma.Web.Endpoint.url())
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def describe do
|
||||||
|
mrf_remote_report =
|
||||||
|
Config.get(:mrf_remote_report)
|
||||||
|
|> Enum.into(%{})
|
||||||
|
|
||||||
|
{:ok, %{mrf_remote_report: mrf_remote_report}}
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def config_description do
|
||||||
|
%{
|
||||||
|
key: :mrf_remote_report,
|
||||||
|
related_policy: "Pleroma.Web.ActivityPub.MRF.RemoteReportPolicy",
|
||||||
|
label: "MRF Remote Report",
|
||||||
|
description: "Drop remote reports if they don't contain enough information.",
|
||||||
|
children: [
|
||||||
|
%{
|
||||||
|
key: :reject_all,
|
||||||
|
type: :boolean,
|
||||||
|
description: "Reject all remote reports? (this option takes precedence)",
|
||||||
|
suggestions: [false]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :reject_anonymous,
|
||||||
|
type: :boolean,
|
||||||
|
description: "Reject anonymous remote reports?",
|
||||||
|
suggestions: [true]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :reject_third_party,
|
||||||
|
type: :boolean,
|
||||||
|
description: "Reject reports on users from third-party instances?",
|
||||||
|
suggestions: [true]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: :reject_empty_message,
|
||||||
|
type: :boolean,
|
||||||
|
description: "Reject remote reports with no message?",
|
||||||
|
suggestions: [true]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
|
@ -11,6 +11,8 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
|
||||||
|
|
||||||
@behaviour Pleroma.Web.ActivityPub.ObjectValidator.Validating
|
@behaviour Pleroma.Web.ActivityPub.ObjectValidator.Validating
|
||||||
|
|
||||||
|
import Pleroma.Constants, only: [activity_types: 0, object_types: 0]
|
||||||
|
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
alias Pleroma.EctoType.ActivityPub.ObjectValidators
|
alias Pleroma.EctoType.ActivityPub.ObjectValidators
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
|
@ -38,6 +40,16 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidator do
|
||||||
@impl true
|
@impl true
|
||||||
def validate(object, meta)
|
def validate(object, meta)
|
||||||
|
|
||||||
|
# This overload works together with the InboxGuardPlug
|
||||||
|
# and ensures that we are not accepting any activity type
|
||||||
|
# that cannot pass InboxGuardPlug.
|
||||||
|
# If we want to support any more activity types, make sure to
|
||||||
|
# add it in Pleroma.Constants's activity_types or object_types,
|
||||||
|
# and, if applicable, allowed_activity_types_from_strangers.
|
||||||
|
def validate(%{"type" => type}, _meta)
|
||||||
|
when type not in activity_types() and type not in object_types(),
|
||||||
|
do: {:error, :not_allowed_object_type}
|
||||||
|
|
||||||
def validate(%{"type" => "Block"} = block_activity, meta) do
|
def validate(%{"type" => "Block"} = block_activity, meta) do
|
||||||
with {:ok, block_activity} <-
|
with {:ok, block_activity} <-
|
||||||
block_activity
|
block_activity
|
||||||
|
|
|
@ -121,7 +121,7 @@ defmodule Pleroma.Web.ApiSpec.MediaOperation do
|
||||||
security: [%{"oAuth" => ["write:media"]}],
|
security: [%{"oAuth" => ["write:media"]}],
|
||||||
requestBody: Helpers.request_body("Parameters", create_request()),
|
requestBody: Helpers.request_body("Parameters", create_request()),
|
||||||
responses: %{
|
responses: %{
|
||||||
202 => Operation.response("Media", "application/json", Attachment),
|
200 => Operation.response("Media", "application/json", Attachment),
|
||||||
400 => Operation.response("Media", "application/json", ApiError),
|
400 => Operation.response("Media", "application/json", ApiError),
|
||||||
422 => Operation.response("Media", "application/json", ApiError),
|
422 => Operation.response("Media", "application/json", ApiError),
|
||||||
500 => Operation.response("Media", "application/json", ApiError)
|
500 => Operation.response("Media", "application/json", ApiError)
|
||||||
|
|
|
@ -10,4 +10,9 @@ defmodule Pleroma.Web.Auth.Authenticator do
|
||||||
@callback handle_error(Plug.Conn.t(), any()) :: any()
|
@callback handle_error(Plug.Conn.t(), any()) :: any()
|
||||||
@callback auth_template() :: String.t() | nil
|
@callback auth_template() :: String.t() | nil
|
||||||
@callback oauth_consumer_template() :: String.t() | nil
|
@callback oauth_consumer_template() :: String.t() | nil
|
||||||
|
|
||||||
|
@callback change_password(Pleroma.User.t(), String.t(), String.t(), String.t()) ::
|
||||||
|
{:ok, Pleroma.User.t()} | {:error, term()}
|
||||||
|
|
||||||
|
@optional_callbacks change_password: 4
|
||||||
end
|
end
|
||||||
|
|
|
@ -30,4 +30,13 @@ defmodule Pleroma.Web.Auth.LDAPAuthenticator do
|
||||||
error
|
error
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def change_password(user, password, new_password, new_password) do
|
||||||
|
case LDAP.change_password(user.nickname, password, new_password) do
|
||||||
|
:ok -> {:ok, user}
|
||||||
|
e -> e
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def change_password(_, _, _, _), do: {:error, :password_confirmation}
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,6 +6,7 @@ defmodule Pleroma.Web.Auth.PleromaAuthenticator do
|
||||||
alias Pleroma.Registration
|
alias Pleroma.Registration
|
||||||
alias Pleroma.Repo
|
alias Pleroma.Repo
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
|
alias Pleroma.Web.CommonAPI
|
||||||
alias Pleroma.Web.Plugs.AuthenticationPlug
|
alias Pleroma.Web.Plugs.AuthenticationPlug
|
||||||
|
|
||||||
import Pleroma.Web.Auth.Helpers, only: [fetch_credentials: 1, fetch_user: 1]
|
import Pleroma.Web.Auth.Helpers, only: [fetch_credentials: 1, fetch_user: 1]
|
||||||
|
@ -101,4 +102,23 @@ defmodule Pleroma.Web.Auth.PleromaAuthenticator do
|
||||||
def auth_template, do: nil
|
def auth_template, do: nil
|
||||||
|
|
||||||
def oauth_consumer_template, do: nil
|
def oauth_consumer_template, do: nil
|
||||||
|
|
||||||
|
@doc "Changes Pleroma.User password in the database"
|
||||||
|
def change_password(user, password, new_password, new_password) do
|
||||||
|
case CommonAPI.Utils.confirm_current_password(user, password) do
|
||||||
|
{:ok, user} ->
|
||||||
|
with {:ok, _user} <-
|
||||||
|
User.reset_password(user, %{
|
||||||
|
password: new_password,
|
||||||
|
password_confirmation: new_password
|
||||||
|
}) do
|
||||||
|
{:ok, user}
|
||||||
|
end
|
||||||
|
|
||||||
|
error ->
|
||||||
|
error
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def change_password(_, _, _, _), do: {:error, :password_confirmation}
|
||||||
end
|
end
|
||||||
|
|
|
@ -39,4 +39,8 @@ defmodule Pleroma.Web.Auth.WrapperAuthenticator do
|
||||||
implementation().oauth_consumer_template() ||
|
implementation().oauth_consumer_template() ||
|
||||||
Pleroma.Config.get([:auth, :oauth_consumer_template], "consumer.html")
|
Pleroma.Config.get([:auth, :oauth_consumer_template], "consumer.html")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def change_password(user, password, new_password, new_password_confirmation),
|
||||||
|
do: implementation().change_password(user, password, new_password, new_password_confirmation)
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,6 +14,7 @@ defmodule Pleroma.Web.Endpoint do
|
||||||
websocket: [
|
websocket: [
|
||||||
path: "/",
|
path: "/",
|
||||||
compress: false,
|
compress: false,
|
||||||
|
connect_info: [:sec_websocket_protocol],
|
||||||
error_handler: {Pleroma.Web.MastodonAPI.WebsocketHandler, :handle_error, []},
|
error_handler: {Pleroma.Web.MastodonAPI.WebsocketHandler, :handle_error, []},
|
||||||
fullsweep_after: 20
|
fullsweep_after: 20
|
||||||
]
|
]
|
||||||
|
|
|
@ -46,7 +46,7 @@ defmodule Pleroma.Web.Fallback.RedirectController do
|
||||||
redirector_with_meta(conn, %{user: user})
|
redirector_with_meta(conn, %{user: user})
|
||||||
else
|
else
|
||||||
nil ->
|
nil ->
|
||||||
redirector(conn, params)
|
redirector_with_meta(conn, Map.delete(params, "maybe_nickname_or_id"))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ defmodule Pleroma.Web.Feed.TagController do
|
||||||
alias Pleroma.Web.Feed.FeedView
|
alias Pleroma.Web.Feed.FeedView
|
||||||
|
|
||||||
def feed(conn, params) do
|
def feed(conn, params) do
|
||||||
if Config.get!([:instance, :public]) do
|
if not Config.restrict_unauthenticated_access?(:timelines, :local) do
|
||||||
render_feed(conn, params)
|
render_feed(conn, params)
|
||||||
else
|
else
|
||||||
render_error(conn, :not_found, "Not found")
|
render_error(conn, :not_found, "Not found")
|
||||||
|
@ -18,10 +18,12 @@ defmodule Pleroma.Web.Feed.TagController do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp render_feed(conn, %{"tag" => raw_tag} = params) do
|
defp render_feed(conn, %{"tag" => raw_tag} = params) do
|
||||||
|
local_only = Config.restrict_unauthenticated_access?(:timelines, :federated)
|
||||||
|
|
||||||
{format, tag} = parse_tag(raw_tag)
|
{format, tag} = parse_tag(raw_tag)
|
||||||
|
|
||||||
activities =
|
activities =
|
||||||
%{type: ["Create"], tag: tag}
|
%{type: ["Create"], tag: tag, local_only: local_only}
|
||||||
|> Pleroma.Maps.put_if_present(:max_id, params["max_id"])
|
|> Pleroma.Maps.put_if_present(:max_id, params["max_id"])
|
||||||
|> ActivityPub.fetch_public_activities()
|
|> ActivityPub.fetch_public_activities()
|
||||||
|
|
||||||
|
|
|
@ -15,11 +15,11 @@ defmodule Pleroma.Web.Feed.UserController do
|
||||||
|
|
||||||
action_fallback(:errors)
|
action_fallback(:errors)
|
||||||
|
|
||||||
def feed_redirect(%{assigns: %{format: "html"}} = conn, %{"nickname" => nickname}) do
|
def feed_redirect(%{assigns: %{format: "html"}} = conn, %{"nickname" => nickname} = params) do
|
||||||
with {_, %User{} = user} <- {:fetch_user, User.get_cached_by_nickname_or_id(nickname)} do
|
with {_, %User{} = user} <- {:fetch_user, User.get_cached_by_nickname_or_id(nickname)} do
|
||||||
Pleroma.Web.Fallback.RedirectController.redirector_with_meta(conn, %{user: user})
|
Pleroma.Web.Fallback.RedirectController.redirector_with_meta(conn, %{user: user})
|
||||||
else
|
else
|
||||||
_ -> Pleroma.Web.Fallback.RedirectController.redirector(conn, nil)
|
_ -> Pleroma.Web.Fallback.RedirectController.redirector_with_meta(conn, params)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -53,9 +53,7 @@ defmodule Pleroma.Web.MastodonAPI.MediaController do
|
||||||
) do
|
) do
|
||||||
attachment_data = Map.put(object.data, "id", object.id)
|
attachment_data = Map.put(object.data, "id", object.id)
|
||||||
|
|
||||||
conn
|
render(conn, "attachment.json", %{attachment: attachment_data})
|
||||||
|> put_status(202)
|
|
||||||
|> render("attachment.json", %{attachment: attachment_data})
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ defmodule Pleroma.Web.MastodonAPI.PollController do
|
||||||
alias Pleroma.Web.ActivityPub.Visibility
|
alias Pleroma.Web.ActivityPub.Visibility
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
alias Pleroma.Web.Plugs.OAuthScopesPlug
|
alias Pleroma.Web.Plugs.OAuthScopesPlug
|
||||||
|
alias Pleroma.Workers.PollWorker
|
||||||
|
|
||||||
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
||||||
|
|
||||||
|
@ -27,12 +28,16 @@ defmodule Pleroma.Web.MastodonAPI.PollController do
|
||||||
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PollOperation
|
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.PollOperation
|
||||||
|
|
||||||
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
|
@cachex Pleroma.Config.get([:cachex, :provider], Cachex)
|
||||||
|
@poll_refresh_interval 120
|
||||||
|
|
||||||
@doc "GET /api/v1/polls/:id"
|
@doc "GET /api/v1/polls/:id"
|
||||||
def show(%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn, _) do
|
def show(%{assigns: %{user: user}, private: %{open_api_spex: %{params: %{id: id}}}} = conn, _) do
|
||||||
with %Object{} = object <- Object.get_by_id_and_maybe_refetch(id, interval: 60),
|
with %Object{} = object <- Object.get_by_id(id),
|
||||||
%Activity{} = activity <- Activity.get_create_by_object_ap_id(object.data["id"]),
|
%Activity{} = activity <-
|
||||||
|
Activity.get_create_by_object_ap_id_with_object(object.data["id"]),
|
||||||
true <- Visibility.visible_for_user?(activity, user) do
|
true <- Visibility.visible_for_user?(activity, user) do
|
||||||
|
maybe_refresh_poll(activity)
|
||||||
|
|
||||||
try_render(conn, "show.json", %{object: object, for: user})
|
try_render(conn, "show.json", %{object: object, for: user})
|
||||||
else
|
else
|
||||||
error when is_nil(error) or error == false ->
|
error when is_nil(error) or error == false ->
|
||||||
|
@ -70,4 +75,13 @@ defmodule Pleroma.Web.MastodonAPI.PollController do
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp maybe_refresh_poll(%Activity{object: %Object{} = object} = activity) do
|
||||||
|
with false <- activity.local,
|
||||||
|
{:ok, end_time} <- NaiveDateTime.from_iso8601(object.data["closed"]),
|
||||||
|
{_, :lt} <- {:closed_compare, NaiveDateTime.compare(object.updated_at, end_time)} do
|
||||||
|
PollWorker.new(%{"op" => "refresh", "activity_id" => activity.id})
|
||||||
|
|> Oban.insert(unique: [period: @poll_refresh_interval])
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -22,7 +22,7 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do
|
||||||
# This only prepares the connection and is not in the process yet
|
# This only prepares the connection and is not in the process yet
|
||||||
@impl Phoenix.Socket.Transport
|
@impl Phoenix.Socket.Transport
|
||||||
def connect(%{params: params} = transport_info) do
|
def connect(%{params: params} = transport_info) do
|
||||||
with access_token <- Map.get(params, "access_token"),
|
with access_token <- find_access_token(transport_info),
|
||||||
{:ok, user, oauth_token} <- authenticate_request(access_token),
|
{:ok, user, oauth_token} <- authenticate_request(access_token),
|
||||||
{:ok, topic} <-
|
{:ok, topic} <-
|
||||||
Streamer.get_topic(params["stream"], user, oauth_token, params) do
|
Streamer.get_topic(params["stream"], user, oauth_token, params) do
|
||||||
|
@ -244,4 +244,13 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do
|
||||||
def handle_error(conn, _reason) do
|
def handle_error(conn, _reason) do
|
||||||
Plug.Conn.send_resp(conn, 404, "Not Found")
|
Plug.Conn.send_resp(conn, 404, "Not Found")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp find_access_token(%{
|
||||||
|
connect_info: %{sec_websocket_protocol: [token]}
|
||||||
|
}),
|
||||||
|
do: token
|
||||||
|
|
||||||
|
defp find_access_token(%{params: %{"access_token" => token}}), do: token
|
||||||
|
|
||||||
|
defp find_access_token(_), do: nil
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,6 +7,7 @@ defmodule Pleroma.Web.Metadata do
|
||||||
|
|
||||||
def build_tags(params) do
|
def build_tags(params) do
|
||||||
providers = [
|
providers = [
|
||||||
|
Pleroma.Web.Metadata.Providers.ActivityPub,
|
||||||
Pleroma.Web.Metadata.Providers.RelMe,
|
Pleroma.Web.Metadata.Providers.RelMe,
|
||||||
Pleroma.Web.Metadata.Providers.RestrictIndexing
|
Pleroma.Web.Metadata.Providers.RestrictIndexing
|
||||||
| activated_providers()
|
| activated_providers()
|
||||||
|
|
22
lib/pleroma/web/metadata/providers/activity_pub.ex
Normal file
22
lib/pleroma/web/metadata/providers/activity_pub.ex
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2024 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.Metadata.Providers.ActivityPub do
|
||||||
|
alias Pleroma.Web.Metadata.Providers.Provider
|
||||||
|
|
||||||
|
@behaviour Provider
|
||||||
|
|
||||||
|
@impl Provider
|
||||||
|
def build_tags(%{object: %{data: %{"id" => object_id}}}) do
|
||||||
|
[{:link, [rel: "alternate", type: "application/activity+json", href: object_id], []}]
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl Provider
|
||||||
|
def build_tags(%{user: user}) do
|
||||||
|
[{:link, [rel: "alternate", type: "application/activity+json", href: user.ap_id], []}]
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl Provider
|
||||||
|
def build_tags(_), do: []
|
||||||
|
end
|
|
@ -10,7 +10,7 @@ defmodule Pleroma.Web.Metadata.Providers.Feed do
|
||||||
@behaviour Provider
|
@behaviour Provider
|
||||||
|
|
||||||
@impl Provider
|
@impl Provider
|
||||||
def build_tags(%{user: user}) do
|
def build_tags(%{user: %{local: true} = user}) do
|
||||||
[
|
[
|
||||||
{:link,
|
{:link,
|
||||||
[
|
[
|
||||||
|
@ -20,4 +20,7 @@ defmodule Pleroma.Web.Metadata.Providers.Feed do
|
||||||
], []}
|
], []}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@impl Provider
|
||||||
|
def build_tags(_), do: []
|
||||||
end
|
end
|
||||||
|
|
|
@ -67,6 +67,9 @@ defmodule Pleroma.Web.Metadata.Providers.OpenGraph do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@impl Provider
|
||||||
|
def build_tags(_), do: []
|
||||||
|
|
||||||
defp build_attachments(%{data: %{"attachment" => attachments}}) do
|
defp build_attachments(%{data: %{"attachment" => attachments}}) do
|
||||||
Enum.reduce(attachments, [], fn attachment, acc ->
|
Enum.reduce(attachments, [], fn attachment, acc ->
|
||||||
rendered_tags =
|
rendered_tags =
|
||||||
|
|
|
@ -20,6 +20,9 @@ defmodule Pleroma.Web.Metadata.Providers.RelMe do
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@impl Provider
|
||||||
|
def build_tags(_), do: []
|
||||||
|
|
||||||
defp append_fields_tag(bio, fields) do
|
defp append_fields_tag(bio, fields) do
|
||||||
fields
|
fields
|
||||||
|> Enum.reduce(bio, fn %{"value" => v}, res -> res <> v end)
|
|> Enum.reduce(bio, fn %{"value" => v}, res -> res <> v end)
|
||||||
|
|
|
@ -44,6 +44,9 @@ defmodule Pleroma.Web.Metadata.Providers.TwitterCard do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@impl Provider
|
||||||
|
def build_tags(_), do: []
|
||||||
|
|
||||||
defp title_tag(user) do
|
defp title_tag(user) do
|
||||||
{:meta, [name: "twitter:title", content: Utils.user_name_string(user)], []}
|
{:meta, [name: "twitter:title", content: Utils.user_name_string(user)], []}
|
||||||
end
|
end
|
||||||
|
|
|
@ -20,7 +20,7 @@ defmodule Pleroma.Web.Push do
|
||||||
end
|
end
|
||||||
|
|
||||||
def vapid_config do
|
def vapid_config do
|
||||||
Application.get_env(:web_push_encryption, :vapid_details, nil)
|
Application.get_env(:web_push_encryption, :vapid_details, [])
|
||||||
end
|
end
|
||||||
|
|
||||||
def enabled, do: match?([subject: _, public_key: _, private_key: _], vapid_config())
|
def enabled, do: match?([subject: _, public_key: _, private_key: _], vapid_config())
|
||||||
|
|
|
@ -13,6 +13,7 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
|
||||||
alias Pleroma.Healthcheck
|
alias Pleroma.Healthcheck
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
|
alias Pleroma.Web.Auth.WrapperAuthenticator, as: Authenticator
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
alias Pleroma.Web.Plugs.OAuthScopesPlug
|
alias Pleroma.Web.Plugs.OAuthScopesPlug
|
||||||
alias Pleroma.Web.WebFinger
|
alias Pleroma.Web.WebFinger
|
||||||
|
@ -195,19 +196,21 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
|
||||||
%{assigns: %{user: user}, private: %{open_api_spex: %{body_params: body_params}}} = conn,
|
%{assigns: %{user: user}, private: %{open_api_spex: %{body_params: body_params}}} = conn,
|
||||||
_
|
_
|
||||||
) do
|
) do
|
||||||
case CommonAPI.Utils.confirm_current_password(user, body_params.password) do
|
with {:ok, %User{}} <-
|
||||||
{:ok, user} ->
|
Authenticator.change_password(
|
||||||
with {:ok, _user} <-
|
user,
|
||||||
User.reset_password(user, %{
|
body_params.password,
|
||||||
password: body_params.new_password,
|
body_params.new_password,
|
||||||
password_confirmation: body_params.new_password_confirmation
|
body_params.new_password_confirmation
|
||||||
}) do
|
) do
|
||||||
json(conn, %{status: "success"})
|
json(conn, %{status: "success"})
|
||||||
else
|
else
|
||||||
{:error, changeset} ->
|
{:error, %Ecto.Changeset{} = changeset} ->
|
||||||
{_, {error, _}} = Enum.at(changeset.errors, 0)
|
{_, {error, _}} = Enum.at(changeset.errors, 0)
|
||||||
json(conn, %{error: "New password #{error}."})
|
json(conn, %{error: "New password #{error}."})
|
||||||
end
|
|
||||||
|
{:error, :password_confirmation} ->
|
||||||
|
json(conn, %{error: "New password does not match confirmation."})
|
||||||
|
|
||||||
{:error, msg} ->
|
{:error, msg} ->
|
||||||
json(conn, %{error: msg})
|
json(conn, %{error: msg})
|
||||||
|
|
|
@ -15,7 +15,8 @@ defmodule Pleroma.Web.TwitterAPI.TokenView do
|
||||||
%{
|
%{
|
||||||
id: token_entry.id,
|
id: token_entry.id,
|
||||||
valid_until: token_entry.valid_until,
|
valid_until: token_entry.valid_until,
|
||||||
app_name: token_entry.app.client_name
|
app_name: token_entry.app.client_name,
|
||||||
|
scopes: token_entry.scopes
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,27 +11,46 @@ defmodule Pleroma.Workers.PollWorker do
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
alias Pleroma.Notification
|
alias Pleroma.Notification
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
|
alias Pleroma.Object.Fetcher
|
||||||
|
|
||||||
|
@stream_out_impl Pleroma.Config.get(
|
||||||
|
[__MODULE__, :stream_out],
|
||||||
|
Pleroma.Web.ActivityPub.ActivityPub
|
||||||
|
)
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def perform(%Job{args: %{"op" => "poll_end", "activity_id" => activity_id}}) do
|
def perform(%Job{args: %{"op" => "poll_end", "activity_id" => activity_id}}) do
|
||||||
with %Activity{} = activity <- find_poll_activity(activity_id),
|
with {_, %Activity{} = activity} <- {:activity, Activity.get_by_id(activity_id)},
|
||||||
{:ok, notifications} <- Notification.create_poll_notifications(activity) do
|
{:ok, notifications} <- Notification.create_poll_notifications(activity) do
|
||||||
|
unless activity.local do
|
||||||
|
# Schedule a final refresh
|
||||||
|
__MODULE__.new(%{"op" => "refresh", "activity_id" => activity_id})
|
||||||
|
|> Oban.insert()
|
||||||
|
end
|
||||||
|
|
||||||
Notification.stream(notifications)
|
Notification.stream(notifications)
|
||||||
else
|
else
|
||||||
{:error, :poll_activity_not_found} = e -> {:cancel, e}
|
{:activity, nil} -> {:cancel, :poll_activity_not_found}
|
||||||
e -> {:error, e}
|
e -> {:error, e}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def perform(%Job{args: %{"op" => "refresh", "activity_id" => activity_id}}) do
|
||||||
|
with {_, %Activity{object: object}} <-
|
||||||
|
{:activity, Activity.get_by_id_with_object(activity_id)},
|
||||||
|
{_, {:ok, _object}} <- {:refetch, Fetcher.refetch_object(object)} do
|
||||||
|
stream_update(activity_id)
|
||||||
|
|
||||||
|
:ok
|
||||||
|
else
|
||||||
|
{:activity, nil} -> {:cancel, :poll_activity_not_found}
|
||||||
|
{:refetch, _} = e -> {:cancel, e}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def timeout(_job), do: :timer.seconds(5)
|
def timeout(_job), do: :timer.seconds(5)
|
||||||
|
|
||||||
defp find_poll_activity(activity_id) do
|
|
||||||
with nil <- Activity.get_by_id(activity_id) do
|
|
||||||
{:error, :poll_activity_not_found}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def schedule_poll_end(%Activity{data: %{"type" => "Create"}, id: activity_id} = activity) do
|
def schedule_poll_end(%Activity{data: %{"type" => "Create"}, id: activity_id} = activity) do
|
||||||
with %Object{data: %{"type" => "Question", "closed" => closed}} when is_binary(closed) <-
|
with %Object{data: %{"type" => "Question", "closed" => closed}} when is_binary(closed) <-
|
||||||
Object.normalize(activity),
|
Object.normalize(activity),
|
||||||
|
@ -49,4 +68,10 @@ defmodule Pleroma.Workers.PollWorker do
|
||||||
end
|
end
|
||||||
|
|
||||||
def schedule_poll_end(activity), do: {:error, activity}
|
def schedule_poll_end(activity), do: {:error, activity}
|
||||||
|
|
||||||
|
defp stream_update(activity_id) do
|
||||||
|
Activity.get_by_id(activity_id)
|
||||||
|
|> Activity.normalize()
|
||||||
|
|> @stream_out_impl.stream_out()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
5
mix.exs
5
mix.exs
|
@ -4,7 +4,7 @@ defmodule Pleroma.Mixfile do
|
||||||
def project do
|
def project do
|
||||||
[
|
[
|
||||||
app: :pleroma,
|
app: :pleroma,
|
||||||
version: version("2.7.0"),
|
version: version("2.7.51"),
|
||||||
elixir: "~> 1.14",
|
elixir: "~> 1.14",
|
||||||
elixirc_paths: elixirc_paths(Mix.env()),
|
elixirc_paths: elixirc_paths(Mix.env()),
|
||||||
compilers: Mix.compilers(),
|
compilers: Mix.compilers(),
|
||||||
|
@ -132,7 +132,8 @@ defmodule Pleroma.Mixfile do
|
||||||
# Type `mix help deps` for examples and options.
|
# Type `mix help deps` for examples and options.
|
||||||
defp deps do
|
defp deps do
|
||||||
[
|
[
|
||||||
{:phoenix, "~> 1.7.3"},
|
{:phoenix,
|
||||||
|
git: "https://github.com/feld/phoenix", branch: "v1.7.14-websocket-headers", override: true},
|
||||||
{:phoenix_ecto, "~> 4.4"},
|
{:phoenix_ecto, "~> 4.4"},
|
||||||
{:ecto_sql, "~> 3.10"},
|
{:ecto_sql, "~> 3.10"},
|
||||||
{:ecto_enum, "~> 1.4"},
|
{:ecto_enum, "~> 1.4"},
|
||||||
|
|
4
mix.lock
4
mix.lock
|
@ -50,7 +50,7 @@
|
||||||
"ex_syslogger": {:hex, :ex_syslogger, "1.5.2", "72b6aa2d47a236e999171f2e1ec18698740f40af0bd02c8c650bf5f1fd1bac79", [:mix], [{:poison, ">= 1.5.0", [hex: :poison, repo: "hexpm", optional: true]}, {:syslog, "~> 1.1.0", [hex: :syslog, repo: "hexpm", optional: false]}], "hexpm", "ab9fab4136dbc62651ec6f16fa4842f10cf02ab4433fa3d0976c01be99398399"},
|
"ex_syslogger": {:hex, :ex_syslogger, "1.5.2", "72b6aa2d47a236e999171f2e1ec18698740f40af0bd02c8c650bf5f1fd1bac79", [:mix], [{:poison, ">= 1.5.0", [hex: :poison, repo: "hexpm", optional: true]}, {:syslog, "~> 1.1.0", [hex: :syslog, repo: "hexpm", optional: false]}], "hexpm", "ab9fab4136dbc62651ec6f16fa4842f10cf02ab4433fa3d0976c01be99398399"},
|
||||||
"exile": {:hex, :exile, "0.10.0", "b69e2d27a9af670b0f0a0898addca0eda78f6f5ba95ccfbc9bc6ccdd04925436", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "c62ee8fee565b5ac4a898d0dcd58d2b04fb5eec1655af1ddcc9eb582c6732c33"},
|
"exile": {:hex, :exile, "0.10.0", "b69e2d27a9af670b0f0a0898addca0eda78f6f5ba95ccfbc9bc6ccdd04925436", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "c62ee8fee565b5ac4a898d0dcd58d2b04fb5eec1655af1ddcc9eb582c6732c33"},
|
||||||
"expo": {:hex, :expo, "0.5.1", "249e826a897cac48f591deba863b26c16682b43711dd15ee86b92f25eafd96d9", [:mix], [], "hexpm", "68a4233b0658a3d12ee00d27d37d856b1ba48607e7ce20fd376958d0ba6ce92b"},
|
"expo": {:hex, :expo, "0.5.1", "249e826a897cac48f591deba863b26c16682b43711dd15ee86b92f25eafd96d9", [:mix], [], "hexpm", "68a4233b0658a3d12ee00d27d37d856b1ba48607e7ce20fd376958d0ba6ce92b"},
|
||||||
"fast_html": {:hex, :fast_html, "2.2.0", "6c5ef1be087a4ed613b0379c13f815c4d11742b36b67bb52cee7859847c84520", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}], "hexpm", "064c4f23b4a6168f9187dac8984b056f2c531bb0787f559fd6a8b34b38aefbae"},
|
"fast_html": {:hex, :fast_html, "2.3.0", "08c1d8ead840dd3060ba02c761bed9f37f456a1ddfe30bcdcfee8f651cec06a6", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}], "hexpm", "f18e3c7668f82d3ae0b15f48d48feeb257e28aa5ab1b0dbf781c7312e5da029d"},
|
||||||
"fast_sanitize": {:hex, :fast_sanitize, "0.2.3", "67b93dfb34e302bef49fec3aaab74951e0f0602fd9fa99085987af05bd91c7a5", [:mix], [{:fast_html, "~> 2.0", [hex: :fast_html, repo: "hexpm", optional: false]}, {:plug, "~> 1.8", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "e8ad286d10d0386e15d67d0ee125245ebcfbc7d7290b08712ba9013c8c5e56e2"},
|
"fast_sanitize": {:hex, :fast_sanitize, "0.2.3", "67b93dfb34e302bef49fec3aaab74951e0f0602fd9fa99085987af05bd91c7a5", [:mix], [{:fast_html, "~> 2.0", [hex: :fast_html, repo: "hexpm", optional: false]}, {:plug, "~> 1.8", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "e8ad286d10d0386e15d67d0ee125245ebcfbc7d7290b08712ba9013c8c5e56e2"},
|
||||||
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
|
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
|
||||||
"finch": {:hex, :finch, "0.18.0", "944ac7d34d0bd2ac8998f79f7a811b21d87d911e77a786bc5810adb75632ada4", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6 or ~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "69f5045b042e531e53edc2574f15e25e735b522c37e2ddb766e15b979e03aa65"},
|
"finch": {:hex, :finch, "0.18.0", "944ac7d34d0bd2ac8998f79f7a811b21d87d911e77a786bc5810adb75632ada4", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6 or ~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "69f5045b042e531e53edc2574f15e25e735b522c37e2ddb766e15b979e03aa65"},
|
||||||
|
@ -98,7 +98,7 @@
|
||||||
"open_api_spex": {:hex, :open_api_spex, "3.18.2", "8c855e83bfe8bf81603d919d6e892541eafece3720f34d1700b58024dadde247", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:poison, "~> 3.0 or ~> 4.0 or ~> 5.0", [hex: :poison, repo: "hexpm", optional: true]}, {:ymlr, "~> 2.0 or ~> 3.0 or ~> 4.0", [hex: :ymlr, repo: "hexpm", optional: true]}], "hexpm", "aa3e6dcfc0ad6a02596b2172662da21c9dd848dac145ea9e603f54e3d81b8d2b"},
|
"open_api_spex": {:hex, :open_api_spex, "3.18.2", "8c855e83bfe8bf81603d919d6e892541eafece3720f34d1700b58024dadde247", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:poison, "~> 3.0 or ~> 4.0 or ~> 5.0", [hex: :poison, repo: "hexpm", optional: true]}, {:ymlr, "~> 2.0 or ~> 3.0 or ~> 4.0", [hex: :ymlr, repo: "hexpm", optional: true]}], "hexpm", "aa3e6dcfc0ad6a02596b2172662da21c9dd848dac145ea9e603f54e3d81b8d2b"},
|
||||||
"parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"},
|
"parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"},
|
||||||
"pbkdf2_elixir": {:hex, :pbkdf2_elixir, "1.2.1", "9cbe354b58121075bd20eb83076900a3832324b7dd171a6895fab57b6bb2752c", [:mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}], "hexpm", "d3b40a4a4630f0b442f19eca891fcfeeee4c40871936fed2f68e1c4faa30481f"},
|
"pbkdf2_elixir": {:hex, :pbkdf2_elixir, "1.2.1", "9cbe354b58121075bd20eb83076900a3832324b7dd171a6895fab57b6bb2752c", [:mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}], "hexpm", "d3b40a4a4630f0b442f19eca891fcfeeee4c40871936fed2f68e1c4faa30481f"},
|
||||||
"phoenix": {:hex, :phoenix, "1.7.14", "a7d0b3f1bc95987044ddada111e77bd7f75646a08518942c72a8440278ae7825", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "c7859bc56cc5dfef19ecfc240775dae358cbaa530231118a9e014df392ace61a"},
|
"phoenix": {:git, "https://github.com/feld/phoenix", "fb6dc76c657422e49600896c64aab4253fceaef6", [branch: "v1.7.14-websocket-headers"]},
|
||||||
"phoenix_ecto": {:hex, :phoenix_ecto, "4.4.3", "86e9878f833829c3f66da03d75254c155d91d72a201eb56ae83482328dc7ca93", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "d36c401206f3011fefd63d04e8ef626ec8791975d9d107f9a0817d426f61ac07"},
|
"phoenix_ecto": {:hex, :phoenix_ecto, "4.4.3", "86e9878f833829c3f66da03d75254c155d91d72a201eb56ae83482328dc7ca93", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "d36c401206f3011fefd63d04e8ef626ec8791975d9d107f9a0817d426f61ac07"},
|
||||||
"phoenix_html": {:hex, :phoenix_html, "3.3.4", "42a09fc443bbc1da37e372a5c8e6755d046f22b9b11343bf885067357da21cb3", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "0249d3abec3714aff3415e7ee3d9786cb325be3151e6c4b3021502c585bf53fb"},
|
"phoenix_html": {:hex, :phoenix_html, "3.3.4", "42a09fc443bbc1da37e372a5c8e6755d046f22b9b11343bf885067357da21cb3", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "0249d3abec3714aff3415e7ee3d9786cb325be3151e6c4b3021502c585bf53fb"},
|
||||||
"phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.8.3", "7ff51c9b6609470f681fbea20578dede0e548302b0c8bdf338b5a753a4f045bf", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_mysql_extras, "~> 0.5", [hex: :ecto_mysql_extras, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.7", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:ecto_sqlite3_extras, "~> 1.1.7 or ~> 1.2.0", [hex: :ecto_sqlite3_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.19 or ~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "f9470a0a8bae4f56430a23d42f977b5a6205fdba6559d76f932b876bfaec652d"},
|
"phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.8.3", "7ff51c9b6609470f681fbea20578dede0e548302b0c8bdf338b5a753a4f045bf", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_mysql_extras, "~> 0.5", [hex: :ecto_mysql_extras, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.7", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:ecto_sqlite3_extras, "~> 1.1.7 or ~> 1.2.0", [hex: :ecto_sqlite3_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.19 or ~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "f9470a0a8bae4f56430a23d42f977b5a6205fdba6559d76f932b876bfaec652d"},
|
||||||
|
|
|
@ -3,14 +3,16 @@ msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2022-07-22 02:09+0300\n"
|
"POT-Creation-Date: 2022-07-22 02:09+0300\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: 2024-10-13 21:03+0000\n"
|
||||||
"Last-Translator: Automatically generated\n"
|
"Last-Translator: Codimp <contact@lithio.fr>\n"
|
||||||
"Language-Team: none\n"
|
"Language-Team: French <https://translate.pleroma.social/projects/pleroma/"
|
||||||
|
"pleroma-backend-domain-config_descriptions/fr/>\n"
|
||||||
"Language: fr\n"
|
"Language: fr\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Generator: Translate Toolkit 3.7.2\n"
|
"Plural-Forms: nplurals=2; plural=n > 1;\n"
|
||||||
|
"X-Generator: Weblate 4.13.1\n"
|
||||||
|
|
||||||
## This file is a PO Template file.
|
## This file is a PO Template file.
|
||||||
##
|
##
|
||||||
|
@ -21,7 +23,6 @@ msgstr ""
|
||||||
## Run "mix gettext.extract" to bring this file up to
|
## Run "mix gettext.extract" to bring this file up to
|
||||||
## date. Leave "msgstr"s empty as changing them here has no
|
## date. Leave "msgstr"s empty as changing them here has no
|
||||||
## effect: edit them in PO (.po) files instead.
|
## effect: edit them in PO (.po) files instead.
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :esshd"
|
msgctxt "config description at :esshd"
|
||||||
|
@ -32,25 +33,30 @@ msgstr ""
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :logger"
|
msgctxt "config description at :logger"
|
||||||
msgid "Logger-related settings"
|
msgid "Logger-related settings"
|
||||||
msgstr ""
|
msgstr "Paramètres liés à la journalisation"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :mime"
|
msgctxt "config description at :mime"
|
||||||
msgid "Mime Types settings"
|
msgid "Mime Types settings"
|
||||||
msgstr ""
|
msgstr "Paramètres des types Mime"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma"
|
msgctxt "config description at :pleroma"
|
||||||
msgid "Allows setting a token that can be used to authenticate requests with admin privileges without a normal user account token. Append the `admin_token` parameter to requests to utilize it. (Please reconsider using HTTP Basic Auth or OAuth-based authentication if possible)"
|
msgid "Allows setting a token that can be used to authenticate requests with admin privileges without a normal user account token. Append the `admin_token` parameter to requests to utilize it. (Please reconsider using HTTP Basic Auth or OAuth-based authentication if possible)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Permet de configurer un jeton qui peut être utilisé pour authentifier les "
|
||||||
|
"requêtes avec des privilèges administrateurs sans utiliser un jeton de "
|
||||||
|
"compte utilisateur standard. Pour l'utiliser, ajoutez le paramètre "
|
||||||
|
"`admin_token`aux requêtes. (Vous devriez utiliser l'authentification HTTP "
|
||||||
|
"Basic ou OAuth à la place si vous le pouvez)"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma"
|
msgctxt "config description at :pleroma"
|
||||||
msgid "Authenticator"
|
msgid "Authenticator"
|
||||||
msgstr ""
|
msgstr "Authentifieur"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
|
@ -62,7 +68,7 @@ msgstr ""
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config label at :cors_plug"
|
msgctxt "config label at :cors_plug"
|
||||||
msgid "CORS plug config"
|
msgid "CORS plug config"
|
||||||
msgstr ""
|
msgstr "Configuration du plug CORS"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
|
@ -74,25 +80,25 @@ msgstr ""
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config label at :logger"
|
msgctxt "config label at :logger"
|
||||||
msgid "Logger"
|
msgid "Logger"
|
||||||
msgstr ""
|
msgstr "Journaliseur"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config label at :mime"
|
msgctxt "config label at :mime"
|
||||||
msgid "Mime Types"
|
msgid "Mime Types"
|
||||||
msgstr ""
|
msgstr "Types Mime"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config label at :pleroma"
|
msgctxt "config label at :pleroma"
|
||||||
msgid "Pleroma Admin Token"
|
msgid "Pleroma Admin Token"
|
||||||
msgstr ""
|
msgstr "Jeton Administrateur Pleroma"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config label at :pleroma"
|
msgctxt "config label at :pleroma"
|
||||||
msgid "Pleroma Authenticator"
|
msgid "Pleroma Authenticator"
|
||||||
msgstr ""
|
msgstr "Authentifieur Pleroma"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
|
@ -104,103 +110,111 @@ msgstr ""
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :logger-:console"
|
msgctxt "config description at :logger-:console"
|
||||||
msgid "Console logger settings"
|
msgid "Console logger settings"
|
||||||
msgstr ""
|
msgstr "Paramètres de journalisation de la console"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :logger-:ex_syslogger"
|
msgctxt "config description at :logger-:ex_syslogger"
|
||||||
msgid "ExSyslogger-related settings"
|
msgid "ExSyslogger-related settings"
|
||||||
msgstr ""
|
msgstr "Paramètres liés à ExSyslogger"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:activitypub"
|
msgctxt "config description at :pleroma-:activitypub"
|
||||||
msgid "ActivityPub-related settings"
|
msgid "ActivityPub-related settings"
|
||||||
msgstr ""
|
msgstr "Paramètres liés à ActivityPub"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:assets"
|
msgctxt "config description at :pleroma-:assets"
|
||||||
msgid "This section configures assets to be used with various frontends. Currently the only option relates to mascots on the mastodon frontend"
|
msgid "This section configures assets to be used with various frontends. Currently the only option relates to mascots on the mastodon frontend"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Cette section configure les annexes (assets) à utiliser avec divers "
|
||||||
|
"frontaux. La seule option est actuellement liée au mascottes du frontal "
|
||||||
|
"mastodon"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:auth"
|
msgctxt "config description at :pleroma-:auth"
|
||||||
msgid "Authentication / authorization settings"
|
msgid "Authentication / authorization settings"
|
||||||
msgstr ""
|
msgstr "Paramètres d'authentification/autorisations"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:connections_pool"
|
msgctxt "config description at :pleroma-:connections_pool"
|
||||||
msgid "Advanced settings for `Gun` connections pool"
|
msgid "Advanced settings for `Gun` connections pool"
|
||||||
msgstr ""
|
msgstr "Paramètres avancés pour le bac (pool) de connexions `Gun`"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:email_notifications"
|
msgctxt "config description at :pleroma-:email_notifications"
|
||||||
msgid "Email notifications settings"
|
msgid "Email notifications settings"
|
||||||
msgstr ""
|
msgstr "Paramètres de notification par email"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:features"
|
msgctxt "config description at :pleroma-:features"
|
||||||
msgid "Customizable features"
|
msgid "Customizable features"
|
||||||
msgstr ""
|
msgstr "Fonctionnalités personnalisables"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:feed"
|
msgctxt "config description at :pleroma-:feed"
|
||||||
msgid "Configure feed rendering"
|
msgid "Configure feed rendering"
|
||||||
msgstr ""
|
msgstr "Configurer le rendu des flux"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:frontend_configurations"
|
msgctxt "config description at :pleroma-:frontend_configurations"
|
||||||
msgid "This form can be used to configure a keyword list that keeps the configuration data for any kind of frontend. By default, settings for pleroma_fe are configured. If you want to add your own configuration your settings all fields must be complete."
|
msgid "This form can be used to configure a keyword list that keeps the configuration data for any kind of frontend. By default, settings for pleroma_fe are configured. If you want to add your own configuration your settings all fields must be complete."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Ce formulaire peut être utilisé pour configurer une liste de clés (keyword) "
|
||||||
|
"qui contiennent les données de configuration pour tout types de frontaux. "
|
||||||
|
"Par défaut, les paramètres pour pleroma_fe sont configurés. Si vous voulez "
|
||||||
|
"ajouter vos propres paramètres de configurations, tout les champs doivent "
|
||||||
|
"être remplis."
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:frontends"
|
msgctxt "config description at :pleroma-:frontends"
|
||||||
msgid "Installed frontends management"
|
msgid "Installed frontends management"
|
||||||
msgstr ""
|
msgstr "Gestion des frontaux installés"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:gopher"
|
msgctxt "config description at :pleroma-:gopher"
|
||||||
msgid "Gopher settings"
|
msgid "Gopher settings"
|
||||||
msgstr ""
|
msgstr "Paramètres Gopher"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:hackney_pools"
|
msgctxt "config description at :pleroma-:hackney_pools"
|
||||||
msgid "Advanced settings for `Hackney` connections pools"
|
msgid "Advanced settings for `Hackney` connections pools"
|
||||||
msgstr ""
|
msgstr "Paramètres avancés pour les bacs (pool) de connexions `Hackney`"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:http"
|
msgctxt "config description at :pleroma-:http"
|
||||||
msgid "HTTP settings"
|
msgid "HTTP settings"
|
||||||
msgstr ""
|
msgstr "Paramètres HTTP"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:http_security"
|
msgctxt "config description at :pleroma-:http_security"
|
||||||
msgid "HTTP security settings"
|
msgid "HTTP security settings"
|
||||||
msgstr ""
|
msgstr "Paramètres de sécurité HTTP"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:instance"
|
msgctxt "config description at :pleroma-:instance"
|
||||||
msgid "Instance-related settings"
|
msgid "Instance-related settings"
|
||||||
msgstr ""
|
msgstr "Paramètres liés à l'instance"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:instances_favicons"
|
msgctxt "config description at :pleroma-:instances_favicons"
|
||||||
msgid "Control favicons for instances"
|
msgid "Control favicons for instances"
|
||||||
msgstr ""
|
msgstr "Gère les favicons des instances"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
|
@ -212,151 +226,177 @@ msgstr ""
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:majic_pool"
|
msgctxt "config description at :pleroma-:majic_pool"
|
||||||
msgid "Majic/libmagic configuration"
|
msgid "Majic/libmagic configuration"
|
||||||
msgstr ""
|
msgstr "Configuration de majic/libmagic"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:manifest"
|
msgctxt "config description at :pleroma-:manifest"
|
||||||
msgid "This section describe PWA manifest instance-specific values. Currently this option relate only for MastoFE."
|
msgid "This section describe PWA manifest instance-specific values. Currently this option relate only for MastoFE."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Cette section décrit les valeurs spécifique à l'instance du manifeste PWA. "
|
||||||
|
"Actuellement, cette option ne concerne que MastoFE."
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:media_preview_proxy"
|
msgctxt "config description at :pleroma-:media_preview_proxy"
|
||||||
msgid "Media preview proxy"
|
msgid "Media preview proxy"
|
||||||
msgstr ""
|
msgstr "Proxy de prévisualisation média"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:media_proxy"
|
msgctxt "config description at :pleroma-:media_proxy"
|
||||||
msgid "Media proxy"
|
msgid "Media proxy"
|
||||||
msgstr ""
|
msgstr "Proxy média"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:modules"
|
msgctxt "config description at :pleroma-:modules"
|
||||||
msgid "Custom Runtime Modules"
|
msgid "Custom Runtime Modules"
|
||||||
msgstr ""
|
msgstr "Modules Runtime Personalisés"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:mrf"
|
msgctxt "config description at :pleroma-:mrf"
|
||||||
msgid "General MRF settings"
|
msgid "General MRF settings"
|
||||||
msgstr ""
|
msgstr "Paramètres généraux MRF"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:mrf_activity_expiration"
|
msgctxt "config description at :pleroma-:mrf_activity_expiration"
|
||||||
msgid "Adds automatic expiration to all local activities"
|
msgid "Adds automatic expiration to all local activities"
|
||||||
msgstr ""
|
msgstr "Ajoute une expiration automatique à toutes les activités locales"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:mrf_follow_bot"
|
msgctxt "config description at :pleroma-:mrf_follow_bot"
|
||||||
msgid "Automatically follows newly discovered accounts."
|
msgid "Automatically follows newly discovered accounts."
|
||||||
msgstr ""
|
msgstr "Suivre automatiquement les comptes venant d'être découverts."
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:mrf_hashtag"
|
msgctxt "config description at :pleroma-:mrf_hashtag"
|
||||||
msgid "Reject, TWKN-remove or Set-Sensitive messsages with specific hashtags (without the leading #)\n\nNote: This MRF Policy is always enabled, if you want to disable it you have to set empty lists.\n"
|
msgid "Reject, TWKN-remove or Set-Sensitive messsages with specific hashtags (without the leading #)\n\nNote: This MRF Policy is always enabled, if you want to disable it you have to set empty lists.\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Rejeter, Enlever de TWKN ou marquer comme contenu sensible les messages avec "
|
||||||
|
"des mots-croisillons (sans mettre le # du début)\n"
|
||||||
|
"\n"
|
||||||
|
"Note: cette politique MRF est toujours activée. Si vous voulez la "
|
||||||
|
"désactiver, vous devez configurer des listes vides.\n"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:mrf_hellthread"
|
msgctxt "config description at :pleroma-:mrf_hellthread"
|
||||||
msgid "Block messages with excessive user mentions"
|
msgid "Block messages with excessive user mentions"
|
||||||
msgstr ""
|
msgstr "Bloquer les messages avec un nombre excessif de mentions"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:mrf_keyword"
|
msgctxt "config description at :pleroma-:mrf_keyword"
|
||||||
msgid "Reject or Word-Replace messages matching a keyword or [Regex](https://hexdocs.pm/elixir/Regex.html)."
|
msgid "Reject or Word-Replace messages matching a keyword or [Regex](https://hexdocs.pm/elixir/Regex.html)."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Rejeter ou remplacer les mots des messages qui correspondent à un mot clef "
|
||||||
|
"ou à une [expression rationnelle (Regex)](https://hexdocs.pm/elixir/Regex."
|
||||||
|
"html)."
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:mrf_mention"
|
msgctxt "config description at :pleroma-:mrf_mention"
|
||||||
msgid "Block messages which mention a specific user"
|
msgid "Block messages which mention a specific user"
|
||||||
msgstr ""
|
msgstr "Bloquer les messages mentionnant un utilisateur particulier"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:mrf_normalize_markup"
|
msgctxt "config description at :pleroma-:mrf_normalize_markup"
|
||||||
msgid "MRF NormalizeMarkup settings. Scrub configured hypertext markup."
|
msgid "MRF NormalizeMarkup settings. Scrub configured hypertext markup."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Paramètres de normalisation MRF. Balaie les balises hypertextes configurées."
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:mrf_object_age"
|
msgctxt "config description at :pleroma-:mrf_object_age"
|
||||||
msgid "Rejects or delists posts based on their timestamp deviance from your server's clock."
|
msgid "Rejects or delists posts based on their timestamp deviance from your server's clock."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Rejette ou retire des listes les messages selon l'écart entre leur heure et "
|
||||||
|
"l'horloge de votre serveur."
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:mrf_rejectnonpublic"
|
msgctxt "config description at :pleroma-:mrf_rejectnonpublic"
|
||||||
msgid "RejectNonPublic drops posts with non-public visibility settings."
|
msgid "RejectNonPublic drops posts with non-public visibility settings."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"RejectNonPublic enlève les messages avec des paramètres de visibilité non-"
|
||||||
|
"publics."
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:mrf_simple"
|
msgctxt "config description at :pleroma-:mrf_simple"
|
||||||
msgid "Simple ingress policies"
|
msgid "Simple ingress policies"
|
||||||
msgstr ""
|
msgstr "Politiques simples pour entrants"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:mrf_steal_emoji"
|
msgctxt "config description at :pleroma-:mrf_steal_emoji"
|
||||||
msgid "Steals emojis from selected instances when it sees them."
|
msgid "Steals emojis from selected instances when it sees them."
|
||||||
msgstr ""
|
msgstr "Vole les emojis des instances sélectionnées quand il les voit."
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:mrf_subchain"
|
msgctxt "config description at :pleroma-:mrf_subchain"
|
||||||
msgid "This policy processes messages through an alternate pipeline when a given message matches certain criteria. All criteria are configured as a map of regular expressions to lists of policy modules."
|
msgid "This policy processes messages through an alternate pipeline when a given message matches certain criteria. All criteria are configured as a map of regular expressions to lists of policy modules."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Cette politique traite les messages à travers un tuyau séparé lorsqu'un "
|
||||||
|
"message donné correspond à certain critères. Chaque critère est configuré "
|
||||||
|
"comme une correspondance entre une expression rationnelle et une liste de "
|
||||||
|
"modules de politiques."
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:mrf_vocabulary"
|
msgctxt "config description at :pleroma-:mrf_vocabulary"
|
||||||
msgid "Filter messages which belong to certain activity vocabularies"
|
msgid "Filter messages which belong to certain activity vocabularies"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Filtrer les messages qui correspondent à certain vocabulaires d'activités"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:oauth2"
|
msgctxt "config description at :pleroma-:oauth2"
|
||||||
msgid "Configure OAuth 2 provider capabilities"
|
msgid "Configure OAuth 2 provider capabilities"
|
||||||
msgstr ""
|
msgstr "Configurer les capacités du fournisseur OAuth 2"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:pools"
|
msgctxt "config description at :pleroma-:pools"
|
||||||
msgid "Advanced settings for `Gun` workers pools"
|
msgid "Advanced settings for `Gun` workers pools"
|
||||||
msgstr ""
|
msgstr "Paramètres avancés pour les bacs (pools) de travailleurs `Gun`"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:populate_hashtags_table"
|
msgctxt "config description at :pleroma-:populate_hashtags_table"
|
||||||
msgid "`populate_hashtags_table` background migration settings"
|
msgid "`populate_hashtags_table` background migration settings"
|
||||||
msgstr ""
|
msgstr "Paramètres de migration en arrière-plan `populate_hashtags_table`"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:rate_limit"
|
msgctxt "config description at :pleroma-:rate_limit"
|
||||||
msgid "Rate limit settings. This is an advanced feature enabled only for :authentication by default."
|
msgid "Rate limit settings. This is an advanced feature enabled only for :authentication by default."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Paramètres de limites par secondes. C'est une fonctionnalité avancée qui, "
|
||||||
|
"par défaut, n'est activée que pour :authentication."
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:restrict_unauthenticated"
|
msgctxt "config description at :pleroma-:restrict_unauthenticated"
|
||||||
msgid "Disallow viewing timelines, user profiles and statuses for unauthenticated users."
|
msgid "Disallow viewing timelines, user profiles and statuses for unauthenticated users."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Empêche de regarder les flux, les profils utilisateurs et les status pour "
|
||||||
|
"les utilisateurs non-authentifiés."
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:rich_media"
|
msgctxt "config description at :pleroma-:rich_media"
|
||||||
msgid "If enabled the instance will parse metadata from attached links to generate link previews"
|
msgid "If enabled the instance will parse metadata from attached links to generate link previews"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Si activé, l'instance interprétera les métadonnées des liens joins pour "
|
||||||
|
"générer les prévisualisations de liens"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
|
@ -369,6 +409,8 @@ msgstr ""
|
||||||
msgctxt "config description at :pleroma-:static_fe"
|
msgctxt "config description at :pleroma-:static_fe"
|
||||||
msgid "Render profiles and posts using server-generated HTML that is viewable without using JavaScript"
|
msgid "Render profiles and posts using server-generated HTML that is viewable without using JavaScript"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Rendre les profils et les status en utilisant du HTML généré par le serveur "
|
||||||
|
"qui ne nécessitera pas de JavaScript"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
|
@ -380,7 +422,7 @@ msgstr ""
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
msgctxt "config description at :pleroma-:uri_schemes"
|
msgctxt "config description at :pleroma-:uri_schemes"
|
||||||
msgid "URI schemes related settings"
|
msgid "URI schemes related settings"
|
||||||
msgstr ""
|
msgstr "Paramètres liés au schémas d'URI"
|
||||||
|
|
||||||
#: lib/pleroma/docs/translator.ex:5
|
#: lib/pleroma/docs/translator.ex:5
|
||||||
#, elixir-autogen, elixir-format
|
#, elixir-autogen, elixir-format
|
||||||
|
|
|
@ -9,3 +9,8 @@
|
||||||
|
|
||||||
## Tweak GC to run more often
|
## Tweak GC to run more often
|
||||||
##-env ERL_FULLSWEEP_AFTER 10
|
##-env ERL_FULLSWEEP_AFTER 10
|
||||||
|
|
||||||
|
# Disable wasteful busywait.
|
||||||
|
+sbwt none
|
||||||
|
+sbwtdcpu none
|
||||||
|
+sbwtdio none
|
||||||
|
|
|
@ -268,6 +268,17 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "accepts valid token on Sec-WebSocket-Protocol header", %{token: token} do
|
||||||
|
assert {:ok, _} = start_socket("?stream=user", [{"Sec-WebSocket-Protocol", token.token}])
|
||||||
|
|
||||||
|
capture_log(fn ->
|
||||||
|
assert {:error, %WebSockex.RequestError{code: 401}} =
|
||||||
|
start_socket("?stream=user", [{"Sec-WebSocket-Protocol", "I am a friend"}])
|
||||||
|
|
||||||
|
Process.sleep(30)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
test "accepts valid token on client-sent event", %{token: token} do
|
test "accepts valid token on client-sent event", %{token: token} do
|
||||||
assert {:ok, pid} = start_socket()
|
assert {:ok, pid} = start_socket()
|
||||||
|
|
||||||
|
|
|
@ -6,12 +6,10 @@ defmodule Pleroma.ObjectTest do
|
||||||
use Pleroma.DataCase
|
use Pleroma.DataCase
|
||||||
use Oban.Testing, repo: Pleroma.Repo
|
use Oban.Testing, repo: Pleroma.Repo
|
||||||
|
|
||||||
import ExUnit.CaptureLog
|
|
||||||
import Mox
|
import Mox
|
||||||
import Pleroma.Factory
|
import Pleroma.Factory
|
||||||
import Tesla.Mock
|
import Tesla.Mock
|
||||||
|
|
||||||
alias Pleroma.Activity
|
|
||||||
alias Pleroma.Hashtag
|
alias Pleroma.Hashtag
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
alias Pleroma.Repo
|
alias Pleroma.Repo
|
||||||
|
@ -176,8 +174,9 @@ defmodule Pleroma.ObjectTest do
|
||||||
|
|
||||||
filename = Path.basename(href)
|
filename = Path.basename(href)
|
||||||
|
|
||||||
assert {:ok, files} = File.ls(uploads_dir)
|
expected_path = Path.join([uploads_dir, Pleroma.Upload.Filter.Dedupe.shard_path(filename)])
|
||||||
assert filename in files
|
|
||||||
|
assert File.exists?(expected_path)
|
||||||
|
|
||||||
Object.delete(note)
|
Object.delete(note)
|
||||||
|
|
||||||
|
@ -185,8 +184,7 @@ defmodule Pleroma.ObjectTest do
|
||||||
|
|
||||||
assert Object.get_by_id(note.id).data["deleted"]
|
assert Object.get_by_id(note.id).data["deleted"]
|
||||||
assert Object.get_by_id(attachment.id) == nil
|
assert Object.get_by_id(attachment.id) == nil
|
||||||
assert {:ok, files} = File.ls(uploads_dir)
|
refute File.exists?(expected_path)
|
||||||
refute filename in files
|
|
||||||
end
|
end
|
||||||
|
|
||||||
test "with objects that have legacy data.url attribute" do
|
test "with objects that have legacy data.url attribute" do
|
||||||
|
@ -282,148 +280,6 @@ defmodule Pleroma.ObjectTest do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "get_by_id_and_maybe_refetch" do
|
|
||||||
setup do
|
|
||||||
mock(fn
|
|
||||||
%{method: :get, url: "https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d"} ->
|
|
||||||
%Tesla.Env{
|
|
||||||
status: 200,
|
|
||||||
body: File.read!("test/fixtures/tesla_mock/poll_original.json"),
|
|
||||||
headers: HttpRequestMock.activitypub_object_headers()
|
|
||||||
}
|
|
||||||
|
|
||||||
env ->
|
|
||||||
apply(HttpRequestMock, :request, [env])
|
|
||||||
end)
|
|
||||||
|
|
||||||
mock_modified = fn resp ->
|
|
||||||
mock(fn
|
|
||||||
%{method: :get, url: "https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d"} ->
|
|
||||||
resp
|
|
||||||
|
|
||||||
env ->
|
|
||||||
apply(HttpRequestMock, :request, [env])
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
on_exit(fn -> mock(fn env -> apply(HttpRequestMock, :request, [env]) end) end)
|
|
||||||
|
|
||||||
[mock_modified: mock_modified]
|
|
||||||
end
|
|
||||||
|
|
||||||
test "refetches if the time since the last refetch is greater than the interval", %{
|
|
||||||
mock_modified: mock_modified
|
|
||||||
} do
|
|
||||||
%Object{} =
|
|
||||||
object =
|
|
||||||
Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d",
|
|
||||||
fetch: true
|
|
||||||
)
|
|
||||||
|
|
||||||
Object.set_cache(object)
|
|
||||||
|
|
||||||
assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
|
|
||||||
assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
|
|
||||||
|
|
||||||
mock_modified.(%Tesla.Env{
|
|
||||||
status: 200,
|
|
||||||
body: File.read!("test/fixtures/tesla_mock/poll_modified.json"),
|
|
||||||
headers: HttpRequestMock.activitypub_object_headers()
|
|
||||||
})
|
|
||||||
|
|
||||||
updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
|
|
||||||
object_in_cache = Object.get_cached_by_ap_id(object.data["id"])
|
|
||||||
assert updated_object == object_in_cache
|
|
||||||
assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 8
|
|
||||||
assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 3
|
|
||||||
end
|
|
||||||
|
|
||||||
test "returns the old object if refetch fails", %{mock_modified: mock_modified} do
|
|
||||||
%Object{} =
|
|
||||||
object =
|
|
||||||
Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d",
|
|
||||||
fetch: true
|
|
||||||
)
|
|
||||||
|
|
||||||
Object.set_cache(object)
|
|
||||||
|
|
||||||
assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
|
|
||||||
assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
|
|
||||||
|
|
||||||
assert capture_log(fn ->
|
|
||||||
mock_modified.(%Tesla.Env{status: 404, body: ""})
|
|
||||||
|
|
||||||
updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
|
|
||||||
object_in_cache = Object.get_cached_by_ap_id(object.data["id"])
|
|
||||||
assert updated_object == object_in_cache
|
|
||||||
assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 4
|
|
||||||
assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 0
|
|
||||||
end) =~
|
|
||||||
"[error] Couldn't refresh https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d"
|
|
||||||
end
|
|
||||||
|
|
||||||
test "does not refetch if the time since the last refetch is greater than the interval", %{
|
|
||||||
mock_modified: mock_modified
|
|
||||||
} do
|
|
||||||
%Object{} =
|
|
||||||
object =
|
|
||||||
Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d",
|
|
||||||
fetch: true
|
|
||||||
)
|
|
||||||
|
|
||||||
Object.set_cache(object)
|
|
||||||
|
|
||||||
assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
|
|
||||||
assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
|
|
||||||
|
|
||||||
mock_modified.(%Tesla.Env{
|
|
||||||
status: 200,
|
|
||||||
body: File.read!("test/fixtures/tesla_mock/poll_modified.json"),
|
|
||||||
headers: HttpRequestMock.activitypub_object_headers()
|
|
||||||
})
|
|
||||||
|
|
||||||
updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: 100)
|
|
||||||
object_in_cache = Object.get_cached_by_ap_id(object.data["id"])
|
|
||||||
assert updated_object == object_in_cache
|
|
||||||
assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 4
|
|
||||||
assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 0
|
|
||||||
end
|
|
||||||
|
|
||||||
test "preserves internal fields on refetch", %{mock_modified: mock_modified} do
|
|
||||||
%Object{} =
|
|
||||||
object =
|
|
||||||
Object.normalize("https://patch.cx/objects/9a172665-2bc5-452d-8428-2361d4c33b1d",
|
|
||||||
fetch: true
|
|
||||||
)
|
|
||||||
|
|
||||||
Object.set_cache(object)
|
|
||||||
|
|
||||||
assert Enum.at(object.data["oneOf"], 0)["replies"]["totalItems"] == 4
|
|
||||||
assert Enum.at(object.data["oneOf"], 1)["replies"]["totalItems"] == 0
|
|
||||||
|
|
||||||
user = insert(:user)
|
|
||||||
activity = Activity.get_create_by_object_ap_id(object.data["id"])
|
|
||||||
{:ok, activity} = CommonAPI.favorite(activity.id, user)
|
|
||||||
object = Object.get_by_ap_id(activity.data["object"])
|
|
||||||
|
|
||||||
assert object.data["like_count"] == 1
|
|
||||||
|
|
||||||
mock_modified.(%Tesla.Env{
|
|
||||||
status: 200,
|
|
||||||
body: File.read!("test/fixtures/tesla_mock/poll_modified.json"),
|
|
||||||
headers: HttpRequestMock.activitypub_object_headers()
|
|
||||||
})
|
|
||||||
|
|
||||||
updated_object = Object.get_by_id_and_maybe_refetch(object.id, interval: -1)
|
|
||||||
object_in_cache = Object.get_cached_by_ap_id(object.data["id"])
|
|
||||||
assert updated_object == object_in_cache
|
|
||||||
assert Enum.at(updated_object.data["oneOf"], 0)["replies"]["totalItems"] == 8
|
|
||||||
assert Enum.at(updated_object.data["oneOf"], 1)["replies"]["totalItems"] == 3
|
|
||||||
|
|
||||||
assert updated_object.data["like_count"] == 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe ":hashtags association" do
|
describe ":hashtags association" do
|
||||||
test "Hashtag records are created with Object record and updated on its change" do
|
test "Hashtag records are created with Object record and updated on its change" do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
19
test/pleroma/release_task_test.exs
Normal file
19
test/pleroma/release_task_test.exs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.ReleaseTaskTest do
|
||||||
|
use Pleroma.DataCase, async: true
|
||||||
|
|
||||||
|
alias Pleroma.ReleaseTasks
|
||||||
|
|
||||||
|
test "finding the module" do
|
||||||
|
task = "search.meilisearch"
|
||||||
|
assert Mix.Tasks.Pleroma.Search.Meilisearch == ReleaseTasks.find_module(task)
|
||||||
|
|
||||||
|
task = "user"
|
||||||
|
assert Mix.Tasks.Pleroma.User == ReleaseTasks.find_module(task)
|
||||||
|
|
||||||
|
refute ReleaseTasks.find_module("doesnt.exist")
|
||||||
|
end
|
||||||
|
end
|
|
@ -10,6 +10,10 @@ defmodule Pleroma.Upload.Filter.DedupeTest do
|
||||||
|
|
||||||
@shasum "e30397b58d226d6583ab5b8b3c5defb0c682bda5c31ef07a9f57c1c4986e3781"
|
@shasum "e30397b58d226d6583ab5b8b3c5defb0c682bda5c31ef07a9f57c1c4986e3781"
|
||||||
|
|
||||||
|
test "generates a shard path for a shasum" do
|
||||||
|
assert "e3/03/97/" <> _path = Dedupe.shard_path(@shasum)
|
||||||
|
end
|
||||||
|
|
||||||
test "adds shasum" do
|
test "adds shasum" do
|
||||||
File.cp!(
|
File.cp!(
|
||||||
"test/fixtures/image.jpg",
|
"test/fixtures/image.jpg",
|
||||||
|
@ -23,10 +27,12 @@ defmodule Pleroma.Upload.Filter.DedupeTest do
|
||||||
tempfile: Path.absname("test/fixtures/image_tmp.jpg")
|
tempfile: Path.absname("test/fixtures/image_tmp.jpg")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expected_path = Dedupe.shard_path(@shasum <> ".jpg")
|
||||||
|
|
||||||
assert {
|
assert {
|
||||||
:ok,
|
:ok,
|
||||||
:filtered,
|
:filtered,
|
||||||
%Pleroma.Upload{id: @shasum, path: @shasum <> ".jpg"}
|
%Pleroma.Upload{id: @shasum, path: ^expected_path}
|
||||||
} = Dedupe.filter(upload)
|
} = Dedupe.filter(upload)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -149,6 +149,9 @@ defmodule Pleroma.UploadTest do
|
||||||
|
|
||||||
test "copies the file to the configured folder with deduping" do
|
test "copies the file to the configured folder with deduping" do
|
||||||
File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg")
|
File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg")
|
||||||
|
expected_filename = "e30397b58d226d6583ab5b8b3c5defb0c682bda5c31ef07a9f57c1c4986e3781.jpg"
|
||||||
|
|
||||||
|
expected_path = Pleroma.Upload.Filter.Dedupe.shard_path(expected_filename)
|
||||||
|
|
||||||
file = %Plug.Upload{
|
file = %Plug.Upload{
|
||||||
content_type: "image/jpeg",
|
content_type: "image/jpeg",
|
||||||
|
@ -159,8 +162,7 @@ defmodule Pleroma.UploadTest do
|
||||||
{:ok, data} = Upload.store(file, filters: [Pleroma.Upload.Filter.Dedupe])
|
{:ok, data} = Upload.store(file, filters: [Pleroma.Upload.Filter.Dedupe])
|
||||||
|
|
||||||
assert List.first(data["url"])["href"] ==
|
assert List.first(data["url"])["href"] ==
|
||||||
Pleroma.Upload.base_url() <>
|
Path.join([Pleroma.Upload.base_url(), expected_path])
|
||||||
"e30397b58d226d6583ab5b8b3c5defb0c682bda5c31ef07a9f57c1c4986e3781.jpg"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
test "copies the file to the configured folder without deduping" do
|
test "copies the file to the configured folder without deduping" do
|
||||||
|
|
|
@ -1320,6 +1320,27 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|
||||||
html_body: ~r/#{note.data["object"]}/i
|
html_body: ~r/#{note.data["object"]}/i
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "it accepts an incoming Block", %{conn: conn, data: data} do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
data =
|
||||||
|
data
|
||||||
|
|> Map.put("type", "Block")
|
||||||
|
|> Map.put("to", [user.ap_id])
|
||||||
|
|> Map.put("cc", [])
|
||||||
|
|> Map.put("object", user.ap_id)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:valid_signature, true)
|
||||||
|
|> put_req_header("content-type", "application/activity+json")
|
||||||
|
|> post("/users/#{user.nickname}/inbox", data)
|
||||||
|
|
||||||
|
assert "ok" == json_response(conn, 200)
|
||||||
|
ObanHelpers.perform(all_enqueued(worker: ReceiverWorker))
|
||||||
|
assert Activity.get_by_ap_id(data["id"])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "GET /users/:nickname/outbox" do
|
describe "GET /users/:nickname/outbox" do
|
||||||
|
|
155
test/pleroma/web/activity_pub/mrf/remote_report_policy_test.exs
Normal file
155
test/pleroma/web/activity_pub/mrf/remote_report_policy_test.exs
Normal file
|
@ -0,0 +1,155 @@
|
||||||
|
defmodule Pleroma.Web.ActivityPub.MRF.RemoteReportPolicyTest do
|
||||||
|
use Pleroma.DataCase, async: true
|
||||||
|
|
||||||
|
alias Pleroma.Web.ActivityPub.MRF.RemoteReportPolicy
|
||||||
|
|
||||||
|
setup do
|
||||||
|
clear_config([:mrf_remote_report, :reject_all], false)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "doesn't impact local report" do
|
||||||
|
clear_config([:mrf_remote_report, :reject_anonymous], true)
|
||||||
|
clear_config([:mrf_remote_report, :reject_empty_message], true)
|
||||||
|
|
||||||
|
activity = %{
|
||||||
|
"type" => "Flag",
|
||||||
|
"actor" => "http://localhost:4001/actor",
|
||||||
|
"object" => ["https://mastodon.online/users/Gargron"]
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {:ok, _} = RemoteReportPolicy.filter(activity)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "rejects anonymous report if `reject_anonymous: true`" do
|
||||||
|
clear_config([:mrf_remote_report, :reject_anonymous], true)
|
||||||
|
clear_config([:mrf_remote_report, :reject_empty_message], true)
|
||||||
|
|
||||||
|
activity = %{
|
||||||
|
"type" => "Flag",
|
||||||
|
"actor" => "https://mastodon.social/actor",
|
||||||
|
"object" => ["https://mastodon.online/users/Gargron"]
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {:reject, _} = RemoteReportPolicy.filter(activity)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "preserves anonymous report if `reject_anonymous: false`" do
|
||||||
|
clear_config([:mrf_remote_report, :reject_anonymous], false)
|
||||||
|
clear_config([:mrf_remote_report, :reject_empty_message], false)
|
||||||
|
|
||||||
|
activity = %{
|
||||||
|
"type" => "Flag",
|
||||||
|
"actor" => "https://mastodon.social/actor",
|
||||||
|
"object" => ["https://mastodon.online/users/Gargron"]
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {:ok, _} = RemoteReportPolicy.filter(activity)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "rejects report on third party if `reject_third_party: true`" do
|
||||||
|
clear_config([:mrf_remote_report, :reject_third_party], true)
|
||||||
|
clear_config([:mrf_remote_report, :reject_empty_message], false)
|
||||||
|
|
||||||
|
activity = %{
|
||||||
|
"type" => "Flag",
|
||||||
|
"actor" => "https://mastodon.social/users/Gargron",
|
||||||
|
"object" => ["https://mastodon.online/users/Gargron"]
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {:reject, _} = RemoteReportPolicy.filter(activity)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "preserves report on first party if `reject_third_party: true`" do
|
||||||
|
clear_config([:mrf_remote_report, :reject_third_party], true)
|
||||||
|
clear_config([:mrf_remote_report, :reject_empty_message], false)
|
||||||
|
|
||||||
|
activity = %{
|
||||||
|
"type" => "Flag",
|
||||||
|
"actor" => "https://mastodon.social/users/Gargron",
|
||||||
|
"object" => ["http://localhost:4001/actor"]
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {:ok, _} = RemoteReportPolicy.filter(activity)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "preserves report on third party if `reject_third_party: false`" do
|
||||||
|
clear_config([:mrf_remote_report, :reject_third_party], false)
|
||||||
|
clear_config([:mrf_remote_report, :reject_empty_message], false)
|
||||||
|
|
||||||
|
activity = %{
|
||||||
|
"type" => "Flag",
|
||||||
|
"actor" => "https://mastodon.social/users/Gargron",
|
||||||
|
"object" => ["https://mastodon.online/users/Gargron"]
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {:ok, _} = RemoteReportPolicy.filter(activity)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "rejects empty message report if `reject_empty_message: true`" do
|
||||||
|
clear_config([:mrf_remote_report, :reject_anonymous], false)
|
||||||
|
clear_config([:mrf_remote_report, :reject_empty_message], true)
|
||||||
|
|
||||||
|
activity = %{
|
||||||
|
"type" => "Flag",
|
||||||
|
"actor" => "https://mastodon.social/users/Gargron",
|
||||||
|
"object" => ["https://mastodon.online/users/Gargron"]
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {:reject, _} = RemoteReportPolicy.filter(activity)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "rejects empty message report (\"\") if `reject_empty_message: true`" do
|
||||||
|
clear_config([:mrf_remote_report, :reject_anonymous], false)
|
||||||
|
clear_config([:mrf_remote_report, :reject_empty_message], true)
|
||||||
|
|
||||||
|
activity = %{
|
||||||
|
"type" => "Flag",
|
||||||
|
"actor" => "https://mastodon.social/users/Gargron",
|
||||||
|
"object" => ["https://mastodon.online/users/Gargron"],
|
||||||
|
"content" => ""
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {:reject, _} = RemoteReportPolicy.filter(activity)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "preserves empty message report if `reject_empty_message: false`" do
|
||||||
|
clear_config([:mrf_remote_report, :reject_anonymous], false)
|
||||||
|
clear_config([:mrf_remote_report, :reject_empty_message], false)
|
||||||
|
|
||||||
|
activity = %{
|
||||||
|
"type" => "Flag",
|
||||||
|
"actor" => "https://mastodon.social/users/Gargron",
|
||||||
|
"object" => ["https://mastodon.online/users/Gargron"]
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {:ok, _} = RemoteReportPolicy.filter(activity)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "preserves anonymous, empty message report with all settings disabled" do
|
||||||
|
clear_config([:mrf_remote_report, :reject_anonymous], false)
|
||||||
|
clear_config([:mrf_remote_report, :reject_empty_message], false)
|
||||||
|
|
||||||
|
activity = %{
|
||||||
|
"type" => "Flag",
|
||||||
|
"actor" => "https://mastodon.social/actor",
|
||||||
|
"object" => ["https://mastodon.online/users/Gargron"]
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {:ok, _} = RemoteReportPolicy.filter(activity)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "reject remote report if `reject_all: true`" do
|
||||||
|
clear_config([:mrf_remote_report, :reject_all], true)
|
||||||
|
clear_config([:mrf_remote_report, :reject_anonymous], false)
|
||||||
|
clear_config([:mrf_remote_report, :reject_empty_message], false)
|
||||||
|
|
||||||
|
activity = %{
|
||||||
|
"type" => "Flag",
|
||||||
|
"actor" => "https://mastodon.social/users/Gargron",
|
||||||
|
"content" => "Transphobia",
|
||||||
|
"object" => ["https://mastodon.online/users/Gargron"]
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {:reject, _} = RemoteReportPolicy.filter(activity)
|
||||||
|
end
|
||||||
|
end
|
|
@ -32,7 +32,7 @@ defmodule Pleroma.Web.FallbackTest do
|
||||||
resp = get(conn, "/foo")
|
resp = get(conn, "/foo")
|
||||||
|
|
||||||
assert html_response(resp, 200) =~ "<title>a cool title</title>"
|
assert html_response(resp, 200) =~ "<title>a cool title</title>"
|
||||||
refute html_response(resp, 200) =~ "initial-results"
|
assert html_response(resp, 200) =~ "<meta content=\"noindex, noarchive\" name=\"robots\">"
|
||||||
end
|
end
|
||||||
|
|
||||||
test "GET /*path", %{conn: conn} do
|
test "GET /*path", %{conn: conn} do
|
||||||
|
|
|
@ -191,4 +191,60 @@ defmodule Pleroma.Web.Feed.TagControllerTest do
|
||||||
|> response(404)
|
|> response(404)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "restricted for unauthenticated" do
|
||||||
|
test "returns 404 when local timeline is disabled", %{conn: conn} do
|
||||||
|
clear_config([:restrict_unauthenticated, :timelines], %{local: true, federated: false})
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_req_header("accept", "application/rss+xml")
|
||||||
|
|> get(tag_feed_path(conn, :feed, "pleromaart.rss"))
|
||||||
|
|> response(404)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "returns local posts only when federated timeline is disabled", %{conn: conn} do
|
||||||
|
clear_config([:restrict_unauthenticated, :timelines], %{local: false, federated: true})
|
||||||
|
|
||||||
|
local_user = insert(:user)
|
||||||
|
remote_user = insert(:user, local: false)
|
||||||
|
|
||||||
|
local_note =
|
||||||
|
insert(:note,
|
||||||
|
user: local_user,
|
||||||
|
data: %{
|
||||||
|
"content" => "local post #PleromaArt",
|
||||||
|
"summary" => "",
|
||||||
|
"tag" => ["pleromaart"]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
remote_note =
|
||||||
|
insert(:note,
|
||||||
|
user: remote_user,
|
||||||
|
data: %{
|
||||||
|
"content" => "remote post #PleromaArt",
|
||||||
|
"summary" => "",
|
||||||
|
"tag" => ["pleromaart"]
|
||||||
|
},
|
||||||
|
local: false
|
||||||
|
)
|
||||||
|
|
||||||
|
insert(:note_activity, user: local_user, note: local_note)
|
||||||
|
insert(:note_activity, user: remote_user, note: remote_note, local: false)
|
||||||
|
|
||||||
|
response =
|
||||||
|
conn
|
||||||
|
|> put_req_header("accept", "application/rss+xml")
|
||||||
|
|> get(tag_feed_path(conn, :feed, "pleromaart.rss"))
|
||||||
|
|> response(200)
|
||||||
|
|
||||||
|
xml = parse(response)
|
||||||
|
|
||||||
|
assert xpath(xml, ~x"//channel/title/text()") == ~c"#pleromaart"
|
||||||
|
|
||||||
|
assert xpath(xml, ~x"//channel/item/title/text()"l) == [
|
||||||
|
~c"local post #PleromaArt"
|
||||||
|
]
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -147,6 +147,15 @@ defmodule Pleroma.Web.Feed.UserControllerTest do
|
||||||
assert response(conn, 404)
|
assert response(conn, 404)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "returns noindex meta for missing user", %{conn: conn} do
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> put_req_header("accept", "text/html")
|
||||||
|
|> get("/users/nonexisting")
|
||||||
|
|
||||||
|
assert html_response(conn, 200) =~ "<meta content=\"noindex, noarchive\" name=\"robots\">"
|
||||||
|
end
|
||||||
|
|
||||||
test "returns feed with public and unlisted activities", %{conn: conn} do
|
test "returns feed with public and unlisted activities", %{conn: conn} do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ defmodule Pleroma.Web.MastodonAPI.MediaControllerTest do
|
||||||
conn
|
conn
|
||||||
|> put_req_header("content-type", "multipart/form-data")
|
|> put_req_header("content-type", "multipart/form-data")
|
||||||
|> post("/api/v2/media", %{"file" => image, "description" => desc})
|
|> post("/api/v2/media", %{"file" => image, "description" => desc})
|
||||||
|> json_response_and_validate_schema(202)
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
assert media_id = response["id"]
|
assert media_id = response["id"]
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ defmodule Pleroma.Web.MastodonAPI.MediaControllerTest do
|
||||||
"file" => large_binary,
|
"file" => large_binary,
|
||||||
"description" => desc
|
"description" => desc
|
||||||
})
|
})
|
||||||
|> json_response_and_validate_schema(202)
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
assert media_id = response["id"]
|
assert media_id = response["id"]
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
defmodule Pleroma.Web.MastodonAPI.PollControllerTest do
|
defmodule Pleroma.Web.MastodonAPI.PollControllerTest do
|
||||||
|
use Oban.Testing, repo: Pleroma.Repo
|
||||||
use Pleroma.Web.ConnCase, async: true
|
use Pleroma.Web.ConnCase, async: true
|
||||||
|
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
|
@ -27,6 +28,33 @@ defmodule Pleroma.Web.MastodonAPI.PollControllerTest do
|
||||||
response = json_response_and_validate_schema(conn, 200)
|
response = json_response_and_validate_schema(conn, 200)
|
||||||
id = to_string(object.id)
|
id = to_string(object.id)
|
||||||
assert %{"id" => ^id, "expired" => false, "multiple" => false} = response
|
assert %{"id" => ^id, "expired" => false, "multiple" => false} = response
|
||||||
|
|
||||||
|
# Local activities should not generate an Oban job to refresh
|
||||||
|
assert activity.local
|
||||||
|
|
||||||
|
refute_enqueued(
|
||||||
|
worker: Pleroma.Workers.PollWorker,
|
||||||
|
args: %{"op" => "refresh", "activity_id" => activity.id}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "creates an oban job to refresh poll if activity is remote", %{conn: conn} do
|
||||||
|
user = insert(:user, local: false)
|
||||||
|
question = insert(:question, user: user)
|
||||||
|
activity = insert(:question_activity, question: question, local: false)
|
||||||
|
|
||||||
|
# Ensure this is not represented as a local activity
|
||||||
|
refute activity.local
|
||||||
|
|
||||||
|
object = Object.normalize(activity, fetch: false)
|
||||||
|
|
||||||
|
get(conn, "/api/v1/polls/#{object.id}")
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
|
assert_enqueued(
|
||||||
|
worker: Pleroma.Workers.PollWorker,
|
||||||
|
args: %{"op" => "refresh", "activity_id" => activity.id}
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "does not expose polls for private statuses", %{conn: conn} do
|
test "does not expose polls for private statuses", %{conn: conn} do
|
||||||
|
|
40
test/pleroma/web/metadata/providers/activity_pub_test.exs
Normal file
40
test/pleroma/web/metadata/providers/activity_pub_test.exs
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2024 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.Metadata.Providers.ActivityPubTest do
|
||||||
|
use Pleroma.DataCase
|
||||||
|
import Pleroma.Factory
|
||||||
|
|
||||||
|
alias Pleroma.Web.CommonAPI
|
||||||
|
alias Pleroma.Web.Metadata.Providers.ActivityPub
|
||||||
|
|
||||||
|
setup do: clear_config([Pleroma.Web.Metadata, :unfurl_nsfw])
|
||||||
|
|
||||||
|
test "it renders a link for user info" do
|
||||||
|
user = insert(:user)
|
||||||
|
res = ActivityPub.build_tags(%{user: user})
|
||||||
|
|
||||||
|
assert res == [
|
||||||
|
{:link, [rel: "alternate", type: "application/activity+json", href: user.ap_id], []}
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it renders a link for a post" do
|
||||||
|
user = insert(:user)
|
||||||
|
{:ok, %{id: activity_id, object: object}} = CommonAPI.post(user, %{status: "hi"})
|
||||||
|
|
||||||
|
result = ActivityPub.build_tags(%{object: object, user: user, activity_id: activity_id})
|
||||||
|
|
||||||
|
assert [
|
||||||
|
{:link,
|
||||||
|
[rel: "alternate", type: "application/activity+json", href: object.data["id"]], []}
|
||||||
|
] == result
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it returns an empty array for anything else" do
|
||||||
|
result = ActivityPub.build_tags(%{})
|
||||||
|
|
||||||
|
assert result == []
|
||||||
|
end
|
||||||
|
end
|
|
@ -15,4 +15,10 @@ defmodule Pleroma.Web.Metadata.Providers.FeedTest do
|
||||||
[rel: "alternate", type: "application/atom+xml", href: "/users/lain/feed.atom"], []}
|
[rel: "alternate", type: "application/atom+xml", href: "/users/lain/feed.atom"], []}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "it doesn't render a link to remote user's feed" do
|
||||||
|
user = insert(:user, nickname: "lain@lain.com", local: false)
|
||||||
|
|
||||||
|
assert Feed.build_tags(%{user: user}) == []
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -69,7 +69,7 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
|
||||||
|> hd()
|
|> hd()
|
||||||
|> Map.keys()
|
|> Map.keys()
|
||||||
|
|
||||||
assert keys -- ["id", "app_name", "valid_until"] == []
|
assert Enum.sort(keys) == Enum.sort(["id", "app_name", "valid_until", "scopes"])
|
||||||
end
|
end
|
||||||
|
|
||||||
test "revoke token", %{token: token} do
|
test "revoke token", %{token: token} do
|
||||||
|
|
|
@ -11,10 +11,10 @@ defmodule Pleroma.Workers.PollWorkerTest do
|
||||||
|
|
||||||
alias Pleroma.Workers.PollWorker
|
alias Pleroma.Workers.PollWorker
|
||||||
|
|
||||||
test "poll notification job" do
|
test "local poll ending notification job" do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
question = insert(:question, user: user)
|
question = insert(:question, user: user)
|
||||||
activity = insert(:question_activity, question: question)
|
activity = insert(:question_activity, question: question, user: user)
|
||||||
|
|
||||||
PollWorker.schedule_poll_end(activity)
|
PollWorker.schedule_poll_end(activity)
|
||||||
|
|
||||||
|
@ -44,6 +44,65 @@ defmodule Pleroma.Workers.PollWorkerTest do
|
||||||
# Ensure notifications were streamed out when job executes
|
# Ensure notifications were streamed out when job executes
|
||||||
assert called(Pleroma.Web.Streamer.stream(["user", "user:notification"], :_))
|
assert called(Pleroma.Web.Streamer.stream(["user", "user:notification"], :_))
|
||||||
assert called(Pleroma.Web.Push.send(:_))
|
assert called(Pleroma.Web.Push.send(:_))
|
||||||
|
|
||||||
|
# Skip refreshing polls for local activities
|
||||||
|
assert activity.local
|
||||||
|
|
||||||
|
refute_enqueued(
|
||||||
|
worker: PollWorker,
|
||||||
|
args: %{"op" => "refresh", "activity_id" => activity.id}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
test "remote poll ending notification job schedules refresh" do
|
||||||
|
user = insert(:user, local: false)
|
||||||
|
question = insert(:question, user: user)
|
||||||
|
activity = insert(:question_activity, question: question, user: user)
|
||||||
|
|
||||||
|
PollWorker.schedule_poll_end(activity)
|
||||||
|
|
||||||
|
expected_job_args = %{"activity_id" => activity.id, "op" => "poll_end"}
|
||||||
|
|
||||||
|
assert_enqueued(args: expected_job_args)
|
||||||
|
|
||||||
|
[job] = all_enqueued(worker: PollWorker)
|
||||||
|
PollWorker.perform(job)
|
||||||
|
|
||||||
|
refute activity.local
|
||||||
|
|
||||||
|
assert_enqueued(
|
||||||
|
worker: PollWorker,
|
||||||
|
args: %{"op" => "refresh", "activity_id" => activity.id}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "poll refresh" do
|
||||||
|
user = insert(:user, local: false)
|
||||||
|
question = insert(:question, user: user)
|
||||||
|
activity = insert(:question_activity, question: question)
|
||||||
|
|
||||||
|
PollWorker.new(%{"op" => "refresh", "activity_id" => activity.id})
|
||||||
|
|> Oban.insert()
|
||||||
|
|
||||||
|
expected_job_args = %{"activity_id" => activity.id, "op" => "refresh"}
|
||||||
|
|
||||||
|
assert_enqueued(args: expected_job_args)
|
||||||
|
|
||||||
|
with_mocks([
|
||||||
|
{
|
||||||
|
Pleroma.Web.Streamer,
|
||||||
|
[],
|
||||||
|
[
|
||||||
|
stream: fn _, _ -> nil end
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]) do
|
||||||
|
[job] = all_enqueued(worker: PollWorker)
|
||||||
|
PollWorker.perform(job)
|
||||||
|
|
||||||
|
# Ensure updates are streamed out
|
||||||
|
assert called(Pleroma.Web.Streamer.stream(["user", "list", "public", "public:local"], :_))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -241,6 +241,7 @@ defmodule Pleroma.Factory do
|
||||||
|
|
||||||
def question_factory(attrs \\ %{}) do
|
def question_factory(attrs \\ %{}) do
|
||||||
user = attrs[:user] || insert(:user)
|
user = attrs[:user] || insert(:user)
|
||||||
|
closed = attrs[:closed] || DateTime.utc_now() |> DateTime.add(86_400) |> DateTime.to_iso8601()
|
||||||
|
|
||||||
data = %{
|
data = %{
|
||||||
"id" => Pleroma.Web.ActivityPub.Utils.generate_object_id(),
|
"id" => Pleroma.Web.ActivityPub.Utils.generate_object_id(),
|
||||||
|
@ -251,7 +252,7 @@ defmodule Pleroma.Factory do
|
||||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||||
"cc" => [user.follower_address],
|
"cc" => [user.follower_address],
|
||||||
"context" => Pleroma.Web.ActivityPub.Utils.generate_context_id(),
|
"context" => Pleroma.Web.ActivityPub.Utils.generate_context_id(),
|
||||||
"closed" => DateTime.utc_now() |> DateTime.add(86_400) |> DateTime.to_iso8601(),
|
"closed" => closed,
|
||||||
"content" => "Which flavor of ice cream do you prefer?",
|
"content" => "Which flavor of ice cream do you prefer?",
|
||||||
"oneOf" => [
|
"oneOf" => [
|
||||||
%{
|
%{
|
||||||
|
@ -509,7 +510,8 @@ defmodule Pleroma.Factory do
|
||||||
%Pleroma.Activity{
|
%Pleroma.Activity{
|
||||||
data: data,
|
data: data,
|
||||||
actor: data["actor"],
|
actor: data["actor"],
|
||||||
recipients: data["to"]
|
recipients: data["to"],
|
||||||
|
local: user.local
|
||||||
}
|
}
|
||||||
|> Map.merge(attrs)
|
|> Map.merge(attrs)
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Reference in a new issue