Merge remote-tracking branch 'upstream/develop' into neckbeard

This commit is contained in:
Your New SJW Waifu 2024-01-23 18:37:38 -06:00
commit 6a9c7c0d68
105 changed files with 686 additions and 414 deletions

View File

@ -28,6 +28,7 @@ cache: &global_cache_policy
stages: stages:
- check-changelog - check-changelog
- build - build
- lint
- test - test
- benchmark - benchmark
- deploy - deploy
@ -71,7 +72,7 @@ check-changelog:
tags: tags:
- amd64 - amd64
build: build-1.12.3:
extends: extends:
- .build_changes_policy - .build_changes_policy
- .using-ci-base - .using-ci-base
@ -79,10 +80,20 @@ build:
script: script:
- mix compile --force - mix compile --force
build-1.15.7-otp-25:
extends:
- .build_changes_policy
- .using-ci-base
stage: build
image: git.pleroma.social:5050/pleroma/pleroma/ci-base:elixir-1.15
allow_failure: true
script:
- mix compile --force
spec-build: spec-build:
extends: extends:
- .using-ci-base - .using-ci-base
stage: test stage: build
rules: rules:
- changes: - changes:
- ".gitlab-ci.yml" - ".gitlab-ci.yml"
@ -110,7 +121,7 @@ benchmark:
- mix ecto.migrate - mix ecto.migrate
- mix pleroma.load_testing - mix pleroma.load_testing
unit-testing: unit-testing-1.12.3:
extends: extends:
- .build_changes_policy - .build_changes_policy
- .using-ci-base - .using-ci-base
@ -118,12 +129,11 @@ unit-testing:
cache: &testing_cache_policy cache: &testing_cache_policy
<<: *global_cache_policy <<: *global_cache_policy
policy: pull policy: pull
services: &testing_services
services:
- name: postgres:13-alpine - name: postgres:13-alpine
alias: postgres alias: postgres
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"] command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
script: script: &testing_script
- mix ecto.create - mix ecto.create
- mix ecto.migrate - mix ecto.migrate
- mix test --cover --preload-modules - mix test --cover --preload-modules
@ -134,27 +144,32 @@ unit-testing:
coverage_format: cobertura coverage_format: cobertura
path: coverage.xml path: coverage.xml
unit-testing-erratic: unit-testing-1.15.7-otp-25:
extends:
- .build_changes_policy
- .using-ci-base
stage: test
image: git.pleroma.social:5050/pleroma/pleroma/ci-base:elixir-1.15-otp25
allow_failure: true
cache: *testing_cache_policy
services: *testing_services
script: *testing_script
unit-testing-1.12-erratic:
extends: extends:
- .build_changes_policy - .build_changes_policy
- .using-ci-base - .using-ci-base
stage: test stage: test
retry: 2 retry: 2
allow_failure: true allow_failure: true
cache: &testing_cache_policy cache: *testing_cache_policy
<<: *global_cache_policy services: *testing_services
policy: pull
services:
- name: postgres:13-alpine
alias: postgres
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
script: script:
- mix ecto.create - mix ecto.create
- mix ecto.migrate - mix ecto.migrate
- mix test --only=erratic - mix test --only=erratic
unit-testing-rum: unit-testing-1.12-rum:
extends: extends:
- .build_changes_policy - .build_changes_policy
- .using-ci-base - .using-ci-base
@ -173,10 +188,10 @@ unit-testing-rum:
- "mix ecto.migrate --migrations-path priv/repo/optional_migrations/rum_indexing/" - "mix ecto.migrate --migrations-path priv/repo/optional_migrations/rum_indexing/"
- mix test --preload-modules - mix test --preload-modules
lint: formatting-1.13:
extends: .build_changes_policy extends: .build_changes_policy
image: &current_elixir elixir:1.13-alpine image: &formatting_elixir elixir:1.13-alpine
stage: test stage: lint
cache: *testing_cache_policy cache: *testing_cache_policy
before_script: &current_bfr_script before_script: &current_bfr_script
- apk update - apk update
@ -187,25 +202,38 @@ lint:
script: script:
- mix format --check-formatted - mix format --check-formatted
analysis: cycles-1.13:
extends:
- .build_changes_policy
- .using-ci-base
stage: test
cache: *testing_cache_policy
script:
- mix credo --strict --only=warnings,todo,fixme,consistency,readability
cycles:
extends: .build_changes_policy extends: .build_changes_policy
image: *current_elixir image: *formatting_elixir
stage: test stage: lint
cache: {} cache: {}
before_script: *current_bfr_script before_script: *current_bfr_script
script: script:
- mix compile - mix compile
- mix xref graph --format cycles --label compile | awk '{print $0} END{exit ($0 != "No cycles found")}' - mix xref graph --format cycles --label compile | awk '{print $0} END{exit ($0 != "No cycles found")}'
analysis:
extends:
- .build_changes_policy
- .using-ci-base
stage: lint
cache: *testing_cache_policy
script:
- mix credo --strict --only=warnings,todo,fixme,consistency,readability
dialyzer:
extends:
- .build_changes_policy
- .using-ci-base
stage: lint
allow_failure: true
when: manual
cache: *testing_cache_policy
tags:
- feld
script:
- mix dialyzer
docs-deploy: docs-deploy:
stage: deploy stage: deploy
cache: *testing_cache_policy cache: *testing_cache_policy

View File

View File

View File

View File

0
changelog.d/exile.skip Normal file
View File

View File

@ -0,0 +1 @@
Remote object fetch failures will prevent the object fetch job from retrying if the object request returns 401, 403, 404, 410, or exceeds the maximum thread depth.

View File

@ -0,0 +1 @@
MRF: Log sensible error for subdomains_regex

View File

@ -0,0 +1 @@
MRF.StealEmojiPolicy: Properly add fallback extension to filenames missing one

View File

@ -0,0 +1 @@
Federated timeline removal of hashtags via MRF HashtagPolicy

View File

@ -0,0 +1 @@
Support objects with a null contentMap (firefish)

1
changelog.d/otp26.add Normal file
View File

@ -0,0 +1 @@
Support for Erlang OTP 26

View File

@ -0,0 +1 @@
MediaProxy Preview failures prevented when encountering certain video files

View File

@ -1 +0,0 @@
docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t git.pleroma.social:5050/pleroma/pleroma/ci-base:latest --push .

View File

@ -0,0 +1 @@
docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t git.pleroma.social:5050/pleroma/pleroma/ci-base:elixir-1.12 --push .

View File

@ -0,0 +1,8 @@
FROM elixir:1.12.3
# Single RUN statement, otherwise intermediate images are created
# https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#run
RUN apt-get update &&\
apt-get install -y libmagic-dev cmake libimage-exiftool-perl ffmpeg &&\
mix local.hex --force &&\
mix local.rebar --force

View File

@ -0,0 +1 @@
docker buildx build --platform linux/amd64 -t git.pleroma.social:5050/pleroma/pleroma/ci-base:elixir-1.15-otp25 --push .

View File

@ -79,6 +79,10 @@ IO.puts("RUM enabled: #{rum_enabled}")
config :pleroma, Pleroma.ReverseProxy.Client, Pleroma.ReverseProxy.ClientMock config :pleroma, Pleroma.ReverseProxy.Client, Pleroma.ReverseProxy.ClientMock
config :pleroma, Pleroma.Application,
background_migrators: false,
streamer_registry: false
if File.exists?("./config/benchmark.secret.exs") do if File.exists?("./config/benchmark.secret.exs") do
import_config "benchmark.secret.exs" import_config "benchmark.secret.exs"
else else

View File

@ -904,6 +904,15 @@ config :pleroma, Pleroma.Search.Meilisearch,
private_key: nil, private_key: nil,
initial_indexing_chunk_size: 100_000 initial_indexing_chunk_size: 100_000
config :pleroma, Pleroma.Application,
background_migrators: true,
internal_fetch: true,
load_custom_modules: true,
max_restarts: 3,
streamer_registry: true
config :pleroma, Pleroma.Uploaders.Uploader, timeout: 30_000
# Import environment specific config. This must remain at the bottom # Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above. # of this file so it overrides the configuration defined above.
import_config "#{Mix.env()}.exs" import_config "#{Mix.env()}.exs"

View File

@ -162,6 +162,18 @@ peer_module =
config :pleroma, Pleroma.Cluster, peer_module: peer_module config :pleroma, Pleroma.Cluster, peer_module: peer_module
config :pleroma, Pleroma.Application,
background_migrators: false,
internal_fetch: false,
load_custom_modules: false,
max_restarts: 100,
streamer_registry: false,
test_http_pools: true
config :pleroma, Pleroma.Uploaders.Uploader, timeout: 1_000
config :pleroma, Pleroma.Emoji.Loader, test_emoji: true
if File.exists?("./config/test.secret.exs") do if File.exists?("./config/test.secret.exs") do
import_config "test.secret.exs" import_config "test.secret.exs"
else else

View File

@ -1,6 +1,6 @@
# Differences in Mastodon API responses from vanilla Mastodon # Differences in Mastodon API responses from vanilla Mastodon
A Pleroma instance can be identified by "<Mastodon version> (compatible; Pleroma <version>)" present in `version` field in response from `/api/v1/instance` A Pleroma instance can be identified by "<Mastodon version> (compatible; Pleroma <version>)" present in `version` field in response from `/api/v1/instance` and `/api/v2/instance`
## Flake IDs ## Flake IDs
@ -39,6 +39,7 @@ Has these additional fields under the `pleroma` object:
- `emoji_reactions`: A list with emoji / reaction maps. The format is `{name: "☕", count: 1, me: true}`. Contains no information about the reacting users, for that use the `/statuses/:id/reactions` endpoint. - `emoji_reactions`: A list with emoji / reaction maps. The format is `{name: "☕", count: 1, me: true}`. Contains no information about the reacting users, for that use the `/statuses/:id/reactions` endpoint.
- `parent_visible`: If the parent of this post is visible to the user or not. - `parent_visible`: If the parent of this post is visible to the user or not.
- `pinned_at`: a datetime (iso8601) when status was pinned, `null` otherwise. - `pinned_at`: a datetime (iso8601) when status was pinned, `null` otherwise.
- `quotes_count`: the count of status quotes.
The `GET /api/v1/statuses/:id/source` endpoint additionally has the following attributes: The `GET /api/v1/statuses/:id/source` endpoint additionally has the following attributes:
@ -304,19 +305,27 @@ Has these additional parameters (which are the same as in Pleroma-API):
`GET /api/v1/instance` has additional fields `GET /api/v1/instance` has additional fields
- `max_toot_chars`: The maximum characters per post - `max_toot_chars`: The maximum characters per post
- `max_media_attachments`: Maximum number of post media attachments
- `chat_limit`: The maximum characters per chat message - `chat_limit`: The maximum characters per chat message
- `description_limit`: The maximum characters per image description - `description_limit`: The maximum characters per image description
- `poll_limits`: The limits of polls - `poll_limits`: The limits of polls
- `shout_limit`: The maximum characters per Shoutbox message
- `upload_limit`: The maximum upload file size - `upload_limit`: The maximum upload file size
- `avatar_upload_limit`: The same for avatars - `avatar_upload_limit`: The same for avatars
- `background_upload_limit`: The same for backgrounds - `background_upload_limit`: The same for backgrounds
- `banner_upload_limit`: The same for banners - `banner_upload_limit`: The same for banners
- `background_image`: A background image that frontends can use - `background_image`: A background image that frontends can use
- `pleroma.metadata.account_activation_required`: Whether users are required to confirm their emails before signing in
- `pleroma.metadata.birthday_required`: Whether users are required to provide their birth day when signing in
- `pleroma.metadata.birthday_min_age`: The minimum user age (in days)
- `pleroma.metadata.features`: A list of supported features - `pleroma.metadata.features`: A list of supported features
- `pleroma.metadata.federation`: The federation restrictions of this instance - `pleroma.metadata.federation`: The federation restrictions of this instance
- `pleroma.metadata.fields_limits`: A list of values detailing the length and count limitation for various instance-configurable fields. - `pleroma.metadata.fields_limits`: A list of values detailing the length and count limitation for various instance-configurable fields.
- `pleroma.metadata.post_formats`: A list of the allowed post format types - `pleroma.metadata.post_formats`: A list of the allowed post format types
- `vapid_public_key`: The public key needed for push messages - `pleroma.stats.mau`: Monthly active user count
- `pleroma.vapid_public_key`: The public key needed for push messages
In, `GET /api/v2/instance` Pleroma-specific fields are all moved into `pleroma` object. `max_toot_chars`, `poll_limits` and `upload_limit` are replaced with their MastoAPI counterparts.
## Push Subscription ## Push Subscription

View File

