forked from AkkomaGang/akkoma
Compare commits
75 commits
keys-extra
...
develop
Author | SHA1 | Date | |
---|---|---|---|
e3c8c4f24f | |||
67cdc38296 | |||
89d209f486 | |||
087ada3b2e | |||
91bedcfa68 | |||
ff5d197341 | |||
7632765b43 | |||
294de939cb | |||
7583eceb38 | |||
834edfcf96 | |||
79b282dea6 | |||
d1d82782db | |||
|
2b1a252cc7 | ||
416aebb76a | |||
932810c35e | |||
4c7ef1e027 | |||
0f9c9aac38 | |||
c0a99df06a | |||
0cb4c35ee4 | |||
c9b3fcc1d3 | |||
11c5838947 | |||
180dc8b472 | |||
d330c57cda | |||
bd64d07082 | |||
9d2c558f64 | |||
ac25b051ae | |||
c5a44a59db | |||
58d5d9d7bf | |||
b6e8fde4dd | |||
bee10eab5e | |||
13215f5f06 | |||
430b376ded | |||
ccf1007883 | |||
6da783b84d | |||
8f322456a0 | |||
9c876cea21 | |||
9728e2f8f7 | |||
b0f7da9ce0 | |||
fc99c694e6 | |||
fbb13fde76 | |||
cbd236aeb5 | |||
71d3bbd7be | |||
98a3dab10a | |||
|
661b7fedb6 | ||
|
8b5aca9619 | ||
f101886709 | |||
09fa7227f6 | |||
d5b0720596 | |||
940792f8ba | |||
3c72b48a05 | |||
6475cf127e | |||
a8a231c5b2 | |||
2901fda29c | |||
bd14440386 | |||
|
b312edac4c | ||
3bb31117e6 | |||
2c5c531c35 | |||
a3101a435b | |||
d488cf476e | |||
ca182a0ae7 | |||
495a1a71e8 | |||
cf19d4901f | |||
07539f7825 | |||
0ab2f2ab45 | |||
95ed4931f8 | |||
7cd3954152 | |||
80a4e30be7 | |||
3ff0f46b9f | |||
4ff5293093 | |||
3b197503d2 | |||
c0b2bba55e | |||
4b765b1886 | |||
cba2c5725f | |||
|
3947012691 | ||
|
d61b7d4b49 |
64 changed files with 510 additions and 282 deletions
|
@ -87,5 +87,5 @@ steps:
|
|||
- mix ecto.create
|
||||
- mix ecto.migrate
|
||||
- mkdir -p test/tmp
|
||||
- mix test --preload-modules --exclude erratic --exclude federated --exclude mocked
|
||||
- mix test --preload-modules --only mocked
|
||||
- mix test --preload-modules --exclude erratic --exclude federated --exclude mocked || mix test --failed
|
||||
- mix test --preload-modules --only mocked || mix test --failed
|
||||
|
|
13
CHANGELOG.md
13
CHANGELOG.md
|
@ -6,8 +6,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||
|
||||
## UNRELEASED
|
||||
|
||||
## Fixed
|
||||
- Media proxy no longer attempts to proxy embedded images
|
||||
|
||||
## 3.13.3
|
||||
|
||||
## BREAKING
|
||||
- Minimum PostgreSQL version is raised to 12
|
||||
- Swagger UI moved from `/akkoma/swaggerui/` to `/pleroma/swaggerui/`
|
||||
|
||||
## Added
|
||||
- Implement [FEP-67ff](https://codeberg.org/fediverse/fep/src/branch/main/fep/67ff/fep-67ff.md) (federation documentation)
|
||||
|
@ -17,6 +23,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||
|
||||
## Fixed
|
||||
- Meilisearch: order of results returned from our REST API now actually matches how Meilisearch ranks results
|
||||
- Emoji are now federated as anonymous objects, fixing issues with
|
||||
some strict servers e.g. rejecting e.g. remote emoji reactions
|
||||
- AP objects with additional JSON-LD profiles beyond ActivityStreams can now be fetched
|
||||
- Single-selection polls no longer expose the voter_count; MastoAPI demands it be null
|
||||
and this confused some clients leading to vote distributions >100%
|
||||
- ObjectAge policy no longer lets unlisted posts slip through
|
||||
- ObjectAge policy no longer leaks belated DMs and follower-only posts
|
||||
|
||||
## Changed
|
||||
- Refactored Rich Media to cache the content in the database. Fetching operations that could block status rendering have been eliminated.
|
||||
|
|
|
@ -51,7 +51,8 @@
|
|||
hostname: System.get_env("DB_HOST") || "localhost",
|
||||
pool: Ecto.Adapters.SQL.Sandbox,
|
||||
pool_size: 50,
|
||||
queue_target: 5000
|
||||
queue_target: 5000,
|
||||
log: false
|
||||
|
||||
config :pleroma, :dangerzone, override_repo_pool_size: true
|
||||
|
||||
|
|
|
@ -11,4 +11,4 @@ echo "-- Running migrations..."
|
|||
mix ecto.migrate
|
||||
|
||||
echo "-- Starting!"
|
||||
mix phx.server
|
||||
elixir --erl "+sbwt none +sbwtdcpu none +sbwtdio none" -S mix phx.server
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
|
||||
1. Stop the Akkoma service.
|
||||
2. Go to the working directory of Akkoma (default is `/opt/akkoma`)
|
||||
3. Run[¹] `sudo -Hu postgres pg_dump -d akkoma --format=custom -f </path/to/backup_location/akkoma.pgdump>` (make sure the postgres user has write access to the destination file)
|
||||
4. Copy `akkoma.pgdump`, `config/prod.secret.exs`[²], `config/setup_db.psql` (if still available) and the `uploads` folder to your backup destination. If you have other modifications, copy those changes too.
|
||||
3. Run `sudo -Hu postgres pg_dump -d akkoma --format=custom -f </path/to/backup_location/akkoma.pgdump>`[¹] (make sure the postgres user has write access to the destination file)
|
||||
4. Copy `akkoma.pgdump`, `config/config.exs`[²], `uploads` folder, and [static directory](../configuration/static_dir.md) to your backup destination. If you have other modifications, copy those changes too.
|
||||
5. Restart the Akkoma service.
|
||||
|
||||
[¹]: We assume the database name is "akkoma". If not, you can find the correct name in your config files.
|
||||
[²]: If you've installed using OTP, you need `config/config.exs` instead of `config/prod.secret.exs`.
|
||||
[¹]: We assume the database name is "akkoma". If not, you can find the correct name in your configuration files.
|
||||
[²]: If you have a from source installation, you need `config/prod.secret.exs` instead of `config/config.exs`. The `config/config.exs` file also exists, but in case of from source installations, it only contains the default values and it is tracked by Git, so you don't need to back it up.
|
||||
|
||||
## Restore/Move
|
||||
|
||||
|
@ -17,19 +17,16 @@
|
|||
2. Stop the Akkoma service.
|
||||
3. Go to the working directory of Akkoma (default is `/opt/akkoma`)
|
||||
4. Copy the above mentioned files back to their original position.
|
||||
5. Drop the existing database and user if restoring in-place[¹]. `sudo -Hu postgres psql -c 'DROP DATABASE akkoma;';` `sudo -Hu postgres psql -c 'DROP USER akkoma;'`
|
||||
6. Restore the database schema and akkoma role using either of the following options
|
||||
* You can use the original `setup_db.psql` if you have it[²]: `sudo -Hu postgres psql -f config/setup_db.psql`.
|
||||
* Or recreate the database and user yourself (replace the password with the one you find in the config file) `sudo -Hu postgres psql -c "CREATE USER akkoma WITH ENCRYPTED PASSWORD '<database-password-wich-you-can-find-in-your-config-file>'; CREATE DATABASE akkoma OWNER akkoma;"`.
|
||||
5. Drop the existing database and user[¹]. `sudo -Hu postgres psql -c 'DROP DATABASE akkoma;';` `sudo -Hu postgres psql -c 'DROP USER akkoma;'`
|
||||
6. Restore the database schema and akkoma role[¹] (replace the password with the one you find in the configuration file), `sudo -Hu postgres psql -c "CREATE USER akkoma WITH ENCRYPTED PASSWORD '<database-password-wich-you-can-find-in-your-configuration-file>';"` `sudo -Hu postgres psql -c "CREATE DATABASE akkoma OWNER akkoma;"`.
|
||||
7. Now restore the Akkoma instance's data into the empty database schema[¹]: `sudo -Hu postgres pg_restore -d akkoma -v -1 </path/to/backup_location/akkoma.pgdump>`
|
||||
8. If you installed a newer Akkoma version, you should run `MIX_ENV=prod mix ecto.migrate`[³]. This task performs database migrations, if there were any.
|
||||
8. If you installed a newer Akkoma version, you should run the database migrations `./bin/pleroma_ctl migrate`[²].
|
||||
9. Restart the Akkoma service.
|
||||
10. Run `sudo -Hu postgres vacuumdb --all --analyze-in-stages`. This will quickly generate the statistics so that postgres can properly plan queries.
|
||||
11. If setting up on a new server configure Nginx by using the `installation/akkoma.nginx` config sample or reference the Akkoma installation guide for your OS which contains the Nginx configuration instructions.
|
||||
11. If setting up on a new server, configure Nginx by using the `installation/nginx/akkoma.nginx` configuration sample or reference the Akkoma installation guide which contains the Nginx configuration instructions.
|
||||
|
||||
[¹]: We assume the database name and user are both "akkoma". If not, you can find the correct name in your config files.
|
||||
[²]: You can recreate the `config/setup_db.psql` by running the `mix pleroma.instance gen` task again. You can ignore most of the questions, but make the database user, name, and password the same as found in your backed up config file. This will also create a new `config/generated_config.exs` file which you may delete as it is not needed.
|
||||
[³]: Prefix with `MIX_ENV=prod` to run it using the production config file.
|
||||
[¹]: We assume the database name and user are both "akkoma". If not, you can find the correct name in your configuration files.
|
||||
[²]: If you have a from source installation, the command is `MIX_ENV=prod mix ecto.migrate`. Note that we prefix with `MIX_ENV=prod` to use the `config/prod.secret.exs` configuration file.
|
||||
|
||||
## Remove
|
||||
|
||||
|
|
|
@ -338,7 +338,7 @@ config :pleroma, :frontends,
|
|||
|
||||
* `:primary` - The frontend that will be served at `/`
|
||||
* `:admin` - The frontend that will be served at `/pleroma/admin`
|
||||
* `:swagger` - Config for developers to act as an API reference to be served at `/akkoma/swaggerui/` (trailing slash _needed_). Disabled by default.
|
||||
* `:swagger` - Config for developers to act as an API reference to be served at `/pleroma/swaggerui/` (trailing slash _needed_). Disabled by default.
|
||||
* `:mastodon` - The mastodon-fe configuration. This shouldn't need to be changed. This is served at `/web` when installed.
|
||||
|
||||
### :static\_fe
|
||||
|
|
|
@ -60,4 +60,4 @@ config :pleroma, :frontends,
|
|||
|
||||
Then run the [pleroma.frontend cli task](../../administration/CLI_tasks/frontend) with the name of `swagger-ui` to install the distribution files.
|
||||
|
||||
You will now be able to view documentation at `/akkoma/swaggerui`
|
||||
You will now be able to view documentation at `/pleroma/swaggerui`
|
||||
|
|
|
@ -6,7 +6,7 @@ as soon as the post is received by your instance.
|
|||
|
||||
## Nginx
|
||||
|
||||
The following are excerpts from the [suggested nginx config](../../../installation/nginx/akkoma.nginx) that demonstrates the necessary config for the media proxy to work.
|
||||
The following are excerpts from the [suggested nginx config](https://akkoma.dev/AkkomaGang/akkoma/src/branch/develop/installation/nginx/akkoma.nginx) that demonstrates the necessary config for the media proxy to work.
|
||||
|
||||
A `proxy_cache_path` must be defined, for example:
|
||||
|
||||
|
|
|
@ -6,7 +6,9 @@ probably install frontends.
|
|||
These are no longer bundled with the distribution and need an extra
|
||||
command to install.
|
||||
|
||||
For most installations, the following will suffice:
|
||||
You **must** run frontend management tasks as the akkoma user,
|
||||
the same way you downloaded the build or cloned the git repo before.
|
||||
But otherwise, for most installations, the following will suffice:
|
||||
|
||||
=== "OTP"
|
||||
```sh
|
||||
|
@ -28,4 +30,3 @@ For most installations, the following will suffice:
|
|||
```
|
||||
|
||||
For more customised installations, refer to [Frontend Management](../../configuration/frontend_management)
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
* PostgreSQL 12+
|
||||
* Elixir 1.14+ (currently tested up to 1.16)
|
||||
* Erlang OTP 25+ (currently tested up to OTP26)
|
||||
* Erlang OTP 25+ (currently tested up to OTP27)
|
||||
* git
|
||||
* file / libmagic
|
||||
* gcc (clang might also work)
|
||||
|
|
|
@ -19,6 +19,9 @@ Environment="MIX_ENV=prod"
|
|||
; Don't listen epmd on 0.0.0.0
|
||||
Environment="ERL_EPMD_ADDRESS=127.0.0.1"
|
||||
|
||||
; Don't busy wait
|
||||
Environment="ERL_AFLAGS=+sbwt none +sbwtdcpu none +sbwtdio none"
|
||||
|
||||
; Make sure that all paths fit your installation.
|
||||
; Path to the home directory of the user running the Akkoma service.
|
||||
Environment="HOME=/var/lib/akkoma"
|
||||
|
|
|
@ -1,23 +1,43 @@
|
|||
#!/sbin/openrc-run
|
||||
supervisor=supervise-daemon
|
||||
command_user=akkoma:akkoma
|
||||
command_background=1
|
||||
# Ask process to terminate within 30 seconds, otherwise kill it
|
||||
retry="SIGTERM/30/SIGKILL/5"
|
||||
pidfile="/var/run/akkoma.pid"
|
||||
directory=/opt/akkoma
|
||||
healthcheck_delay=60
|
||||
healthcheck_timer=30
|
||||
no_new_privs="yes"
|
||||
pidfile="/var/run/akkoma.pid"
|
||||
|
||||
: ${akkoma_port:-4000}
|
||||
# Ask process first to terminate itself within 60s, otherwise kill it
|
||||
retry="SIGTERM/60/SIGKILL/5"
|
||||
|
||||
# Needs OpenRC >= 0.42
|
||||
#respawn_max=0
|
||||
#respawn_delay=5
|
||||
# if you really want to use start-stop-daemon instead,
|
||||
# also put the following in the config:
|
||||
# command_background=1
|
||||
|
||||
# Adjust defaults as needed in /etc/conf.d/akkoma;
|
||||
# no need to directly edit the service file
|
||||
command_user="${command_user:-akkoma:akkoma}"
|
||||
directory="${directory:-/var/lib/akkoma/akkoma}"
|
||||
akkoma_port="${akkoma_port:-4000}"
|
||||
# whether to allow connecting a remote exlixir shell to the running Akkoma instance
|
||||
akkoma_console=${akkoma_console:-NO}
|
||||
|
||||
output_log="${output_log:-/var/log/akkoma}"
|
||||
error_log="${error_log:-/var/log/akkoma}"
|
||||
|
||||
# 0 means unlimited restarts
|
||||
respawn_max="${respawn_max:-0}"
|
||||
respawn_delay="${respawn_delay:-5}"
|
||||
# define respawn period to only count crashes within a
|
||||
# sliding time window towards respawn_max, e.g.:
|
||||
# respawn_period=2850
|
||||
|
||||
healthcheck_delay="${healthcheck_delay:-60}"
|
||||
healthcheck_timer="${healthcheck_timer:-30}"
|
||||
|
||||
MIX_ENV=prod
|
||||
ERL_EPMD_ADDRESS="${ERL_EPMD_ADDRESS:-127.0.0.1}"
|
||||
ERL_AFLAGS="${ERL_AFLAGS:-+sbwt none +sbwtdcpu none +sbwtdio none}"
|
||||
supervise_daemon_args="${supervise_daemon_args} --env MIX_ENV=${MIX_ENV}"
|
||||
supervise_daemon_args="${supervise_daemon_args} --env ERL_EPMD_ADDRESS=${ERL_EPMD_ADDRESS}"
|
||||
supervise_daemon_args="${supervise_daemon_args} --env ERL_AFLAGS='${ERL_AFLAGS}'"
|
||||
|
||||
# put akkoma_console=YES in /etc/conf.d/akkoma if you want to be able to
|
||||
# connect to akkoma via an elixir console
|
||||
if yesno "${akkoma_console}"; then
|
||||
command=elixir
|
||||
command_args="--name akkoma@127.0.0.1 --erl '-kernel inet_dist_listen_min 9001 inet_dist_listen_max 9001 inet_dist_use_interface {127,0,0,1}' -S mix phx.server"
|
||||
|
@ -31,13 +51,24 @@ else
|
|||
command_args="phx.server"
|
||||
fi
|
||||
|
||||
export MIX_ENV=prod
|
||||
export ERL_EPMD_ADDRESS=127.0.0.1
|
||||
|
||||
depend() {
|
||||
need nginx postgresql
|
||||
}
|
||||
|
||||
start_pre() {
|
||||
# Ensure logfile ownership and perms are alright
|
||||
checkpath --file --owner "$command_user" "$output_log" "$error_log" \
|
||||
|| eerror "Logfile(s) not owned by $command_user, or not a file!"
|
||||
checkpath --writable "$output_log" "$error_log" \
|
||||
|| eerror "Logfile(s) not writable!"
|
||||
|
||||
# If a recompile is needed perform it with lowest prio
|
||||
# (delaying the actual start) to avoid hogging too much
|
||||
# CPU from other services
|
||||
cd "$directory"
|
||||
doas -u "${command_user%%:*}" env MIX_ENV="$MIX_ENV" nice -n 19 "$command" compile
|
||||
}
|
||||
|
||||
healthcheck() {
|
||||
# put akkoma_health=YES in /etc/conf.d/akkoma if you want healthchecking
|
||||
# and make sure you have curl installed
|
||||
|
|
|
@ -111,7 +111,7 @@ def run(["get-packs" | args]) do
|
|||
|
||||
{:ok, _} =
|
||||
:zip.unzip(binary_archive,
|
||||
cwd: pack_path,
|
||||
cwd: to_charlist(pack_path),
|
||||
file_list: files_to_unzip
|
||||
)
|
||||
|
||||
|
|
|
@ -125,7 +125,7 @@ def add_file(%Pack{} = pack, _, _, %Plug.Upload{content_type: "application/zip"}
|
|||
{:ok, _emoji_files} =
|
||||
:zip.unzip(
|
||||
to_charlist(file.path),
|
||||
[{:file_list, Enum.map(emojies, & &1[:path])}, {:cwd, tmp_dir}]
|
||||
[{:file_list, Enum.map(emojies, & &1[:path])}, {:cwd, to_charlist(tmp_dir)}]
|
||||
)
|
||||
|
||||
{_, updated_pack} =
|
||||
|
|
|
@ -79,6 +79,10 @@ def unzip(zip, dest) do
|
|||
|
||||
new_file_path = Path.join(dest, path)
|
||||
|
||||
new_file_path
|
||||
|> Path.dirname()
|
||||
|> File.rm()
|
||||
|
||||
new_file_path
|
||||
|> Path.dirname()
|
||||
|> File.mkdir_p!()
|
||||
|
|
|
@ -12,8 +12,6 @@ defmodule Pleroma.Object.Containment do
|
|||
spoofing, therefore removal of object containment functions is NOT recommended.
|
||||
"""
|
||||
|
||||
alias Pleroma.Web.ActivityPub.Transmogrifier
|
||||
|
||||
def get_actor(%{"actor" => actor}) when is_binary(actor) do
|
||||
actor
|
||||
end
|
||||
|
@ -50,16 +48,39 @@ def get_object(_) do
|
|||
defp compare_uris(%URI{host: host} = _id_uri, %URI{host: host} = _other_uri), do: :ok
|
||||
defp compare_uris(_id_uri, _other_uri), do: :error
|
||||
|
||||
defp compare_uris_exact(uri, uri), do: :ok
|
||||
defp uri_strip_slash(%URI{path: path} = uri) when is_binary(path),
|
||||
do: %{uri | path: String.replace_suffix(path, "/", "")}
|
||||
|
||||
defp compare_uris_exact(%URI{} = id, %URI{} = other),
|
||||
do: compare_uris_exact(URI.to_string(id), URI.to_string(other))
|
||||
defp uri_strip_slash(uri), do: uri
|
||||
|
||||
defp compare_uris_exact(id_uri, other_uri)
|
||||
when is_binary(id_uri) and is_binary(other_uri) do
|
||||
norm_id = String.replace_suffix(id_uri, "/", "")
|
||||
norm_other = String.replace_suffix(other_uri, "/", "")
|
||||
if norm_id == norm_other, do: :ok, else: :error
|
||||
# domain names are case-insensitive per spec (other parts of URIs aren’t necessarily)
|
||||
defp uri_normalise_host(%URI{host: host} = uri) when is_binary(host),
|
||||
do: %{uri | host: String.downcase(host, :ascii)}
|
||||
|
||||
defp uri_normalise_host(uri), do: uri
|
||||
|
||||
defp compare_uri_identities(uri, uri), do: :ok
|
||||
|
||||
defp compare_uri_identities(id_uri, other_uri) when is_binary(id_uri) and is_binary(other_uri),
|
||||
do: compare_uri_identities(URI.parse(id_uri), URI.parse(other_uri))
|
||||
|
||||
defp compare_uri_identities(%URI{} = id, %URI{} = other) do
|
||||
normid =
|
||||
%{id | fragment: nil}
|
||||
|> uri_strip_slash()
|
||||
|> uri_normalise_host()
|
||||
|
||||
normother =
|
||||
%{other | fragment: nil}
|
||||
|> uri_strip_slash()
|
||||
|> uri_normalise_host()
|
||||
|
||||
# Conversion back to binary avoids issues from non-normalised deprecated authority field
|
||||
if URI.to_string(normid) == URI.to_string(normother) do
|
||||
:ok
|
||||
else
|
||||
:error
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
|
@ -93,21 +114,13 @@ def contain_origin(id, %{"attributedTo" => actor} = params),
|
|||
def contain_origin(_id, _data), do: :ok
|
||||
|
||||
@doc """
|
||||
Check whether the fetch URL (after redirects) exactly (sans tralining slash) matches either
|
||||
the canonical ActivityPub id or the objects url field (for display URLs from *key and Mastodon)
|
||||
Check whether the fetch URL (after redirects) is the
|
||||
same location the canonical ActivityPub id points to.
|
||||
|
||||
Since this is meant to be used for fetches, anonymous or transient objects are not accepted here.
|
||||
"""
|
||||
def contain_id_to_fetch(url, %{"id" => id} = data) when is_binary(id) do
|
||||
with {:id, :error} <- {:id, compare_uris_exact(id, url)},
|
||||
# "url" can be a "Link" object and this is checked before full normalisation
|
||||
display_url <- Transmogrifier.fix_url(data)["url"],
|
||||
true <- display_url != nil do
|
||||
compare_uris_exact(display_url, url)
|
||||
else
|
||||
{:id, :ok} -> :ok
|
||||
_ -> :error
|
||||
end
|
||||
def contain_id_to_fetch(url, %{"id" => id}) when is_binary(id) do
|
||||
compare_uri_identities(url, id)
|
||||
end
|
||||
|
||||
def contain_id_to_fetch(_url, _data), do: :error
|
||||
|
|
|
@ -116,7 +116,7 @@ defp reinject_object(%Object{} = object, new_data) do
|
|||
@doc "Assumes object already is in our database and refetches from remote to update (e.g. for polls)"
|
||||
def refetch_object(%Object{data: %{"id" => id}} = object) do
|
||||
with {:local, false} <- {:local, Object.local?(object)},
|
||||
{:ok, new_data} <- fetch_and_contain_remote_object_from_id(id),
|
||||
{:ok, new_data} <- fetch_and_contain_remote_object_from_id(id, true),
|
||||
{:id, true} <- {:id, new_data["id"] == id},
|
||||
{:ok, object} <- reinject_object(object, new_data) do
|
||||
{:ok, object}
|
||||
|
@ -253,14 +253,17 @@ defp maybe_date_fetch(headers, date) do
|
|||
end
|
||||
end
|
||||
|
||||
@doc "Fetches arbitrary remote object and performs basic safety and authenticity checks"
|
||||
def fetch_and_contain_remote_object_from_id(id)
|
||||
@doc """
|
||||
Fetches arbitrary remote object and performs basic safety and authenticity checks.
|
||||
When the fetch URL is known to already be a canonical AP id, checks are stricter.
|
||||
"""
|
||||
def fetch_and_contain_remote_object_from_id(id, is_ap_id \\ false)
|
||||
|
||||
def fetch_and_contain_remote_object_from_id(%{"id" => id}),
|
||||
do: fetch_and_contain_remote_object_from_id(id)
|
||||
def fetch_and_contain_remote_object_from_id(%{"id" => id}, is_ap_id),
|
||||
do: fetch_and_contain_remote_object_from_id(id, is_ap_id)
|
||||
|
||||
def fetch_and_contain_remote_object_from_id(id) when is_binary(id) do
|
||||
Logger.debug("Fetching object #{id} via AP")
|
||||
def fetch_and_contain_remote_object_from_id(id, is_ap_id) when is_binary(id) do
|
||||
Logger.debug("Fetching object #{id} via AP [ap_id=#{is_ap_id}]")
|
||||
|
||||
with {:valid_uri_scheme, true} <- {:valid_uri_scheme, String.starts_with?(id, "http")},
|
||||
%URI{} = uri <- URI.parse(id),
|
||||
|
@ -270,18 +273,31 @@ def fetch_and_contain_remote_object_from_id(id) when is_binary(id) do
|
|||
{:mrf_accept_check, Pleroma.Web.ActivityPub.MRF.SimplePolicy.check_accept(uri)},
|
||||
{:local_fetch, :ok} <- {:local_fetch, Containment.contain_local_fetch(id)},
|
||||
{:ok, final_id, body} <- get_object(id),
|
||||
# a canonical ID shouldn't be a redirect
|
||||
true <- !is_ap_id || final_id == id,
|
||||
{:ok, data} <- safe_json_decode(body),
|
||||
{_, :ok} <- {:strict_id, Containment.contain_id_to_fetch(final_id, data)},
|
||||
{_, :ok} <- {:containment, Containment.contain_origin(final_id, data)} do
|
||||
{_, :ok} <- {:containment, Containment.contain_origin(final_id, data)},
|
||||
{_, _, :ok} <- {:strict_id, data["id"], Containment.contain_id_to_fetch(final_id, data)} do
|
||||
unless Instances.reachable?(final_id) do
|
||||
Instances.set_reachable(final_id)
|
||||
end
|
||||
|
||||
{:ok, data}
|
||||
else
|
||||
{:strict_id, _} = e ->
|
||||
log_fetch_error(id, e)
|
||||
{:error, :id_mismatch}
|
||||
# E.g. Mastodon and *key serve the AP object directly under their display URLs without
|
||||
# redirecting to their canonical location first, thus ids will expectedly differ.
|
||||
# Similarly keys, either use a fragment ID and are a subobjects or a distinct ID
|
||||
# but for compatibility are still a subobject presenting their owning actors ID at the toplevel.
|
||||
# Refetching _once_ from the listed id, should yield a strict match afterwards.
|
||||
{:strict_id, ap_id, _} = e ->
|
||||
case is_ap_id do
|
||||
false ->
|
||||
fetch_and_contain_remote_object_from_id(ap_id, true)
|
||||
|
||||
true ->
|
||||
log_fetch_error(id, e)
|
||||
{:error, :id_mismatch}
|
||||
end
|
||||
|
||||
{:mrf_reject_check, _} = e ->
|
||||
log_fetch_error(id, e)
|
||||
|
@ -301,7 +317,7 @@ def fetch_and_contain_remote_object_from_id(id) when is_binary(id) do
|
|||
|
||||
{:containment, reason} ->
|
||||
log_fetch_error(id, reason)
|
||||
{:error, reason}
|
||||
{:error, {:containment, reason}}
|
||||
|
||||
{:error, e} ->
|
||||
{:error, e}
|
||||
|
@ -311,25 +327,13 @@ def fetch_and_contain_remote_object_from_id(id) when is_binary(id) do
|
|||
end
|
||||
end
|
||||
|
||||
def fetch_and_contain_remote_object_from_id(_id),
|
||||
def fetch_and_contain_remote_object_from_id(_id, _is_ap_id),
|
||||
do: {:error, :invalid_id}
|
||||
|
||||
defp check_crossdomain_redirect(final_host, original_url)
|
||||
|
||||
# HOPEFULLY TEMPORARY
|
||||
# Basically none of our Tesla mocks in tests set the (supposed to
|
||||
# exist for Tesla proper) url parameter for their responses
|
||||
# causing almost every fetch in test to fail otherwise
|
||||
if @mix_env == :test do
|
||||
defp check_crossdomain_redirect(nil, _) do
|
||||
{:cross_domain_redirect, false}
|
||||
end
|
||||
end
|
||||
|
||||
defp check_crossdomain_redirect(final_host, original_url) do
|
||||
{:cross_domain_redirect, final_host != URI.parse(original_url).host}
|
||||
end
|
||||
|
||||
if @mix_env == :test do
|
||||
defp get_final_id(nil, initial_url), do: initial_url
|
||||
defp get_final_id("", initial_url), do: initial_url
|
||||
|
@ -339,6 +343,7 @@ defp get_final_id(final_url, _intial_url) do
|
|||
final_url
|
||||
end
|
||||
|
||||
@doc "Do NOT use; only public for use in tests"
|
||||
def get_object(id) do
|
||||
date = Pleroma.Signature.signed_date()
|
||||
|
||||
|
@ -354,10 +359,6 @@ def get_object(id) do
|
|||
with {:ok, %{body: body, status: code, headers: headers, url: final_url}}
|
||||
when code in 200..299 <-
|
||||
HTTP.Backoff.get(id, headers),
|
||||
remote_host <-
|
||||
URI.parse(final_url).host,
|
||||
{:cross_domain_redirect, false} <-
|
||||
check_crossdomain_redirect(remote_host, id),
|
||||
{:has_content_type, {_, content_type}} <-
|
||||
{:has_content_type, List.keyfind(headers, "content-type", 0)},
|
||||
{:parse_content_type, {:ok, "application", subtype, type_params}} <-
|
||||
|
@ -368,8 +369,12 @@ def get_object(id) do
|
|||
{"activity+json", _} ->
|
||||
{:ok, final_id, body}
|
||||
|
||||
{"ld+json", %{"profile" => "https://www.w3.org/ns/activitystreams"}} ->
|
||||
{:ok, final_id, body}
|
||||
{"ld+json", %{"profile" => profiles}} ->
|
||||
if "https://www.w3.org/ns/activitystreams" in String.split(profiles) do
|
||||
{:ok, final_id, body}
|
||||
else
|
||||
{:error, {:content_type, content_type}}
|
||||
end
|
||||
|
||||
_ ->
|
||||
{:error, {:content_type, content_type}}
|
||||
|
|
|
@ -6,12 +6,10 @@ defmodule Pleroma.Signature do
|
|||
@behaviour HTTPSignatures.Adapter
|
||||
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.User.SigningKey
|
||||
require Logger
|
||||
|
||||
def key_id_to_actor_id(key_id) do
|
||||
# Given the key ID, first attempt to look it up in the signing keys table.
|
||||
case SigningKey.key_id_to_ap_id(key_id) do
|
||||
nil ->
|
||||
# hm, we SHOULD have gotten this in the pipeline before we hit here!
|
||||
|
@ -49,7 +47,7 @@ def refetch_public_key(conn) do
|
|||
|
||||
def sign(%User{} = user, headers) do
|
||||
with {:ok, private_key} <- SigningKey.private_key(user) do
|
||||
HTTPSignatures.sign(private_key, user.ap_id <> "#main-key", headers)
|
||||
HTTPSignatures.sign(private_key, SigningKey.local_key_id(user.ap_id), headers)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ defmodule Pleroma.Upload.Filter.Exiftool.StripMetadata do
|
|||
|
||||
# Formats not compatible with exiftool at this time
|
||||
def filter(%Pleroma.Upload{content_type: "image/webp"}), do: {:ok, :noop}
|
||||
def filter(%Pleroma.Upload{content_type: "image/bmp"}), do: {:ok, :noop}
|
||||
def filter(%Pleroma.Upload{content_type: "image/svg+xml"}), do: {:ok, :noop}
|
||||
|
||||
def filter(%Pleroma.Upload{tempfile: file, content_type: "image" <> _}) do
|
||||
|
|
|
@ -101,7 +101,6 @@ defmodule Pleroma.User do
|
|||
field(:password, :string, virtual: true)
|
||||
field(:password_confirmation, :string, virtual: true)
|
||||
field(:keys, :string)
|
||||
field(:public_key, :string)
|
||||
field(:ap_id, :string)
|
||||
field(:avatar, :map, default: %{})
|
||||
field(:local, :boolean, default: true)
|
||||
|
@ -444,6 +443,7 @@ defp fix_follower_address(params), do: params
|
|||
def remote_user_changeset(struct \\ %User{local: false}, params) do
|
||||
bio_limit = Config.get([:instance, :user_bio_length], 5000)
|
||||
name_limit = Config.get([:instance, :user_name_length], 100)
|
||||
fields_limit = Config.get([:instance, :max_remote_account_fields], 0)
|
||||
|
||||
name =
|
||||
case params[:name] do
|
||||
|
@ -457,6 +457,7 @@ def remote_user_changeset(struct \\ %User{local: false}, params) do
|
|||
|> Map.put_new(:last_refreshed_at, NaiveDateTime.utc_now())
|
||||
|> truncate_if_exists(:name, name_limit)
|
||||
|> truncate_if_exists(:bio, bio_limit)
|
||||
|> Map.update(:fields, [], &Enum.take(&1, fields_limit))
|
||||
|> truncate_fields_param()
|
||||
|> fix_follower_address()
|
||||
|
||||
|
@ -471,7 +472,6 @@ def remote_user_changeset(struct \\ %User{local: false}, params) do
|
|||
:inbox,
|
||||
:shared_inbox,
|
||||
:nickname,
|
||||
:public_key,
|
||||
:avatar,
|
||||
:ap_enabled,
|
||||
:banner,
|
||||
|
@ -532,7 +532,6 @@ def update_changeset(struct, params \\ %{}) do
|
|||
:name,
|
||||
:emoji,
|
||||
:avatar,
|
||||
:public_key,
|
||||
:inbox,
|
||||
:shared_inbox,
|
||||
:is_locked,
|
||||
|
@ -1634,8 +1633,12 @@ def blocks_user?(%User{} = user, %User{} = target) do
|
|||
|
||||
def blocks_user?(_, _), do: false
|
||||
|
||||
def blocks_domain?(%User{} = user, %User{} = target) do
|
||||
%{host: host} = URI.parse(target.ap_id)
|
||||
def blocks_domain?(%User{} = user, %User{ap_id: ap_id}) do
|
||||
blocks_domain?(user, ap_id)
|
||||
end
|
||||
|
||||
def blocks_domain?(%User{} = user, url) when is_binary(url) do
|
||||
%{host: host} = URI.parse(url)
|
||||
Enum.member?(user.domain_blocks, host)
|
||||
# TODO: functionality should probably be changed such that subdomains block as well,
|
||||
# but as it stands, this just hecks up the relationships endpoint
|
||||
|
|
|
@ -2,9 +2,9 @@ defmodule Pleroma.User.SigningKey do
|
|||
use Ecto.Schema
|
||||
import Ecto.Query
|
||||
import Ecto.Changeset
|
||||
require Pleroma.Constants
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.HTTP
|
||||
|
||||
require Logger
|
||||
|
||||
|
@ -91,7 +91,15 @@ def generate_local_keys(ap_id) do
|
|||
|> change()
|
||||
|> put_change(:public_key, local_pem)
|
||||
|> put_change(:private_key, private_pem)
|
||||
|> put_change(:key_id, ap_id <> "#main-key")
|
||||
|> put_change(:key_id, local_key_id(ap_id))
|
||||
end
|
||||
|
||||
@spec local_key_id(String.t()) :: String.t()
|
||||
@doc """
|
||||
Given an AP ID, return the key ID for the local user.
|
||||
"""
|
||||
def local_key_id(ap_id) do
|
||||
ap_id <> "#main-key"
|
||||
end
|
||||
|
||||
@spec private_pem_to_public_pem(binary) :: {:ok, binary()} | {:error, String.t()}
|
||||
|
@ -136,7 +144,7 @@ def public_key_pem(%User{} = user) do
|
|||
end
|
||||
end
|
||||
|
||||
def public_key_pem(e) do
|
||||
def public_key_pem(_e) do
|
||||
{:error, "key not found"}
|
||||
end
|
||||
|
||||
|
@ -186,32 +194,24 @@ def get_or_fetch_by_key_id(key_id) do
|
|||
"""
|
||||
def fetch_remote_key(key_id) do
|
||||
Logger.debug("Fetching remote key: #{key_id}")
|
||||
# we should probably sign this, just in case
|
||||
resp = Pleroma.Object.Fetcher.get_object(key_id)
|
||||
|
||||
case resp do
|
||||
{:ok, _original_url, body} ->
|
||||
case handle_signature_response(resp) do
|
||||
{:ok, ap_id, public_key_pem} ->
|
||||
Logger.debug("Fetched remote key: #{ap_id}")
|
||||
# fetch the user
|
||||
{:ok, user} = User.get_or_fetch_by_ap_id(ap_id)
|
||||
# store the key
|
||||
key = %__MODULE__{
|
||||
user_id: user.id,
|
||||
public_key: public_key_pem,
|
||||
key_id: key_id
|
||||
}
|
||||
with {:ok, _body} = resp <-
|
||||
Pleroma.Object.Fetcher.fetch_and_contain_remote_object_from_id(key_id),
|
||||
{:ok, ap_id, public_key_pem} <- handle_signature_response(resp) do
|
||||
Logger.debug("Fetched remote key: #{ap_id}")
|
||||
# fetch the user
|
||||
{:ok, user} = User.get_or_fetch_by_ap_id(ap_id)
|
||||
# store the key
|
||||
key = %__MODULE__{
|
||||
user_id: user.id,
|
||||
public_key: public_key_pem,
|
||||
key_id: key_id
|
||||
}
|
||||
|
||||
Repo.insert(key, on_conflict: :replace_all, conflict_target: :key_id)
|
||||
|
||||
e ->
|
||||
Logger.debug("Failed to fetch remote key: #{inspect(e)}")
|
||||
{:error, "Could not fetch key"}
|
||||
end
|
||||
|
||||
_ ->
|
||||
Logger.debug("Failed to fetch remote key: #{inspect(resp)}")
|
||||
Repo.insert(key, on_conflict: :replace_all, conflict_target: :key_id)
|
||||
else
|
||||
e ->
|
||||
Logger.debug("Failed to fetch remote key: #{inspect(e)}")
|
||||
{:error, "Could not fetch key"}
|
||||
end
|
||||
end
|
||||
|
@ -227,16 +227,26 @@ defp extract_key_details(%{"id" => ap_id, "publicKey" => public_key}) do
|
|||
end
|
||||
end
|
||||
|
||||
defp handle_signature_response({:ok, _original_url, body}) do
|
||||
case Jason.decode(body) do
|
||||
{:ok, %{"id" => _user_id, "publicKey" => _public_key} = body} ->
|
||||
defp handle_signature_response({:ok, body}) do
|
||||
case body do
|
||||
%{
|
||||
"type" => "CryptographicKey",
|
||||
"publicKeyPem" => public_key_pem,
|
||||
"owner" => ap_id
|
||||
} ->
|
||||
{:ok, ap_id, public_key_pem}
|
||||
|
||||
# for when we get a subset of the user object
|
||||
%{
|
||||
"id" => _user_id,
|
||||
"publicKey" => _public_key,
|
||||
"type" => actor_type
|
||||
}
|
||||
when actor_type in Pleroma.Constants.actor_types() ->
|
||||
extract_key_details(body)
|
||||
|
||||
{:ok, %{"error" => error}} ->
|
||||
%{"error" => error} ->
|
||||
{:error, error}
|
||||
|
||||
{:error, _} ->
|
||||
{:error, "Could not parse key"}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -34,16 +34,34 @@ defp check_reject(message, actions) do
|
|||
end
|
||||
end
|
||||
|
||||
@spec delete_and_count(list(), term()) :: {integer(), list()}
|
||||
defp delete_and_count(list, element), do: delete_and_count(list, element, {0, [], list})
|
||||
|
||||
defp delete_and_count([], _element, {0, _nlist, olist}), do: {0, olist}
|
||||
defp delete_and_count([], _element, {count, nlist, _olist}), do: {count, Enum.reverse(nlist)}
|
||||
|
||||
defp delete_and_count([h | r], h, {count, nlist, olist}),
|
||||
do: delete_and_count(r, h, {count + 1, nlist, olist})
|
||||
|
||||
defp delete_and_count([h | r], element, {count, nlist, olist}),
|
||||
do: delete_and_count(r, element, {count, [h | nlist], olist})
|
||||
|
||||
defp insert_if_needed(list, oldcount, element) do
|
||||
if oldcount <= 0 || Enum.member?(list, element) do
|
||||
list
|
||||
else
|
||||
[element | list]
|
||||
end
|
||||
end
|
||||
|
||||
defp check_delist(message, actions) do
|
||||
if :delist in actions do
|
||||
with %User{} = user <- User.get_cached_by_ap_id(message["actor"]) do
|
||||
to =
|
||||
List.delete(message["to"] || [], Pleroma.Constants.as_public()) ++
|
||||
[user.follower_address]
|
||||
{pubcnt, to} = delete_and_count(message["to"] || [], Pleroma.Constants.as_public())
|
||||
{flwcnt, cc} = delete_and_count(message["cc"] || [], user.follower_address)
|
||||
|
||||
cc =
|
||||
List.delete(message["cc"] || [], user.follower_address) ++
|
||||
[Pleroma.Constants.as_public()]
|
||||
cc = insert_if_needed(cc, pubcnt, Pleroma.Constants.as_public())
|
||||
to = insert_if_needed(to, flwcnt, user.follower_address)
|
||||
|
||||
message =
|
||||
message
|
||||
|
@ -65,8 +83,8 @@ defp check_delist(message, actions) do
|
|||
defp check_strip_followers(message, actions) do
|
||||
if :strip_followers in actions do
|
||||
with %User{} = user <- User.get_cached_by_ap_id(message["actor"]) do
|
||||
to = List.delete(message["to"] || [], user.follower_address)
|
||||
cc = List.delete(message["cc"] || [], user.follower_address)
|
||||
{_, to} = delete_and_count(message["to"] || [], user.follower_address)
|
||||
{_, cc} = delete_and_count(message["cc"] || [], user.follower_address)
|
||||
|
||||
message =
|
||||
message
|
||||
|
|
|
@ -950,8 +950,7 @@ defp build_emoji_tag({name, url}) do
|
|||
"icon" => %{"url" => "#{URI.encode(url)}", "type" => "Image"},
|
||||
"name" => ":" <> name <> ":",
|
||||
"type" => "Emoji",
|
||||
"updated" => "1970-01-01T00:00:00Z",
|
||||
"id" => url
|
||||
"updated" => "1970-01-01T00:00:00Z"
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ def render("service.json", %{user: user}) do
|
|||
"url" => user.ap_id,
|
||||
"manuallyApprovesFollowers" => false,
|
||||
"publicKey" => %{
|
||||
"id" => "#{user.ap_id}#main-key",
|
||||
"id" => User.SigningKey.local_key_id(user.ap_id),
|
||||
"owner" => user.ap_id,
|
||||
"publicKeyPem" => public_key
|
||||
},
|
||||
|
@ -97,7 +97,7 @@ def render("user.json", %{user: user}) do
|
|||
"url" => user.ap_id,
|
||||
"manuallyApprovesFollowers" => user.is_locked,
|
||||
"publicKey" => %{
|
||||
"id" => "#{user.ap_id}#main-key",
|
||||
"id" => User.SigningKey.local_key_id(user.ap_id),
|
||||
"owner" => user.ap_id,
|
||||
"publicKeyPem" => public_key
|
||||
},
|
||||
|
|
|
@ -32,7 +32,9 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Poll do
|
|||
},
|
||||
voters_count: %Schema{
|
||||
type: :integer,
|
||||
description: "How many unique accounts have voted. Number."
|
||||
nullable: true,
|
||||
description:
|
||||
"How many unique accounts have voted for a multi-selection poll. Number, or null if single-selection poll."
|
||||
},
|
||||
voted: %Schema{
|
||||
type: :boolean,
|
||||
|
|
|
@ -66,10 +66,10 @@ defmodule Pleroma.Web.Endpoint do
|
|||
}
|
||||
)
|
||||
|
||||
plug(Plug.Static.IndexHtml, at: "/akkoma/swaggerui")
|
||||
plug(Plug.Static.IndexHtml, at: "/pleroma/swaggerui/")
|
||||
|
||||
plug(Pleroma.Web.Plugs.FrontendStatic,
|
||||
at: "/akkoma/swaggerui",
|
||||
at: "/pleroma/swaggerui",
|
||||
frontend_type: :swagger,
|
||||
gzip: true,
|
||||
if: &Pleroma.Web.Swagger.ui_enabled?/0,
|
||||
|
|
|
@ -19,7 +19,7 @@ def render("show.json", %{object: object, multiple: multiple, options: options}
|
|||
expired: expired,
|
||||
multiple: multiple,
|
||||
votes_count: votes_count,
|
||||
voters_count: voters_count(object),
|
||||
voters_count: voters_count(multiple, object),
|
||||
options: options,
|
||||
emojis: Pleroma.Web.MastodonAPI.StatusView.build_emojis(object.data["emoji"])
|
||||
}
|
||||
|
@ -68,11 +68,19 @@ defp options_and_votes_count(options) do
|
|||
end)
|
||||
end
|
||||
|
||||
defp voters_count(%{data: %{"voters" => voters}}) when is_list(voters) do
|
||||
defp voters_count(false, _poll_data) do
|
||||
# Mastodon always sets voter count to "null" unless multiple options were selectable
|
||||
# Some clients may rely on this to detect multiple selection polls and it can mess
|
||||
# up percentages for some clients if we never got a correct remote voter count and
|
||||
# only count local voters here; see https://akkoma.dev/AkkomaGang/akkoma/issues/190
|
||||
nil
|
||||
end
|
||||
|
||||
defp voters_count(_multiple, %{data: %{"voters" => voters}}) when is_list(voters) do
|
||||
length(voters)
|
||||
end
|
||||
|
||||
defp voters_count(_), do: 0
|
||||
defp voters_count(_, _), do: 0
|
||||
|
||||
defp voted_and_own_votes(%{object: object} = params, options) do
|
||||
if params[:for] do
|
||||
|
|
|
@ -52,11 +52,11 @@ def url(url) do
|
|||
|
||||
@spec url_proxiable?(String.t()) :: boolean()
|
||||
def url_proxiable?(url) do
|
||||
not local?(url) and not whitelisted?(url) and not blocked?(url)
|
||||
not local?(url) and not whitelisted?(url) and not blocked?(url) and http_scheme?(url)
|
||||
end
|
||||
|
||||
def preview_url(url, preview_params \\ []) do
|
||||
if preview_enabled?() do
|
||||
if preview_enabled?() and url_proxiable?(url) do
|
||||
encode_preview_url(url, preview_params)
|
||||
else
|
||||
url(url)
|
||||
|
@ -71,6 +71,8 @@ def preview_enabled?, do: enabled?() and !!Config.get([:media_preview_proxy, :en
|
|||
|
||||
def local?(url), do: String.starts_with?(url, Endpoint.url())
|
||||
|
||||
def http_scheme?(url), do: String.starts_with?(url, ["http:", "https:"])
|
||||
|
||||
def whitelisted?(url) do
|
||||
%{host: domain} = URI.parse(url)
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ def nodeinfo(conn, %{"version" => version}) when version in ["2.0", "2.1"] do
|
|||
conn
|
||||
|> put_resp_header(
|
||||
"content-type",
|
||||
"application/json; profile=http://nodeinfo.diaspora.software/ns/schema/2.0#; charset=utf-8"
|
||||
"application/json; profile=\"http://nodeinfo.diaspora.software/ns/schema/#{version}#\"; charset=utf-8"
|
||||
)
|
||||
|> json(Nodeinfo.get_nodeinfo(version))
|
||||
end
|
||||
|
|
|
@ -52,6 +52,14 @@ defp filter_allowed_user_by_ap_id(ap_ids, excluded_ap_ids) do
|
|||
end)
|
||||
end
|
||||
|
||||
defp filter_allowed_users_by_domain(ap_ids, %User{} = for_user) do
|
||||
Enum.reject(ap_ids, fn ap_id ->
|
||||
User.blocks_domain?(for_user, ap_id)
|
||||
end)
|
||||
end
|
||||
|
||||
defp filter_allowed_users_by_domain(ap_ids, nil), do: ap_ids
|
||||
|
||||
def filter_allowed_users(reactions, user, with_muted) do
|
||||
exclude_ap_ids =
|
||||
if is_nil(user) do
|
||||
|
@ -62,7 +70,10 @@ def filter_allowed_users(reactions, user, with_muted) do
|
|||
end
|
||||
|
||||
filter_emoji = fn emoji, users, url ->
|
||||
case filter_allowed_user_by_ap_id(users, exclude_ap_ids) do
|
||||
users
|
||||
|> filter_allowed_user_by_ap_id(exclude_ap_ids)
|
||||
|> filter_allowed_users_by_domain(user)
|
||||
|> case do
|
||||
[] -> nil
|
||||
users -> {emoji, users, url}
|
||||
end
|
||||
|
|
|
@ -4,8 +4,6 @@ defmodule Pleroma.Web.Plugs.EnsureUserPublicKeyPlug do
|
|||
We _should_ be able to request the URL from the key URL...
|
||||
"""
|
||||
|
||||
import Plug.Conn
|
||||
|
||||
alias Pleroma.User
|
||||
|
||||
def init(options), do: options
|
||||
|
@ -14,7 +12,7 @@ def call(conn, _opts) do
|
|||
key_id = key_id_from_conn(conn)
|
||||
|
||||
unless is_nil(key_id) do
|
||||
User.SigningKey.fetch_remote_key(key_id)
|
||||
User.SigningKey.get_or_fetch_by_key_id(key_id)
|
||||
# now we SHOULD have the user that owns the key locally. maybe.
|
||||
# if we don't, we'll error out when we try to validate.
|
||||
end
|
||||
|
|
|
@ -67,7 +67,8 @@ def call(%{assigns: %{valid_signature: true}} = conn, _opts) do
|
|||
Logger.debug("Failed to map identity from signature (lookup failure)")
|
||||
Logger.debug("key_id=#{inspect(key_id_from_conn(conn))}")
|
||||
|
||||
only_permit_user_routes(conn)
|
||||
conn
|
||||
|> assign(:valid_signature, false)
|
||||
|
||||
_ ->
|
||||
Logger.debug("Failed to map identity from signature (no payload actor mismatch)")
|
||||
|
@ -81,16 +82,6 @@ def call(%{assigns: %{valid_signature: true}} = conn, _opts) do
|
|||
# no signature at all
|
||||
def call(conn, _opts), do: conn
|
||||
|
||||
defp only_permit_user_routes(%{path_info: ["users", _]} = conn) do
|
||||
conn
|
||||
|> assign(:limited_ap, true)
|
||||
end
|
||||
|
||||
defp only_permit_user_routes(conn) do
|
||||
conn
|
||||
|> assign(:valid_signature, false)
|
||||
end
|
||||
|
||||
defp key_id_from_conn(conn) do
|
||||
case HTTPSignatures.signature_for_conn(conn) do
|
||||
%{"keyId" => key_id} when is_binary(key_id) ->
|
||||
|
|
6
mix.exs
6
mix.exs
|
@ -4,7 +4,7 @@ defmodule Pleroma.Mixfile do
|
|||
def project do
|
||||
[
|
||||
app: :pleroma,
|
||||
version: version("3.13.2"),
|
||||
version: version("3.13.3"),
|
||||
elixir: "~> 1.14",
|
||||
elixirc_paths: elixirc_paths(Mix.env()),
|
||||
compilers: Mix.compilers(),
|
||||
|
@ -144,7 +144,7 @@ defp deps do
|
|||
{:ex_aws, "~> 2.4"},
|
||||
{:ex_aws_s3, "~> 2.4"},
|
||||
{:sweet_xml, "~> 0.7"},
|
||||
{:earmark, "~> 1.4"},
|
||||
{:earmark, "1.4.46"},
|
||||
{:bbcode_pleroma, "~> 0.2.0"},
|
||||
{:argon2_elixir, "~> 3.1"},
|
||||
{:cors_plug, "~> 3.0"},
|
||||
|
@ -180,7 +180,7 @@ defp deps do
|
|||
{:remote_ip, "~> 1.1.0"},
|
||||
{:captcha,
|
||||
git: "https://git.pleroma.social/pleroma/elixir-libraries/elixir-captcha.git",
|
||||
ref: "90f6ce7672f70f56708792a98d98bd05176c9176"},
|
||||
ref: "6630c42aaaab124e697b4e513190c89d8b64e410"},
|
||||
{:restarter, path: "./restarter"},
|
||||
{:majic,
|
||||
git: "https://akkoma.dev/AkkomaGang/majic.git",
|
||||
|
|
57
mix.lock
57
mix.lock
|
@ -7,29 +7,29 @@
|
|||
"bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"},
|
||||
"cachex": {:hex, :cachex, "3.6.0", "14a1bfbeee060dd9bec25a5b6f4e4691e3670ebda28c8ba2884b12fe30b36bf8", [:mix], [{:eternal, "~> 1.2", [hex: :eternal, repo: "hexpm", optional: false]}, {:jumper, "~> 1.0", [hex: :jumper, repo: "hexpm", optional: false]}, {:sleeplocks, "~> 1.1", [hex: :sleeplocks, repo: "hexpm", optional: false]}, {:unsafe, "~> 1.0", [hex: :unsafe, repo: "hexpm", optional: false]}], "hexpm", "ebf24e373883bc8e0c8d894a63bbe102ae13d918f790121f5cfe6e485cc8e2e2"},
|
||||
"calendar": {:hex, :calendar, "1.0.0", "f52073a708528482ec33d0a171954ca610fe2bd28f1e871f247dc7f1565fa807", [:mix], [{:tzdata, "~> 0.1.201603 or ~> 0.5.20 or ~> 1.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "990e9581920c82912a5ee50e62ff5ef96da6b15949a2ee4734f935fdef0f0a6f"},
|
||||
"captcha": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/elixir-captcha.git", "90f6ce7672f70f56708792a98d98bd05176c9176", [ref: "90f6ce7672f70f56708792a98d98bd05176c9176"]},
|
||||
"castore": {:hex, :castore, "1.0.7", "b651241514e5f6956028147fe6637f7ac13802537e895a724f90bf3e36ddd1dd", [:mix], [], "hexpm", "da7785a4b0d2a021cd1292a60875a784b6caef71e76bf4917bdee1f390455cf5"},
|
||||
"captcha": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/elixir-captcha.git", "6630c42aaaab124e697b4e513190c89d8b64e410", [ref: "6630c42aaaab124e697b4e513190c89d8b64e410"]},
|
||||
"castore": {:hex, :castore, "1.0.9", "5cc77474afadf02c7c017823f460a17daa7908e991b0cc917febc90e466a375c", [:mix], [], "hexpm", "5ea956504f1ba6f2b4eb707061d8e17870de2bee95fb59d512872c2ef06925e7"},
|
||||
"certifi": {:hex, :certifi, "2.12.0", "2d1cca2ec95f59643862af91f001478c9863c2ac9cb6e2f89780bfd8de987329", [:rebar3], [], "hexpm", "ee68d85df22e554040cdb4be100f33873ac6051387baf6a8f6ce82272340ff1c"},
|
||||
"combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"},
|
||||
"comeonin": {:hex, :comeonin, "5.4.0", "246a56ca3f41d404380fc6465650ddaa532c7f98be4bda1b4656b3a37cc13abe", [:mix], [], "hexpm", "796393a9e50d01999d56b7b8420ab0481a7538d0caf80919da493b4a6e51faf1"},
|
||||
"comeonin": {:hex, :comeonin, "5.5.0", "364d00df52545c44a139bad919d7eacb55abf39e86565878e17cebb787977368", [:mix], [], "hexpm", "6287fc3ba0aad34883cbe3f7949fc1d1e738e5ccdce77165bc99490aa69f47fb"},
|
||||
"concurrent_limiter": {:git, "https://akkoma.dev/AkkomaGang/concurrent-limiter.git", "a9e0b3d64574bdba761f429bb4fba0cf687b3338", [ref: "a9e0b3d64574bdba761f429bb4fba0cf687b3338"]},
|
||||
"connection": {:hex, :connection, "1.1.0", "ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm", "722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"},
|
||||
"cors_plug": {:hex, :cors_plug, "3.0.3", "7c3ac52b39624bc616db2e937c282f3f623f25f8d550068b6710e58d04a0e330", [:mix], [{:plug, "~> 1.13", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "3f2d759e8c272ed3835fab2ef11b46bddab8c1ab9528167bd463b6452edf830d"},
|
||||
"cowboy": {:hex, :cowboy, "2.12.0", "f276d521a1ff88b2b9b4c54d0e753da6c66dd7be6c9fca3d9418b561828a3731", [:make, :rebar3], [{:cowlib, "2.13.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "8a7abe6d183372ceb21caa2709bec928ab2b72e18a3911aa1771639bef82651e"},
|
||||
"cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"},
|
||||
"cowlib": {:hex, :cowlib, "2.13.0", "db8f7505d8332d98ef50a3ef34b34c1afddec7506e4ee4dd4a3a266285d282ca", [:make, :rebar3], [], "hexpm", "e1e1284dc3fc030a64b1ad0d8382ae7e99da46c3246b815318a4b848873800a4"},
|
||||
"credo": {:hex, :credo, "1.7.7", "771445037228f763f9b2afd612b6aa2fd8e28432a95dbbc60d8e03ce71ba4446", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "8bc87496c9aaacdc3f90f01b7b0582467b69b4bd2441fe8aae3109d843cc2f2e"},
|
||||
"credo": {:hex, :credo, "1.7.8", "9722ba1681e973025908d542ec3d95db5f9c549251ba5b028e251ad8c24ab8c5", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "cb9e87cc64f152f3ed1c6e325e7b894dea8f5ef2e41123bd864e3cd5ceb44968"},
|
||||
"custom_base": {:hex, :custom_base, "0.2.1", "4a832a42ea0552299d81652aa0b1f775d462175293e99dfbe4d7dbaab785a706", [:mix], [], "hexpm", "8df019facc5ec9603e94f7270f1ac73ddf339f56ade76a721eaa57c1493ba463"},
|
||||
"db_connection": {:hex, :db_connection, "2.6.0", "77d835c472b5b67fc4f29556dee74bf511bbafecdcaf98c27d27fa5918152086", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c2f992d15725e721ec7fbc1189d4ecdb8afef76648c746a8e1cad35e3b8a35f3"},
|
||||
"db_connection": {:hex, :db_connection, "2.7.0", "b99faa9291bb09892c7da373bb82cba59aefa9b36300f6145c5f201c7adf48ec", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dcf08f31b2701f857dfc787fbad78223d61a32204f217f15e881dd93e4bdd3ff"},
|
||||
"decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"},
|
||||
"deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm", "ce708e5f094b9cd4e8f2be4f00d2f4250c4095be93f8cd6d018c753894885430"},
|
||||
"dialyxir": {:hex, :dialyxir, "1.4.3", "edd0124f358f0b9e95bfe53a9fcf806d615d8f838e2202a9f430d59566b6b53b", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "bf2cfb75cd5c5006bec30141b131663299c661a864ec7fbbc72dfa557487a986"},
|
||||
"dialyxir": {:hex, :dialyxir, "1.4.4", "fb3ce8741edeaea59c9ae84d5cec75da00fa89fe401c72d6e047d11a61f65f70", [:mix], [{:erlex, ">= 0.2.7", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "cd6111e8017ccd563e65621a4d9a4a1c5cd333df30cebc7face8029cacb4eff6"},
|
||||
"earmark": {:hex, :earmark, "1.4.46", "8c7287bd3137e99d26ae4643e5b7ef2129a260e3dcf41f251750cb4563c8fb81", [:mix], [], "hexpm", "798d86db3d79964e759ddc0c077d5eb254968ed426399fbf5a62de2b5ff8910a"},
|
||||
"earmark_parser": {:hex, :earmark_parser, "1.4.39", "424642f8335b05bb9eb611aa1564c148a8ee35c9c8a8bba6e129d51a3e3c6769", [:mix], [], "hexpm", "06553a88d1f1846da9ef066b87b57c6f605552cfbe40d20bd8d59cc6bde41944"},
|
||||
"earmark_parser": {:hex, :earmark_parser, "1.4.41", "ab34711c9dc6212dda44fcd20ecb87ac3f3fce6f0ca2f28d4a00e4154f8cd599", [:mix], [], "hexpm", "a81a04c7e34b6617c2792e291b5a2e57ab316365c2644ddc553bb9ed863ebefa"},
|
||||
"eblurhash": {:hex, :eblurhash, "1.2.2", "7da4255aaea984b31bb71155f673257353b0e0554d0d30dcf859547e74602582", [:rebar3], [], "hexpm", "8c20ca00904de023a835a9dcb7b7762fed32264c85a80c3cafa85288e405044c"},
|
||||
"ecto": {:hex, :ecto, "3.10.3", "eb2ae2eecd210b4eb8bece1217b297ad4ff824b4384c0e3fdd28aaf96edd6135", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "44bec74e2364d491d70f7e42cd0d690922659d329f6465e89feb8a34e8cd3433"},
|
||||
"ecto_enum": {:hex, :ecto_enum, "1.4.0", "d14b00e04b974afc69c251632d1e49594d899067ee2b376277efd8233027aec8", [:mix], [{:ecto, ">= 3.0.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "> 3.0.0", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:mariaex, ">= 0.0.0", [hex: :mariaex, repo: "hexpm", optional: true]}, {:postgrex, ">= 0.0.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "8fb55c087181c2b15eee406519dc22578fa60dd82c088be376d0010172764ee4"},
|
||||
"ecto_psql_extras": {:hex, :ecto_psql_extras, "0.8.0", "440719cd74f09b3f01c84455707a2c3972b725c513808e68eb6c5b0ab82bf523", [:mix], [{:ecto_sql, "~> 3.7", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16.0 or ~> 0.17.0 or ~> 0.18.0", [hex: :postgrex, repo: "hexpm", optional: false]}, {:table_rex, "~> 3.1.1 or ~> 4.0.0", [hex: :table_rex, repo: "hexpm", optional: false]}], "hexpm", "f1512812dc196bcb932a96c82e55f69b543dc125e9d39f5e3631a9c4ec65ef12"},
|
||||
"ecto_psql_extras": {:hex, :ecto_psql_extras, "0.8.2", "79350a53246ac5ec27326d208496aebceb77fa82a91744f66a9154560f0759d3", [:mix], [{:ecto_sql, "~> 3.7", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:postgrex, "> 0.16.0 and < 0.20.0", [hex: :postgrex, repo: "hexpm", optional: false]}, {:table_rex, "~> 3.1.1 or ~> 4.0.0", [hex: :table_rex, repo: "hexpm", optional: false]}], "hexpm", "6149c1c4a5ba6602a76cb09ee7a269eb60dab9694a1dbbb797f032555212de75"},
|
||||
"ecto_sql": {:hex, :ecto_sql, "3.10.2", "6b98b46534b5c2f8b8b5f03f126e75e2a73c64f3c071149d32987a5378b0fdbd", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.10.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16.0 or ~> 0.17.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "68c018debca57cb9235e3889affdaec7a10616a4e3a80c99fa1d01fdafaa9007"},
|
||||
"elasticsearch": {:git, "https://akkoma.dev/AkkomaGang/elasticsearch-elixir.git", "6cd946f75f6ab9042521a009d1d32d29a90113ca", [ref: "main"]},
|
||||
"elixir_make": {:hex, :elixir_make, "0.8.4", "4960a03ce79081dee8fe119d80ad372c4e7badb84c493cc75983f9d3bc8bde0f", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.0", [hex: :certifi, repo: "hexpm", optional: true]}], "hexpm", "6e7f1d619b5f61dfabd0a20aa268e575572b542ac31723293a4c1a567d5ef040"},
|
||||
|
@ -37,10 +37,10 @@
|
|||
"erlex": {:hex, :erlex, "0.2.7", "810e8725f96ab74d17aac676e748627a07bc87eb950d2b83acd29dc047a30595", [:mix], [], "hexpm", "3ed95f79d1a844c3f6bf0cea61e0d5612a42ce56da9c03f01df538685365efb0"},
|
||||
"erlsom": {:hex, :erlsom, "1.5.1", "c8fe2babd33ff0846403f6522328b8ab676f896b793634cfe7ef181c05316c03", [:rebar3], [], "hexpm", "7965485494c5844dd127656ac40f141aadfa174839ec1be1074e7edf5b4239eb"},
|
||||
"eternal": {:hex, :eternal, "1.2.2", "d1641c86368de99375b98d183042dd6c2b234262b8d08dfd72b9eeaafc2a1abd", [:mix], [], "hexpm", "2c9fe32b9c3726703ba5e1d43a1d255a4f3f2d8f8f9bc19f094c7cb1a7a9e782"},
|
||||
"ex_aws": {:hex, :ex_aws, "2.5.4", "86c5bb870a49e0ab6f5aa5dd58cf505f09d2624ebe17530db3c1b61c88a673af", [:mix], [{:configparser_ex, "~> 4.0", [hex: :configparser_ex, repo: "hexpm", optional: true]}, {:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:jsx, "~> 2.8 or ~> 3.0", [hex: :jsx, repo: "hexpm", optional: true]}, {:mime, "~> 1.2 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:sweet_xml, "~> 0.7", [hex: :sweet_xml, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "e82bd0091bb9a5bb190139599f922ff3fc7aebcca4374d65c99c4e23aa6d1625"},
|
||||
"ex_aws_s3": {:hex, :ex_aws_s3, "2.5.3", "422468e5c3e1a4da5298e66c3468b465cfd354b842e512cb1f6fbbe4e2f5bdaf", [:mix], [{:ex_aws, "~> 2.0", [hex: :ex_aws, repo: "hexpm", optional: false]}, {:sweet_xml, ">= 0.0.0", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "4f09dd372cc386550e484808c5ac5027766c8d0cd8271ccc578b82ee6ef4f3b8"},
|
||||
"ex_aws": {:hex, :ex_aws, "2.5.6", "6f642e0f82eff10a9b470044f084b81a791cf15b393d647ea5f3e65da2794e3d", [:mix], [{:configparser_ex, "~> 4.0", [hex: :configparser_ex, repo: "hexpm", optional: true]}, {:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:jsx, "~> 2.8 or ~> 3.0", [hex: :jsx, repo: "hexpm", optional: true]}, {:mime, "~> 1.2 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:req, "~> 0.3", [hex: :req, repo: "hexpm", optional: true]}, {:sweet_xml, "~> 0.7", [hex: :sweet_xml, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c69eec59e31fdd89d0beeb1d97e16518dd1b23ad95b3d5c9f1dcfec23d97f960"},
|
||||
"ex_aws_s3": {:hex, :ex_aws_s3, "2.5.4", "87aaf4a2f24a48f516d7f5aaced9d128dd5d0f655c4431f9037a11a85c71109c", [:mix], [{:ex_aws, "~> 2.0", [hex: :ex_aws, repo: "hexpm", optional: false]}, {:sweet_xml, ">= 0.0.0", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "c06e7f68b33f7c0acba1361dbd951c79661a28f85aa2e0582990fccca4425355"},
|
||||
"ex_const": {:hex, :ex_const, "0.3.0", "9d79516679991baf540ef445438eef1455ca91cf1a3c2680d8fb9e5bea2fe4de", [:mix], [], "hexpm", "76546322abb9e40ee4a2f454cf1c8a5b25c3672fa79bed1ea52c31e0d2428ca9"},
|
||||
"ex_doc": {:hex, :ex_doc, "0.34.1", "9751a0419bc15bc7580c73fde506b17b07f6402a1e5243be9e0f05a68c723368", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "d441f1a86a235f59088978eff870de2e815e290e44a8bd976fe5d64470a4c9d2"},
|
||||
"ex_doc": {:hex, :ex_doc, "0.34.2", "13eedf3844ccdce25cfd837b99bea9ad92c4e511233199440488d217c92571e8", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "5ce5f16b41208a50106afed3de6a2ed34f4acfd65715b82a0b84b49d995f95c1"},
|
||||
"ex_machina": {:hex, :ex_machina, "2.8.0", "a0e847b5712065055ec3255840e2c78ef9366634d62390839d4880483be38abe", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm", "79fe1a9c64c0c1c1fab6c4fa5d871682cb90de5885320c187d117004627a7729"},
|
||||
"ex_syslogger": {:hex, :ex_syslogger, "2.0.0", "de6de5c5472a9c4fdafb28fa6610e381ae79ebc17da6490b81d785d68bd124c9", [:mix], [{:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: true]}, {:syslog, "~> 1.1.0", [hex: :syslog, repo: "hexpm", optional: false]}], "hexpm", "a52b2fe71764e9e6ecd149ab66635812f68e39279cbeee27c52c0e35e8b8019e"},
|
||||
"excoveralls": {:hex, :excoveralls, "0.16.1", "0bd42ed05c7d2f4d180331a20113ec537be509da31fed5c8f7047ce59ee5a7c5", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "dae763468e2008cf7075a64cb1249c97cb4bc71e236c5c2b5e5cdf1cfa2bf138"},
|
||||
|
@ -48,10 +48,10 @@
|
|||
"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"},
|
||||
"file_ex": {:git, "https://akkoma.dev/AkkomaGang/file_ex.git", "cc7067c7d446c2526e9ecf91d40896b088851569", [ref: "cc7067c7d446c2526e9ecf91d40896b088851569"]},
|
||||
"file_system": {:hex, :file_system, "1.0.0", "b689cc7dcee665f774de94b5a832e578bd7963c8e637ef940cd44327db7de2cd", [:mix], [], "hexpm", "6752092d66aec5a10e662aefeed8ddb9531d79db0bc145bb8c40325ca1d8536d"},
|
||||
"file_system": {:hex, :file_system, "1.0.1", "79e8ceaddb0416f8b8cd02a0127bdbababe7bf4a23d2a395b983c1f8b3f73edd", [:mix], [], "hexpm", "4414d1f38863ddf9120720cd976fce5bdde8e91d8283353f0e31850fa89feb9e"},
|
||||
"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"},
|
||||
"flake_id": {:hex, :flake_id, "0.1.0", "7716b086d2e405d09b647121a166498a0d93d1a623bead243e1f74216079ccb3", [:mix], [{:base62, "~> 1.2", [hex: :base62, repo: "hexpm", optional: false]}, {:ecto, ">= 2.0.0", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm", "31fc8090fde1acd267c07c36ea7365b8604055f897d3a53dd967658c691bd827"},
|
||||
"floki": {:hex, :floki, "0.36.2", "a7da0193538c93f937714a6704369711998a51a6164a222d710ebd54020aa7a3", [:mix], [], "hexpm", "a8766c0bc92f074e5cb36c4f9961982eda84c5d2b8e979ca67f5c268ec8ed580"},
|
||||
"floki": {:hex, :floki, "0.36.3", "1102f93b16a55bc5383b85ae3ec470f82dee056eaeff9195e8afdf0ef2a43c30", [:mix], [], "hexpm", "fe0158bff509e407735f6d40b3ee0d7deb47f3f3ee7c6c182ad28599f9f6b27a"},
|
||||
"gen_smtp": {:hex, :gen_smtp, "1.2.0", "9cfc75c72a8821588b9b9fe947ae5ab2aed95a052b81237e0928633a13276fd3", [:rebar3], [{:ranch, ">= 1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "5ee0375680bca8f20c4d85f58c2894441443a743355430ff33a783fe03296779"},
|
||||
"gettext": {:hex, :gettext, "0.22.3", "c8273e78db4a0bb6fba7e9f0fd881112f349a3117f7f7c598fa18c66c888e524", [:mix], [{:expo, "~> 0.4.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "935f23447713954a6866f1bb28c3a878c4c011e802bcd68a726f5e558e4b64bd"},
|
||||
"hackney": {:hex, :hackney, "1.20.1", "8d97aec62ddddd757d128bfd1df6c5861093419f8f7a4223823537bad5d064e2", [:rebar3], [{:certifi, "~> 2.12.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "fe9094e5f1a2a2c0a7d10918fee36bfec0ec2a979994cff8cfe8058cd9af38e3"},
|
||||
|
@ -61,33 +61,34 @@
|
|||
"httpoison": {:hex, :httpoison, "1.8.2", "9eb9c63ae289296a544842ef816a85d881d4a31f518a0fec089aaa744beae290", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "2bb350d26972e30c96e2ca74a1aaf8293d61d0742ff17f01e0279fef11599921"},
|
||||
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
|
||||
"inet_cidr": {:hex, :inet_cidr, "1.0.8", "d26bb7bdbdf21ae401ead2092bf2bb4bf57fe44a62f5eaa5025280720ace8a40", [:mix], [], "hexpm", "d5b26da66603bb56c933c65214c72152f0de9a6ea53618b56d63302a68f6a90e"},
|
||||
"jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"},
|
||||
"joken": {:hex, :joken, "2.6.1", "2ca3d8d7f83bf7196296a3d9b2ecda421a404634bfc618159981a960020480a1", [:mix], [{:jose, "~> 1.11.9", [hex: :jose, repo: "hexpm", optional: false]}], "hexpm", "ab26122c400b3d254ce7d86ed066d6afad27e70416df947cdcb01e13a7382e68"},
|
||||
"jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
|
||||
"joken": {:hex, :joken, "2.6.2", "5daaf82259ca603af4f0b065475099ada1b2b849ff140ccd37f4b6828ca6892a", [:mix], [{:jose, "~> 1.11.10", [hex: :jose, repo: "hexpm", optional: false]}], "hexpm", "5134b5b0a6e37494e46dbf9e4dad53808e5e787904b7c73972651b51cce3d72b"},
|
||||
"jose": {:hex, :jose, "1.11.10", "a903f5227417bd2a08c8a00a0cbcc458118be84480955e8d251297a425723f83", [:mix, :rebar3], [], "hexpm", "0d6cd36ff8ba174db29148fc112b5842186b68a90ce9fc2b3ec3afe76593e614"},
|
||||
"jumper": {:hex, :jumper, "1.0.2", "68cdcd84472a00ac596b4e6459a41b3062d4427cbd4f1e8c8793c5b54f1406a7", [:mix], [], "hexpm", "9b7782409021e01ab3c08270e26f36eb62976a38c1aa64b2eaf6348422f165e1"},
|
||||
"linkify": {:hex, :linkify, "0.5.3", "5f8143d8f61f5ff08d3aeeff47ef6509492b4948d8f08007fbf66e4d2246a7f2", [:mix], [], "hexpm", "3ef35a1377d47c25506e07c1c005ea9d38d700699d92ee92825f024434258177"},
|
||||
"mail": {:hex, :mail, "0.3.1", "cb0a14e4ed8904e4e5a08214e686ccf6f9099346885db17d8c309381f865cc5c", [:mix], [], "hexpm", "1db701e89865c1d5fa296b2b57b1cd587587cca8d8a1a22892b35ef5a8e352a6"},
|
||||
"mail": {:hex, :mail, "0.4.2", "959229676ef11dfdfb1269ce4a611622cb70415a1d6f925d79e547848bafc14d", [:mix], [], "hexpm", "08e5b70c72b8d1605cb88ef2df2c7e41d002210a621503ea1c13f1a7916b6bd3"},
|
||||
"majic": {:git, "https://akkoma.dev/AkkomaGang/majic.git", "80540b36939ec83f48e76c61e5000e0fd67706f0", [ref: "80540b36939ec83f48e76c61e5000e0fd67706f0"]},
|
||||
"makeup": {:hex, :makeup, "1.1.2", "9ba8837913bdf757787e71c1581c21f9d2455f4dd04cfca785c70bbfff1a76a3", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cce1566b81fbcbd21eca8ffe808f33b221f9eee2cbc7a1706fc3da9ff18e6cac"},
|
||||
"makeup_elixir": {:hex, :makeup_elixir, "0.16.2", "627e84b8e8bf22e60a2579dad15067c755531fea049ae26ef1020cad58fe9578", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "41193978704763f6bbe6cc2758b84909e62984c7752b3784bd3c218bb341706b"},
|
||||
"makeup_erlang": {:hex, :makeup_erlang, "1.0.0", "6f0eff9c9c489f26b69b61440bf1b238d95badae49adac77973cbacae87e3c2e", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "ea7a9307de9d1548d2a72d299058d1fd2339e3d398560a0e46c27dab4891e4d2"},
|
||||
"makeup_erlang": {:hex, :makeup_erlang, "1.0.1", "c7f58c120b2b5aa5fd80d540a89fdf866ed42f1f3994e4fe189abebeab610839", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "8a89a1eeccc2d798d6ea15496a6e4870b75e014d1af514b1b71fa33134f57814"},
|
||||
"meck": {:hex, :meck, "0.9.2", "85ccbab053f1db86c7ca240e9fc718170ee5bda03810a6292b5306bf31bae5f5", [:rebar3], [], "hexpm", "81344f561357dc40a8344afa53767c32669153355b626ea9fcbc8da6b3045826"},
|
||||
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
|
||||
"mfm_parser": {:git, "https://akkoma.dev/AkkomaGang/mfm-parser.git", "b21ab7754024af096f2d14247574f55f0063295b", [ref: "b21ab7754024af096f2d14247574f55f0063295b"]},
|
||||
"mime": {:hex, :mime, "2.0.5", "dc34c8efd439abe6ae0343edbb8556f4d63f178594894720607772a041b04b02", [:mix], [], "hexpm", "da0d64a365c45bc9935cc5c8a7fc5e49a0e0f9932a761c55d6c52b142780a05c"},
|
||||
"mime": {:hex, :mime, "2.0.6", "8f18486773d9b15f95f4f4f1e39b710045fa1de891fada4516559967276e4dc2", [:mix], [], "hexpm", "c9945363a6b26d747389aac3643f8e0e09d30499a138ad64fe8fd1d13d9b153e"},
|
||||
"mimerl": {:hex, :mimerl, "1.3.0", "d0cd9fc04b9061f82490f6581e0128379830e78535e017f7780f37fea7545726", [:rebar3], [], "hexpm", "a1e15a50d1887217de95f0b9b0793e32853f7c258a5cd227650889b38839fe9d"},
|
||||
"mint": {:hex, :mint, "1.5.2", "4805e059f96028948870d23d7783613b7e6b0e2fb4e98d720383852a760067fd", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "d77d9e9ce4eb35941907f1d3df38d8f750c357865353e21d335bdcdf6d892a02"},
|
||||
"mock": {:hex, :mock, "0.3.8", "7046a306b71db2488ef54395eeb74df0a7f335a7caca4a3d3875d1fc81c884dd", [:mix], [{:meck, "~> 0.9.2", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm", "7fa82364c97617d79bb7d15571193fc0c4fe5afd0c932cef09426b3ee6fe2022"},
|
||||
"mogrify": {:hex, :mogrify, "0.9.3", "238c782f00271dace01369ad35ae2e9dd020feee3443b9299ea5ea6bed559841", [:mix], [], "hexpm", "0189b1e1de27455f2b9ae8cf88239cefd23d38de9276eb5add7159aea51731e6"},
|
||||
"mox": {:hex, :mox, "1.1.0", "0f5e399649ce9ab7602f72e718305c0f9cdc351190f72844599545e4996af73c", [:mix], [], "hexpm", "d44474c50be02d5b72131070281a5d3895c0e7a95c780e90bc0cfe712f633a13"},
|
||||
"mox": {:hex, :mox, "1.2.0", "a2cd96b4b80a3883e3100a221e8adc1b98e4c3a332a8fc434c39526babafd5b3", [:mix], [{:nimble_ownership, "~> 1.0", [hex: :nimble_ownership, repo: "hexpm", optional: false]}], "hexpm", "c7b92b3cc69ee24a7eeeaf944cd7be22013c52fcb580c1f33f50845ec821089a"},
|
||||
"nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"},
|
||||
"nimble_ownership": {:hex, :nimble_ownership, "1.0.0", "3f87744d42c21b2042a0aa1d48c83c77e6dd9dd357e425a038dd4b49ba8b79a1", [:mix], [], "hexpm", "7c16cc74f4e952464220a73055b557a273e8b1b7ace8489ec9d86e9ad56cb2cc"},
|
||||
"nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"},
|
||||
"nimble_pool": {:hex, :nimble_pool, "1.1.0", "bf9c29fbdcba3564a8b800d1eeb5a3c58f36e1e11d7b7fb2e084a643f645f06b", [:mix], [], "hexpm", "af2e4e6b34197db81f7aad230c1118eac993acc0dae6bc83bac0126d4ae0813a"},
|
||||
"oban": {:hex, :oban, "2.17.11", "7a641f9f737b626030c3e2209b53df6db83740ac5537208bac7d3b9871c2d5e7", [:mix], [{:ecto_sql, "~> 3.10", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:ecto_sqlite3, "~> 0.9", [hex: :ecto_sqlite3, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c445c488151939d64265a5efea51973fa0b42ee4ebbb31aa83fac26543b8ac6d"},
|
||||
"open_api_spex": {:hex, :open_api_spex, "3.19.1", "65ccb5d06e3d664d1eec7c5ea2af2289bd2f37897094a74d7219fb03fc2b5994", [: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 or ~> 5.0", [hex: :ymlr, repo: "hexpm", optional: true]}], "hexpm", "392895827ce2984a3459c91a484e70708132d8c2c6c5363972b4b91d6bbac3dd"},
|
||||
"oban": {:hex, :oban, "2.17.12", "33fb0cbfb92b910d48dd91a908590fe3698bb85eacec8cd0d9bc6aa13dddd6d6", [:mix], [{:ecto_sql, "~> 3.10", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:ecto_sqlite3, "~> 0.9", [hex: :ecto_sqlite3, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7a647d6cd6bb300073db17faabce22d80ae135da3baf3180a064fa7c4fa046e3"},
|
||||
"open_api_spex": {:hex, :open_api_spex, "3.21.2", "6a704f3777761feeb5657340250d6d7332c545755116ca98f33d4b875777e1e5", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {: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 or ~> 6.0", [hex: :poison, repo: "hexpm", optional: true]}, {:ymlr, "~> 2.0 or ~> 3.0 or ~> 4.0 or ~> 5.0", [hex: :ymlr, repo: "hexpm", optional: true]}], "hexpm", "f42ae6ed668b895ebba3e02773cfb4b41050df26f803f2ef634c72a7687dc387"},
|
||||
"parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"},
|
||||
"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_ecto": {:hex, :phoenix_ecto, "4.6.1", "96798325fab2fed5a824ca204e877b81f9afd2e480f581e81f7b4b64a5a477f2", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.17", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "0ae544ff99f3c482b0807c5cec2c8289e810ecacabc04959d82c3337f4703391"},
|
||||
"phoenix_ecto": {:hex, :phoenix_ecto, "4.6.3", "f686701b0499a07f2e3b122d84d52ff8a31f5def386e03706c916f6feddf69ef", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "909502956916a657a197f94cc1206d9a65247538de8a5e186f7537c895d95764"},
|
||||
"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.7.2", "97cc4ff2dba1ebe504db72cb45098cb8e91f11160528b980bd282cc45c73b29c", [: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]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.18.3", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "0e5fdf063c7a3b620c566a30fcf68b7ee02e5e46fe48ee46a6ec3ba382dc05b7"},
|
||||
"phoenix_live_view": {:hex, :phoenix_live_view, "0.18.18", "1f38fbd7c363723f19aad1a04b5490ff3a178e37daaf6999594d5f34796c47fc", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3", [hex: :phoenix_html, 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]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a5810d0472f3189ede6d2a95bda7f31c6113156b91784a3426cb0ab6a6d85214"},
|
||||
|
@ -96,7 +97,7 @@
|
|||
"phoenix_template": {:hex, :phoenix_template, "1.0.4", "e2092c132f3b5e5b2d49c96695342eb36d0ed514c5b252a77048d5969330d639", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "2c0c81f0e5c6753faf5cca2f229c9709919aba34fab866d3bc05060c9c444206"},
|
||||
"phoenix_view": {:hex, :phoenix_view, "2.0.4", "b45c9d9cf15b3a1af5fb555c674b525391b6a1fe975f040fb4d913397b31abf4", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}], "hexpm", "4e992022ce14f31fe57335db27a28154afcc94e9983266835bb3040243eb620b"},
|
||||
"plug": {:hex, :plug, "1.16.1", "40c74619c12f82736d2214557dedec2e9762029b2438d6d175c5074c933edc9d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a13ff6b9006b03d7e33874945b2755253841b238c34071ed85b0e86057f8cddc"},
|
||||
"plug_cowboy": {:hex, :plug_cowboy, "2.7.1", "87677ffe3b765bc96a89be7960f81703223fe2e21efa42c125fcd0127dd9d6b2", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "02dbd5f9ab571b864ae39418db7811618506256f6d13b4a45037e5fe78dc5de3"},
|
||||
"plug_cowboy": {:hex, :plug_cowboy, "2.7.2", "fdadb973799ae691bf9ecad99125b16625b1c6039999da5fe544d99218e662e4", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "245d8a11ee2306094840c000e8816f0cbed69a23fc0ac2bcf8d7835ae019bb2f"},
|
||||
"plug_crypto": {:hex, :plug_crypto, "2.1.0", "f44309c2b06d249c27c8d3f65cfe08158ade08418cf540fd4f72d4d6863abb7b", [:mix], [], "hexpm", "131216a4b030b8f8ce0f26038bc4421ae60e4bb95c5cf5395e1421437824c4fa"},
|
||||
"plug_static_index_html": {:hex, :plug_static_index_html, "1.0.0", "840123d4d3975585133485ea86af73cb2600afd7f2a976f9f5fd8b3808e636a0", [:mix], [{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "79fd4fcf34d110605c26560cbae8f23c603ec4158c08298bd4360fdea90bb5cf"},
|
||||
"poison": {:hex, :poison, "5.0.0", "d2b54589ab4157bbb82ec2050757779bfed724463a544b6e20d79855a9e43b24", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "11dc6117c501b80c62a7594f941d043982a1bd05a1184280c0d9166eb4d8d3fc"},
|
||||
|
@ -104,7 +105,7 @@
|
|||
"postgrex": {:hex, :postgrex, "0.17.5", "0483d054938a8dc069b21bdd636bf56c487404c241ce6c319c1f43588246b281", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "50b8b11afbb2c4095a3ba675b4f055c416d0f3d7de6633a595fc131a828a67eb"},
|
||||
"pot": {:hex, :pot, "1.0.2", "13abb849139fdc04ab8154986abbcb63bdee5de6ed2ba7e1713527e33df923dd", [:rebar3], [], "hexpm", "78fe127f5a4f5f919d6ea5a2a671827bd53eb9d37e5b4128c0ad3df99856c2e0"},
|
||||
"ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"},
|
||||
"recon": {:hex, :recon, "2.5.5", "c108a4c406fa301a529151a3bb53158cadc4064ec0c5f99b03ddb8c0e4281bdf", [:mix, :rebar3], [], "hexpm", "632a6f447df7ccc1a4a10bdcfce71514412b16660fe59deca0fcf0aa3c054404"},
|
||||
"recon": {:hex, :recon, "2.5.6", "9052588e83bfedfd9b72e1034532aee2a5369d9d9343b61aeb7fbce761010741", [:mix, :rebar3], [], "hexpm", "96c6799792d735cc0f0fd0f86267e9d351e63339cbe03df9d162010cefc26bb0"},
|
||||
"remote_ip": {:hex, :remote_ip, "1.1.0", "cb308841595d15df3f9073b7c39243a1dd6ca56e5020295cb012c76fbec50f2d", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "616ffdf66aaad6a72fc546dabf42eed87e2a99e97b09cbd92b10cc180d02ed74"},
|
||||
"search_parser": {:git, "https://github.com/FloatingGhost/pleroma-contrib-search-parser.git", "08971a81e68686f9ac465cfb6661d51c5e4e1e7f", [ref: "08971a81e68686f9ac465cfb6661d51c5e4e1e7f"]},
|
||||
"sleeplocks": {:hex, :sleeplocks, "1.1.3", "96a86460cc33b435c7310dbd27ec82ca2c1f24ae38e34f8edde97f756503441a", [:rebar3], [], "hexpm", "d3b3958552e6eb16f463921e70ae7c767519ef8f5be46d7696cc1ed649421321"},
|
||||
|
@ -114,22 +115,22 @@
|
|||
"swoosh": {:hex, :swoosh, "1.14.4", "94e9dba91f7695a10f49b0172c4a4cb658ef24abef7e8140394521b7f3bbb2d4", [:mix], [{:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:ex_aws, "~> 2.1", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:finch, "~> 0.6", [hex: :finch, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:req, "~> 0.4 or ~> 1.0", [hex: :req, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "081c5a590e4ba85cc89baddf7b2beecf6c13f7f84a958f1cd969290815f0f026"},
|
||||
"syslog": {:hex, :syslog, "1.1.0", "6419a232bea84f07b56dc575225007ffe34d9fdc91abe6f1b2f254fd71d8efc2", [:rebar3], [], "hexpm", "4c6a41373c7e20587be33ef841d3de6f3beba08519809329ecc4d27b15b659e1"},
|
||||
"table_rex": {:hex, :table_rex, "4.0.0", "3c613a68ebdc6d4d1e731bc973c233500974ec3993c99fcdabb210407b90959b", [:mix], [], "hexpm", "c35c4d5612ca49ebb0344ea10387da4d2afe278387d4019e4d8111e815df8f55"},
|
||||
"telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"},
|
||||
"telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"},
|
||||
"telemetry_metrics": {:hex, :telemetry_metrics, "0.6.2", "2caabe9344ec17eafe5403304771c3539f3b6e2f7fb6a6f602558c825d0d0bfb", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9b43db0dc33863930b9ef9d27137e78974756f5f198cae18409970ed6fa5b561"},
|
||||
"telemetry_metrics_prometheus": {:hex, :telemetry_metrics_prometheus, "1.1.0", "1cc23e932c1ef9aa3b91db257ead31ea58d53229d407e059b29bb962c1505a13", [:mix], [{:plug_cowboy, "~> 2.1", [hex: :plug_cowboy, repo: "hexpm", optional: false]}, {:telemetry_metrics_prometheus_core, "~> 1.0", [hex: :telemetry_metrics_prometheus_core, repo: "hexpm", optional: false]}], "hexpm", "d43b3659b3244da44fe0275b717701542365d4519b79d9ce895b9719c1ce4d26"},
|
||||
"telemetry_metrics_prometheus_core": {:hex, :telemetry_metrics_prometheus_core, "1.1.0", "4e15f6d7dbedb3a4e3aed2262b7e1407f166fcb9c30ca3f96635dfbbef99965c", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "0dd10e7fe8070095df063798f82709b0a1224c31b8baf6278b423898d591a069"},
|
||||
"telemetry_poller": {:hex, :telemetry_poller, "1.1.0", "58fa7c216257291caaf8d05678c8d01bd45f4bdbc1286838a28c4bb62ef32999", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9eb9d9cbfd81cbd7cdd24682f8711b6e2b691289a0de6826e58452f28c103c8f"},
|
||||
"temple": {:git, "https://akkoma.dev/AkkomaGang/temple.git", "066a699ade472d8fa42a9d730b29a61af9bc8b59", [ref: "066a699ade472d8fa42a9d730b29a61af9bc8b59"]},
|
||||
"tesla": {:hex, :tesla, "1.11.0", "81b2b10213dddb27105ec6102d9eb0cc93d7097a918a0b1594f2dfd1a4601190", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.13", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, ">= 1.0.0", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.2", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:msgpax, "~> 2.3", [hex: :msgpax, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "b83ab5d4c2d202e1ea2b7e17a49f788d49a699513d7c4f08f2aef2c281be69db"},
|
||||
"tesla": {:hex, :tesla, "1.13.0", "24a068a48d107080dd7c943a593997eee265977a38020eb2ab657cca78a12502", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.13", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, ">= 1.0.0", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.2", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:mox, "~> 1.0", [hex: :mox, repo: "hexpm", optional: true]}, {:msgpax, "~> 2.3", [hex: :msgpax, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "7b8fc8f6b0640fa0d090af7889d12eb396460e044b6f8688a8e55e30406a2200"},
|
||||
"timex": {:hex, :timex, "3.7.11", "bb95cb4eb1d06e27346325de506bcc6c30f9c6dea40d1ebe390b262fad1862d1", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.20", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 1.1", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "8b9024f7efbabaf9bd7aa04f65cf8dcd7c9818ca5737677c7b76acbc6a94d1aa"},
|
||||
"trailing_format_plug": {:hex, :trailing_format_plug, "0.0.7", "64b877f912cf7273bed03379936df39894149e35137ac9509117e59866e10e45", [:mix], [{:plug, "> 0.12.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "bd4fde4c15f3e993a999e019d64347489b91b7a9096af68b2bdadd192afa693f"},
|
||||
"tzdata": {:hex, :tzdata, "1.1.1", "20c8043476dfda8504952d00adac41c6eda23912278add38edc140ae0c5bcc46", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "a69cec8352eafcd2e198dea28a34113b60fdc6cb57eb5ad65c10292a6ba89787"},
|
||||
"tzdata": {:hex, :tzdata, "1.1.2", "45e5f1fcf8729525ec27c65e163be5b3d247ab1702581a94674e008413eef50b", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "cec7b286e608371602318c414f344941d5eb0375e14cfdab605cca2fe66cba8b"},
|
||||
"ueberauth": {:hex, :ueberauth, "0.10.5", "806adb703df87e55b5615cf365e809f84c20c68aa8c08ff8a416a5a6644c4b02", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "3efd1f31d490a125c7ed453b926f7c31d78b97b8a854c755f5c40064bf3ac9e1"},
|
||||
"unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"},
|
||||
"unsafe": {:hex, :unsafe, "1.0.2", "23c6be12f6c1605364801f4b47007c0c159497d0446ad378b5cf05f1855c0581", [:mix], [], "hexpm", "b485231683c3ab01a9cd44cb4a79f152c6f3bb87358439c6f68791b85c2df675"},
|
||||
"vex": {:hex, :vex, "0.9.2", "fe061acc9e0907d983d46b51bf35d58176f0fe6eb7ba3b33c9336401bf42b6d1", [:mix], [], "hexpm", "76e709a9762e98c6b462dfce92e9b5dfbf712839227f2da8add6dd11549b12cb"},
|
||||
"web_push_encryption": {:hex, :web_push_encryption, "0.3.1", "76d0e7375142dfee67391e7690e89f92578889cbcf2879377900b5620ee4708d", [:mix], [{:httpoison, "~> 1.0", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jose, "~> 1.11.1", [hex: :jose, repo: "hexpm", optional: false]}], "hexpm", "4f82b2e57622fb9337559058e8797cb0df7e7c9790793bdc4e40bc895f70e2a2"},
|
||||
"websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"},
|
||||
"websock_adapter": {:hex, :websock_adapter, "0.5.6", "0437fe56e093fd4ac422de33bf8fc89f7bc1416a3f2d732d8b2c8fd54792fe60", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "e04378d26b0af627817ae84c92083b7e97aca3121196679b73c73b99d0d133ea"},
|
||||
"websock_adapter": {:hex, :websock_adapter, "0.5.7", "65fa74042530064ef0570b75b43f5c49bb8b235d6515671b3d250022cb8a1f9e", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "d0f478ee64deddfec64b800673fd6e0c8888b079d9f3444dd96d2a98383bdbd1"},
|
||||
"websockex": {:hex, :websockex, "0.4.3", "92b7905769c79c6480c02daacaca2ddd49de936d912976a4d3c923723b647bf0", [:mix], [], "hexpm", "95f2e7072b85a3a4cc385602d42115b73ce0b74a9121d0d6dbbf557645ac53e4"},
|
||||
}
|
||||
|
|
|
@ -9,7 +9,5 @@ def change do
|
|||
add :private_key, :text
|
||||
timestamps()
|
||||
end
|
||||
|
||||
create unique_index(:signing_keys, [:key_id])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,13 +8,15 @@ def up do
|
|||
# we do not handle remote users here!
|
||||
# because we want to store a key id -> user id mapping, and we don't
|
||||
# currently store key ids for remote users...
|
||||
query =
|
||||
from(u in User)
|
||||
|> where(local: true)
|
||||
|
||||
Repo.stream(query, timeout: :infinity)
|
||||
# Also this MUST use select, else the migration will fail in future installs with new user fields!
|
||||
from(u in Pleroma.User,
|
||||
where: u.local == true,
|
||||
select: {u.id, u.keys, u.ap_id}
|
||||
)
|
||||
|> Repo.stream(timeout: :infinity)
|
||||
|> Enum.each(fn
|
||||
%User{id: user_id, keys: private_key, local: true} ->
|
||||
{user_id, private_key, ap_id} ->
|
||||
IO.puts("Migrating user #{user_id}")
|
||||
# we can precompute the public key here...
|
||||
# we do use it on every user view which makes it a bit of a dos attack vector
|
||||
# so we should probably cache it
|
||||
|
@ -23,6 +25,7 @@ def up do
|
|||
key = %User.SigningKey{
|
||||
user_id: user_id,
|
||||
public_key: public_key,
|
||||
key_id: User.SigningKey.local_key_id(ap_id),
|
||||
private_key: private_key
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
defmodule Pleroma.Repo.Migrations.AddSigningKeyIndex do
|
||||
use Ecto.Migration
|
||||
|
||||
def change do
|
||||
create_if_not_exists(index(:signing_keys, [:user_id], name: :signing_keys_user_id_index))
|
||||
end
|
||||
end
|
|
@ -51,7 +51,6 @@ test "error if file with custom settings doesn't exist" do
|
|||
clear_config(:configurable_from_database, true)
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "config migration refused when deprecated settings are found" do
|
||||
clear_config([:media_proxy, :whitelist], ["domain_without_scheme.com"])
|
||||
assert config_records() == []
|
||||
|
|
|
@ -64,7 +64,10 @@ test "returns error when zip file is bad", %{pack: pack} do
|
|||
path: Path.absname("test/instance_static/emoji/test_pack/blank.png")
|
||||
}
|
||||
|
||||
assert Pack.add_file(pack, nil, nil, file) == {:error, :einval}
|
||||
# this varies by erlang OTP
|
||||
possible_error_codes = [:bad_eocd, :einval]
|
||||
{:error, code} = Pack.add_file(pack, nil, nil, file)
|
||||
assert Enum.member?(possible_error_codes, code)
|
||||
end
|
||||
|
||||
test "returns pack when zip file is empty", %{pack: pack} do
|
||||
|
|
|
@ -9,7 +9,6 @@ defmodule Pleroma.Object.ContainmentTest do
|
|||
alias Pleroma.User
|
||||
|
||||
import Pleroma.Factory
|
||||
import ExUnit.CaptureLog
|
||||
|
||||
setup_all do
|
||||
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
|
||||
|
@ -136,23 +135,17 @@ test "contain_id_to_fetch() allows matching IDs" do
|
|||
)
|
||||
end
|
||||
|
||||
test "contain_id_to_fetch() allows display URLs" do
|
||||
test "contain_id_to_fetch() allows fragments and normalises domain casing" do
|
||||
data = %{
|
||||
"id" => "http://example.com/~alyssa/activities/1234.json",
|
||||
"url" => "http://example.com/@alyssa/status/1234"
|
||||
"id" => "http://example.com/users/capybara",
|
||||
"url" => "http://example.com/@capybara"
|
||||
}
|
||||
|
||||
:ok =
|
||||
Containment.contain_id_to_fetch(
|
||||
"http://example.com/@alyssa/status/1234",
|
||||
data
|
||||
)
|
||||
|
||||
:ok =
|
||||
Containment.contain_id_to_fetch(
|
||||
"http://example.com/@alyssa/status/1234/",
|
||||
data
|
||||
)
|
||||
assert :ok ==
|
||||
Containment.contain_id_to_fetch(
|
||||
"http://EXAMPLE.com/users/capybara#key",
|
||||
data
|
||||
)
|
||||
end
|
||||
|
||||
test "users cannot be collided through fake direction spoofing attempts" do
|
||||
|
@ -164,10 +157,14 @@ test "users cannot be collided through fake direction spoofing attempts" do
|
|||
follower_address: User.ap_followers(%User{nickname: "rye@niu.moe"})
|
||||
})
|
||||
|
||||
assert capture_log(fn ->
|
||||
{:error, _} = User.get_or_fetch_by_ap_id("https://n1u.moe/users/rye")
|
||||
end) =~
|
||||
"[error] Could not decode user at fetch https://n1u.moe/users/rye"
|
||||
# Fetch from an attempted spoof id will suceed, but automatically retrieve
|
||||
# the real data from the homeserver instead of naïvely using the spoof
|
||||
{:ok, fetched_user} = User.get_or_fetch_by_ap_id("https://n1u.moe/users/rye")
|
||||
|
||||
refute fetched_user.name == "evil rye"
|
||||
refute fetched_user.raw_bio == "boooo!"
|
||||
assert fetched_user.name == "♡ rye ♡"
|
||||
assert fetched_user.nickname == "rye@niu.moe"
|
||||
end
|
||||
|
||||
test "contain_origin_from_id() gracefully handles cases where no ID is present" do
|
||||
|
|
|
@ -22,6 +22,7 @@ defp spoofed_object_with_ids(
|
|||
|> Jason.decode!()
|
||||
|> Map.put("id", id)
|
||||
|> Map.put("actor", actor_id)
|
||||
|> Map.put("attributedTo", actor_id)
|
||||
|> Jason.encode!()
|
||||
end
|
||||
|
||||
|
@ -109,7 +110,7 @@ defp spoofed_object_with_ids(
|
|||
body: spoofed_object_with_ids("https://patch.cx/objects/spoof_media_redirect1")
|
||||
}
|
||||
|
||||
# Spoof: cross-domain redirect with final domain id
|
||||
# Spoof: cross-domain redirect with final domain id, but original id actor
|
||||
%{method: :get, url: "https://patch.cx/objects/spoof_media_redirect2"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
|
@ -118,6 +119,19 @@ defp spoofed_object_with_ids(
|
|||
body: spoofed_object_with_ids("https://media.patch.cx/objects/spoof_media_redirect2")
|
||||
}
|
||||
|
||||
# No-Spoof: cross-domain redirect with id and actor from final domain
|
||||
%{method: :get, url: "https://patch.cx/objects/spoof_media_redirect3"} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
url: "https://media.patch.cx/objects/spoof_media_redirect3",
|
||||
headers: [{"content-type", "application/activity+json"}],
|
||||
body:
|
||||
spoofed_object_with_ids(
|
||||
"https://media.patch.cx/objects/spoof_media_redirect3",
|
||||
"https://media.patch.cx/users/rin"
|
||||
)
|
||||
}
|
||||
|
||||
# No-Spoof: same domain redirect
|
||||
%{method: :get, url: "https://patch.cx/objects/spoof_redirect"} ->
|
||||
%Tesla.Env{
|
||||
|
@ -189,7 +203,6 @@ defp spoofed_object_with_ids(
|
|||
:ok
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "it works when fetching the OP actor errors out" do
|
||||
# Here we simulate a case where the author of the OP can't be read
|
||||
assert {:ok, _} =
|
||||
|
@ -252,7 +265,7 @@ test "it does not fetch a spoofed object with wrong content type" do
|
|||
end
|
||||
|
||||
test "it does not fetch a spoofed object with id different from URL" do
|
||||
assert {:error, :id_mismatch} =
|
||||
assert {:error, :not_found} =
|
||||
Fetcher.fetch_and_contain_remote_object_from_id(
|
||||
"https://patch.cx/media/03ca3c8b4ac3ddd08bf0f84be7885f2f88de0f709112131a22d83650819e36c2.json"
|
||||
)
|
||||
|
@ -264,19 +277,29 @@ test "it does not fetch a spoofed object with id different from URL" do
|
|||
end
|
||||
|
||||
test "it does not fetch an object via cross-domain redirects (initial id)" do
|
||||
assert {:error, {:cross_domain_redirect, true}} =
|
||||
assert {:error, {:containment, _}} =
|
||||
Fetcher.fetch_and_contain_remote_object_from_id(
|
||||
"https://patch.cx/objects/spoof_media_redirect1"
|
||||
)
|
||||
end
|
||||
|
||||
test "it does not fetch an object via cross-domain redirects (final id)" do
|
||||
assert {:error, {:cross_domain_redirect, true}} =
|
||||
test "it does not fetch an object via cross-domain redirect if the actor is from the original domain" do
|
||||
assert {:error, {:containment, :error}} =
|
||||
Fetcher.fetch_and_contain_remote_object_from_id(
|
||||
"https://patch.cx/objects/spoof_media_redirect2"
|
||||
)
|
||||
end
|
||||
|
||||
test "it allows cross-domain redirects when id and author are from final domain" do
|
||||
assert {:ok, %{"id" => id, "attributedTo" => author}} =
|
||||
Fetcher.fetch_and_contain_remote_object_from_id(
|
||||
"https://patch.cx/objects/spoof_media_redirect3"
|
||||
)
|
||||
|
||||
assert URI.parse(id).host == "media.patch.cx"
|
||||
assert URI.parse(author).host == "media.patch.cx"
|
||||
end
|
||||
|
||||
test "it accepts same-domain redirects" do
|
||||
assert {:ok, %{"id" => id} = _object} =
|
||||
Fetcher.fetch_and_contain_remote_object_from_id(
|
||||
|
@ -755,7 +778,7 @@ test "should return ok if the content type is application/activity+json" do
|
|||
assert {:ok, _, "{}"} = Fetcher.get_object("https://mastodon.social/2")
|
||||
end
|
||||
|
||||
test "should return ok if the content type is application/ld+json with a profile" do
|
||||
test "should return ok if the content type is application/ld+json with the ActivityStream profile" do
|
||||
Tesla.Mock.mock(fn
|
||||
%{
|
||||
method: :get,
|
||||
|
@ -775,6 +798,26 @@ test "should return ok if the content type is application/ld+json with a profile
|
|||
assert {:ok, _, "{}"} = Fetcher.get_object("https://mastodon.social/2")
|
||||
end
|
||||
|
||||
test "should return ok if the content type is application/ld+json with several profiles" do
|
||||
Tesla.Mock.mock(fn
|
||||
%{
|
||||
method: :get,
|
||||
url: "https://mastodon.social/2"
|
||||
} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
url: "https://mastodon.social/2",
|
||||
headers: [
|
||||
{"content-type",
|
||||
"application/ld+json; profile=\"https://example.org/ns/superduperspec https://www.w3.org/ns/activitystreams\""}
|
||||
],
|
||||
body: "{}"
|
||||
}
|
||||
end)
|
||||
|
||||
assert {:ok, _, "{}"} = Fetcher.get_object("https://mastodon.social/2")
|
||||
end
|
||||
|
||||
test "should not return ok with other content types" do
|
||||
Tesla.Mock.mock(fn
|
||||
%{
|
||||
|
|
|
@ -6,7 +6,6 @@ defmodule Pleroma.SignatureTest do
|
|||
use Pleroma.DataCase, async: false
|
||||
@moduletag :mocked
|
||||
|
||||
import ExUnit.CaptureLog
|
||||
import Pleroma.Factory
|
||||
import Tesla.Mock
|
||||
import Mock
|
||||
|
|
|
@ -115,6 +115,15 @@ test "verify webp files are skipped" do
|
|||
assert Filter.Exiftool.StripMetadata.filter(upload) == {:ok, :noop}
|
||||
end
|
||||
|
||||
test "verify bmp files are skipped" do
|
||||
upload = %Pleroma.Upload{
|
||||
name: "sample.bmp",
|
||||
content_type: "image/bmp"
|
||||
}
|
||||
|
||||
assert Filter.Exiftool.StripMetadata.filter(upload) == {:ok, :noop}
|
||||
end
|
||||
|
||||
test "verify svg files are skipped" do
|
||||
upload = %Pleroma.Upload{
|
||||
name: "sample.svg",
|
||||
|
|
|
@ -815,7 +815,6 @@ test "gets an existing user by fully qualified nickname, case insensitive" do
|
|||
assert user == fetched_user
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "returns nil if no user could be fetched" do
|
||||
{:error, fetched_user} = User.get_or_fetch_by_nickname("nonexistant@social.heldscal.la")
|
||||
assert fetched_user == "not found nonexistant@social.heldscal.la"
|
||||
|
@ -872,7 +871,6 @@ test "if nicknames clash, the old user gets a prefix with the old id to the nick
|
|||
assert orig_user.nickname == "#{orig_user.id}.admin@mastodon.example.org"
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "it returns the old user if stale, but unfetchable" do
|
||||
a_week_ago = NaiveDateTime.add(NaiveDateTime.utc_now(), -604_800)
|
||||
|
||||
|
@ -968,6 +966,21 @@ test "it is invalid given a local user" do
|
|||
|
||||
refute cs.valid?
|
||||
end
|
||||
|
||||
test "it truncates fields" do
|
||||
clear_config([:instance, :max_remote_account_fields], 2)
|
||||
|
||||
fields = [
|
||||
%{"name" => "One", "value" => "Uno"},
|
||||
%{"name" => "Two", "value" => "Dos"},
|
||||
%{"name" => "Three", "value" => "Tres"}
|
||||
]
|
||||
|
||||
cs = User.remote_user_changeset(@valid_remote |> Map.put(:fields, fields))
|
||||
|
||||
assert [%{"name" => "One", "value" => "Uno"}, %{"name" => "Two", "value" => "Dos"}] ==
|
||||
Ecto.Changeset.get_field(cs, :fields)
|
||||
end
|
||||
end
|
||||
|
||||
describe "followers and friends" do
|
||||
|
@ -1150,6 +1163,18 @@ test "it blocks people" do
|
|||
assert User.blocks?(user, blocked_user)
|
||||
end
|
||||
|
||||
test "it blocks domains" do
|
||||
user = insert(:user)
|
||||
blocked_user = insert(:user)
|
||||
|
||||
refute User.blocks_domain?(user, blocked_user)
|
||||
|
||||
url = URI.parse(blocked_user.ap_id)
|
||||
{:ok, user} = User.block_domain(user, url.host)
|
||||
|
||||
assert User.blocks_domain?(user, blocked_user)
|
||||
end
|
||||
|
||||
test "it unblocks users" do
|
||||
user = insert(:user)
|
||||
blocked_user = insert(:user)
|
||||
|
@ -1160,6 +1185,17 @@ test "it unblocks users" do
|
|||
refute User.blocks?(user, blocked_user)
|
||||
end
|
||||
|
||||
test "it unblocks domains" do
|
||||
user = insert(:user)
|
||||
blocked_user = insert(:user)
|
||||
|
||||
url = URI.parse(blocked_user.ap_id)
|
||||
{:ok, user} = User.block_domain(user, url.host)
|
||||
{:ok, user} = User.unblock_domain(user, url.host)
|
||||
|
||||
refute User.blocks_domain?(user, blocked_user)
|
||||
end
|
||||
|
||||
test "blocks tear down cyclical follow relationships" do
|
||||
blocker = insert(:user)
|
||||
blocked = insert(:user)
|
||||
|
|
|
@ -573,7 +573,6 @@ test "it inserts an incoming activity into the database", %{conn: conn} do
|
|||
assert Activity.get_by_ap_id(data["id"])
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "it inserts an incoming activity into the database" <>
|
||||
"even if we can't fetch the user but have it in our db",
|
||||
%{conn: conn} do
|
||||
|
@ -1094,7 +1093,7 @@ test "it returns a note activity in a collection", %{conn: conn} do
|
|||
|
||||
test "it clears `unreachable` federation status of the sender", %{conn: conn, data: data} do
|
||||
user =
|
||||
insert(:user)
|
||||
insert(:user, ap_id: data["actor"])
|
||||
|> with_signing_key()
|
||||
|
||||
data = Map.put(data, "bcc", [user.ap_id])
|
||||
|
@ -1114,7 +1113,6 @@ test "it clears `unreachable` federation status of the sender", %{conn: conn, da
|
|||
assert Instances.reachable?(sender_host)
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "it removes all follower collections but actor's", %{conn: conn} do
|
||||
[actor, recipient] = insert_pair(:user)
|
||||
actor = with_signing_key(actor)
|
||||
|
@ -1179,7 +1177,6 @@ test "it requires authentication", %{conn: conn} do
|
|||
assert json_response(ret_conn, 200)
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "forwarded report", %{conn: conn} do
|
||||
admin = insert(:user, is_admin: true)
|
||||
|
||||
|
@ -1260,7 +1257,6 @@ test "forwarded report", %{conn: conn} do
|
|||
)
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "forwarded report from mastodon", %{conn: conn} do
|
||||
admin = insert(:user, is_admin: true)
|
||||
actor = insert(:user, local: false)
|
||||
|
@ -1277,12 +1273,22 @@ test "forwarded report from mastodon", %{conn: conn} do
|
|||
|> File.read!()
|
||||
|> String.replace("{{DOMAIN}}", remote_domain)
|
||||
|
||||
Tesla.Mock.mock(fn %{url: ^remote_actor} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: mock_json_body,
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
key_url = "#{remote_actor}#main-key"
|
||||
|
||||
Tesla.Mock.mock(fn
|
||||
%{url: ^remote_actor} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: mock_json_body,
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
|
||||
%{url: ^key_url} ->
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: mock_json_body,
|
||||
headers: [{"content-type", "application/activity+json"}]
|
||||
}
|
||||
end)
|
||||
|
||||
data = %{
|
||||
|
|
|
@ -79,7 +79,7 @@ test "works with objects with empty to or cc fields" do
|
|||
|
||||
{:ok, data} = ObjectAgePolicy.filter(data)
|
||||
|
||||
assert Visibility.get_visibility(%{data: data}) == "unlisted"
|
||||
assert Visibility.get_visibility(%{data: data}) == "direct"
|
||||
end
|
||||
|
||||
test "it delists an old post" do
|
||||
|
|
|
@ -114,7 +114,6 @@ test "returns error when activity not `Create` type" do
|
|||
assert Relay.publish(activity) == {:error, "Not implemented"}
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "returns error when activity not public" do
|
||||
activity = insert(:direct_note_activity)
|
||||
assert Relay.publish(activity) == {:error, false}
|
||||
|
|
|
@ -83,7 +83,6 @@ test "it works for incoming announces, fetching the announced object" do
|
|||
assert(Activity.get_create_by_object_ap_id(data["object"]))
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "it works for incoming announces with an existing activity" do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hey"})
|
||||
|
@ -136,7 +135,6 @@ test "it works for incoming announces with an inlined activity" do
|
|||
assert object.data["content"] == "this is a private toot"
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "it rejects incoming announces with an inlined activity from another origin" do
|
||||
Tesla.Mock.mock(fn
|
||||
%{method: :get} -> %Tesla.Env{status: 404, body: ""}
|
||||
|
|
|
@ -86,7 +86,6 @@ test "it fails for incoming deletes with spoofed origin" do
|
|||
assert match?({:error, _}, Transmogrifier.handle_incoming(data))
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "it works for incoming user deletes" do
|
||||
%{ap_id: ap_id} = insert(:user, ap_id: "http://mastodon.example.org/users/admin")
|
||||
|
||||
|
|
|
@ -57,7 +57,6 @@ test "it ignores an incoming notice if we already have it" do
|
|||
assert activity == returned_activity
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "it fetches reply-to activities if we don't have them" do
|
||||
data =
|
||||
File.read!("test/fixtures/mastodon-post-activity.json")
|
||||
|
@ -537,7 +536,6 @@ test "returns object with inReplyTo when denied incoming reply", %{data: data} d
|
|||
assert modified_object["inReplyTo"] == []
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "returns modified object when allowed incoming reply", %{data: data} do
|
||||
object_with_reply =
|
||||
Map.put(
|
||||
|
@ -700,7 +698,6 @@ test "take_emoji_tags/1" do
|
|||
assert Transmogrifier.take_emoji_tags(user) == [
|
||||
%{
|
||||
"icon" => %{"type" => "Image", "url" => "https://example.org/firefox.png"},
|
||||
"id" => "https://example.org/firefox.png",
|
||||
"name" => ":firefox:",
|
||||
"type" => "Emoji",
|
||||
"updated" => "1970-01-01T00:00:00Z"
|
||||
|
|
|
@ -119,8 +119,8 @@ test "it works with custom profile fields" do
|
|||
user = User.get_cached_by_ap_id(user.ap_id)
|
||||
|
||||
assert user.fields == [
|
||||
%{"name" => "foo", "value" => "updated"},
|
||||
%{"name" => "foo1", "value" => "updated"}
|
||||
%{"name" => "foo", "value" => "bar"},
|
||||
%{"name" => "foo11", "value" => "bar11"}
|
||||
]
|
||||
|
||||
update_data =
|
||||
|
|
|
@ -561,7 +561,6 @@ test "returns nil when cannot normalize object" do
|
|||
end) =~ ":valid_uri_scheme"
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "returns {:ok, %Object{}} for success case" do
|
||||
assert {:ok, %Object{}} =
|
||||
Transmogrifier.get_obj_helper(
|
||||
|
|
|
@ -11,7 +11,9 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do
|
|||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
test "Renders a user, including the public key" do
|
||||
user = insert(:user)
|
||||
user =
|
||||
insert(:user)
|
||||
|> with_signing_key()
|
||||
|
||||
result = UserView.render("user.json", %{user: user})
|
||||
|
||||
|
@ -37,13 +39,14 @@ test "Renders profile fields" do
|
|||
end
|
||||
|
||||
test "Renders with emoji tags" do
|
||||
user = insert(:user, emoji: %{"bib" => "/test"})
|
||||
user =
|
||||
insert(:user, emoji: %{"bib" => "/test"})
|
||||
|> with_signing_key()
|
||||
|
||||
assert %{
|
||||
"tag" => [
|
||||
%{
|
||||
"icon" => %{"type" => "Image", "url" => "/test"},
|
||||
"id" => "/test",
|
||||
"name" => ":bib:",
|
||||
"type" => "Emoji",
|
||||
"updated" => "1970-01-01T00:00:00Z"
|
||||
|
@ -74,13 +77,18 @@ test "Does not add an avatar image if the user hasn't set one" do
|
|||
end
|
||||
|
||||
test "renders an invisible user with the invisible property set to true" do
|
||||
user = insert(:user, invisible: true)
|
||||
user =
|
||||
insert(:user, invisible: true)
|
||||
|> with_signing_key()
|
||||
|
||||
assert %{"invisible" => true} = UserView.render("service.json", %{user: user})
|
||||
end
|
||||
|
||||
test "service has a few essential fields" do
|
||||
user = insert(:user)
|
||||
user =
|
||||
insert(:user)
|
||||
|> with_signing_key()
|
||||
|
||||
result = UserView.render("service.json", %{user: user})
|
||||
assert result["id"]
|
||||
assert result["type"] == "Application"
|
||||
|
@ -120,7 +128,9 @@ test "remote users have an empty endpoints structure" do
|
|||
end
|
||||
|
||||
test "instance users do not expose oAuth endpoints" do
|
||||
user = insert(:user, nickname: nil, local: true)
|
||||
user =
|
||||
insert(:user, nickname: nil, local: true)
|
||||
|> with_signing_key()
|
||||
|
||||
result = UserView.render("user.json", %{user: user})
|
||||
|
||||
|
|
|
@ -79,7 +79,6 @@ test "search", %{conn: conn} do
|
|||
assert status["id"] == to_string(activity.id)
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "constructs hashtags from search query", %{conn: conn} do
|
||||
results =
|
||||
conn
|
||||
|
|
|
@ -152,7 +152,6 @@ test "filtering", %{conn: conn, user: user} do
|
|||
end
|
||||
|
||||
describe "public" do
|
||||
@tag capture_log: true
|
||||
test "the public timeline", %{conn: conn} do
|
||||
user = insert(:user)
|
||||
|
||||
|
@ -810,7 +809,6 @@ test "filtering", %{user: user, conn: conn} do
|
|||
describe "hashtag" do
|
||||
setup do: oauth_access(["n/a"])
|
||||
|
||||
@tag capture_log: true
|
||||
test "hashtag timeline", %{conn: conn} do
|
||||
following = insert(:user)
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ test "renders a poll" do
|
|||
%{title: "why are you even asking?", votes_count: 0}
|
||||
],
|
||||
votes_count: 0,
|
||||
voters_count: 0
|
||||
voters_count: nil
|
||||
}
|
||||
|
||||
result = PollView.render("show.json", %{object: object})
|
||||
|
|
|
@ -33,6 +33,10 @@ test "has an emoji reaction list" do
|
|||
user = insert(:user)
|
||||
other_user = insert(:user)
|
||||
third_user = insert(:user)
|
||||
domain_blocked_user = insert(:user, %{ap_id: "https://blocked.com/@blocked"})
|
||||
|
||||
{:ok, user} = User.block_domain(user, "blocked.com")
|
||||
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "dae cofe??"})
|
||||
|
||||
{:ok, _} = CommonAPI.react_with_emoji(activity.id, user, "☕")
|
||||
|
@ -40,6 +44,8 @@ test "has an emoji reaction list" do
|
|||
{:ok, _} = CommonAPI.react_with_emoji(activity.id, third_user, "🍵")
|
||||
{:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, "☕")
|
||||
{:ok, _} = CommonAPI.react_with_emoji(activity.id, other_user, ":dinosaur:")
|
||||
# this should not show up when the user is viewing the status
|
||||
{:ok, _} = CommonAPI.react_with_emoji(activity.id, domain_blocked_user, "😈")
|
||||
|
||||
activity = Repo.get(Activity, activity.id)
|
||||
status = StatusView.render("show.json", activity: activity)
|
||||
|
@ -55,7 +61,8 @@ test "has an emoji reaction list" do
|
|||
url: "http://localhost:4001/emoji/dino walking.gif",
|
||||
account_ids: [other_user.id, user.id]
|
||||
},
|
||||
%{name: "🍵", count: 1, me: false, url: nil, account_ids: [third_user.id]}
|
||||
%{name: "🍵", count: 1, me: false, url: nil, account_ids: [third_user.id]},
|
||||
%{name: "😈", count: 1, me: false, url: nil, account_ids: [domain_blocked_user.id]}
|
||||
]
|
||||
|
||||
status = StatusView.render("show.json", activity: activity, for: user)
|
||||
|
@ -73,6 +80,8 @@ test "has an emoji reaction list" do
|
|||
},
|
||||
%{name: "🍵", count: 1, me: false, url: nil, account_ids: [third_user.id]}
|
||||
]
|
||||
|
||||
refute Enum.any?(status[:pleroma][:emoji_reactions], fn reaction -> reaction[:name] == "😈" end)
|
||||
end
|
||||
|
||||
test "works correctly with badly formatted emojis" do
|
||||
|
|
|
@ -37,6 +37,10 @@ test "ignores local url" do
|
|||
assert MediaProxy.url(local_root) == local_root
|
||||
end
|
||||
|
||||
test "ignores data url" do
|
||||
assert MediaProxy.url("data:image/png;base64,") == "data:image/png;base64,"
|
||||
end
|
||||
|
||||
test "encodes and decodes URL" do
|
||||
url = "https://pleroma.soykaf.com/static/logo.png"
|
||||
encoded = MediaProxy.url(url)
|
||||
|
|
|
@ -67,7 +67,6 @@ test "performs sending notifications" do
|
|||
assert Impl.perform(notif) == {:ok, [:ok, :ok]}
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "returns error if notif does not match " do
|
||||
assert Impl.perform(%{}) == {:error, :unknown_type}
|
||||
end
|
||||
|
@ -76,7 +75,6 @@ test "successful message sending" do
|
|||
assert Impl.push_message(@message, @sub, @api_key, %Subscription{}) == :ok
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "fail message sending" do
|
||||
assert Impl.push_message(
|
||||
@message,
|
||||
|
|
|
@ -190,7 +190,6 @@ test "prevents spoofing" do
|
|||
end
|
||||
end
|
||||
|
||||
@tag capture_log: true
|
||||
test "prevents forgeries" do
|
||||
Tesla.Mock.mock(fn
|
||||
%{url: "https://bad.com/.well-known/webfinger?resource=acct:meanie@bad.com"} ->
|
||||
|
|
|
@ -263,7 +263,12 @@ def get("https://n1u.moe/users/rye", _, _, @activitypub_accept_headers) do
|
|||
{:ok,
|
||||
%Tesla.Env{
|
||||
status: 200,
|
||||
body: File.read!("test/fixtures/tesla_mock/rye.json"),
|
||||
body:
|
||||
File.read!("test/fixtures/tesla_mock/rye.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("name", "evil rye")
|
||||
|> Map.put("bio", "boooo!")
|
||||
|> Jason.encode!(),
|
||||
headers: activitypub_object_headers()
|
||||
}}
|
||||
end
|
||||
|
|
|
@ -3,7 +3,11 @@
|
|||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
os_exclude = if :os.type() == {:unix, :darwin}, do: [skip_on_mac: true], else: []
|
||||
ExUnit.start(exclude: [:federated, :erratic] ++ os_exclude)
|
||||
|
||||
ExUnit.start(
|
||||
capture_log: true,
|
||||
exclude: [:federated, :erratic] ++ os_exclude
|
||||
)
|
||||
|
||||
Ecto.Adapters.SQL.Sandbox.mode(Pleroma.Repo, :manual)
|
||||
|
||||
|
|
Loading…
Reference in a new issue