@ -129,7 +129,7 @@ The `/api/v1/pleroma/*` path is backwards compatible with `/api/pleroma/*` (`/ap
* method: `GET` * method: `GET`
* Authentication: required * Authentication: required
* OAuth scope: `write:security` * OAuth scope: `write:security`
* Response: JSON. Returns `{"codes": codes}`when successful, otherwise HTTP 422 `{"error": "[error message]"}` * Response: JSON. Returns `{"codes": codes}` when successful, otherwise HTTP 422 `{"error": "[error message]"}`
## `/api/v1/pleroma/admin/` ## `/api/v1/pleroma/admin/`
See [Admin-API](admin_api.md) See [Admin-API](admin_api.md)
@ -251,6 +251,15 @@ See [Admin-API](admin_api.md)
] ]
``` ```
## `/api/v1/pleroma/accounts/:id/endorsements`
### Returns users endorsed by a user
* Method `GET`
* Authentication: not required
* Params:
* `id`: the id of the account for whom to return results
* Response: JSON, returns a list of Mastodon Account entities
## `/api/v1/pleroma/accounts/update_*` ## `/api/v1/pleroma/accounts/update_*`
### Set and clear account avatar, banner, and background ### Set and clear account avatar, banner, and background
@ -266,6 +275,14 @@ See [Admin-API](admin_api.md)
* Authentication: not required * Authentication: not required
* Response: 204 No Content * Response: 204 No Content
## `/api/v1/pleroma/statuses/:id/quotes`
### Gets quotes for a given status
* Method `GET`
* Authentication: not required
* Params:
* `id`: the id of the status
* Response: JSON, returns a list of Mastodon Status entities
## `/api/v1/pleroma/mascot` ## `/api/v1/pleroma/mascot`
### Gets user mascot image ### Gets user mascot image
* Method `GET` * Method `GET`
@ -372,6 +389,15 @@ See [Admin-API](admin_api.md)
* `alias`: the nickname of the alias to delete, e.g. `foo@example.org`. * `alias`: the nickname of the alias to delete, e.g. `foo@example.org`.
* Response: JSON. Returns `{"status": "success"}` if the change was successful, `{"error": "[error message]"}` otherwise * Response: JSON. Returns `{"status": "success"}` if the change was successful, `{"error": "[error message]"}` otherwise
## `/api/v1/pleroma/remote_interaction`
## Interact with profile or status from remote account
* Metod `POST`
* Authentication: not required
* Params:
* `ap_id`: Profile or status ActivityPub ID
* `profile`: Remote profile webfinger
* Response: JSON. Returns `{"url": "[redirect url]"}` on success, `{"error": "[error message]"}` otherwise
# Pleroma Conversations # Pleroma Conversations
Pleroma Conversations have the same general structure that Mastodon Conversations have. The behavior differs in the following ways when using these endpoints: Pleroma Conversations have the same general structure that Mastodon Conversations have. The behavior differs in the following ways when using these endpoints:

View File

@ -2,7 +2,7 @@
* PostgreSQL >=9.6 * PostgreSQL >=9.6
* Elixir >=1.11.0 <1.15 * Elixir >=1.11.0 <1.15
* Erlang OTP >=22.2.0 <26 * Erlang OTP >=22.2.0 (supported: <27)
* git * git
* file / libmagic * file / libmagic
* gcc or clang * gcc or clang

View File

@ -352,6 +352,4 @@ defmodule Mix.Tasks.Pleroma.Instance do
enabled_filters enabled_filters
end end
defp upload_filters(_), do: []
end end

View File

@ -9,7 +9,7 @@ defmodule Pleroma.Activity.Queries do
import Ecto.Query, only: [from: 2, where: 3] import Ecto.Query, only: [from: 2, where: 3]
@type query :: Ecto.Queryable.t() | Activity.t() @type query :: Ecto.Queryable.t() | Pleroma.Activity.t()
alias Pleroma.Activity alias Pleroma.Activity
alias Pleroma.User alias Pleroma.User

View File

@ -23,19 +23,21 @@ defmodule Pleroma.Announcement do
timestamps(type: :utc_datetime) timestamps(type: :utc_datetime)
end end
def change(struct, params \\ %{}) do @doc "Generates changeset for %Pleroma.Announcement{}"
struct @spec changeset(%__MODULE__{}, map()) :: %Ecto.Changeset{}
|> cast(validate_params(struct, params), [:data, :starts_at, :ends_at, :rendered]) def changeset(announcement \\ %__MODULE__{}, params \\ %{data: %{}}) do
announcement
|> cast(validate_params(announcement, params), [:data, :starts_at, :ends_at, :rendered])
|> validate_required([:data]) |> validate_required([:data])
end end
defp validate_params(struct, params) do defp validate_params(announcement, params) do
base_data = base_data =
%{ %{
"content" => "", "content" => "",
"all_day" => false "all_day" => false
} }
|> Map.merge((struct && struct.data) || %{}) |> Map.merge((announcement && announcement.data) || %{})
merged_data = merged_data =
Map.merge(base_data, params.data) Map.merge(base_data, params.data)
@ -61,13 +63,13 @@ defmodule Pleroma.Announcement do
end end
def add(params) do def add(params) do
changeset = change(%__MODULE__{}, params) changeset = changeset(%__MODULE__{}, params)
Repo.insert(changeset) Repo.insert(changeset)
end end
def update(announcement, params) do def update(announcement, params) do
changeset = change(announcement, params) changeset = changeset(announcement, params)
Repo.update(changeset) Repo.update(changeset)
end end

View File

@ -14,7 +14,6 @@ defmodule Pleroma.Application do
@name Mix.Project.config()[:name] @name Mix.Project.config()[:name]
@version Mix.Project.config()[:version] @version Mix.Project.config()[:version]
@repository Mix.Project.config()[:source_url] @repository Mix.Project.config()[:source_url]
@mix_env Mix.env()
def name, do: @name def name, do: @name
def version, do: @version def version, do: @version
@ -98,7 +97,7 @@ defmodule Pleroma.Application do
{Task.Supervisor, name: Pleroma.TaskSupervisor} {Task.Supervisor, name: Pleroma.TaskSupervisor}
] ++ ] ++
cachex_children() ++ cachex_children() ++
http_children(adapter, @mix_env) ++ http_children(adapter) ++
[ [
Pleroma.Stats, Pleroma.Stats,
Pleroma.JobQueueMonitor, Pleroma.JobQueueMonitor,
@ -106,8 +105,9 @@ defmodule Pleroma.Application do
{Oban, Config.get(Oban)}, {Oban, Config.get(Oban)},
Pleroma.Web.Endpoint Pleroma.Web.Endpoint
] ++ ] ++
task_children(@mix_env) ++ task_children() ++
dont_run_in_test(@mix_env) ++ streamer_registry() ++
background_migrators() ++
shout_child(shout_enabled?()) ++ shout_child(shout_enabled?()) ++
[Pleroma.Gopher.Server] [Pleroma.Gopher.Server]
@ -116,12 +116,7 @@ defmodule Pleroma.Application do
# If we have a lot of caches, default max_restarts can cause test # If we have a lot of caches, default max_restarts can cause test
# resets to fail. # resets to fail.
# Go for the default 3 unless we're in test # Go for the default 3 unless we're in test
max_restarts = max_restarts = Application.get_env(:pleroma, __MODULE__)[:max_restarts]
if @mix_env == :test do
100
else
3
end
opts = [strategy: :one_for_one, name: Pleroma.Supervisor, max_restarts: max_restarts] opts = [strategy: :one_for_one, name: Pleroma.Supervisor, max_restarts: max_restarts]
result = Supervisor.start_link(children, opts) result = Supervisor.start_link(children, opts)
@ -159,7 +154,7 @@ defmodule Pleroma.Application do
raise "Invalid custom modules" raise "Invalid custom modules"
{:ok, modules, _warnings} -> {:ok, modules, _warnings} ->
if @mix_env != :test do if Application.get_env(:pleroma, __MODULE__)[:load_custom_modules] do
Enum.each(modules, fn mod -> Enum.each(modules, fn mod ->
Logger.info("Custom module loaded: #{inspect(mod)}") Logger.info("Custom module loaded: #{inspect(mod)}")
end) end)
@ -213,24 +208,30 @@ defmodule Pleroma.Application do
defp shout_enabled?, do: Config.get([:shout, :enabled]) defp shout_enabled?, do: Config.get([:shout, :enabled])
defp dont_run_in_test(env) when env in [:test, :benchmark], do: [] defp streamer_registry do
if Application.get_env(:pleroma, __MODULE__)[:streamer_registry] do
defp dont_run_in_test(_) do [
[ {Registry,
{Registry, [
[ name: Pleroma.Web.Streamer.registry(),
name: Pleroma.Web.Streamer.registry(), keys: :duplicate,
keys: :duplicate, partitions: System.schedulers_online()
partitions: System.schedulers_online() ]}
]} ]
] ++ background_migrators() else
[]
end
end end
defp background_migrators do defp background_migrators do
[ if Application.get_env(:pleroma, __MODULE__)[:background_migrators] do
Pleroma.Migrators.HashtagsTableMigrator, [
Pleroma.Migrators.ContextObjectsDeletionMigrator Pleroma.Migrators.HashtagsTableMigrator,
] Pleroma.Migrators.ContextObjectsDeletionMigrator
]
else
[]
end
end end
defp shout_child(true) do defp shout_child(true) do
@ -242,37 +243,43 @@ defmodule Pleroma.Application do
defp shout_child(_), do: [] defp shout_child(_), do: []
defp task_children(:test) do defp task_children do
[ children = [
%{ %{
id: :web_push_init, id: :web_push_init,
start: {Task, :start_link, [&Pleroma.Web.Push.init/0]}, start: {Task, :start_link, [&Pleroma.Web.Push.init/0]},
restart: :temporary restart: :temporary
} }
] ]
end
defp task_children(_) do if Application.get_env(:pleroma, __MODULE__)[:internal_fetch] do
[ children ++
%{ [
id: :web_push_init, %{
start: {Task, :start_link, [&Pleroma.Web.Push.init/0]}, id: :internal_fetch_init,
restart: :temporary start: {Task, :start_link, [&Pleroma.Web.ActivityPub.InternalFetchActor.init/0]},
}, restart: :temporary
%{ }
id: :internal_fetch_init, ]
start: {Task, :start_link, [&Pleroma.Web.ActivityPub.InternalFetchActor.init/0]}, else
restart: :temporary children
} end
]
end end
# start hackney and gun pools in tests # start hackney and gun pools in tests
defp http_children(_, :test) do defp http_children(adapter) do
http_children(Tesla.Adapter.Hackney, nil) ++ http_children(Tesla.Adapter.Gun, nil) if Application.get_env(:pleroma, __MODULE__)[:test_http_pools] do
http_children_hackney() ++ http_children_gun()
else
cond do
match?(Tesla.Adapter.Hackney, adapter) -> http_children_hackney()
match?(Tesla.Adapter.Gun, adapter) -> http_children_gun()
true -> []
end
end
end end
defp http_children(Tesla.Adapter.Hackney, _) do defp http_children_hackney do
pools = [:federation, :media] pools = [:federation, :media]
pools = pools =
@ -288,13 +295,11 @@ defmodule Pleroma.Application do
end end
end end
defp http_children(Tesla.Adapter.Gun, _) do defp http_children_gun do
Pleroma.Gun.ConnectionPool.children() ++ Pleroma.Gun.ConnectionPool.children() ++
[{Task, &Pleroma.HTTP.AdapterHelper.Gun.limiter_setup/0}] [{Task, &Pleroma.HTTP.AdapterHelper.Gun.limiter_setup/0}]
end end
defp http_children(_, _), do: []
@spec limiters_setup() :: :ok @spec limiters_setup() :: :ok
def limiters_setup do def limiters_setup do
config = Config.get(ConcurrentLimiter, []) config = Config.get(ConcurrentLimiter, [])

View File

@ -7,7 +7,10 @@ defmodule Pleroma.ApplicationRequirements do
The module represents the collection of validations to runs before start server. The module represents the collection of validations to runs before start server.
""" """
defmodule VerifyError, do: defexception([:message]) defmodule VerifyError do
defexception([:message])
@type t :: %__MODULE__{}
end
alias Pleroma.Config alias Pleroma.Config
alias Pleroma.Helpers.MediaHelper alias Pleroma.Helpers.MediaHelper
@ -193,8 +196,6 @@ defmodule Pleroma.ApplicationRequirements do
end end
end end
defp check_system_commands!(result), do: result
defp check_repo_pool_size!(:ok) do defp check_repo_pool_size!(:ok) do
if Pleroma.Config.get([Pleroma.Repo, :pool_size], 10) != 10 and if Pleroma.Config.get([Pleroma.Repo, :pool_size], 10) != 10 and
not Pleroma.Config.get([:dangerzone, :override_repo_pool_size], false) do not Pleroma.Config.get([:dangerzone, :override_repo_pool_size], false) do

View File

@ -22,8 +22,8 @@ defmodule Pleroma.Bookmark do
timestamps() timestamps()
end end
@spec create(FlakeId.Ecto.CompatType.t(), FlakeId.Ecto.CompatType.t()) :: @spec create(Ecto.UUID.t(), Ecto.UUID.t()) ::
{:ok, Bookmark.t()} | {:error, Changeset.t()} {:ok, Bookmark.t()} | {:error, Ecto.Changeset.t()}
def create(user_id, activity_id) do def create(user_id, activity_id) do
attrs = %{ attrs = %{
user_id: user_id, user_id: user_id,
@ -37,7 +37,7 @@ defmodule Pleroma.Bookmark do
|> Repo.insert() |> Repo.insert()
end end
@spec for_user_query(FlakeId.Ecto.CompatType.t()) :: Ecto.Query.t() @spec for_user_query(Ecto.UUID.t()) :: Ecto.Query.t()
def for_user_query(user_id) do def for_user_query(user_id) do
Bookmark Bookmark
|> where(user_id: ^user_id) |> where(user_id: ^user_id)
@ -52,8 +52,8 @@ defmodule Pleroma.Bookmark do
|> Repo.one() |> Repo.one()
end end
@spec destroy(FlakeId.Ecto.CompatType.t(), FlakeId.Ecto.CompatType.t()) :: @spec destroy(Ecto.UUID.t(), Ecto.UUID.t()) ::
{:ok, Bookmark.t()} | {:error, Changeset.t()} {:ok, Bookmark.t()} | {:error, Ecto.Changeset.t()}
def destroy(user_id, activity_id) do def destroy(user_id, activity_id) do
from(b in Bookmark, from(b in Bookmark,
where: b.user_id == ^user_id, where: b.user_id == ^user_id,

View File

@ -42,7 +42,7 @@ defmodule Pleroma.Chat do
|> unique_constraint(:user_id, name: :chats_user_id_recipient_index) |> unique_constraint(:user_id, name: :chats_user_id_recipient_index)
end end
@spec get_by_user_and_id(User.t(), FlakeId.Ecto.CompatType.t()) :: @spec get_by_user_and_id(User.t(), Ecto.UUID.t()) ::
{:ok, t()} | {:error, :not_found} {:ok, t()} | {:error, :not_found}
def get_by_user_and_id(%User{id: user_id}, id) do def get_by_user_and_id(%User{id: user_id}, id) do
from(c in __MODULE__, from(c in __MODULE__,
@ -52,17 +52,17 @@ defmodule Pleroma.Chat do
|> Repo.find_resource() |> Repo.find_resource()
end end
@spec get_by_id(FlakeId.Ecto.CompatType.t()) :: t() | nil @spec get_by_id(Ecto.UUID.t()) :: t() | nil
def get_by_id(id) do def get_by_id(id) do
Repo.get(__MODULE__, id) Repo.get(__MODULE__, id)
end end
@spec get(FlakeId.Ecto.CompatType.t(), String.t()) :: t() | nil @spec get(Ecto.UUID.t(), String.t()) :: t() | nil
def get(user_id, recipient) do def get(user_id, recipient) do
Repo.get_by(__MODULE__, user_id: user_id, recipient: recipient) Repo.get_by(__MODULE__, user_id: user_id, recipient: recipient)
end end
@spec get_or_create(FlakeId.Ecto.CompatType.t(), String.t()) :: @spec get_or_create(Ecto.UUID.t(), String.t()) ::
{:ok, t()} | {:error, Ecto.Changeset.t()} {:ok, t()} | {:error, Ecto.Changeset.t()}
def get_or_create(user_id, recipient) do def get_or_create(user_id, recipient) do
%__MODULE__{} %__MODULE__{}
@ -75,7 +75,7 @@ defmodule Pleroma.Chat do
) )
end end
@spec bump_or_create(FlakeId.Ecto.CompatType.t(), String.t()) :: @spec bump_or_create(Ecto.UUID.t(), String.t()) ::
{:ok, t()} | {:error, Ecto.Changeset.t()} {:ok, t()} | {:error, Ecto.Changeset.t()}
def bump_or_create(user_id, recipient) do def bump_or_create(user_id, recipient) do
%__MODULE__{} %__MODULE__{}
@ -87,7 +87,7 @@ defmodule Pleroma.Chat do
) )
end end
@spec for_user_query(FlakeId.Ecto.CompatType.t()) :: Ecto.Query.t() @spec for_user_query(Ecto.UUID.t()) :: Ecto.Query.t()
def for_user_query(user_id) do def for_user_query(user_id) do
from(c in Chat, from(c in Chat,
where: c.user_id == ^user_id, where: c.user_id == ^user_id,

View File

@ -54,7 +54,7 @@ defmodule Pleroma.ConfigDB do
@spec get_by_params(map()) :: ConfigDB.t() | nil @spec get_by_params(map()) :: ConfigDB.t() | nil
def get_by_params(%{group: _, key: _} = params), do: Repo.get_by(ConfigDB, params) def get_by_params(%{group: _, key: _} = params), do: Repo.get_by(ConfigDB, params)
@spec changeset(ConfigDB.t(), map()) :: Changeset.t() @spec changeset(ConfigDB.t(), map()) :: Ecto.Changeset.t()
def changeset(config, params \\ %{}) do def changeset(config, params \\ %{}) do
config config
|> cast(params, [:key, :group, :value]) |> cast(params, [:key, :group, :value])
@ -138,7 +138,7 @@ defmodule Pleroma.ConfigDB do
end end
end end
@spec update_or_create(map()) :: {:ok, ConfigDB.t()} | {:error, Changeset.t()} @spec update_or_create(map()) :: {:ok, ConfigDB.t()} | {:error, Ecto.Changeset.t()}
def update_or_create(params) do def update_or_create(params) do
params = Map.put(params, :value, to_elixir_types(params[:value])) params = Map.put(params, :value, to_elixir_types(params[:value]))
search_opts = Map.take(params, [:group, :key]) search_opts = Map.take(params, [:group, :key])
@ -175,7 +175,7 @@ defmodule Pleroma.ConfigDB do
end) end)
end end
@spec delete(ConfigDB.t() | map()) :: {:ok, ConfigDB.t()} | {:error, Changeset.t()} @spec delete(ConfigDB.t() | map()) :: {:ok, ConfigDB.t()} | {:error, Ecto.Changeset.t()}
def delete(%ConfigDB{} = config), do: Repo.delete(config) def delete(%ConfigDB{} = config), do: Repo.delete(config)
def delete(params) do def delete(params) do

View File

@ -12,6 +12,8 @@ defmodule Pleroma.DataMigration do
import Ecto.Changeset import Ecto.Changeset
import Ecto.Query import Ecto.Query
@type t :: %__MODULE__{}
schema "data_migrations" do schema "data_migrations" do
field(:name, :string) field(:name, :string)
field(:state, State, default: :pending) field(:state, State, default: :pending)

View File

@ -18,7 +18,7 @@ defmodule Pleroma.Docs.JSON do
:persistent_term.put(@term, Pleroma.Docs.Generator.convert_to_strings(descriptions)) :persistent_term.put(@term, Pleroma.Docs.Generator.convert_to_strings(descriptions))
end end
@spec compiled_descriptions :: Map.t() @spec compiled_descriptions :: map()
def compiled_descriptions do def compiled_descriptions do
:persistent_term.get(@term) :persistent_term.get(@term)
end end

View File

@ -8,10 +8,12 @@ defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.BareUri do
def type, do: :string def type, do: :string
def cast(uri) when is_binary(uri) do def cast(uri) when is_binary(uri) do
case URI.parse(uri) do parsed = URI.parse(uri)
%URI{scheme: nil} -> :error
%URI{} -> {:ok, uri} if is_nil(parsed.scheme) do
_ -> :error :error
else
{:ok, uri}
end end
end end

View File

@ -24,6 +24,8 @@ defmodule Pleroma.Emoji do
defstruct [:code, :file, :tags, :safe_code, :safe_file] defstruct [:code, :file, :tags, :safe_code, :safe_file]
@type t :: %__MODULE__{}
@doc "Build emoji struct" @doc "Build emoji struct"
def build({code, file, tags}) do def build({code, file, tags}) do
%__MODULE__{ %__MODULE__{

View File

@ -15,8 +15,6 @@ defmodule Pleroma.Emoji.Loader do
require Logger require Logger
@mix_env Mix.env()
@type pattern :: Regex.t() | module() | String.t() @type pattern :: Regex.t() | module() | String.t()
@type patterns :: pattern() | [pattern()] @type patterns :: pattern() | [pattern()]
@type group_patterns :: keyword(patterns()) @type group_patterns :: keyword(patterns())
@ -79,7 +77,7 @@ defmodule Pleroma.Emoji.Loader do
# for testing emoji.txt entries we do not want exposed in normal operation # for testing emoji.txt entries we do not want exposed in normal operation
test_emoji = test_emoji =
if @mix_env == :test do if Application.get_env(:pleroma, __MODULE__)[:test_emoji] do
load_from_file("test/config/emoji.txt", emoji_groups) load_from_file("test/config/emoji.txt", emoji_groups)
else else
[] []

View File

@ -21,7 +21,7 @@ defmodule Pleroma.Gun.ConnectionPool.WorkerSupervisor do
def start_worker(opts, retry \\ false) do def start_worker(opts, retry \\ false) do
case DynamicSupervisor.start_child(__MODULE__, {Pleroma.Gun.ConnectionPool.Worker, opts}) do case DynamicSupervisor.start_child(__MODULE__, {Pleroma.Gun.ConnectionPool.Worker, opts}) do
{:error, :max_children} -> {:error, :max_children} ->
if retry or free_pool() == :error do if Enum.any?([retry, free_pool()], &match?(&1, :error)) do
:telemetry.execute([:pleroma, :connection_pool, :provision_failure], %{opts: opts}) :telemetry.execute([:pleroma, :connection_pool, :provision_failure], %{opts: opts})
{:error, :pool_full} {:error, :pool_full}
else else

View File

@ -43,89 +43,28 @@ defmodule Pleroma.Helpers.MediaHelper do
def video_framegrab(url) do def video_framegrab(url) do
with executable when is_binary(executable) <- System.find_executable("ffmpeg"), with executable when is_binary(executable) <- System.find_executable("ffmpeg"),
{:ok, env} <- HTTP.get(url, [], pool: :media), {:ok, env} <- HTTP.get(url, [], pool: :media),
{:ok, fifo_path} <- mkfifo(), {:ok, pid} <- StringIO.open(env.body) do
args = [ body_stream = IO.binstream(pid, 1)
"-y",
"-i", Exile.stream!(
fifo_path, [
"-vframes", executable,
"1", "-i",
"-f", "pipe:0",
"mjpeg", "-vframes",
"-loglevel", "1",
"error", "-f",
"-" "mjpeg",
] do "pipe:1"
run_fifo(fifo_path, env, executable, args) ],
input: body_stream,
ignore_epipe: true,
stderr: :disable
)
|> Enum.into(<<>>)
else else
nil -> {:error, {:ffmpeg, :command_not_found}} nil -> {:error, {:ffmpeg, :command_not_found}}
{:error, _} = error -> error {:error, _} = error -> error
end end
end end
defp run_fifo(fifo_path, env, executable, args) do
pid =
Port.open({:spawn_executable, executable}, [
:use_stdio,
:stream,
:exit_status,
:binary,
args: args
])
fifo = Port.open(to_charlist(fifo_path), [:eof, :binary, :stream, :out])
fix = Pleroma.Helpers.QtFastStart.fix(env.body)
true = Port.command(fifo, fix)
:erlang.port_close(fifo)
loop_recv(pid)
after
File.rm(fifo_path)
end
defp mkfifo do
path = Path.join(System.tmp_dir!(), "pleroma-media-preview-pipe-#{Ecto.UUID.generate()}")
case System.cmd("mkfifo", [path]) do
{_, 0} ->
spawn(fifo_guard(path))
{:ok, path}
{_, err} ->
{:error, {:fifo_failed, err}}
end
end
defp fifo_guard(path) do
pid = self()
fn ->
ref = Process.monitor(pid)
receive do
{:DOWN, ^ref, :process, ^pid, _} ->
File.rm(path)
end
end
end
defp loop_recv(pid) do
loop_recv(pid, <<>>)
end
defp loop_recv(pid, acc) do
receive do
{^pid, {:data, data}} ->
loop_recv(pid, acc <> data)
{^pid, {:exit_status, 0}} ->
{:ok, acc}
{^pid, {:exit_status, status}} ->
{:error, status}
after
5000 ->
:erlang.port_close(pid)
{:error, :timeout}
end
end
end end

View File

@ -40,16 +40,21 @@ defmodule Pleroma.Helpers.QtFastStart do
got_mdat, got_mdat,
acc acc
) do ) do
full_size = (size - 8) * 8 try do
<<data::bits-size(full_size), rest::bits>> = rest full_size = (size - 8) * 8
<<data::bits-size(full_size), rest::bits>> = rest
acc = [ acc = [
{fourcc, pos, pos + size, size, {fourcc, pos, pos + size, size,
<<size::integer-big-size(32), fourcc::bits-size(32), data::bits>>} <<size::integer-big-size(32), fourcc::bits-size(32), data::bits>>}
| acc | acc
] ]
fix(rest, pos + size, got_moov || fourcc == "moov", got_mdat || fourcc == "mdat", acc) fix(rest, pos + size, got_moov || fourcc == "moov", got_mdat || fourcc == "mdat", acc)
rescue
_ ->
:abort
end
end end
defp fix(<<>>, _pos, _, _, acc) do defp fix(<<>>, _pos, _, _, acc) do

View File

@ -15,8 +15,8 @@ defmodule Pleroma.HTTP.AdapterHelper do
require Logger require Logger
@type proxy :: @type proxy ::
{Connection.host(), pos_integer()} {host(), pos_integer()}
| {Connection.proxy_type(), Connection.host(), pos_integer()} | {proxy_type(), host(), pos_integer()}
@callback options(keyword(), URI.t()) :: keyword() @callback options(keyword(), URI.t()) :: keyword()

View File

@ -100,7 +100,7 @@ defmodule Pleroma.Migrators.HashtagsTableMigrator do
|> where([_o, hashtags_objects], is_nil(hashtags_objects.object_id)) |> where([_o, hashtags_objects], is_nil(hashtags_objects.object_id))
end end
@spec transfer_object_hashtags(Map.t()) :: {:noop | :ok | :error, integer()} @spec transfer_object_hashtags(map()) :: {:noop | :ok | :error, integer()}
defp transfer_object_hashtags(object) do defp transfer_object_hashtags(object) do
embedded_tags = if Map.has_key?(object, :tag), do: object.tag, else: object.data["tag"] embedded_tags = if Map.has_key?(object, :tag), do: object.tag, else: object.data["tag"]
hashtags = Object.object_data_hashtags(%{"tag" => embedded_tags}) hashtags = Object.object_data_hashtags(%{"tag" => embedded_tags})

View File

@ -188,10 +188,11 @@ defmodule Pleroma.Migrators.Support.BaseMigrator do
end end
defp fault_rate do defp fault_rate do
with failures_count when is_integer(failures_count) <- failures_count() do with failures_count when is_integer(failures_count) <- failures_count(),
true <- failures_count > 0 do
failures_count / Enum.max([get_stat(:affected_count, 0), 1]) failures_count / Enum.max([get_stat(:affected_count, 0), 1])
else else
_ -> :error _ -> 0
end end
end end

View File

@ -177,7 +177,10 @@ defmodule Pleroma.Object do
ap_id ap_id
Keyword.get(options, :fetch) -> Keyword.get(options, :fetch) ->
Fetcher.fetch_object_from_id!(ap_id, options) case Fetcher.fetch_object_from_id(ap_id, options) do
{:ok, object} -> object
_ -> nil
end
true -> true ->
get_cached_by_ap_id(ap_id) get_cached_by_ap_id(ap_id)

View File

@ -72,20 +72,25 @@ defmodule Pleroma.Object.Fetcher do
{:object, data, Object.normalize(activity, fetch: false)} do {:object, data, Object.normalize(activity, fetch: false)} do
{:ok, object} {:ok, object}
else else
{:allowed_depth, false} -> {:allowed_depth, false} = e ->
{:error, "Max thread distance exceeded."} log_fetch_error(id, e)
{:error, :allowed_depth}
{:containment, _} -> {:containment, reason} = e ->
{:error, "Object containment failed."} log_fetch_error(id, e)
{:error, reason}
{:transmogrifier, {:error, {:reject, e}}} -> {:transmogrifier, {:error, {:reject, reason}}} = e ->
{:reject, e} log_fetch_error(id, e)
{:reject, reason}
{:transmogrifier, {:reject, e}} -> {:transmogrifier, {:reject, reason}} = e ->
{:reject, e} log_fetch_error(id, e)
{:reject, reason}
{:transmogrifier, _} = e -> {:transmogrifier, reason} = e ->
{:error, e} log_fetch_error(id, e)
{:error, reason}
{:object, data, nil} -> {:object, data, nil} ->
reinject_object(%Object{}, data) reinject_object(%Object{}, data)
@ -96,14 +101,21 @@ defmodule Pleroma.Object.Fetcher do
{:fetch_object, %Object{} = object} -> {:fetch_object, %Object{} = object} ->
{:ok, object} {:ok, object}
{:fetch, {:error, error}} -> {:fetch, {:error, reason}} = e ->
{:error, error} log_fetch_error(id, e)
{:error, reason}
e -> e ->
e log_fetch_error(id, e)
{:error, e}
end end
end end
defp log_fetch_error(id, error) do
Logger.metadata(object: id)
Logger.error("Object rejected while fetching #{id} #{inspect(error)}")
end
defp prepare_activity_params(data) do defp prepare_activity_params(data) do
%{ %{
"type" => "Create", "type" => "Create",
@ -117,26 +129,6 @@ defmodule Pleroma.Object.Fetcher do
|> Maps.put_if_present("bcc", data["bcc"]) |> Maps.put_if_present("bcc", data["bcc"])
end end
def fetch_object_from_id!(id, options \\ []) do
with {:ok, object} <- fetch_object_from_id(id, options) do
object
else
{:error, %Tesla.Mock.Error{}} ->
nil
{:error, "Object has been deleted"} ->
nil
{:reject, reason} ->
Logger.info("Rejected #{id} while fetching: #{inspect(reason)}")
nil
e ->
Logger.error("Error while fetching #{id}: #{inspect(e)}")
nil
end
end
defp make_signature(id, date) do defp make_signature(id, date) do
uri = URI.parse(id) uri = URI.parse(id)
@ -227,8 +219,11 @@ defmodule Pleroma.Object.Fetcher do
{:error, {:content_type, nil}} {:error, {:content_type, nil}}
end end
{:ok, %{status: code}} when code in [401, 403] ->
{:error, :forbidden}
{:ok, %{status: code}} when code in [404, 410] -> {:ok, %{status: code}} when code in [404, 410] ->
{:error, "Object has been deleted"} {:error, :not_found}
{:error, e} -> {:error, e} ->
{:error, e} {:error, e}

View File

@ -55,12 +55,6 @@ defmodule Pleroma.ReleaseTasks do
{:error, term} when is_binary(term) -> {:error, term} when is_binary(term) ->
IO.puts(:stderr, "The database for #{inspect(@repo)} couldn't be created: #{term}") IO.puts(:stderr, "The database for #{inspect(@repo)} couldn't be created: #{term}")
{:error, term} ->
IO.puts(
:stderr,
"The database for #{inspect(@repo)} couldn't be created: #{inspect(term)}"
)
end end
end end
end end

View File

@ -23,8 +23,8 @@ defmodule Pleroma.ReportNote do
timestamps() timestamps()
end end
@spec create(FlakeId.Ecto.CompatType.t(), FlakeId.Ecto.CompatType.t(), String.t()) :: @spec create(Ecto.UUID.t(), Ecto.UUID.t(), String.t()) ::
{:ok, ReportNote.t()} | {:error, Changeset.t()} {:ok, ReportNote.t()} | {:error, Ecto.Changeset.t()}
def create(user_id, activity_id, content) do def create(user_id, activity_id, content) do
attrs = %{ attrs = %{
user_id: user_id, user_id: user_id,
@ -38,8 +38,8 @@ defmodule Pleroma.ReportNote do
|> Repo.insert() |> Repo.insert()
end end
@spec destroy(FlakeId.Ecto.CompatType.t()) :: @spec destroy(Ecto.UUID.t()) ::
{:ok, ReportNote.t()} | {:error, Changeset.t()} {:ok, ReportNote.t()} | {:error, Ecto.Changeset.t()}
def destroy(id) do def destroy(id) do
from(r in ReportNote, where: r.id == ^id) from(r in ReportNote, where: r.id == ^id)
|> Repo.one() |> Repo.one()

View File

@ -81,9 +81,9 @@ defmodule Pleroma.ReverseProxy do
import Plug.Conn import Plug.Conn
@type option() :: @type option() ::
{:max_read_duration, :timer.time() | :infinity} {:max_read_duration, non_neg_integer() | :infinity}
| {:max_body_length, non_neg_integer() | :infinity} | {:max_body_length, non_neg_integer() | :infinity}
| {:failed_request_ttl, :timer.time() | :infinity} | {:failed_request_ttl, non_neg_integer() | :infinity}
| {:http, []} | {:http, []}
| {:req_headers, [{String.t(), String.t()}]} | {:req_headers, [{String.t(), String.t()}]}
| {:resp_headers, [{String.t(), String.t()}]} | {:resp_headers, [{String.t(), String.t()}]}

View File

@ -86,7 +86,7 @@ defmodule Pleroma.Upload do
end end
end end
@spec store(source, options :: [option()]) :: {:ok, Map.t()} | {:error, any()} @spec store(source, options :: [option()]) :: {:ok, map()} | {:error, any()}
@doc "Store a file. If using a `Plug.Upload{}` as the source, be sure to use `Majic.Plug` to ensure its content_type and filename is correct." @doc "Store a file. If using a `Plug.Upload{}` as the source, be sure to use `Majic.Plug` to ensure its content_type and filename is correct."
def store(upload, opts \\ []) do def store(upload, opts \\ []) do
opts = get_opts(opts) opts = get_opts(opts)

View File

@ -5,8 +5,6 @@
defmodule Pleroma.Uploaders.Uploader do defmodule Pleroma.Uploaders.Uploader do
import Pleroma.Web.Gettext import Pleroma.Web.Gettext
@mix_env Mix.env()
@moduledoc """ @moduledoc """
Defines the contract to put and get an uploaded file to any backend. Defines the contract to put and get an uploaded file to any backend.
""" """
@ -40,7 +38,7 @@ defmodule Pleroma.Uploaders.Uploader do
@callback delete_file(file :: String.t()) :: :ok | {:error, String.t()} @callback delete_file(file :: String.t()) :: :ok | {:error, String.t()}
@callback http_callback(Plug.Conn.t(), Map.t()) :: @callback http_callback(Plug.Conn.t(), map()) ::
{:ok, Plug.Conn.t()} {:ok, Plug.Conn.t()}
| {:ok, Plug.Conn.t(), file_spec()} | {:ok, Plug.Conn.t(), file_spec()}
| {:error, Plug.Conn.t(), String.t()} | {:error, Plug.Conn.t(), String.t()}
@ -75,10 +73,5 @@ defmodule Pleroma.Uploaders.Uploader do
end end
end end
defp callback_timeout do defp callback_timeout, do: Application.get_env(:pleroma, __MODULE__)[:timeout]
case @mix_env do
:test -> 1_000
_ -> 30_000
end
end
end end

View File

@ -672,7 +672,7 @@ defmodule Pleroma.User do
|> validate_inclusion(:actor_type, ["Person", "Service"]) |> validate_inclusion(:actor_type, ["Person", "Service"])
end end
@spec update_as_admin(User.t(), map()) :: {:ok, User.t()} | {:error, Changeset.t()} @spec update_as_admin(User.t(), map()) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()}
def update_as_admin(user, params) do def update_as_admin(user, params) do
params = Map.put(params, "password_confirmation", params["password"]) params = Map.put(params, "password_confirmation", params["password"])
changeset = update_as_admin_changeset(user, params) changeset = update_as_admin_changeset(user, params)
@ -693,7 +693,7 @@ defmodule Pleroma.User do
|> put_change(:password_reset_pending, false) |> put_change(:password_reset_pending, false)
end end
@spec reset_password(User.t(), map()) :: {:ok, User.t()} | {:error, Changeset.t()} @spec reset_password(User.t(), map()) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()}
def reset_password(%User{} = user, params) do def reset_password(%User{} = user, params) do
reset_password(user, user, params) reset_password(user, user, params)
end end
@ -1011,7 +1011,7 @@ defmodule Pleroma.User do
def maybe_send_confirmation_email(_), do: {:ok, :noop} def maybe_send_confirmation_email(_), do: {:ok, :noop}
@spec send_confirmation_email(Uset.t()) :: User.t() @spec send_confirmation_email(User.t()) :: User.t()
def send_confirmation_email(%User{} = user) do def send_confirmation_email(%User{} = user) do
user user
|> Pleroma.Emails.UserEmail.account_confirmation_email() |> Pleroma.Emails.UserEmail.account_confirmation_email()
@ -1048,7 +1048,8 @@ defmodule Pleroma.User do
def needs_update?(_), do: true def needs_update?(_), do: true
@spec maybe_direct_follow(User.t(), User.t()) :: {:ok, User.t()} | {:error, String.t()} @spec maybe_direct_follow(User.t(), User.t()) ::
{:ok, User.t(), User.t()} | {:error, String.t()}
# "Locked" (self-locked) users demand explicit authorization of follow requests # "Locked" (self-locked) users demand explicit authorization of follow requests
def maybe_direct_follow(%User{} = follower, %User{local: true, is_locked: true} = followed) do def maybe_direct_follow(%User{} = follower, %User{local: true, is_locked: true} = followed) do
@ -1783,14 +1784,14 @@ defmodule Pleroma.User do
BackgroundWorker.enqueue("user_activation", %{"user_id" => user.id, "status" => status}) BackgroundWorker.enqueue("user_activation", %{"user_id" => user.id, "status" => status})
end end
@spec set_activation([User.t()], boolean()) :: {:ok, User.t()} | {:error, Changeset.t()} @spec set_activation([User.t()], boolean()) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()}
def set_activation(users, status) when is_list(users) do def set_activation(users, status) when is_list(users) do
Repo.transaction(fn -> Repo.transaction(fn ->
for user <- users, do: set_activation(user, status) for user <- users, do: set_activation(user, status)
end) end)
end end
@spec set_activation(User.t(), boolean()) :: {:ok, User.t()} | {:error, Changeset.t()} @spec set_activation(User.t(), boolean()) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()}
def set_activation(%User{} = user, status) do def set_activation(%User{} = user, status) do
with {:ok, user} <- set_activation_status(user, status) do with {:ok, user} <- set_activation_status(user, status) do
user user
@ -1868,7 +1869,7 @@ defmodule Pleroma.User do
|> update_and_set_cache() |> update_and_set_cache()
end end
@spec purge_user_changeset(User.t()) :: Changeset.t() @spec purge_user_changeset(User.t()) :: Ecto.Changeset.t()
def purge_user_changeset(user) do def purge_user_changeset(user) do
# "Right to be forgotten" # "Right to be forgotten"
# https://gdpr.eu/right-to-be-forgotten/ # https://gdpr.eu/right-to-be-forgotten/
@ -2359,7 +2360,7 @@ defmodule Pleroma.User do
updated_user updated_user
end end
@spec set_confirmation(User.t(), boolean()) :: {:ok, User.t()} | {:error, Changeset.t()} @spec set_confirmation(User.t(), boolean()) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()}
def set_confirmation(%User{} = user, bool) do def set_confirmation(%User{} = user, bool) do
user user
|> confirmation_changeset(set_confirmation: bool) |> confirmation_changeset(set_confirmation: bool)
@ -2537,7 +2538,7 @@ defmodule Pleroma.User do
|> update_and_set_cache() |> update_and_set_cache()
end end
@spec confirmation_changeset(User.t(), keyword()) :: Changeset.t() @spec confirmation_changeset(User.t(), keyword()) :: Ecto.Changeset.t()
def confirmation_changeset(user, set_confirmation: confirmed?) do def confirmation_changeset(user, set_confirmation: confirmed?) do
params = params =
if confirmed? do if confirmed? do
@ -2555,7 +2556,7 @@ defmodule Pleroma.User do
cast(user, params, [:is_confirmed, :confirmation_token]) cast(user, params, [:is_confirmed, :confirmation_token])
end end
@spec approval_changeset(User.t(), keyword()) :: Changeset.t() @spec approval_changeset(User.t(), keyword()) :: Ecto.Changeset.t()
def approval_changeset(user, set_approval: approved?) do def approval_changeset(user, set_approval: approved?) do
cast(user, %{is_approved: approved?}, [:is_approved]) cast(user, %{is_approved: approved?}, [:is_approved])
end end

View File

@ -22,6 +22,8 @@ defmodule Pleroma.User.Backup do
alias Pleroma.Web.ActivityPub.UserView alias Pleroma.Web.ActivityPub.UserView
alias Pleroma.Workers.BackupWorker alias Pleroma.Workers.BackupWorker
@type t :: %__MODULE__{}
schema "backups" do schema "backups" do
field(:content_type, :string) field(:content_type, :string)
field(:file_name, :string) field(:file_name, :string)
@ -195,6 +197,7 @@ defmodule Pleroma.User.Backup do
end end
@files ['actor.json', 'outbox.json', 'likes.json', 'bookmarks.json'] @files ['actor.json', 'outbox.json', 'likes.json', 'bookmarks.json']
@spec export(Pleroma.User.Backup.t(), pid()) :: {:ok, String.t()} | :error
def export(%__MODULE__{} = backup, caller_pid) do def export(%__MODULE__{} = backup, caller_pid) do
backup = Repo.preload(backup, :user) backup = Repo.preload(backup, :user)
dir = backup_tempdir(backup) dir = backup_tempdir(backup)
@ -204,9 +207,11 @@ defmodule Pleroma.User.Backup do
:ok <- statuses(dir, backup.user, caller_pid), :ok <- statuses(dir, backup.user, caller_pid),
:ok <- likes(dir, backup.user, caller_pid), :ok <- likes(dir, backup.user, caller_pid),
:ok <- bookmarks(dir, backup.user, caller_pid), :ok <- bookmarks(dir, backup.user, caller_pid),
{:ok, zip_path} <- :zip.create(String.to_charlist(dir <> ".zip"), @files, cwd: dir), {:ok, zip_path} <- :zip.create(backup.file_name, @files, cwd: dir),
{:ok, _} <- File.rm_rf(dir) do {:ok, _} <- File.rm_rf(dir) do
{:ok, to_string(zip_path)} {:ok, zip_path}
else
_ -> :error
end end
end end
@ -382,6 +387,8 @@ defmodule Pleroma.User.Backup.Processor do
[:file_size, :processed, :state] [:file_size, :processed, :state]
) )
|> Repo.update() |> Repo.update()
else
e -> {:error, e}
end end
end end
end end

View File

@ -71,7 +71,7 @@ defmodule Pleroma.User.Query do
@equal_criteria [:email] @equal_criteria [:email]
@contains_criteria [:ap_id, :nickname] @contains_criteria [:ap_id, :nickname]
@spec build(Query.t(), criteria()) :: Query.t() @spec build(Ecto.Query.t(), criteria()) :: Ecto.Query.t()
def build(query \\ base_query(), criteria) do def build(query \\ base_query(), criteria) do
prepare_query(query, criteria) prepare_query(query, criteria)
end end

View File

@ -64,7 +64,7 @@ defmodule Pleroma.UserInviteToken do
end end
@spec update_invite(UserInviteToken.t(), map()) :: @spec update_invite(UserInviteToken.t(), map()) ::
{:ok, UserInviteToken.t()} | {:error, Changeset.t()} {:ok, UserInviteToken.t()} | {:error, Ecto.Changeset.t()}
def update_invite(invite, changes) do def update_invite(invite, changes) do
change(invite, changes) |> Repo.update() change(invite, changes) |> Repo.update()
end end

View File

@ -14,6 +14,8 @@ defmodule Pleroma.UserRelationship do
alias Pleroma.User alias Pleroma.User
alias Pleroma.UserRelationship alias Pleroma.UserRelationship
@type t :: %__MODULE__{}
schema "user_relationships" do schema "user_relationships" do
belongs_to(:source, User, type: FlakeId.Ecto.CompatType) belongs_to(:source, User, type: FlakeId.Ecto.CompatType)
belongs_to(:target, User, type: FlakeId.Ecto.CompatType) belongs_to(:target, User, type: FlakeId.Ecto.CompatType)

View File

@ -499,7 +499,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
end end
@spec fetch_latest_direct_activity_id_for_context(String.t(), keyword() | map()) :: @spec fetch_latest_direct_activity_id_for_context(String.t(), keyword() | map()) ::
FlakeId.Ecto.CompatType.t() | nil Ecto.UUID.t() | nil
def fetch_latest_direct_activity_id_for_context(context, opts \\ %{}) do def fetch_latest_direct_activity_id_for_context(context, opts \\ %{}) do
context context
|> fetch_activities_for_context_query(Map.merge(%{skip_preload: true}, opts)) |> fetch_activities_for_context_query(Map.merge(%{skip_preload: true}, opts))
@ -1698,9 +1698,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
Fetcher.fetch_and_contain_remote_object_from_id(first) do Fetcher.fetch_and_contain_remote_object_from_id(first) do
{:ok, false} {:ok, false}
else else
{:error, {:ok, %{status: code}}} when code in [401, 403] -> {:ok, true} {:error, _} -> {:ok, true}
{:error, _} = e -> e
e -> {:error, e}
end end
end end

View File

@ -9,6 +9,7 @@ defmodule Pleroma.Web.ActivityPub.Builder do
This module encodes our addressing policies and general shape of our objects. This module encodes our addressing policies and general shape of our objects.
""" """
alias Pleroma.Activity
alias Pleroma.Emoji alias Pleroma.Emoji
alias Pleroma.Object alias Pleroma.Object
alias Pleroma.User alias Pleroma.User

View File

@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server # Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/> # Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF do defmodule Pleroma.Web.ActivityPub.MRF do
@ -139,7 +139,16 @@ defmodule Pleroma.Web.ActivityPub.MRF do
@spec subdomains_regex([String.t()]) :: [Regex.t()] @spec subdomains_regex([String.t()]) :: [Regex.t()]
def subdomains_regex(domains) when is_list(domains) do def subdomains_regex(domains) when is_list(domains) do
for domain <- domains, do: ~r(^#{String.replace(domain, "*.", "(.*\\.)*")}$)i for domain <- domains do
try do
target = String.replace(domain, "*.", "(.*\\.)*")
~r<^#{target}$>i
rescue
e ->
Logger.error("MRF: Invalid subdomain Regex: #{domain}")
reraise e, __STACKTRACE__
end
end
end end
@spec subdomain_match?([Regex.t()], String.t()) :: boolean() @spec subdomain_match?([Regex.t()], String.t()) :: boolean()

View File

@ -56,8 +56,6 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiFollowbotPolicy do
nick_score + name_score + actor_type_score nick_score + name_score + actor_type_score
end end
defp determine_if_followbot(_), do: 0.0
defp bot_allowed?(%{"object" => target}, bot_actor) do defp bot_allowed?(%{"object" => target}, bot_actor) do
%User{} = user = normalize_by_ap_id(target) %User{} = user = normalize_by_ap_id(target)

View File

@ -84,7 +84,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.HashtagPolicy do
if hashtags != [] do if hashtags != [] do
with {:ok, message} <- check_reject(message, hashtags), with {:ok, message} <- check_reject(message, hashtags),
{:ok, message} <- {:ok, message} <-
(if "type" == "Create" do (if type == "Create" do
check_ftl_removal(message, hashtags) check_ftl_removal(message, hashtags)
else else
{:ok, message} {:ok, message}

View File

@ -62,7 +62,6 @@ defmodule Pleroma.Web.ActivityPub.MRF.InlineQuotePolicy do
key: :mrf_inline_quote, key: :mrf_inline_quote,
related_policy: "Pleroma.Web.ActivityPub.MRF.InlineQuotePolicy", related_policy: "Pleroma.Web.ActivityPub.MRF.InlineQuotePolicy",
label: "MRF Inline Quote Policy", label: "MRF Inline Quote Policy",
type: :group,
description: "Force quote url to appear in post content.", description: "Force quote url to appear in post content.",
children: [ children: [
%{ %{

View File

@ -10,15 +10,12 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
@moduledoc "Reject or Word-Replace messages with a keyword or regex" @moduledoc "Reject or Word-Replace messages with a keyword or regex"
@behaviour Pleroma.Web.ActivityPub.MRF.Policy @behaviour Pleroma.Web.ActivityPub.MRF.Policy
defp string_matches?(string, _) when not is_binary(string) do
false
end
defp string_matches?(string, pattern) when is_binary(pattern) do defp string_matches?(string, pattern) when is_binary(pattern) do
String.contains?(string, pattern) String.contains?(string, pattern)
end end
defp string_matches?(string, pattern) do defp string_matches?(string, %Regex{} = pattern) do
String.match?(string, pattern) String.match?(string, pattern)
end end

View File

@ -3,8 +3,8 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRF.Policy do defmodule Pleroma.Web.ActivityPub.MRF.Policy do
@callback filter(Map.t()) :: {:ok | :reject, Map.t()} @callback filter(map()) :: {:ok | :reject, map()}
@callback describe() :: {:ok | :error, Map.t()} @callback describe() :: {:ok | :error, map()}
@callback config_description() :: %{ @callback config_description() :: %{
optional(:children) => [map()], optional(:children) => [map()],
key: atom(), key: atom(),

View File

@ -34,7 +34,9 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicy do
|> Path.basename() |> Path.basename()
|> Path.extname() |> Path.extname()
file_path = Path.join(emoji_dir_path, shortcode <> (extension || ".png")) extension = if extension == "", do: ".png", else: extension
file_path = Path.join(emoji_dir_path, shortcode <> extension)
case File.write(file_path, response.body) do case File.write(file_path, response.body) do
:ok -> :ok ->

View File

@ -28,7 +28,7 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
@doc """ @doc """
Enqueue publishing a single activity. Enqueue publishing a single activity.
""" """
@spec enqueue_one(Map.t(), Keyword.t()) :: {:ok, %Oban.Job{}} @spec enqueue_one(map(), Keyword.t()) :: {:ok, %Oban.Job{}}
def enqueue_one(%{} = params, worker_args \\ []) do def enqueue_one(%{} = params, worker_args \\ []) do
PublisherWorker.enqueue( PublisherWorker.enqueue(
"publish_one", "publish_one",

View File

@ -23,7 +23,6 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
import Ecto.Query import Ecto.Query
require Logger
require Pleroma.Constants require Pleroma.Constants
@doc """ @doc """
@ -155,8 +154,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|> Map.put("context", replied_object.data["context"] || object["conversation"]) |> Map.put("context", replied_object.data["context"] || object["conversation"])
|> Map.drop(["conversation", "inReplyToAtomUri"]) |> Map.drop(["conversation", "inReplyToAtomUri"])
else else
e -> _ ->
Logger.warning("Couldn't fetch #{inspect(in_reply_to_id)}, error: #{inspect(e)}")
object object
end end
else else
@ -181,8 +179,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
{:quoting?, _} -> {:quoting?, _} ->
object object
e -> _ ->
Logger.warning("Couldn't fetch #{inspect(quote_url)}, error: #{inspect(e)}")
object object
end end
end end
@ -339,6 +336,10 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
def fix_tag(object), do: object def fix_tag(object), do: object
def fix_content_map(%{"contentMap" => nil} = object) do
Map.drop(object, ["contentMap"])
end
# content map usually only has one language so this will do for now. # content map usually only has one language so this will do for now.
def fix_content_map(%{"contentMap" => content_map} = object) do def fix_content_map(%{"contentMap" => content_map} = object) do
content_groups = Map.to_list(content_map) content_groups = Map.to_list(content_map)
@ -852,8 +853,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
relative_object do relative_object do
Map.put(data, "object", external_url) Map.put(data, "object", external_url)
else else
{:fetch, e} -> {:fetch, _} ->
Logger.error("Couldn't fetch #{object} #{inspect(e)}")
data data
_ -> _ ->

View File

@ -5,7 +5,7 @@
defmodule Pleroma.Web.Auth.Authenticator do defmodule Pleroma.Web.Auth.Authenticator do
@callback get_user(Plug.Conn.t()) :: {:ok, user :: struct()} | {:error, any()} @callback get_user(Plug.Conn.t()) :: {:ok, user :: struct()} | {:error, any()}
@callback create_from_registration(Plug.Conn.t(), registration :: struct()) :: @callback create_from_registration(Plug.Conn.t(), registration :: struct()) ::
{:ok, User.t()} | {:error, any()} {:ok, Pleroma.User.t()} | {:error, any()}
@callback get_registration(Plug.Conn.t()) :: {:ok, registration :: struct()} | {:error, any()} @callback get_registration(Plug.Conn.t()) :: {:ok, registration :: struct()} | {:error, any()}
@callback handle_error(Plug.Conn.t(), any()) :: any() @callback handle_error(Plug.Conn.t(), any()) :: any()
@callback auth_template() :: String.t() | nil @callback auth_template() :: String.t() | nil

View File

@ -505,7 +505,7 @@ defmodule Pleroma.Web.CommonAPI do
end end
end end
@spec unpin(String.t(), User.t()) :: {:ok, User.t()} | {:error, term()} @spec unpin(String.t(), User.t()) :: {:ok, Activity.t()} | {:error, term()}
def unpin(id, user) do def unpin(id, user) do
with %Activity{} = activity <- create_activity_by_id(id), with %Activity{} = activity <- create_activity_by_id(id),
{:ok, unpin_data, _} <- Builder.unpin(user, activity.object), {:ok, unpin_data, _} <- Builder.unpin(user, activity.object),

View File

@ -14,6 +14,8 @@ defmodule Pleroma.Web.CommonAPI.ActivityDraft do
import Pleroma.Web.Gettext import Pleroma.Web.Gettext
import Pleroma.Web.Utils.Guards, only: [not_empty_string: 1] import Pleroma.Web.Utils.Guards, only: [not_empty_string: 1]
@type t :: %__MODULE__{}
defstruct valid?: true, defstruct valid?: true,
errors: [], errors: [],
user: nil, user: nil,

View File

@ -132,7 +132,7 @@ defmodule Pleroma.Web.Feed.FeedView do
|> safe_to_string() |> safe_to_string()
end end
@spec to_rfc3339(String.t() | NativeDateTime.t()) :: String.t() @spec to_rfc3339(String.t() | NaiveDateTime.t()) :: String.t()
def to_rfc3339(date) when is_binary(date) do def to_rfc3339(date) when is_binary(date) do
date date
|> Timex.parse!("{ISO:Extended}") |> Timex.parse!("{ISO:Extended}")
@ -145,7 +145,7 @@ defmodule Pleroma.Web.Feed.FeedView do
|> Timex.format!("{RFC3339}") |> Timex.format!("{RFC3339}")
end end
@spec to_rfc2822(String.t() | DateTime.t() | NativeDateTime.t()) :: String.t() @spec to_rfc2822(String.t() | DateTime.t() | NaiveDateTime.t()) :: String.t()
def to_rfc2822(datestr) when is_binary(datestr) do def to_rfc2822(datestr) when is_binary(datestr) do
datestr datestr
|> Timex.parse!("{ISO:Extended}") |> Timex.parse!("{ISO:Extended}")

View File

@ -40,6 +40,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do
background_image: Pleroma.Web.Endpoint.url() <> Keyword.get(instance, :background_image), background_image: Pleroma.Web.Endpoint.url() <> Keyword.get(instance, :background_image),
shout_limit: Config.get([:shout, :limit]), shout_limit: Config.get([:shout, :limit]),
description_limit: Keyword.get(instance, :description_limit), description_limit: Keyword.get(instance, :description_limit),
chat_limit: Keyword.get(instance, :chat_limit),
pleroma: pleroma_configuration(instance) pleroma: pleroma_configuration(instance)
}) })
end end
@ -222,6 +223,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do
banner_upload_limit: Keyword.get(instance, :banner_upload_limit), banner_upload_limit: Keyword.get(instance, :banner_upload_limit),
background_image: background_image:
Pleroma.Web.Endpoint.url() <> Keyword.get(instance, :background_image), Pleroma.Web.Endpoint.url() <> Keyword.get(instance, :background_image),
chat_limit: Keyword.get(instance, :chat_limit),
description_limit: Keyword.get(instance, :description_limit), description_limit: Keyword.get(instance, :description_limit),
shout_limit: Config.get([:shout, :limit]) shout_limit: Config.get([:shout, :limit])
}) })

View File

@ -28,7 +28,7 @@ defmodule Pleroma.Web.OAuth.Authorization do
end end
@spec create_authorization(App.t(), User.t() | %{}, [String.t()] | nil) :: @spec create_authorization(App.t(), User.t() | %{}, [String.t()] | nil) ::
{:ok, Authorization.t()} | {:error, Changeset.t()} {:ok, Authorization.t()} | {:error, Ecto.Changeset.t()}
def create_authorization(%App{} = app, %User{} = user, scopes \\ nil) do def create_authorization(%App{} = app, %User{} = user, scopes \\ nil) do
%{ %{
scopes: scopes || app.scopes, scopes: scopes || app.scopes,
@ -39,7 +39,7 @@ defmodule Pleroma.Web.OAuth.Authorization do
|> Repo.insert() |> Repo.insert()
end end
@spec create_changeset(map()) :: Changeset.t() @spec create_changeset(map()) :: Ecto.Changeset.t()
def create_changeset(attrs \\ %{}) do def create_changeset(attrs \\ %{}) do
%Authorization{} %Authorization{}
|> cast(attrs, [:user_id, :app_id, :scopes, :valid_until]) |> cast(attrs, [:user_id, :app_id, :scopes, :valid_until])
@ -58,7 +58,7 @@ defmodule Pleroma.Web.OAuth.Authorization do
put_change(changeset, :valid_until, NaiveDateTime.add(NaiveDateTime.utc_now(), lifespan)) put_change(changeset, :valid_until, NaiveDateTime.add(NaiveDateTime.utc_now(), lifespan))
end end
@spec use_changeset(Authtorizatiton.t(), map()) :: Changeset.t() @spec use_changeset(Authorization.t(), map()) :: Ecto.Changeset.t()
def use_changeset(%Authorization{} = auth, params) do def use_changeset(%Authorization{} = auth, params) do
auth auth
|> cast(params, [:used]) |> cast(params, [:used])
@ -66,7 +66,7 @@ defmodule Pleroma.Web.OAuth.Authorization do
end end
@spec use_token(Authorization.t()) :: @spec use_token(Authorization.t()) ::
{:ok, Authorization.t()} | {:error, Changeset.t()} | {:error, String.t()} {:ok, Authorization.t()} | {:error, Ecto.Changeset.t()} | {:error, String.t()}
def use_token(%Authorization{used: false, valid_until: valid_until} = auth) do def use_token(%Authorization{used: false, valid_until: valid_until} = auth) do
if NaiveDateTime.diff(NaiveDateTime.utc_now(), valid_until) < 0 do if NaiveDateTime.diff(NaiveDateTime.utc_now(), valid_until) < 0 do
Repo.update(use_changeset(auth, %{used: true})) Repo.update(use_changeset(auth, %{used: true}))

View File

@ -56,7 +56,8 @@ defmodule Pleroma.Web.OAuth.Token do
|> Repo.find_resource() |> Repo.find_resource()
end end
@spec exchange_token(App.t(), Authorization.t()) :: {:ok, Token.t()} | {:error, Changeset.t()} @spec exchange_token(App.t(), Authorization.t()) ::
{:ok, Token.t()} | {:error, Ecto.Changeset.t()}
def exchange_token(app, auth) do def exchange_token(app, auth) do
with {:ok, auth} <- Authorization.use_token(auth), with {:ok, auth} <- Authorization.use_token(auth),
true <- auth.app_id == app.id do true <- auth.app_id == app.id do
@ -95,7 +96,7 @@ defmodule Pleroma.Web.OAuth.Token do
|> validate_required([:valid_until]) |> validate_required([:valid_until])
end end
@spec create(App.t(), User.t(), map()) :: {:ok, Token} | {:error, Changeset.t()} @spec create(App.t(), User.t(), map()) :: {:ok, Token} | {:error, Ecto.Changeset.t()}
def create(%App{} = app, %User{} = user, attrs \\ %{}) do def create(%App{} = app, %User{} = user, attrs \\ %{}) do
with {:ok, token} <- do_create(app, user, attrs) do with {:ok, token} <- do_create(app, user, attrs) do
if Pleroma.Config.get([:oauth2, :clean_expired_tokens]) do if Pleroma.Config.get([:oauth2, :clean_expired_tokens]) do

View File

@ -9,10 +9,10 @@ defmodule Pleroma.Web.OAuth.Token.Query do
import Ecto.Query, only: [from: 2] import Ecto.Query, only: [from: 2]
@type query :: Ecto.Queryable.t() | Token.t()
alias Pleroma.Web.OAuth.Token alias Pleroma.Web.OAuth.Token
@type query :: Ecto.Queryable.t() | Token.t()
@spec get_by_refresh_token(query, String.t()) :: query @spec get_by_refresh_token(query, String.t()) :: query
def get_by_refresh_token(query \\ Token, refresh_token) do def get_by_refresh_token(query \\ Token, refresh_token) do
from(q in query, where: q.refresh_token == ^refresh_token) from(q in query, where: q.refresh_token == ^refresh_token)

View File

@ -102,7 +102,7 @@ defmodule Pleroma.Web.RichMedia.Parser do
ttl_setters: [MyModule] ttl_setters: [MyModule]
""" """
@spec set_ttl_based_on_image(map(), String.t()) :: @spec set_ttl_based_on_image(map(), String.t()) ::
{:ok, Integer.t() | :noop} | {:error, :no_key} {:ok, integer() | :noop} | {:error, :no_key}
def set_ttl_based_on_image(data, url) do def set_ttl_based_on_image(data, url) do
case get_ttl_from_image(data, url) do case get_ttl_from_image(data, url) do
{:ok, ttl} when is_number(ttl) -> {:ok, ttl} when is_number(ttl) ->

View File

@ -3,5 +3,5 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.RichMedia.Parser.TTL do defmodule Pleroma.Web.RichMedia.Parser.TTL do
@callback ttl(Map.t(), String.t()) :: Integer.t() | nil @callback ttl(map(), String.t()) :: integer() | nil
end end

View File

@ -182,7 +182,7 @@ defmodule Pleroma.Web.Router do
end end
pipeline :well_known do pipeline :well_known do
plug(:accepts, ["json", "jrd+json", "xml", "xrd+xml"]) plug(:accepts, ["json", "jrd", "jrd+json", "xml", "xrd+xml"])
end end
pipeline :config do pipeline :config do

View File

@ -20,7 +20,6 @@ defmodule Pleroma.Web.Streamer do
alias Pleroma.Web.Plugs.OAuthScopesPlug alias Pleroma.Web.Plugs.OAuthScopesPlug
alias Pleroma.Web.StreamerView alias Pleroma.Web.StreamerView
@mix_env Mix.env()
@registry Pleroma.Web.StreamerRegistry @registry Pleroma.Web.StreamerRegistry
def registry, do: @registry def registry, do: @registry
@ -34,7 +33,7 @@ defmodule Pleroma.Web.Streamer do
stream :: String.t(), stream :: String.t(),
User.t() | nil, User.t() | nil,
Token.t() | nil, Token.t() | nil,
Map.t() | nil map() | nil
) :: ) ::
{:ok, topic :: String.t()} | {:error, :bad_topic} | {:error, :unauthorized} {:ok, topic :: String.t()} | {:error, :bad_topic} | {:error, :unauthorized}
def get_topic_and_add_socket(stream, user, oauth_token, params \\ %{}) do def get_topic_and_add_socket(stream, user, oauth_token, params \\ %{}) do
@ -60,7 +59,7 @@ defmodule Pleroma.Web.Streamer do
end end
@doc "Expand and authorizes a stream" @doc "Expand and authorizes a stream"
@spec get_topic(stream :: String.t() | nil, User.t() | nil, Token.t() | nil, Map.t()) :: @spec get_topic(stream :: String.t() | nil, User.t() | nil, Token.t() | nil, map()) ::
{:ok, topic :: String.t() | nil} | {:error, :bad_topic} {:ok, topic :: String.t() | nil} | {:error, :bad_topic}
def get_topic(stream, user, oauth_token, params \\ %{}) def get_topic(stream, user, oauth_token, params \\ %{})
@ -396,25 +395,20 @@ defmodule Pleroma.Web.Streamer do
end end
end end
# In test environment, only return true if the registry is started. # In dev/prod the streamer registry is expected to be started, so return true
# In benchmark environment, returns false. # In test it is possible to have the registry started for a test so it will check
# In any other environment, always returns true. # In benchmark it will never find the process alive and return false
cond do def should_env_send? do
@mix_env == :test -> if Application.get_env(:pleroma, Pleroma.Application)[:streamer_registry] do
def should_env_send? do true
case Process.whereis(@registry) do else
nil -> case Process.whereis(@registry) do
false nil ->
false
pid -> pid ->
Process.alive?(pid) Process.alive?(pid)
end
end end
end
@mix_env == :benchmark ->
def should_env_send?, do: false
true ->
def should_env_send?, do: true
end end
end end

View File

@ -30,7 +30,7 @@ defmodule Pleroma.Web.WebFinger.WebFingerController do
end end
def webfinger(%{assigns: %{format: format}} = conn, %{"resource" => resource}) def webfinger(%{assigns: %{format: format}} = conn, %{"resource" => resource})
when format in ["json", "jrd+json"] do when format in ["jrd", "json", "jrd+json"] do
with {:ok, response} <- WebFinger.webfinger(resource, "JSON") do with {:ok, response} <- WebFinger.webfinger(resource, "JSON") do
json(conn, response) json(conn, response)
else else

View File

@ -9,7 +9,22 @@ defmodule Pleroma.Workers.RemoteFetcherWorker do
@impl Oban.Worker @impl Oban.Worker
def perform(%Job{args: %{"op" => "fetch_remote", "id" => id} = args}) do def perform(%Job{args: %{"op" => "fetch_remote", "id" => id} = args}) do
{:ok, _object} = Fetcher.fetch_object_from_id(id, depth: args["depth"]) case Fetcher.fetch_object_from_id(id, depth: args["depth"]) do
{:ok, _object} ->
:ok
{:error, :forbidden} ->
{:discard, :forbidden}
{:error, :not_found} ->
{:discard, :not_found}
{:error, :allowed_depth} ->
{:discard, :allowed_depth}
_ ->
:error
end
end end
@impl Oban.Worker @impl Oban.Worker

16
mix.exs
View File

@ -10,6 +10,7 @@ defmodule Pleroma.Mixfile do
compilers: Mix.compilers(), compilers: Mix.compilers(),
elixirc_options: [warnings_as_errors: warnings_as_errors()], elixirc_options: [warnings_as_errors: warnings_as_errors()],
xref: [exclude: [:eldap]], xref: [exclude: [:eldap]],
dialyzer: [plt_add_apps: [:mix, :eldap]],
start_permanent: Mix.env() == :prod, start_permanent: Mix.env() == :prod,
aliases: aliases(), aliases: aliases(),
deps: deps(), deps: deps(),
@ -156,14 +157,11 @@ defmodule Pleroma.Mixfile do
{:phoenix_swoosh, "~> 1.1"}, {:phoenix_swoosh, "~> 1.1"},
{:gen_smtp, "~> 0.13"}, {:gen_smtp, "~> 0.13"},
{:ex_syslogger, "~> 1.4"}, {:ex_syslogger, "~> 1.4"},
{:floki, "~> 0.27"}, {:floki, "~> 0.35"},
{:timex, "~> 3.6"}, {:timex, "~> 3.6"},
{:ueberauth, "~> 0.4"}, {:ueberauth, "~> 0.4"},
# {:linkify, "~> 0.5.2"}, {:linkify, "~> 0.5.3"},
{:linkify, {:http_signatures, "~> 0.1.2"},
git: "https://git.froth.zone/sam/linkify.git",
branch: "master"},
{:http_signatures, "~> 0.1.1"},
{:telemetry, "~> 1.0.0", override: true}, {:telemetry, "~> 1.0.0", override: true},
{:poolboy, "~> 1.5"}, {:poolboy, "~> 1.5"},
{:prom_ex, "~> 1.9"}, {:prom_ex, "~> 1.9"},
@ -187,6 +185,9 @@ defmodule Pleroma.Mixfile do
{:vix, "~> 0.26.0"}, {:vix, "~> 0.26.0"},
{:elixir_make, "~> 0.7.7", override: true}, {:elixir_make, "~> 0.7.7", override: true},
{:blurhash, "~> 0.1.0", hex: :rinpatch_blurhash}, {:blurhash, "~> 0.1.0", hex: :rinpatch_blurhash},
{:exile,
git: "https://git.pleroma.social/pleroma/elixir-libraries/exile.git",
ref: "0d6337cf68e7fbc8a093cae000955aa93b067f91"},
## dev & test ## dev & test
{:ex_doc, "~> 0.22", only: :dev, runtime: false}, {:ex_doc, "~> 0.22", only: :dev, runtime: false},
@ -197,7 +198,8 @@ defmodule Pleroma.Mixfile do
{:hackney, "~> 1.18.0", override: true}, {:hackney, "~> 1.18.0", override: true},
{:mox, "~> 1.0", only: :test}, {:mox, "~> 1.0", only: :test},
{:websockex, "~> 0.4.3", only: :test}, {:websockex, "~> 0.4.3", only: :test},
{:benchee, "~> 1.0", only: :benchmark} {:benchee, "~> 1.0", only: :benchmark},
{:dialyxir, "~> 1.4", only: [:dev, :test], runtime: false}
] ++ oauth_deps() ] ++ oauth_deps()
end end

View File

@ -27,6 +27,7 @@
"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.6.0", "77d835c472b5b67fc4f29556dee74bf511bbafecdcaf98c27d27fa5918152086", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c2f992d15725e721ec7fbc1189d4ecdb8afef76648c746a8e1cad35e3b8a35f3"},
"decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"}, "decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"},
"deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm", "ce708e5f094b9cd4e8f2be4f00d2f4250c4095be93f8cd6d018c753894885430"}, "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"},
"earmark": {:hex, :earmark, "1.4.22", "ea3e45c6359446dc308be0a64ce82a03260d973de7d0625a762e6d352ff57958", [:mix], [{:earmark_parser, "~> 1.4.23", [hex: :earmark_parser, repo: "hexpm", optional: false]}], "hexpm", "1caf5145665a42fd76d5317286b0c171861fb1c04f86ab103dde76868814fdfb"}, "earmark": {:hex, :earmark, "1.4.22", "ea3e45c6359446dc308be0a64ce82a03260d973de7d0625a762e6d352ff57958", [:mix], [{:earmark_parser, "~> 1.4.23", [hex: :earmark_parser, repo: "hexpm", optional: false]}], "hexpm", "1caf5145665a42fd76d5317286b0c171861fb1c04f86ab103dde76868814fdfb"},
"earmark_parser": {:hex, :earmark_parser, "1.4.32", "fa739a0ecfa34493de19426681b23f6814573faee95dfd4b4aafe15a7b5b32c6", [:mix], [], "hexpm", "b8b0dd77d60373e77a3d7e8afa598f325e49e8663a51bcc2b88ef41838cca755"}, "earmark_parser": {:hex, :earmark_parser, "1.4.32", "fa739a0ecfa34493de19426681b23f6814573faee95dfd4b4aafe15a7b5b32c6", [:mix], [], "hexpm", "b8b0dd77d60373e77a3d7e8afa598f325e49e8663a51bcc2b88ef41838cca755"},
"eblurhash": {:git, "https://github.com/zotonic/eblurhash.git", "bc37ceb426ef021ee9927fb249bb93f7059194ab", [ref: "bc37ceb426ef021ee9927fb249bb93f7059194ab"]}, "eblurhash": {:git, "https://github.com/zotonic/eblurhash.git", "bc37ceb426ef021ee9927fb249bb93f7059194ab", [ref: "bc37ceb426ef021ee9927fb249bb93f7059194ab"]},
@ -35,7 +36,8 @@
"ecto_psql_extras": {:hex, :ecto_psql_extras, "0.7.14", "7a20cfe913b0476542b43870e67386461258734896035e3f284039fd18bd4c4c", [:mix], [{:ecto_sql, "~> 3.7", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16.0 or ~> 0.17.0", [hex: :postgrex, repo: "hexpm", optional: false]}, {:table_rex, "~> 3.1.1", [hex: :table_rex, repo: "hexpm", optional: false]}], "hexpm", "22f5f98592dd597db9416fcef00effae0787669fdcb6faf447e982b553798e98"}, "ecto_psql_extras": {:hex, :ecto_psql_extras, "0.7.14", "7a20cfe913b0476542b43870e67386461258734896035e3f284039fd18bd4c4c", [:mix], [{:ecto_sql, "~> 3.7", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16.0 or ~> 0.17.0", [hex: :postgrex, repo: "hexpm", optional: false]}, {:table_rex, "~> 3.1.1", [hex: :table_rex, repo: "hexpm", optional: false]}], "hexpm", "22f5f98592dd597db9416fcef00effae0787669fdcb6faf447e982b553798e98"},
"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"}, "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"},
"eimp": {:hex, :eimp, "1.0.14", "fc297f0c7e2700457a95a60c7010a5f1dcb768a083b6d53f49cd94ab95a28f22", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "501133f3112079b92d9e22da8b88bf4f0e13d4d67ae9c15c42c30bd25ceb83b6"}, "eimp": {:hex, :eimp, "1.0.14", "fc297f0c7e2700457a95a60c7010a5f1dcb768a083b6d53f49cd94ab95a28f22", [:rebar3], [{:p1_utils, "1.0.18", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "501133f3112079b92d9e22da8b88bf4f0e13d4d67ae9c15c42c30bd25ceb83b6"},
"elixir_make": {:hex, :elixir_make, "0.7.7", "7128c60c2476019ed978210c245badf08b03dbec4f24d05790ef791da11aa17c", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "5bc19fff950fad52bbe5f211b12db9ec82c6b34a9647da0c2224b8b8464c7e6c"}, "elixir_make": {:hex, :elixir_make, "0.7.8", "505026f266552ee5aabca0b9f9c229cbb496c689537c9f922f3eb5431157efc7", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.0", [hex: :certifi, repo: "hexpm", optional: true]}], "hexpm", "7a71945b913d37ea89b06966e1342c85cfe549b15e6d6d081e8081c493062c07"},
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
"esbuild": {:hex, :esbuild, "0.5.0", "d5bb08ff049d7880ee3609ed5c4b864bd2f46445ea40b16b4acead724fb4c4a3", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "f183a0b332d963c4cfaf585477695ea59eef9a6f2204fdd0efa00e099694ffe5"}, "esbuild": {:hex, :esbuild, "0.5.0", "d5bb08ff049d7880ee3609ed5c4b864bd2f46445ea40b16b4acead724fb4c4a3", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "f183a0b332d963c4cfaf585477695ea59eef9a6f2204fdd0efa00e099694ffe5"},
"eternal": {:hex, :eternal, "1.2.2", "d1641c86368de99375b98d183042dd6c2b234262b8d08dfd72b9eeaafc2a1abd", [:mix], [], "hexpm", "2c9fe32b9c3726703ba5e1d43a1d255a4f3f2d8f8f9bc19f094c7cb1a7a9e782"}, "eternal": {:hex, :eternal, "1.2.2", "d1641c86368de99375b98d183042dd6c2b234262b8d08dfd72b9eeaafc2a1abd", [:mix], [], "hexpm", "2c9fe32b9c3726703ba5e1d43a1d255a4f3f2d8f8f9bc19f094c7cb1a7a9e782"},
"ex_aws": {:hex, :ex_aws, "2.1.9", "dc4865ecc20a05190a34a0ac5213e3e5e2b0a75a0c2835e923ae7bfeac5e3c31", [:mix], [{:configparser_ex, "~> 4.0", [hex: :configparser_ex, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:jsx, "~> 3.0", [hex: :jsx, repo: "hexpm", optional: true]}, {:sweet_xml, "~> 0.6", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "3e6c776703c9076001fbe1f7c049535f042cb2afa0d2cbd3b47cbc4e92ac0d10"}, "ex_aws": {:hex, :ex_aws, "2.1.9", "dc4865ecc20a05190a34a0ac5213e3e5e2b0a75a0c2835e923ae7bfeac5e3c31", [:mix], [{:configparser_ex, "~> 4.0", [hex: :configparser_ex, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:jsx, "~> 3.0", [hex: :jsx, repo: "hexpm", optional: true]}, {:sweet_xml, "~> 0.6", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "3e6c776703c9076001fbe1f7c049535f042cb2afa0d2cbd3b47cbc4e92ac0d10"},
@ -44,20 +46,21 @@
"ex_doc": {:hex, :ex_doc, "0.29.4", "6257ecbb20c7396b1fe5accd55b7b0d23f44b6aa18017b415cb4c2b91d997729", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "2c6699a737ae46cb61e4ed012af931b57b699643b24dabe2400a8168414bc4f5"}, "ex_doc": {:hex, :ex_doc, "0.29.4", "6257ecbb20c7396b1fe5accd55b7b0d23f44b6aa18017b415cb4c2b91d997729", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "2c6699a737ae46cb61e4ed012af931b57b699643b24dabe2400a8168414bc4f5"},
"ex_machina": {:hex, :ex_machina, "2.7.0", "b792cc3127fd0680fecdb6299235b4727a4944a09ff0fa904cc639272cd92dc7", [: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", "419aa7a39bde11894c87a615c4ecaa52d8f107bbdd81d810465186f783245bf8"}, "ex_machina": {:hex, :ex_machina, "2.7.0", "b792cc3127fd0680fecdb6299235b4727a4944a09ff0fa904cc639272cd92dc7", [: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", "419aa7a39bde11894c87a615c4ecaa52d8f107bbdd81d810465186f783245bf8"},
"ex_syslogger": {:hex, :ex_syslogger, "1.5.2", "72b6aa2d47a236e999171f2e1ec18698740f40af0bd02c8c650bf5f1fd1bac79", [:mix], [{:poison, ">= 1.5.0", [hex: :poison, repo: "hexpm", optional: true]}, {:syslog, "~> 1.1.0", [hex: :syslog, repo: "hexpm", optional: false]}], "hexpm", "ab9fab4136dbc62651ec6f16fa4842f10cf02ab4433fa3d0976c01be99398399"}, "ex_syslogger": {:hex, :ex_syslogger, "1.5.2", "72b6aa2d47a236e999171f2e1ec18698740f40af0bd02c8c650bf5f1fd1bac79", [:mix], [{:poison, ">= 1.5.0", [hex: :poison, repo: "hexpm", optional: true]}, {:syslog, "~> 1.1.0", [hex: :syslog, repo: "hexpm", optional: false]}], "hexpm", "ab9fab4136dbc62651ec6f16fa4842f10cf02ab4433fa3d0976c01be99398399"},
"exile": {:git, "https://git.pleroma.social/pleroma/elixir-libraries/exile.git", "0d6337cf68e7fbc8a093cae000955aa93b067f91", [ref: "0d6337cf68e7fbc8a093cae000955aa93b067f91"]},
"expo": {:hex, :expo, "0.4.1", "1c61d18a5df197dfda38861673d392e642649a9cef7694d2f97a587b2cfb319b", [:mix], [], "hexpm", "2ff7ba7a798c8c543c12550fa0e2cbc81b95d4974c65855d8d15ba7b37a1ce47"}, "expo": {:hex, :expo, "0.4.1", "1c61d18a5df197dfda38861673d392e642649a9cef7694d2f97a587b2cfb319b", [:mix], [], "hexpm", "2ff7ba7a798c8c543c12550fa0e2cbc81b95d4974c65855d8d15ba7b37a1ce47"},
"fast_html": {:hex, :fast_html, "2.0.5", "c61760340606c1077ff1f196f17834056cb1dd3d5cb92a9f2cabf28bc6221c3c", [: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", "605f4f4829443c14127694ebabb681778712ceecb4470ec32aa31012330e6506"}, "fast_html": {:hex, :fast_html, "2.0.5", "c61760340606c1077ff1f196f17834056cb1dd3d5cb92a9f2cabf28bc6221c3c", [: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", "605f4f4829443c14127694ebabb681778712ceecb4470ec32aa31012330e6506"},
"fast_sanitize": {:hex, :fast_sanitize, "0.2.3", "67b93dfb34e302bef49fec3aaab74951e0f0602fd9fa99085987af05bd91c7a5", [:mix], [{:fast_html, "~> 2.0", [hex: :fast_html, repo: "hexpm", optional: false]}, {:plug, "~> 1.8", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "e8ad286d10d0386e15d67d0ee125245ebcfbc7d7290b08712ba9013c8c5e56e2"}, "fast_sanitize": {:hex, :fast_sanitize, "0.2.3", "67b93dfb34e302bef49fec3aaab74951e0f0602fd9fa99085987af05bd91c7a5", [:mix], [{:fast_html, "~> 2.0", [hex: :fast_html, repo: "hexpm", optional: false]}, {:plug, "~> 1.8", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "e8ad286d10d0386e15d67d0ee125245ebcfbc7d7290b08712ba9013c8c5e56e2"},
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"}, "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
"finch": {:hex, :finch, "0.16.0", "40733f02c89f94a112518071c0a91fe86069560f5dbdb39f9150042f44dcfb1a", [: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", "f660174c4d519e5fec629016054d60edd822cdfe2b7270836739ac2f97735ec5"}, "finch": {:hex, :finch, "0.16.0", "40733f02c89f94a112518071c0a91fe86069560f5dbdb39f9150042f44dcfb1a", [: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", "f660174c4d519e5fec629016054d60edd822cdfe2b7270836739ac2f97735ec5"},
"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"}, "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.34.3", "5e2dcaec5d7c228ce5b1d3501502e308b2d79eb655e4191751a1fe491c37feac", [:mix], [], "hexpm", "9577440eea5b97924b4bf3c7ea55f7b8b6dce589f9b28b096cc294a8dc342341"}, "floki": {:hex, :floki, "0.35.2", "87f8c75ed8654b9635b311774308b2760b47e9a579dabf2e4d5f1e1d42c39e0b", [:mix], [], "hexpm", "6b05289a8e9eac475f644f09c2e4ba7e19201fd002b89c28c1293e7bd16773d9"},
"gen_smtp": {:hex, :gen_smtp, "0.15.0", "9f51960c17769b26833b50df0b96123605a8024738b62db747fece14eb2fbfcc", [:rebar3], [], "hexpm", "29bd14a88030980849c7ed2447b8db6d6c9278a28b11a44cafe41b791205440f"}, "gen_smtp": {:hex, :gen_smtp, "0.15.0", "9f51960c17769b26833b50df0b96123605a8024738b62db747fece14eb2fbfcc", [:rebar3], [], "hexpm", "29bd14a88030980849c7ed2447b8db6d6c9278a28b11a44cafe41b791205440f"},
"gettext": {:hex, :gettext, "0.22.2", "6bfca374de34ecc913a28ba391ca184d88d77810a3e427afa8454a71a51341ac", [:mix], [{:expo, "~> 0.4.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "8a2d389673aea82d7eae387e6a2ccc12660610080ae7beb19452cfdc1ec30f60"}, "gettext": {:hex, :gettext, "0.22.2", "6bfca374de34ecc913a28ba391ca184d88d77810a3e427afa8454a71a51341ac", [:mix], [{:expo, "~> 0.4.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "8a2d389673aea82d7eae387e6a2ccc12660610080ae7beb19452cfdc1ec30f60"},
"gun": {:hex, :gun, "2.0.1", "160a9a5394800fcba41bc7e6d421295cf9a7894c2252c0678244948e3336ad73", [:make, :rebar3], [{:cowlib, "2.12.1", [hex: :cowlib, repo: "hexpm", optional: false]}], "hexpm", "a10bc8d6096b9502205022334f719cc9a08d9adcfbfc0dbee9ef31b56274a20b"}, "gun": {:hex, :gun, "2.0.1", "160a9a5394800fcba41bc7e6d421295cf9a7894c2252c0678244948e3336ad73", [:make, :rebar3], [{:cowlib, "2.12.1", [hex: :cowlib, repo: "hexpm", optional: false]}], "hexpm", "a10bc8d6096b9502205022334f719cc9a08d9adcfbfc0dbee9ef31b56274a20b"},
"hackney": {:hex, :hackney, "1.18.1", "f48bf88f521f2a229fc7bae88cf4f85adc9cd9bcf23b5dc8eb6a1788c662c4f6", [:rebar3], [{:certifi, "~>2.9.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.3.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", "a4ecdaff44297e9b5894ae499e9a070ea1888c84afdd1fd9b7b2bc384950128e"}, "hackney": {:hex, :hackney, "1.18.1", "f48bf88f521f2a229fc7bae88cf4f85adc9cd9bcf23b5dc8eb6a1788c662c4f6", [:rebar3], [{:certifi, "~>2.9.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.3.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", "a4ecdaff44297e9b5894ae499e9a070ea1888c84afdd1fd9b7b2bc384950128e"},
"hpax": {:hex, :hpax, "0.1.2", "09a75600d9d8bbd064cdd741f21fc06fc1f4cf3d0fcc335e5aa19be1a7235c84", [:mix], [], "hexpm", "2c87843d5a23f5f16748ebe77969880e29809580efdaccd615cd3bed628a8c13"}, "hpax": {:hex, :hpax, "0.1.2", "09a75600d9d8bbd064cdd741f21fc06fc1f4cf3d0fcc335e5aa19be1a7235c84", [:mix], [], "hexpm", "2c87843d5a23f5f16748ebe77969880e29809580efdaccd615cd3bed628a8c13"},
"html_entities": {:hex, :html_entities, "0.5.2", "9e47e70598da7de2a9ff6af8758399251db6dbb7eebe2b013f2bbd2515895c3c", [:mix], [], "hexpm", "c53ba390403485615623b9531e97696f076ed415e8d8058b1dbaa28181f4fdcc"}, "html_entities": {:hex, :html_entities, "0.5.2", "9e47e70598da7de2a9ff6af8758399251db6dbb7eebe2b013f2bbd2515895c3c", [:mix], [], "hexpm", "c53ba390403485615623b9531e97696f076ed415e8d8058b1dbaa28181f4fdcc"},
"http_signatures": {:hex, :http_signatures, "0.1.1", "ca7ebc1b61542b163644c8c3b1f0e0f41037d35f2395940d3c6c7deceab41fd8", [:mix], [], "hexpm", "cc3b8a007322cc7b624c0c15eec49ee58ac977254ff529a3c482f681465942a3"}, "http_signatures": {:hex, :http_signatures, "0.1.2", "ed1cc7043abcf5bb4f30d68fb7bad9d618ec1a45c4ff6c023664e78b67d9c406", [:mix], [], "hexpm", "f08aa9ac121829dae109d608d83c84b940ef2f183ae50f2dd1e9a8bc619d8be7"},
"httpoison": {:hex, :httpoison, "1.8.2", "9eb9c63ae289296a544842ef816a85d881d4a31f518a0fec089aaa744beae290", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "2bb350d26972e30c96e2ca74a1aaf8293d61d0742ff17f01e0279fef11599921"}, "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"}, "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.4", "a05744ab7c221ca8e395c926c3919a821eb512e8f36547c062f62c4ca0cf3d6e", [:mix], [], "hexpm", "64a2d30189704ae41ca7dbdd587f5291db5d1dda1414e0774c29ffc81088c1bc"}, "inet_cidr": {:hex, :inet_cidr, "1.0.4", "a05744ab7c221ca8e395c926c3919a821eb512e8f36547c062f62c4ca0cf3d6e", [:mix], [], "hexpm", "64a2d30189704ae41ca7dbdd587f5291db5d1dda1414e0774c29ffc81088c1bc"},

View File

@ -182,8 +182,8 @@ defmodule Mix.Tasks.Pleroma.ConfigTest do
assert File.exists?(temp_file) assert File.exists?(temp_file)
{:ok, file} = File.read(temp_file) {:ok, file} = File.read(temp_file)
assert file == assert file =~ "import Config\n"
"import Config\n\nconfig :pleroma, :instance,\n name: \"Pleroma\",\n email: \"example@example.com\",\n notify_email: \"noreply@example.com\",\n description: \"A Pleroma instance, an alternative fediverse server\",\n limit: 5000,\n chat_limit: 5000,\n remote_limit: 100_000,\n upload_limit: 16_000_000,\n avatar_upload_limit: 2_000_000,\n background_upload_limit: 4_000_000,\n banner_upload_limit: 4_000_000,\n poll_limits: %{\n max_expiration: 31_536_000,\n max_option_chars: 200,\n max_options: 20,\n min_expiration: 0\n },\n registrations_open: true,\n federating: true,\n federation_incoming_replies_max_depth: 100,\n federation_reachability_timeout_days: 7,\n allow_relay: true,\n public: true,\n quarantined_instances: [],\n managed_config: true,\n static_dir: \"instance/static/\",\n allowed_post_formats: [\"text/plain\", \"text/html\", \"text/markdown\", \"text/bbcode\"],\n autofollowed_nicknames: [],\n max_pinned_statuses: 1,\n attachment_links: false,\n max_report_comment_size: 1000,\n safe_dm_mentions: false,\n healthcheck: false,\n remote_post_retention_days: 90,\n skip_thread_containment: true,\n limit_to_local_content: :unauthenticated,\n user_bio_length: 5000,\n user_name_length: 100,\n max_account_fields: 10,\n max_remote_account_fields: 20,\n account_field_name_length: 512,\n account_field_value_length: 2048,\n external_user_synchronization: true,\n extended_nickname_format: true,\n multi_factor_authentication: [\n totp: [digits: 6, period: 30],\n backup_codes: [number: 2, length: 6]\n ]\n" assert file =~ "A Pleroma instance, an alternative fediverse server"
end end
end end

View File

@ -145,6 +145,7 @@ defmodule Pleroma.ActivityTest do
setup do: clear_config([:instance, :limit_to_local_content]) setup do: clear_config([:instance, :limit_to_local_content])
@tag :skip_darwin
test "finds utf8 text in statuses", %{ test "finds utf8 text in statuses", %{
japanese_activity: japanese_activity, japanese_activity: japanese_activity,
user: user user: user

View File

@ -125,13 +125,12 @@ defmodule Pleroma.Config.DeprecationWarningsTest do
media_removal: ["some.removal", {"some.other.instance", "Some reason"}] media_removal: ["some.removal", {"some.other.instance", "Some reason"}]
) )
expected_config = [ expected_config =
{:media_removal, [{"some.removal", ""}, {"some.other.instance", "Some reason"}]} {:media_removal, [{"some.removal", ""}, {"some.other.instance", "Some reason"}]}
]
capture_log(fn -> DeprecationWarnings.warn() end) capture_log(fn -> DeprecationWarnings.warn() end)
assert Config.get([:mrf_simple]) == expected_config assert expected_config in Config.get([:mrf_simple])
end end
test "doesn't give a warning with correct config" do test "doesn't give a warning with correct config" do

View File

@ -9,14 +9,16 @@ defmodule Pleroma.HealthcheckTest do
test "system_info/0" do test "system_info/0" do
result = Healthcheck.system_info() |> Map.from_struct() result = Healthcheck.system_info() |> Map.from_struct()
assert Map.keys(result) == [ keys = Map.keys(result)
assert Keyword.equal?(keys, [
:active, :active,
:healthy, :healthy,
:idle, :idle,
:job_queue_stats, :job_queue_stats,
:memory_used, :memory_used,
:pool_size :pool_size
] ])
end end
describe "check_health/1" do describe "check_health/1" do

View File

@ -7,6 +7,8 @@ defmodule Pleroma.MFA.TOTPTest do
alias Pleroma.MFA.TOTP alias Pleroma.MFA.TOTP
import Pleroma.Tests.Helpers, only: [uri_equal?: 2]
test "create provisioning_uri to generate qrcode" do test "create provisioning_uri to generate qrcode" do
uri = uri =
TOTP.provisioning_uri("test-secrcet", "test@example.com", TOTP.provisioning_uri("test-secrcet", "test@example.com",
@ -15,7 +17,9 @@ defmodule Pleroma.MFA.TOTPTest do
period: 60 period: 60
) )
assert uri == assert uri_equal?(
uri,
"otpauth://totp/test@example.com?digits=8&issuer=Plerome-42&period=60&secret=test-secrcet" "otpauth://totp/test@example.com?digits=8&issuer=Plerome-42&period=60&secret=test-secrcet"
)
end end
end end

View File

@ -101,8 +101,7 @@ defmodule Pleroma.Object.FetcherTest do
test "it returns thread depth exceeded error if thread depth is exceeded" do test "it returns thread depth exceeded error if thread depth is exceeded" do
clear_config([:instance, :federation_incoming_replies_max_depth], 0) clear_config([:instance, :federation_incoming_replies_max_depth], 0)
assert {:error, "Max thread distance exceeded."} = assert {:error, :allowed_depth} = Fetcher.fetch_object_from_id(@ap_id, depth: 1)
Fetcher.fetch_object_from_id(@ap_id, depth: 1)
end end
test "it fetches object if max thread depth is restricted to 0 and depth is not specified" do test "it fetches object if max thread depth is restricted to 0 and depth is not specified" do
@ -220,14 +219,14 @@ defmodule Pleroma.Object.FetcherTest do
end end
test "handle HTTP 410 Gone response" do test "handle HTTP 410 Gone response" do
assert {:error, "Object has been deleted"} == assert {:error, :not_found} ==
Fetcher.fetch_and_contain_remote_object_from_id( Fetcher.fetch_and_contain_remote_object_from_id(
"https://mastodon.example.org/users/userisgone" "https://mastodon.example.org/users/userisgone"
) )
end end
test "handle HTTP 404 response" do test "handle HTTP 404 response" do
assert {:error, "Object has been deleted"} == assert {:error, :not_found} ==
Fetcher.fetch_and_contain_remote_object_from_id( Fetcher.fetch_and_contain_remote_object_from_id(
"https://mastodon.example.org/users/userisgone404" "https://mastodon.example.org/users/userisgone404"
) )

View File

@ -29,13 +29,13 @@ defmodule Pleroma.Repo.Migrations.AutolinkerToLinkifyTest do
%{value: new_opts} = ConfigDB.get_by_params(%{group: :pleroma, key: Pleroma.Formatter}) %{value: new_opts} = ConfigDB.get_by_params(%{group: :pleroma, key: Pleroma.Formatter})
assert new_opts == [ assert Keyword.equal?(new_opts,
class: false, class: false,
extra: true, extra: true,
new_window: false, new_window: false,
rel: "testing", rel: "testing",
strip_prefix: false strip_prefix: false
] )
clear_config(Pleroma.Formatter, new_opts) clear_config(Pleroma.Formatter, new_opts)
assert new_opts == Pleroma.Config.get(Pleroma.Formatter) assert new_opts == Pleroma.Config.get(Pleroma.Formatter)
@ -67,6 +67,6 @@ defmodule Pleroma.Repo.Migrations.AutolinkerToLinkifyTest do
strip_prefix: false strip_prefix: false
] ]
assert migration.transform_opts(old_opts) == expected_opts assert Keyword.equal?(migration.transform_opts(old_opts), expected_opts)
end end
end end

View File

@ -26,13 +26,13 @@ defmodule Pleroma.Repo.Migrations.FixMalformedFormatterConfigTest do
%{value: new_opts} = ConfigDB.get_by_params(%{group: :pleroma, key: Pleroma.Formatter}) %{value: new_opts} = ConfigDB.get_by_params(%{group: :pleroma, key: Pleroma.Formatter})
assert new_opts == [ assert Keyword.equal?(new_opts,
class: false, class: false,
extra: true, extra: true,
new_window: false, new_window: false,
rel: "F", rel: "F",
strip_prefix: false strip_prefix: false
] )
clear_config(Pleroma.Formatter, new_opts) clear_config(Pleroma.Formatter, new_opts)
assert new_opts == Pleroma.Config.get(Pleroma.Formatter) assert new_opts == Pleroma.Config.get(Pleroma.Formatter)

View File

@ -60,6 +60,33 @@ defmodule Pleroma.Web.ActivityPub.MRF.StealEmojiPolicyTest do
|> File.exists?() |> File.exists?()
end end
test "works with unknown extension", %{path: path} do
message = %{
"type" => "Create",
"object" => %{
"emoji" => [{"firedfox", "https://example.org/emoji/firedfox"}],
"actor" => "https://example.org/users/admin"
}
}
fullpath = Path.join(path, "firedfox.png")
Tesla.Mock.mock(fn %{method: :get, url: "https://example.org/emoji/firedfox"} ->
%Tesla.Env{status: 200, body: File.read!("test/fixtures/image.jpg")}
end)
clear_config(:mrf_steal_emoji, hosts: ["example.org"], size_limit: 284_468)
refute "firedfox" in installed()
refute File.exists?(path)
assert {:ok, _message} = StealEmojiPolicy.filter(message)
assert "firedfox" in installed()
assert File.exists?(path)
assert File.exists?(fullpath)
end
test "reject regex shortcode", %{message: message} do test "reject regex shortcode", %{message: message} do
refute "firedfox" in installed() refute "firedfox" in installed()

View File

@ -1,10 +1,13 @@
# Pleroma: A lightweight social networking server # Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/> # Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.ActivityPub.MRFTest do defmodule Pleroma.Web.ActivityPub.MRFTest do
use ExUnit.Case use ExUnit.Case
use Pleroma.Tests.Helpers use Pleroma.Tests.Helpers
import ExUnit.CaptureLog
alias Pleroma.Web.ActivityPub.MRF alias Pleroma.Web.ActivityPub.MRF
test "subdomains_regex/1" do test "subdomains_regex/1" do
@ -61,6 +64,14 @@ defmodule Pleroma.Web.ActivityPub.MRFTest do
refute MRF.subdomain_match?(regexes, "EXAMPLE.COM") refute MRF.subdomain_match?(regexes, "EXAMPLE.COM")
refute MRF.subdomain_match?(regexes, "example.com") refute MRF.subdomain_match?(regexes, "example.com")
end end
@tag capture_log: true
test "logs sensible error on accidental wildcard" do
assert_raise Regex.CompileError, fn ->
assert capture_log(MRF.subdomains_regex(["*unsafe.tld"])) =~
"MRF: Invalid subdomain Regex: *unsafe.tld"
end
end
end end
describe "instance_list_from_tuples/1" do describe "instance_list_from_tuples/1" do

View File

@ -221,6 +221,19 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.NoteHandlingTest do
"<p><span class=\"h-card\"><a href=\"http://localtesting.pleroma.lol/users/lain\" class=\"u-url mention\">@<span>lain</span></a></span></p>" "<p><span class=\"h-card\"><a href=\"http://localtesting.pleroma.lol/users/lain\" class=\"u-url mention\">@<span>lain</span></a></span></p>"
end end
test "it works for incoming notices with a nil contentMap (firefish)" do
data =
File.read!("test/fixtures/mastodon-post-activity-contentmap.json")
|> Jason.decode!()
|> Map.put("contentMap", nil)
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
object = Object.normalize(data["object"], fetch: false)
assert object.data["content"] ==
"<p><span class=\"h-card\"><a href=\"http://localtesting.pleroma.lol/users/lain\" class=\"u-url mention\">@<span>lain</span></a></span></p>"
end
test "it works for incoming notices with to/cc not being an array (kroeg)" do test "it works for incoming notices with to/cc not being an array (kroeg)" do
data = File.read!("test/fixtures/kroeg-post-activity.json") |> Jason.decode!() data = File.read!("test/fixtures/kroeg-post-activity.json") |> Jason.decode!()

View File

@ -132,7 +132,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert {:ok, activity} = Transmogrifier.handle_incoming(message) assert {:ok, activity} = Transmogrifier.handle_incoming(message)
object = Object.normalize(activity) object = Object.normalize(activity)
assert [%{"type" => "Mention"}, %{"type" => "Link"}] = object.data["tag"] assert [%{"type" => "Mention"}, %{"type" => "Link"}] = object.data["tag"]
end) =~ "Error while fetching" end) =~ "Object rejected while fetching"
end end
test "it accepts quote posts" do test "it accepts quote posts" do
@ -410,7 +410,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert capture_log(fn -> assert capture_log(fn ->
{:error, _} = Transmogrifier.handle_incoming(data) {:error, _} = Transmogrifier.handle_incoming(data)
end) =~ "Object containment failed" end) =~ "Object rejected while fetching"
end end
test "it rejects activities which reference objects that have an incorrect attribution (variant 1)" do test "it rejects activities which reference objects that have an incorrect attribution (variant 1)" do
@ -425,7 +425,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert capture_log(fn -> assert capture_log(fn ->
{:error, _} = Transmogrifier.handle_incoming(data) {:error, _} = Transmogrifier.handle_incoming(data)
end) =~ "Object containment failed" end) =~ "Object rejected while fetching"
end end
test "it rejects activities which reference objects that have an incorrect attribution (variant 2)" do test "it rejects activities which reference objects that have an incorrect attribution (variant 2)" do
@ -440,7 +440,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert capture_log(fn -> assert capture_log(fn ->
{:error, _} = Transmogrifier.handle_incoming(data) {:error, _} = Transmogrifier.handle_incoming(data)
end) =~ "Object containment failed" end) =~ "Object rejected while fetching"
end end
end end

View File

@ -42,6 +42,7 @@ defmodule Pleroma.Web.MastodonAPI.SearchControllerTest do
end end
end end
@tag :skip_darwin
test "search", %{conn: conn} do test "search", %{conn: conn} do
user = insert(:user) user = insert(:user)
user_two = insert(:user, %{nickname: "shp@shitposter.club"}) user_two = insert(:user, %{nickname: "shp@shitposter.club"})

View File

@ -12,6 +12,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
alias Pleroma.Object alias Pleroma.Object
alias Pleroma.Repo alias Pleroma.Repo
alias Pleroma.ScheduledActivity alias Pleroma.ScheduledActivity
alias Pleroma.Tests.Helpers
alias Pleroma.Tests.ObanHelpers alias Pleroma.Tests.ObanHelpers
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.ActivityPub
@ -2191,7 +2192,10 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
# Using the header for pagination works correctly # Using the header for pagination works correctly
[next, _] = get_resp_header(result, "link") |> hd() |> String.split(", ") [next, _] = get_resp_header(result, "link") |> hd() |> String.split(", ")
[_, max_id] = Regex.run(~r/max_id=([^&]+)/, next) [next_url, _next_rel] = String.split(next, ";")
next_url = String.trim_trailing(next_url, ">") |> String.trim_leading("<")
max_id = Helpers.get_query_parameter(next_url, "max_id")
assert max_id == third_favorite.id assert max_id == third_favorite.id

View File

@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only # SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do
use Pleroma.Web.ConnCase, async: true use Pleroma.Web.ConnCase, async: false
import Pleroma.Factory import Pleroma.Factory
@ -35,17 +35,20 @@ defmodule Pleroma.Web.MastodonAPI.SubscriptionControllerTest do
defmacro assert_error_when_disable_push(do: yield) do defmacro assert_error_when_disable_push(do: yield) do
quote do quote do
vapid_details = Application.get_env(:web_push_encryption, :vapid_details, [])
Application.put_env(:web_push_encryption, :vapid_details, [])
assert %{"error" => "Web push subscription is disabled on this Pleroma instance"} == assert %{"error" => "Web push subscription is disabled on this Pleroma instance"} ==
unquote(yield) unquote(yield)
Application.put_env(:web_push_encryption, :vapid_details, vapid_details)
end end
end end
describe "when disabled" do describe "when disabled" do
setup do
vapid_config = Application.get_env(:web_push_encryption, :vapid_details)
Application.put_env(:web_push_encryption, :vapid_details, [])
on_exit(fn -> Application.put_env(:web_push_encryption, :vapid_details, vapid_config) end)
end
test "POST returns error", %{conn: conn} do test "POST returns error", %{conn: conn} do
assert_error_when_disable_push do assert_error_when_disable_push do
conn conn

View File

@ -7,6 +7,7 @@ defmodule Pleroma.Web.PleromaAPI.ChatControllerTest do
alias Pleroma.Chat alias Pleroma.Chat
alias Pleroma.Chat.MessageReference alias Pleroma.Chat.MessageReference
alias Pleroma.Object alias Pleroma.Object
alias Pleroma.Tests.Helpers
alias Pleroma.UnstubbedConfigMock, as: ConfigMock alias Pleroma.UnstubbedConfigMock, as: ConfigMock
alias Pleroma.User alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.ActivityPub
@ -212,36 +213,63 @@ defmodule Pleroma.Web.PleromaAPI.ChatControllerTest do
result = json_response_and_validate_schema(response, 200) result = json_response_and_validate_schema(response, 200)
[next, prev] = get_resp_header(response, "link") |> hd() |> String.split(", ") [next, prev] = get_resp_header(response, "link") |> hd() |> String.split(", ")
api_endpoint = "/api/v1/pleroma/chats/" api_endpoint = Pleroma.Web.Endpoint.url() <> "/api/v1/pleroma/chats/"
[next_url, next_rel] = String.split(next, ";")
next_url = String.trim_trailing(next_url, ">") |> String.trim_leading("<")
next_url_sorted = Helpers.uri_query_sort(next_url)
assert String.match?( assert String.match?(
next, next_url_sorted,
~r(#{api_endpoint}.*/messages\?limit=\d+&max_id=.*; rel=\"next\"$) ~r(#{api_endpoint}.*/messages\?limit=\d+&max_id=.*&offset=\d+$)
) )
assert next_rel =~ "next"
[prev_url, prev_rel] = String.split(prev, ";")
prev_url = String.trim_trailing(prev_url, ">") |> String.trim_leading("<")
prev_url_sorted = Helpers.uri_query_sort(prev_url)
assert String.match?( assert String.match?(
prev, prev_url_sorted,
~r(#{api_endpoint}.*/messages\?limit=\d+&min_id=.*; rel=\"prev\"$) ~r(#{api_endpoint}.*/messages\?limit=\d+&min_id=.*&offset=\d+$)
) )
assert prev_rel =~ "prev"
assert length(result) == 20 assert length(result) == 20
response = response = get(conn, "#{api_endpoint}#{chat.id}/messages?max_id=#{List.last(result)["id"]}")
get(conn, "/api/v1/pleroma/chats/#{chat.id}/messages?max_id=#{List.last(result)["id"]}")
result = json_response_and_validate_schema(response, 200) result = json_response_and_validate_schema(response, 200)
[next, prev] = get_resp_header(response, "link") |> hd() |> String.split(", ") [next, prev] = get_resp_header(response, "link") |> hd() |> String.split(", ")
assert String.match?( [next_url, next_rel] = String.split(next, ";")
next, next_url = String.trim_trailing(next_url, ">") |> String.trim_leading("<")
~r(#{api_endpoint}.*/messages\?limit=\d+&max_id=.*; rel=\"next\"$)
) next_url_sorted = Helpers.uri_query_sort(next_url)
assert String.match?( assert String.match?(
prev, next_url_sorted,
~r(#{api_endpoint}.*/messages\?limit=\d+&max_id=.*&min_id=.*; rel=\"prev\"$) ~r(#{api_endpoint}.*/messages\?limit=\d+&max_id=.*&offset=\d+$)
) )
assert next_rel =~ "next"
[prev_url, prev_rel] = String.split(prev, ";")
prev_url = String.trim_trailing(prev_url, ">") |> String.trim_leading("<")
prev_url_sorted = Helpers.uri_query_sort(prev_url)
assert String.match?(
prev_url_sorted,
~r(#{api_endpoint}.*/messages\?limit=\d+&max_id=.*&min_id=.*&offset=\d+$)
)
assert prev_rel =~ "prev"
assert length(result) == 10 assert length(result) == 10
end end

Some files were not shown because too many files have changed in this diff Show More