summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md9
-rw-r--r--config/config.exs18
-rw-r--r--config/description.exs26
-rw-r--r--docs/API/admin_api.md7
-rw-r--r--docs/API/differences_in_mastoapi_responses.md2
-rw-r--r--docs/API/pleroma_api.md4
-rw-r--r--docs/admin/config.md79
-rw-r--r--docs/administration/CLI_tasks/config.md18
-rw-r--r--docs/configuration/cheatsheet.md40
-rw-r--r--lib/pleroma/application.ex1
-rw-r--r--lib/pleroma/config/loader.ex6
-rw-r--r--lib/pleroma/config/transfer_task.ex95
-rw-r--r--lib/pleroma/formatter.ex3
-rw-r--r--lib/pleroma/object.ex13
-rw-r--r--lib/pleroma/plugs/http_security_plug.ex47
-rw-r--r--lib/pleroma/plugs/rate_limiter/rate_limiter.ex37
-rw-r--r--lib/pleroma/plugs/remote_ip.ex3
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub.ex6
-rw-r--r--lib/pleroma/web/admin_api/admin_api_controller.ex128
-rw-r--r--lib/pleroma/web/admin_api/views/config_view.ex10
-rw-r--r--lib/pleroma/web/common_api/common_api.ex3
-rw-r--r--lib/pleroma/web/mastodon_api/views/status_view.ex6
-rw-r--r--lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex12
-rw-r--r--lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex9
-rw-r--r--lib/pleroma/web/router.ex2
-rw-r--r--mix.exs10
-rw-r--r--restarter/lib/pleroma.ex28
-rw-r--r--restarter/lib/restarter.ex8
-rw-r--r--restarter/mix.exs21
-rw-r--r--test/config/transfer_task_test.exs73
-rw-r--r--test/fixtures/emoji-reaction-no-emoji.json30
-rw-r--r--test/fixtures/emoji-reaction-too-long.json30
-rw-r--r--test/object_test.exs42
-rw-r--r--test/plugs/rate_limiter_test.exs35
-rw-r--r--test/web/activity_pub/transmogrifier_test.exs19
-rw-r--r--test/web/admin_api/admin_api_controller_test.exs80
-rw-r--r--test/web/common_api/common_api_test.exs19
-rw-r--r--test/web/mastodon_api/controllers/account_controller_test.exs1
-rw-r--r--test/web/mastodon_api/views/status_view_test.exs11
-rw-r--r--test/web/pleroma_api/controllers/emoji_api_controller_test.exs1
-rw-r--r--test/web/pleroma_api/controllers/pleroma_api_controller_test.exs25
41 files changed, 729 insertions, 288 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 917e5d4ef..b470b74ed 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,11 +9,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- **Breaking**: OStatus protocol support
- **Breaking**: MDII uploader
- **Breaking**: Using third party engines for user recommendation
+<details>
+ <summary>API Changes</summary>
+- **Breaking**: AdminAPI: migrate_from_db endpoint
+</details>
### Changed
- **Breaking:** Pleroma won't start if it detects unapplied migrations
-- **Breaking:** attachments are removed along with statuses. Does not affect duplicate files and attachments without status.
- **Breaking:** Elixir >=1.8 is now required (was >= 1.7)
+- **Breaking:** `Pleroma.Plugs.RemoteIp` and `:rate_limiter` enabled by default. Please ensure your reverse proxy forwards the real IP!
- **Breaking:** attachment links (`config :pleroma, :instance, no_attachment_links` and `config :pleroma, Pleroma.Upload, link_name`) disabled by default
- **Breaking:** OAuth: defaulted `[:auth, :enforce_oauth_admin_scope_usage]` setting to `true` which demands `admin` OAuth scope to perform admin actions (in addition to `is_admin` flag on User); make sure to use bundled or newer versions of AdminFE & PleromaFE to access admin / moderator features.
- **Breaking:** Dynamic configuration has been rearchitected. The `:pleroma, :instance, dynamic_configuration` setting has been replaced with `config :pleroma, configurable_from_database`. Please backup your configuration to a file and run the migration task to ensure consistency with the new schema.
@@ -27,6 +31,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Deprecated `User.Info` embedded schema (fields moved to `User`)
- Store status data inside Flag activity
- Deprecated (reorganized as `UserRelationship` entity) User fields with user AP IDs (`blocks`, `mutes`, `muted_reblogs`, `muted_notifications`, `subscribers`).
+- Rate limiter is now disabled for localhost/socket (unless remoteip plug is enabled)
- Logger: default log level changed from `warn` to `info`.
- Config mix task `migrate_to_db` truncates `config` table before migrating the config file.
<details>
@@ -53,6 +58,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Added
- `:chat_limit` option to limit chat characters.
+- `cleanup_attachments` option to remove attachments along with statuses. Does not affect duplicate files and attachments without status. Enabling this will increase load to database when deleting statuses on larger instances.
- Refreshing poll results for remote polls
- Authentication: Added rate limit for password-authorized actions / login existence checks
- Static Frontend: Add the ability to render user profiles and notices server-side without requiring JS app.
@@ -105,6 +111,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Mastodon API: Change emoji reaction reply format once more
- Configuration: `feed.logo` option for tag feed.
- Tag feed: `/tags/:tag.rss` - list public statuses by hashtag.
+- Mastodon API: Add `reacted` property to `emoji_reactions`
</details>
### Fixed
diff --git a/config/config.exs b/config/config.exs
index f4e307e18..34716cf37 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -271,7 +271,8 @@ config :pleroma, :instance,
account_field_name_length: 512,
account_field_value_length: 2048,
external_user_synchronization: true,
- extended_nickname_format: true
+ extended_nickname_format: true,
+ cleanup_attachments: false
config :pleroma, :feed,
post_title: %{
@@ -508,7 +509,6 @@ config :pleroma, :fetch_initial_posts,
config :auto_linker,
opts: [
- scheme: true,
extra: true,
# TODO: Set to :no_scheme when it works properly
validate_tld: true,
@@ -596,11 +596,21 @@ config :pleroma, :env, Mix.env()
config :http_signatures,
adapter: Pleroma.Signature
-config :pleroma, :rate_limit, authentication: {60_000, 15}
+config :pleroma, :rate_limit,
+ authentication: {60_000, 15},
+ search: [{1000, 10}, {1000, 30}],
+ app_account_creation: {1_800_000, 25},
+ relations_actions: {10_000, 10},
+ relation_id_action: {60_000, 2},
+ statuses_actions: {10_000, 15},
+ status_id_action: {60_000, 3},
+ password_reset: {1_800_000, 5},
+ account_confirmation_resend: {8_640_000, 5},
+ ap_routes: {60_000, 15}
config :pleroma, Pleroma.ActivityExpiration, enabled: true
-config :pleroma, Pleroma.Plugs.RemoteIp, enabled: false
+config :pleroma, Pleroma.Plugs.RemoteIp, enabled: true
config :pleroma, :static_fe, enabled: false
diff --git a/config/description.exs b/config/description.exs
index 5f3c58b08..6b912a07e 100644
--- a/config/description.exs
+++ b/config/description.exs
@@ -765,6 +765,15 @@ config :pleroma, :config_description, [
" This will break federation with older software for theses nicknames."
},
%{
+ key: :cleanup_attachments,
+ type: :boolean,
+ description: """
+ "Set to `true` to remove associated attachments when status is removed.
+ This will not affect duplicates and attachments without status.
+ Enabling this will increase load to database when deleting statuses on larger instances.
+ """
+ },
+ %{
key: :max_pinned_statuses,
type: :integer,
description: "The maximum number of pinned statuses. 0 will disable the feature.",
@@ -862,7 +871,7 @@ config :pleroma, :config_description, [
},
%{
key: :limit_to_local_content,
- type: [:atom, false],
+ type: {:dropdown, :atom},
description:
"Limit unauthenticated users to search for local statutes and users only. Default: `:unauthenticated`.",
suggestions: [
@@ -933,7 +942,7 @@ config :pleroma, :config_description, [
children: [
%{
key: :level,
- type: :atom,
+ type: {:dropdown, :atom},
description: "Log level",
suggestions: [:debug, :info, :warn, :error]
},
@@ -965,7 +974,7 @@ config :pleroma, :config_description, [
children: [
%{
key: :level,
- type: :atom,
+ type: {:dropdown, :atom},
description: "Log level",
suggestions: [:debug, :info, :warn, :error]
},
@@ -989,7 +998,7 @@ config :pleroma, :config_description, [
children: [
%{
key: :level,
- type: :atom,
+ type: {:dropdown, :atom},
description: "Log level",
suggestions: [:debug, :info, :warn, :error]
},
@@ -1960,7 +1969,7 @@ config :pleroma, :config_description, [
},
%{
key: :verbose,
- type: [:atom, false],
+ type: {:dropdown, :atom},
description: "Logs verbose mode",
suggestions: [false, :error, :warn, :info, :debug]
},
@@ -2169,12 +2178,7 @@ config :pleroma, :config_description, [
%{
key: :new_window,
type: :boolean,
- description: "Set to `false` to remove target='_blank' attribute"
- },
- %{
- key: :scheme,
- type: :boolean,
- description: "Set to `true` to link urls with schema http://google.com"
+ description: "Link urls will open in new window/tab"
},
%{
key: :truncate,
diff --git a/docs/API/admin_api.md b/docs/API/admin_api.md
index 07aa7ec3f..fb6dfcb08 100644
--- a/docs/API/admin_api.md
+++ b/docs/API/admin_api.md
@@ -665,11 +665,9 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret
- 404 Not Found `"Not found"`
- On success: 200 OK `{}`
-## `GET /api/pleroma/admin/config/migrate_from_db`
+## `GET /api/pleroma/admin/restart`
-### Run mix task pleroma.config migrate_from_db
-
-Copies all settings from database to `config/{env}.exported_from_db.secret.exs` with deletion from the table. Where `{env}` is the environment in which `pleroma` is running.
+### Restarts pleroma application
- Params: none
- Response:
@@ -691,7 +689,6 @@ Copies all settings from database to `config/{env}.exported_from_db.secret.exs`
- Response:
- On failure:
- 400 Bad Request `"To use this endpoint you need to enable configuration from database."`
- - 400 Bad Request `"To use configuration from database migrate your settings to database."`
```json
{
diff --git a/docs/API/differences_in_mastoapi_responses.md b/docs/API/differences_in_mastoapi_responses.md
index 030660b34..82d967e4d 100644
--- a/docs/API/differences_in_mastoapi_responses.md
+++ b/docs/API/differences_in_mastoapi_responses.md
@@ -29,7 +29,7 @@ Has these additional fields under the `pleroma` object:
- `spoiler_text`: a map consisting of alternate representations of the `spoiler_text` property with the key being it's mimetype. Currently the only alternate representation supported is `text/plain`
- `expires_at`: a datetime (iso8601) that states when the post will expire (be deleted automatically), or empty if the post won't expire
- `thread_muted`: true if the thread the post belongs to is muted
-- `emoji_reactions`: A list with emoji / reaction maps. The format is {emoji: "☕", count: 1}. Contains no information about the reacting users, for that use the `emoji_reactions_by` endpoint.
+- `emoji_reactions`: A list with emoji / reaction maps. The format is `{emoji: "☕", count: 1, reacted: true}`. Contains no information about the reacting users, for that use the `emoji_reactions_by` endpoint.
## Attachments
diff --git a/docs/API/pleroma_api.md b/docs/API/pleroma_api.md
index 9f5cafe5a..c7125c1cd 100644
--- a/docs/API/pleroma_api.md
+++ b/docs/API/pleroma_api.md
@@ -455,7 +455,7 @@ Emoji reactions work a lot like favourites do. They make it possible to react to
* Example Response:
```json
[
- {"emoji": "😀", "count": 2, "accounts": [{"id" => "xyz.."...}, {"id" => "zyx..."}]},
- {"emoji": "☕", "count": 1, "accounts": [{"id" => "abc..."}]}
+ {"emoji": "😀", "count": 2, "reacted": true, "accounts": [{"id" => "xyz.."...}, {"id" => "zyx..."}]},
+ {"emoji": "☕", "count": 1, "reacted": false, "accounts": [{"id" => "abc..."}]}
]
```
diff --git a/docs/admin/config.md b/docs/admin/config.md
deleted file mode 100644
index 35e43b6a9..000000000
--- a/docs/admin/config.md
+++ /dev/null
@@ -1,79 +0,0 @@
-# Configuring instance
-You can configure your instance from admin interface. You need account with admin rights and little change in config file, which will allow settings configuration from database.
-
-```elixir
-config :pleroma, configurable_from_database: true
-```
-
-## How it works
-Settings are stored in database and are applied in `runtime` after each change. Most of the settings take effect immediately, except some, which need instance reboot. These settings are needed in `compile time`, that's why settings are duplicated to the file.
-
-File with duplicated settings is located in `config/{env}.exported_from_db.exs` if pleroma is runned from source. For prod env it will be `config/prod.exported_from_db.exs`.
-
-For releases: `/etc/pleroma/prod.exported_from_db.secret.exs` or `PLEROMA_CONFIG_PATH/prod.exported_from_db.exs`.
-
-## How to set it up
-You need to migrate your existing settings to the database. This task will migrate only added by user settings.
-For example you add settings to `prod.secret.exs` file, only these settings will be migrated to database. For release it will be `/etc/pleroma/config.exs` or `PLEROMA_CONFIG_PATH`.
-You can do this with mix task (all config files will remain untouched):
-
-```sh tab="OTP"
- ./bin/pleroma_ctl config migrate_to_db
-```
-
-```sh tab="From Source"
-mix pleroma.config migrate_to_db
-```
-
-Now you can change settings in admin interface. After each save, settings from database are duplicated to the `config/{env}.exported_from_db.exs` file.
-
-<span style="color:red">**ATTENTION**</span>
-
-**<span style="color:red">Be careful while changing the settings. Every inaccurate configuration change can break the federation or the instance load.</span>**
-
-*Compile time settings, which require instance reboot and can break instance loading:*
-- all settings inside these keys:
- - `:hackney_pools`
- - `:chat`
-- partially settings inside these keys:
- - `:seconds_valid` in `Pleroma.Captcha`
- - `:proxy_remote` in `Pleroma.Upload`
- - `:upload_limit` in `:instance`
-
-## How to dump settings from database to file
-
-*Adding `-d` flag will delete migrated settings from database table.*
-
-```sh tab="OTP"
- ./bin/pleroma_ctl config migrate_from_db [-d]
-```
-
-```sh tab="From Source"
-mix pleroma.config migrate_from_db [-d]
-```
-
-
-## How to completely remove it
-
-1. Truncate or delete all values from `config` table
-```sql
-TRUNCATE TABLE config;
-```
-2. Delete `config/{env}.exported_from_db.exs`.
-
-For `prod` env:
-```bash
-cd /opt/pleroma
-cp config/prod.exported_from_db.exs config/exported_from_db.back
-rm -rf config/prod.exported_from_db.exs
-```
-*If you don't want to backup settings, you can skip step with `cp` command.*
-
-3. Set configurable_from_database to `false`.
-```elixir
-config :pleroma, configurable_from_database: false
-```
-4. Restart pleroma instance
-```bash
-sudo service pleroma restart
-```
diff --git a/docs/administration/CLI_tasks/config.md b/docs/administration/CLI_tasks/config.md
index 2af51c247..873775962 100644
--- a/docs/administration/CLI_tasks/config.md
+++ b/docs/administration/CLI_tasks/config.md
@@ -1,12 +1,16 @@
# Transfering the config to/from the database
-!!! danger
- This is a Work In Progress, not usable just yet.
-
{! backend/administration/CLI_tasks/general_cli_task_info.include !}
## Transfer config from file to DB.
+!!! note
+ You need to add the following to your config before executing this command:
+
+ ```elixir
+ config :pleroma, configurable_from_database: true
+ ```
+
```sh tab="OTP"
./bin/pleroma_ctl config migrate_to_db
```
@@ -18,7 +22,15 @@ mix pleroma.config migrate_to_db
## Transfer config from DB to `config/env.exported_from_db.secret.exs`
+!!! note
+ In-Database configuration will still be applied after executing this command unless you set the following in your config:
+
+ ```elixir
+ config :pleroma, configurable_from_database: false
+ ```
+
To delete transfered settings from database optional flag `-d` can be used. <env> is `prod` by default.
+
```sh tab="OTP"
./bin/pleroma_ctl config migrate_from_db [--env=<env>] [-d]
```
diff --git a/docs/configuration/cheatsheet.md b/docs/configuration/cheatsheet.md
index 30d673eba..f30aedc01 100644
--- a/docs/configuration/cheatsheet.md
+++ b/docs/configuration/cheatsheet.md
@@ -69,6 +69,7 @@ You shouldn't edit the base config directly to avoid breakages and merge conflic
* `account_field_name_length`: An account field name maximum length (default: `512`).
* `account_field_value_length`: An account field value maximum length (default: `2048`).
* `external_user_synchronization`: Enabling following/followers counters synchronization for external users.
+* `cleanup_attachments`: Remove attachments along with statuses. Does not affect duplicate files and attachments without status. Enabling this will increase load to database when deleting statuses on larger instances.
## Federation
### MRF policies
@@ -308,16 +309,15 @@ This will make Pleroma listen on `127.0.0.1` port `8080` and generate urls start
Available options:
* `enabled` - Enable/disable the plug. Defaults to `false`.
-* `headers` - A list of strings naming the `req_headers` to use when deriving the `remote_ip`. Order does not matter. Defaults to `~w[forwarded x-forwarded-for x-client-ip x-real-ip]`.
+* `headers` - A list of strings naming the `req_headers` to use when deriving the `remote_ip`. Order does not matter. Defaults to `["x-forwarded-for"]`.
* `proxies` - A list of strings in [CIDR](https://en.wikipedia.org/wiki/CIDR) notation specifying the IPs of known proxies. Defaults to `[]`.
* `reserved` - Defaults to [localhost](https://en.wikipedia.org/wiki/Localhost) and [private network](https://en.wikipedia.org/wiki/Private_network).
### :rate_limit
-This is an advanced feature and disabled by default.
-
-If your instance is behind a reverse proxy you must enable and configure [`Pleroma.Plugs.RemoteIp`](#pleroma-plugs-remoteip).
+!!! note
+ If your instance is behind a reverse proxy ensure [`Pleroma.Plugs.RemoteIp`](#pleroma-plugs-remoteip) is enabled (it is enabled by default).
A keyword list of rate limiters where a key is a limiter name and value is the limiter configuration. The basic configuration is a tuple where:
@@ -326,14 +326,31 @@ A keyword list of rate limiters where a key is a limiter name and value is the l
It is also possible to have different limits for unauthenticated and authenticated users: the keyword value must be a list of two tuples where the first one is a config for unauthenticated users and the second one is for authenticated.
+For example:
+
+```elixir
+config :pleroma, :rate_limit,
+ authentication: {60_000, 15},
+ search: [{1000, 10}, {1000, 30}]
+```
+
+Means that:
+
+1. In 60 seconds, 15 authentication attempts can be performed from the same IP address.
+2. In 1 second, 10 search requests can be performed from the same IP adress by unauthenticated users, while authenticated users can perform 30 search requests per second.
+
Supported rate limiters:
-* `:search` for the search requests (account & status search etc.)
-* `:app_account_creation` for registering user accounts from the same IP address
-* `:relations_actions` for actions on relations with all users (follow, unfollow)
-* `:relation_id_action` for actions on relation with a specific user (follow, unfollow)
-* `:statuses_actions` for create / delete / fav / unfav / reblog / unreblog actions on any statuses
-* `:status_id_action` for fav / unfav or reblog / unreblog actions on the same status by the same user
+* `:search` - Account/Status search.
+* `:app_account_creation` - Account registration from the API.
+* `:relations_actions` - Following/Unfollowing in general.
+* `:relation_id_action` - Following/Unfollowing for a specific user.
+* `:statuses_actions` - Status actions such as: (un)repeating, (un)favouriting, creating, deleting.
+* `:status_id_action` - (un)Repeating/(un)Favouriting a particular status.
+* `:authentication` - Authentication actions, i.e getting an OAuth token.
+* `:password_reset` - Requesting password reset emails.
+* `:account_confirmation_resend` - Requesting resending account confirmation emails.
+* `:ap_routes` - Requesting statuses via ActivityPub.
### :web_cache_ttl
@@ -839,4 +856,5 @@ config :auto_linker,
## :configurable_from_database
-Enable/disable configuration from database.
+
+Boolean, enables/disables in-database configuration. Read [Transfering the config to/from the database](../administration/CLI_tasks/config.md) for more information.
diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex
index e17068876..2c8889ce5 100644
--- a/lib/pleroma/application.ex
+++ b/lib/pleroma/application.ex
@@ -33,6 +33,7 @@ defmodule Pleroma.Application do
def start(_type, _args) do
Pleroma.HTML.compile_scrubbers()
Pleroma.Config.DeprecationWarnings.warn()
+ Pleroma.Plugs.HTTPSecurityPlug.warn_if_disabled()
Pleroma.Repo.check_migrations_applied!()
setup_instrumenters()
load_custom_modules()
diff --git a/lib/pleroma/config/loader.ex b/lib/pleroma/config/loader.ex
index 68b247381..b8787cb49 100644
--- a/lib/pleroma/config/loader.ex
+++ b/lib/pleroma/config/loader.ex
@@ -3,8 +3,6 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Config.Loader do
- @paths ["config/config.exs", "config/#{Mix.env()}.exs"]
-
@reject_keys [
Pleroma.Repo,
Pleroma.Web.Endpoint,
@@ -35,8 +33,8 @@ defmodule Pleroma.Config.Loader do
def load_and_merge do
all_paths =
if Pleroma.Config.get(:release),
- do: @paths ++ ["config/releases.exs"],
- else: @paths
+ do: ["config/config.exs", "config/releases.exs"],
+ else: ["config/config.exs"]
all_paths
|> Enum.map(&load(&1))
diff --git a/lib/pleroma/config/transfer_task.ex b/lib/pleroma/config/transfer_task.ex
index d54f38ee4..6c5ba1f95 100644
--- a/lib/pleroma/config/transfer_task.ex
+++ b/lib/pleroma/config/transfer_task.ex
@@ -10,6 +10,30 @@ defmodule Pleroma.Config.TransferTask do
require Logger
+ @type env() :: :test | :benchmark | :dev | :prod
+
+ @reboot_time_keys [
+ {:pleroma, :hackney_pools},
+ {:pleroma, :chat},
+ {:pleroma, Oban},
+ {:pleroma, :rate_limit},
+ {:pleroma, :markup},
+ {:plerome, :streamer}
+ ]
+
+ @reboot_time_subkeys [
+ {:pleroma, Pleroma.Captcha, [:seconds_valid]},
+ {:pleroma, Pleroma.Upload, [:proxy_remote]},
+ {:pleroma, :instance, [:upload_limit]},
+ {:pleroma, :email_notifications, [:digest]},
+ {:pleroma, :oauth2, [:clean_expired_tokens]},
+ {:pleroma, Pleroma.ActivityExpiration, [:enabled]},
+ {:pleroma, Pleroma.ScheduledActivity, [:enabled]},
+ {:pleroma, :gopher, [:enabled]}
+ ]
+
+ @reject [nil, :prometheus]
+
def start_link(_) do
load_and_update_env()
if Pleroma.Config.get(:env) == :test, do: Ecto.Adapters.SQL.Sandbox.checkin(Repo)
@@ -17,21 +41,34 @@ defmodule Pleroma.Config.TransferTask do
end
@spec load_and_update_env([ConfigDB.t()]) :: :ok | false
- def load_and_update_env(deleted \\ []) do
+ def load_and_update_env(deleted \\ [], restart_pleroma? \\ true) do
with true <- Pleroma.Config.get(:configurable_from_database),
true <- Ecto.Adapters.SQL.table_exists?(Repo, "config"),
started_applications <- Application.started_applications() do
# We need to restart applications for loaded settings take effect
+
in_db = Repo.all(ConfigDB)
with_deleted = in_db ++ deleted
- with_deleted
- |> Enum.map(&merge_and_update(&1))
- |> Enum.uniq()
- # TODO: some problem with prometheus after restart!
- |> Enum.reject(&(&1 in [:pleroma, nil, :prometheus]))
- |> Enum.each(&restart(started_applications, &1))
+ reject_for_restart = if restart_pleroma?, do: @reject, else: [:pleroma | @reject]
+
+ applications =
+ with_deleted
+ |> Enum.map(&merge_and_update(&1))
+ |> Enum.uniq()
+ # TODO: some problem with prometheus after restart!
+ |> Enum.reject(&(&1 in reject_for_restart))
+
+ # to be ensured that pleroma will be restarted last
+ applications =
+ if :pleroma in applications do
+ List.delete(applications, :pleroma) ++ [:pleroma]
+ else
+ applications
+ end
+
+ Enum.each(applications, &restart(started_applications, &1, Pleroma.Config.get(:env)))
:ok
end
@@ -43,12 +80,25 @@ defmodule Pleroma.Config.TransferTask do
group = ConfigDB.from_string(setting.group)
default = Pleroma.Config.Holder.config(group, key)
- merged_value = merge_value(setting, default, group, key)
+ value = ConfigDB.from_binary(setting.value)
+
+ merged_value =
+ if Ecto.get_meta(setting, :state) == :deleted do
+ default
+ else
+ if can_be_merged?(default, value) do
+ ConfigDB.merge_group(group, key, default, value)
+ else
+ value
+ end
+ end
:ok = update_env(group, key, merged_value)
if group != :logger do
- group
+ if group != :pleroma or pleroma_need_restart?(group, key, value) do
+ group
+ end
else
# change logger configuration in runtime, without restart
if Keyword.keyword?(merged_value) and
@@ -76,22 +126,31 @@ defmodule Pleroma.Config.TransferTask do
end
end
- defp merge_value(%{__meta__: %{state: :deleted}}, default, _group, _key), do: default
+ @spec pleroma_need_restart?(atom(), atom(), any()) :: boolean()
+ def pleroma_need_restart?(group, key, value) do
+ group_and_key_need_reboot?(group, key) or group_and_subkey_need_reboot?(group, key, value)
+ end
- defp merge_value(setting, default, group, key) do
- value = ConfigDB.from_binary(setting.value)
+ defp group_and_key_need_reboot?(group, key) do
+ Enum.any?(@reboot_time_keys, fn {g, k} -> g == group and k == key end)
+ end
- if can_be_merged?(default, value) do
- ConfigDB.merge_group(group, key, default, value)
- else
- value
- end
+ defp group_and_subkey_need_reboot?(group, key, value) do
+ Keyword.keyword?(value) and
+ Enum.any?(@reboot_time_subkeys, fn {g, k, subkeys} ->
+ g == group and k == key and
+ Enum.any?(Keyword.keys(value), &(&1 in subkeys))
+ end)
end
defp update_env(group, key, nil), do: Application.delete_env(group, key)
defp update_env(group, key, value), do: Application.put_env(group, key, value)
- defp restart(started_applications, app) do
+ defp restart(_, :pleroma, :test), do: Logger.warn("pleroma restarted")
+
+ defp restart(_, :pleroma, _), do: send(Restarter.Pleroma, :after_boot)
+
+ defp restart(started_applications, app, _) do
with {^app, _, _} <- List.keyfind(started_applications, app, 0),
:ok <- Application.stop(app) do
:ok = Application.start(app)
diff --git a/lib/pleroma/formatter.ex b/lib/pleroma/formatter.ex
index 19b9af46c..90895374d 100644
--- a/lib/pleroma/formatter.ex
+++ b/lib/pleroma/formatter.ex
@@ -13,7 +13,8 @@ defmodule Pleroma.Formatter do
@auto_linker_config hashtag: true,
hashtag_handler: &Pleroma.Formatter.hashtag_handler/4,
mention: true,
- mention_handler: &Pleroma.Formatter.mention_handler/4
+ mention_handler: &Pleroma.Formatter.mention_handler/4,
+ scheme: true
def escape_mention_handler("@" <> nickname = mention, buffer, _, _) do
case User.get_cached_by_nickname(nickname) do
diff --git a/lib/pleroma/object.ex b/lib/pleroma/object.ex
index 38e372f6d..52556bf31 100644
--- a/lib/pleroma/object.ex
+++ b/lib/pleroma/object.ex
@@ -184,11 +184,14 @@ defmodule Pleroma.Object do
with {:ok, _obj} = swap_object_with_tombstone(object),
deleted_activity = Activity.delete_all_by_object_ap_id(id),
{:ok, true} <- Cachex.del(:object_cache, "object:#{id}"),
- {:ok, _} <- Cachex.del(:web_resp_cache, URI.parse(id).path),
- {:ok, _} <-
- Pleroma.Workers.AttachmentsCleanupWorker.enqueue("cleanup_attachments", %{
- "object" => object
- }) do
+ {:ok, _} <- Cachex.del(:web_resp_cache, URI.parse(id).path) do
+ with true <- Pleroma.Config.get([:instance, :cleanup_attachments]) do
+ {:ok, _} =
+ Pleroma.Workers.AttachmentsCleanupWorker.enqueue("cleanup_attachments", %{
+ "object" => object
+ })
+ end
+
{:ok, object, deleted_activity}
end
end
diff --git a/lib/pleroma/plugs/http_security_plug.ex b/lib/pleroma/plugs/http_security_plug.ex
index a7cc22831..b04273979 100644
--- a/lib/pleroma/plugs/http_security_plug.ex
+++ b/lib/pleroma/plugs/http_security_plug.ex
@@ -6,6 +6,8 @@ defmodule Pleroma.Plugs.HTTPSecurityPlug do
alias Pleroma.Config
import Plug.Conn
+ require Logger
+
def init(opts), do: opts
def call(conn, _options) do
@@ -90,6 +92,51 @@ defmodule Pleroma.Plugs.HTTPSecurityPlug do
|> Enum.join("; ")
end
+ def warn_if_disabled do
+ unless Config.get([:http_security, :enabled]) do
+ Logger.warn("
+ .i;;;;i.
+ iYcviii;vXY:
+ .YXi .i1c.
+ .YC. . in7.
+ .vc. ...... ;1c.
+ i7, .. .;1;
+ i7, .. ... .Y1i
+ ,7v .6MMM@; .YX,
+ .7;. ..IMMMMMM1 :t7.
+ .;Y. ;$MMMMMM9. :tc.
+ vY. .. .nMMM@MMU. ;1v.
+ i7i ... .#MM@M@C. .....:71i
+ it: .... $MMM@9;.,i;;;i,;tti
+ :t7. ..... 0MMMWv.,iii:::,,;St.
+ .nC. ..... IMMMQ..,::::::,.,czX.
+ .ct: ....... .ZMMMI..,:::::::,,:76Y.
+ c2: ......,i..Y$M@t..:::::::,,..inZY
+ vov ......:ii..c$MBc..,,,,,,,,,,..iI9i
+ i9Y ......iii:..7@MA,..,,,,,,,,,....;AA:
+ iIS. ......:ii::..;@MI....,............;Ez.
+ .I9. ......:i::::...8M1..................C0z.
+ .z9; ......:i::::,.. .i:...................zWX.
+ vbv ......,i::::,,. ................. :AQY
+ c6Y. .,...,::::,,..:t0@@QY. ................ :8bi
+ :6S. ..,,...,:::,,,..EMMMMMMI. ............... .;bZ,
+ :6o, .,,,,..:::,,,..i#MMMMMM#v................. YW2.
+ .n8i ..,,,,,,,::,,,,.. tMMMMM@C:.................. .1Wn
+ 7Uc. .:::,,,,,::,,,,.. i1t;,..................... .UEi
+ 7C...::::::::::::,,,,.. .................... vSi.
+ ;1;...,,::::::,......... .................. Yz:
+ v97,......... .voC.
+ izAotX7777777777777777777777777777777777777777Y7n92:
+ .;CoIIIIIUAA666666699999ZZZZZZZZZZZZZZZZZZZZ6ov.
+
+HTTP Security is disabled. Please re-enable it to prevent users from attacking
+your instance and your users via malicious posts:
+
+ config :pleroma, :http_security, enabled: true
+ ")
+ end
+ end
+
defp maybe_send_sts_header(conn, true) do
max_age_sts = Config.get([:http_security, :sts_max_age])
max_age_ct = Config.get([:http_security, :ct_max_age])
diff --git a/lib/pleroma/plugs/rate_limiter/rate_limiter.ex b/lib/pleroma/plugs/rate_limiter/rate_limiter.ex
index d720508c8..7fb92489c 100644
--- a/lib/pleroma/plugs/rate_limiter/rate_limiter.ex
+++ b/lib/pleroma/plugs/rate_limiter/rate_limiter.ex
@@ -67,6 +67,8 @@ defmodule Pleroma.Plugs.RateLimiter do
alias Pleroma.Plugs.RateLimiter.LimiterSupervisor
alias Pleroma.User
+ require Logger
+
def init(opts) do
limiter_name = Keyword.get(opts, :name)
@@ -89,18 +91,39 @@ defmodule Pleroma.Plugs.RateLimiter do
def call(conn, nil), do: conn
def call(conn, settings) do
- settings
- |> incorporate_conn_info(conn)
- |> check_rate()
- |> case do
- {:ok, _count} ->
+ case disabled?() do
+ true ->
+ if Pleroma.Config.get(:env) == :prod,
+ do: Logger.warn("Rate limiter is disabled for localhost/socket")
+
conn
- {:error, _count} ->
- render_throttled_error(conn)
+ false ->
+ settings
+ |> incorporate_conn_info(conn)
+ |> check_rate()
+ |> case do
+ {:ok, _count} ->
+ conn
+
+ {:error, _count} ->
+ render_throttled_error(conn)
+ end
end
end
+ def disabled? do
+ localhost_or_socket =
+ Pleroma.Config.get([Pleroma.Web.Endpoint, :http, :ip])
+ |> Tuple.to_list()
+ |> Enum.join(".")
+ |> String.match?(~r/^local|^127.0.0.1/)
+
+ remote_ip_disabled = not Pleroma.Config.get([Pleroma.Plugs.RemoteIp, :enabled])
+
+ localhost_or_socket and remote_ip_disabled
+ end
+
def inspect_bucket(conn, name_root, settings) do
settings =
settings
diff --git a/lib/pleroma/plugs/remote_ip.ex b/lib/pleroma/plugs/remote_ip.ex
index fdedc27ee..1cd5af48a 100644
--- a/lib/pleroma/plugs/remote_ip.ex
+++ b/lib/pleroma/plugs/remote_ip.ex
@@ -10,10 +10,7 @@ defmodule Pleroma.Plugs.RemoteIp do
@behaviour Plug
@headers ~w[
- forwarded
x-forwarded-for
- x-client-ip
- x-real-ip
]
# https://en.wikipedia.org/wiki/Localhost
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index 1ac67b618..5c436941a 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -325,12 +325,14 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
def react_with_emoji(user, object, emoji, options \\ []) do
with local <- Keyword.get(options, :local, true),
activity_id <- Keyword.get(options, :activity_id, nil),
- Pleroma.Emoji.is_unicode_emoji?(emoji),
+ true <- Pleroma.Emoji.is_unicode_emoji?(emoji),
reaction_data <- make_emoji_reaction_data(user, object, emoji, activity_id),
{:ok, activity} <- insert(reaction_data, local),
{:ok, object} <- add_emoji_reaction_to_object(activity, object),
:ok <- maybe_federate(activity) do
{:ok, activity, object}
+ else
+ e -> {:error, e}
end
end
@@ -345,6 +347,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
{:ok, object} <- remove_emoji_reaction_from_object(reaction_activity, object),
:ok <- maybe_federate(activity) do
{:ok, activity, object}
+ else
+ e -> {:error, e}
end
end
diff --git a/lib/pleroma/web/admin_api/admin_api_controller.ex b/lib/pleroma/web/admin_api/admin_api_controller.ex
index 2314d3274..c95cd182d 100644
--- a/lib/pleroma/web/admin_api/admin_api_controller.ex
+++ b/lib/pleroma/web/admin_api/admin_api_controller.ex
@@ -97,7 +97,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
plug(
OAuthScopesPlug,
%{scopes: ["read"], admin: true}
- when action in [:config_show, :migrate_from_db, :list_log]
+ when action in [:config_show, :list_log]
)
plug(
@@ -793,33 +793,13 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
|> Plug.Conn.send_resp(200, @descriptions_json)
end
- def migrate_from_db(conn, _params) do
- with :ok <- configurable_from_database(conn) do
- Mix.Tasks.Pleroma.Config.run([
- "migrate_from_db",
- "--env",
- to_string(Pleroma.Config.get(:env)),
- "-d"
- ])
-
- json(conn, %{})
- end
- end
-
def config_show(conn, %{"only_db" => true}) do
with :ok <- configurable_from_database(conn) do
configs = Pleroma.Repo.all(ConfigDB)
- if configs == [] do
- errors(
- conn,
- {:error, "To use configuration from database migrate your settings to database."}
- )
- else
- conn
- |> put_view(ConfigView)
- |> render("index.json", %{configs: configs})
- end
+ conn
+ |> put_view(ConfigView)
+ |> render("index.json", %{configs: configs})
end
end
@@ -827,45 +807,38 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
with :ok <- configurable_from_database(conn) do
configs = ConfigDB.get_all_as_keyword()
- if configs == [] do
- errors(
- conn,
- {:error, "To use configuration from database migrate your settings to database."}
- )
- else
- merged =
- Pleroma.Config.Holder.config()
- |> ConfigDB.merge(configs)
- |> Enum.map(fn {group, values} ->
- Enum.map(values, fn {key, value} ->
- db =
- if configs[group][key] do
- ConfigDB.get_db_keys(configs[group][key], key)
- end
-
- db_value = configs[group][key]
-
- merged_value =
- if !is_nil(db_value) and Keyword.keyword?(db_value) and
- ConfigDB.sub_key_full_update?(group, key, Keyword.keys(db_value)) do
- ConfigDB.merge_group(group, key, value, db_value)
- else
- value
- end
-
- setting = %{
- group: ConfigDB.convert(group),
- key: ConfigDB.convert(key),
- value: ConfigDB.convert(merged_value)
- }
-
- if db, do: Map.put(setting, :db, db), else: setting
- end)
+ merged =
+ Pleroma.Config.Holder.config()
+ |> ConfigDB.merge(configs)
+ |> Enum.map(fn {group, values} ->
+ Enum.map(values, fn {key, value} ->
+ db =
+ if configs[group][key] do
+ ConfigDB.get_db_keys(configs[group][key], key)
+ end
+
+ db_value = configs[group][key]
+
+ merged_value =
+ if !is_nil(db_value) and Keyword.keyword?(db_value) and
+ ConfigDB.sub_key_full_update?(group, key, Keyword.keys(db_value)) do
+ ConfigDB.merge_group(group, key, value, db_value)
+ else
+ value
+ end
+
+ setting = %{
+ group: ConfigDB.convert(group),
+ key: ConfigDB.convert(key),
+ value: ConfigDB.convert(merged_value)
+ }
+
+ if db, do: Map.put(setting, :db, db), else: setting
end)
- |> List.flatten()
+ end)
+ |> List.flatten()
- json(conn, %{configs: merged})
- end
+ json(conn, %{configs: merged})
end
end
@@ -890,17 +863,36 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
Ecto.get_meta(config, :state) == :deleted
end)
- Pleroma.Config.TransferTask.load_and_update_env(deleted)
+ Pleroma.Config.TransferTask.load_and_update_env(deleted, false)
+
+ need_reboot? =
+ Enum.any?(updated, fn config ->
+ group = ConfigDB.from_string(config.group)
+ key = ConfigDB.from_string(config.key)
+ value = ConfigDB.from_binary(config.value)
+ Pleroma.Config.TransferTask.pleroma_need_restart?(group, key, value)
+ end)
+
+ response = %{configs: updated}
- Mix.Tasks.Pleroma.Config.run([
- "migrate_from_db",
- "--env",
- to_string(Pleroma.Config.get(:env))
- ])
+ response =
+ if need_reboot?, do: Map.put(response, :need_reboot, need_reboot?), else: response
conn
|> put_view(ConfigView)
- |> render("index.json", %{configs: updated})
+ |> render("index.json", response)
+ end
+ end
+
+ def restart(conn, _params) do
+ with :ok <- configurable_from_database(conn) do
+ if Pleroma.Config.get(:env) == :test do
+ Logger.warn("pleroma restarted")
+ else
+ send(Restarter.Pleroma, {:restart, 50})
+ end
+
+ json(conn, %{})
end
end
diff --git a/lib/pleroma/web/admin_api/views/config_view.ex b/lib/pleroma/web/admin_api/views/config_view.ex
index 23d97e847..bbb53efcd 100644
--- a/lib/pleroma/web/admin_api/views/config_view.ex
+++ b/lib/pleroma/web/admin_api/views/config_view.ex
@@ -5,10 +5,16 @@
defmodule Pleroma.Web.AdminAPI.ConfigView do
use Pleroma.Web, :view
- def render("index.json", %{configs: configs}) do
- %{
+ def render("index.json", %{configs: configs} = params) do
+ map = %{
configs: render_many(configs, __MODULE__, "show.json", as: :config)
}
+
+ if params[:need_reboot] do
+ Map.put(map, :need_reboot, true)
+ else
+ map
+ end
end
def render("show.json", %{config: config}) do
diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex
index c05a6c544..2a348dcf6 100644
--- a/lib/pleroma/web/common_api/common_api.ex
+++ b/lib/pleroma/web/common_api/common_api.ex
@@ -315,8 +315,9 @@ defmodule Pleroma.Web.CommonAPI do
with %Activity{
actor: ^user_ap_id,
data: %{"type" => "Create"},
- object: %Object{data: %{"type" => "Note"}}
+ object: %Object{data: %{"type" => object_type}}
} = activity <- get_by_id_or_ap_id(id_or_ap_id),
+ true <- object_type in ["Note", "Article", "Question"],
true <- Visibility.is_public?(activity),
{:ok, _user} <- User.add_pinnned_activity(user, activity) do
{:ok, activity}
diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex
index 721e9f566..6cb158bbf 100644
--- a/lib/pleroma/web/mastodon_api/views/status_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/status_view.ex
@@ -241,7 +241,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
emoji_reactions =
with %{data: %{"reactions" => emoji_reactions}} <- object do
Enum.map(emoji_reactions, fn [emoji, users] ->
- %{emoji: emoji, count: length(users)}
+ %{
+ emoji: emoji,
+ count: length(users),
+ reacted: !!(opts[:for] && opts[:for].ap_id in users)
+ }
end)
else
_ -> []
diff --git a/lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex b/lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex
index 0bbf84fd3..a2f6d2287 100644
--- a/lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex
+++ b/lib/pleroma/web/pleroma_api/controllers/emoji_api_controller.ex
@@ -573,11 +573,14 @@ keeping it in cache for #{div(cache_ms, 1000)}s")
assumed to be emojis and stored in the new `pack.json` file.
"""
def import_from_fs(conn, _params) do
- with {:ok, results} <- File.ls(emoji_dir_path()) do
+ emoji_path = emoji_dir_path()
+
+ with {:ok, %{access: :read_write}} <- File.stat(emoji_path),
+ {:ok, results} <- File.ls(emoji_path) do
imported_pack_names =
results
|> Enum.filter(fn file ->
- dir_path = Path.join(emoji_dir_path(), file)
+ dir_path = Path.join(emoji_path, file)
# Find the directories that do NOT have pack.json
File.dir?(dir_path) and not File.exists?(Path.join(dir_path, "pack.json"))
end)
@@ -585,6 +588,11 @@ keeping it in cache for #{div(cache_ms, 1000)}s")
json(conn, imported_pack_names)
else
+ {:ok, %{access: _}} ->
+ conn
+ |> put_status(:internal_server_error)
+ |> json(%{error: "Error: emoji pack directory must be writable"})
+
{:error, _} ->
conn
|> put_status(:internal_server_error)
diff --git a/lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex b/lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex
index cd1c0764f..d76e39795 100644
--- a/lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex
+++ b/lib/pleroma/web/pleroma_api/controllers/pleroma_api_controller.ex
@@ -47,13 +47,16 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIController do
Object.normalize(activity) do
reactions =
emoji_reactions
- |> Enum.map(fn [emoji, users] ->
- users = Enum.map(users, &User.get_cached_by_ap_id/1)
+ |> Enum.map(fn [emoji, user_ap_ids] ->
+ users =
+ Enum.map(user_ap_ids, &User.get_cached_by_ap_id/1)
+ |> Enum.filter(& &1)
%{
emoji: emoji,
count: length(users),
- accounts: AccountView.render("index.json", %{users: users, for: user, as: :user})
+ accounts: AccountView.render("index.json", %{users: users, for: user, as: :user}),
+ reacted: !!(user && user.ap_id in user_ap_ids)
}
end)
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index b5c1d85c7..e86bc3cc3 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -196,7 +196,7 @@ defmodule Pleroma.Web.Router do
get("/config", AdminAPIController, :config_show)
post("/config", AdminAPIController, :config_update)
get("/config/descriptions", AdminAPIController, :config_descriptions)
- get("/config/migrate_from_db", AdminAPIController, :migrate_from_db)
+ get("/restart", AdminAPIController, :restart)
get("/moderation_log", AdminAPIController, :list_log)
diff --git a/mix.exs b/mix.exs
index ea6b29f57..f6794f126 100644
--- a/mix.exs
+++ b/mix.exs
@@ -8,7 +8,7 @@ defmodule Pleroma.Mixfile do
elixir: "~> 1.8",
elixirc_paths: elixirc_paths(Mix.env()),
compilers: [:phoenix, :gettext] ++ Mix.compilers(),
- elixirc_options: [warnings_as_errors: true],
+ elixirc_options: [warnings_as_errors: warnings_as_errors(Mix.env())],
xref: [exclude: [:eldap]],
start_permanent: Mix.env() == :prod,
aliases: aliases(),
@@ -73,6 +73,11 @@ defmodule Pleroma.Mixfile do
defp elixirc_paths(:test), do: ["lib", "test/support"]
defp elixirc_paths(_), do: ["lib"]
+ defp warnings_as_errors(:prod), do: false
+ # Uncomment this if you need testing configurable_from_database logic
+ # defp warnings_as_errors(:dev), do: false
+ defp warnings_as_errors(_), do: true
+
# Specifies OAuth dependencies.
defp oauth_deps do
oauth_strategy_packages =
@@ -166,7 +171,8 @@ defmodule Pleroma.Mixfile do
{:captcha,
git: "https://git.pleroma.social/pleroma/elixir-libraries/elixir-captcha.git",
ref: "e0f16822d578866e186a0974d65ad58cddc1e2ab"},
- {:mox, "~> 0.5", only: :test}
+ {:mox, "~> 0.5", only: :test},
+ {:restarter, path: "./restarter"}
] ++ oauth_deps()
end
diff --git a/restarter/lib/pleroma.ex b/restarter/lib/pleroma.ex
new file mode 100644
index 000000000..da714654c
--- /dev/null
+++ b/restarter/lib/pleroma.ex
@@ -0,0 +1,28 @@
+defmodule Restarter.Pleroma do
+ use GenServer
+
+ def start_link(_) do
+ GenServer.start_link(__MODULE__, [], name: __MODULE__)
+ end
+
+ def init(_), do: {:ok, %{}}
+
+ def handle_info(:after_boot, %{after_boot: true} = state), do: {:noreply, state}
+
+ def handle_info(:after_boot, state) do
+ restart(:pleroma)
+ {:noreply, Map.put(state, :after_boot, true)}
+ end
+
+ def handle_info({:restart, delay}, state) do
+ Process.sleep(delay)
+ restart(:pleroma)
+ {:noreply, state}
+ end
+
+ defp restart(app) do
+ :ok = Application.ensure_started(app)
+ :ok = Application.stop(app)
+ :ok = Application.start(app)
+ end
+end
diff --git a/restarter/lib/restarter.ex b/restarter/lib/restarter.ex
new file mode 100644
index 000000000..eadd86f89
--- /dev/null
+++ b/restarter/lib/restarter.ex
@@ -0,0 +1,8 @@
+defmodule Restarter do
+ use Application
+
+ def start(_, _) do
+ opts = [strategy: :one_for_one, name: Restarter.Supervisor]
+ Supervisor.start_link([Restarter.Pleroma], opts)
+ end
+end
diff --git a/restarter/mix.exs b/restarter/mix.exs
new file mode 100644
index 000000000..b0908aece
--- /dev/null
+++ b/restarter/mix.exs
@@ -0,0 +1,21 @@
+defmodule Restarter.MixProject do
+ use Mix.Project
+
+ def project do
+ [
+ app: :restarter,
+ version: "0.1.0",
+ elixir: "~> 1.8",
+ start_permanent: Mix.env() == :prod,
+ deps: deps()
+ ]
+ end
+
+ def application do
+ [
+ mod: {Restarter, []}
+ ]
+ end
+
+ defp deps, do: []
+end
diff --git a/test/config/transfer_task_test.exs b/test/config/transfer_task_test.exs
index 53e8703fd..ebdc951cf 100644
--- a/test/config/transfer_task_test.exs
+++ b/test/config/transfer_task_test.exs
@@ -5,6 +5,8 @@
defmodule Pleroma.Config.TransferTaskTest do
use Pleroma.DataCase
+ import ExUnit.CaptureLog
+
alias Pleroma.Config.TransferTask
alias Pleroma.ConfigDB
@@ -105,4 +107,75 @@ defmodule Pleroma.Config.TransferTaskTest do
Application.put_env(:pleroma, :assets, assets)
end)
end
+
+ describe "pleroma restart" do
+ test "don't restart if no reboot time settings were changed" do
+ emoji = Application.get_env(:pleroma, :emoji)
+ on_exit(fn -> Application.put_env(:pleroma, :emoji, emoji) end)
+
+ ConfigDB.create(%{
+ group: ":pleroma",
+ key: ":emoji",
+ value: [groups: [a: 1, b: 2]]
+ })
+
+ refute String.contains?(
+ capture_log(fn -> TransferTask.start_link([]) end),
+ "pleroma restarted"
+ )
+ end
+
+ test "restart pleroma on reboot time key" do
+ chat = Application.get_env(:pleroma, :chat)
+ on_exit(fn -> Application.put_env(:pleroma, :chat, chat) end)
+
+ ConfigDB.create(%{
+ group: ":pleroma",
+ key: ":chat",
+ value: [enabled: false]
+ })
+
+ assert capture_log(fn -> TransferTask.start_link([]) end) =~ "pleroma restarted"
+ end
+
+ test "restart pleroma on reboot time subkey" do
+ captcha = Application.get_env(:pleroma, Pleroma.Captcha)
+ on_exit(fn -> Application.put_env(:pleroma, Pleroma.Captcha, captcha) end)
+
+ ConfigDB.create(%{
+ group: ":pleroma",
+ key: "Pleroma.Captcha",
+ value: [seconds_valid: 60]
+ })
+
+ assert capture_log(fn -> TransferTask.start_link([]) end) =~ "pleroma restarted"
+ end
+
+ test "don't restart pleroma on reboot time key and subkey if there is false flag" do
+ chat = Application.get_env(:pleroma, :chat)
+ captcha = Application.get_env(:pleroma, Pleroma.Captcha)
+
+ on_exit(fn ->
+ Application.put_env(:pleroma, :chat, chat)
+ Application.put_env(:pleroma, Pleroma.Captcha, captcha)
+ end)
+
+ ConfigDB.create(%{
+ group: ":pleroma",
+ key: ":chat",
+ value: [enabled: false]
+ })
+
+ ConfigDB.create(%{
+ group: ":pleroma",
+ key: "Pleroma.Captcha",
+ value: [seconds_valid: 60]
+ })
+
+ refute String.contains?(
+ capture_log(fn -> TransferTask.load_and_update_env([], false) end),
+ "pleroma restarted"
+ )
+ end
+ end
end
diff --git a/test/fixtures/emoji-reaction-no-emoji.json b/test/fixtures/emoji-reaction-no-emoji.json
new file mode 100644
index 000000000..fff77b29b
--- /dev/null
+++ b/test/fixtures/emoji-reaction-no-emoji.json
@@ -0,0 +1,30 @@
+{
+ "type": "EmojiReaction",
+ "signature": {
+ "type": "RsaSignature2017",
+ "signatureValue": "fdxMfQSMwbC6wP6sh6neS/vM5879K67yQkHTbiT5Npr5wAac0y6+o3Ij+41tN3rL6wfuGTosSBTHOtta6R4GCOOhCaCSLMZKypnp1VltCzLDoyrZELnYQIC8gpUXVmIycZbREk22qWUe/w7DAFaKK4UscBlHDzeDVcA0K3Se5Sluqi9/Zh+ldAnEzj/rSEPDjrtvf5wGNf3fHxbKSRKFt90JvKK6hS+vxKUhlRFDf6/SMETw+EhwJSNW4d10yMUakqUWsFv4Acq5LW7l+HpYMvlYY1FZhNde1+uonnCyuQDyvzkff8zwtEJmAXC4RivO/VVLa17SmqheJZfI8oluVg==",
+ "creator": "http://mastodon.example.org/users/admin#main-key",
+ "created": "2018-02-17T18:57:49Z"
+ },
+ "object": "http://localtesting.pleroma.lol/objects/eb92579d-3417-42a8-8652-2492c2d4f454",
+ "content": "~",
+ "nickname": "lain",
+ "id": "http://mastodon.example.org/users/admin#reactions/2",
+ "actor": "http://mastodon.example.org/users/admin",
+ "@context": [
+ "https://www.w3.org/ns/activitystreams",
+ "https://w3id.org/security/v1",
+ {
+ "toot": "http://joinmastodon.org/ns#",
+ "sensitive": "as:sensitive",
+ "ostatus": "http://ostatus.org#",
+ "movedTo": "as:movedTo",
+ "manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
+ "inReplyToAtomUri": "ostatus:inReplyToAtomUri",
+ "conversation": "ostatus:conversation",
+ "atomUri": "ostatus:atomUri",
+ "Hashtag": "as:Hashtag",
+ "Emoji": "toot:Emoji"
+ }
+ ]
+}
diff --git a/test/fixtures/emoji-reaction-too-long.json b/test/fixtures/emoji-reaction-too-long.json
new file mode 100644
index 000000000..31830d90c
--- /dev/null
+++ b/test/fixtures/emoji-reaction-too-long.json
@@ -0,0 +1,30 @@
+{
+ "type": "EmojiReaction",
+ "signature": {
+ "type": "RsaSignature2017",
+ "signatureValue": "fdxMfQSMwbC6wP6sh6neS/vM5879K67yQkHTbiT5Npr5wAac0y6+o3Ij+41tN3rL6wfuGTosSBTHOtta6R4GCOOhCaCSLMZKypnp1VltCzLDoyrZELnYQIC8gpUXVmIycZbREk22qWUe/w7DAFaKK4UscBlHDzeDVcA0K3Se5Sluqi9/Zh+ldAnEzj/rSEPDjrtvf5wGNf3fHxbKSRKFt90JvKK6hS+vxKUhlRFDf6/SMETw+EhwJSNW4d10yMUakqUWsFv4Acq5LW7l+HpYMvlYY1FZhNde1+uonnCyuQDyvzkff8zwtEJmAXC4RivO/VVLa17SmqheJZfI8oluVg==",
+ "creator": "http://mastodon.example.org/users/admin#main-key",
+ "created": "2018-02-17T18:57:49Z"
+ },
+ "object": "http://localtesting.pleroma.lol/objects/eb92579d-3417-42a8-8652-2492c2d4f454",
+ "content": "👌👌",
+ "nickname": "lain",
+ "id": "http://mastodon.example.org/users/admin#reactions/2",
+ "actor": "http://mastodon.example.org/users/admin",
+ "@context": [
+ "https://www.w3.org/ns/activitystreams",
+ "https://w3id.org/security/v1",
+ {
+ "toot": "http://joinmastodon.org/ns#",
+ "sensitive": "as:sensitive",
+ "ostatus": "http://ostatus.org#",
+ "movedTo": "as:movedTo",
+ "manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
+ "inReplyToAtomUri": "ostatus:inReplyToAtomUri",
+ "conversation": "ostatus:conversation",
+ "atomUri": "ostatus:atomUri",
+ "Hashtag": "as:Hashtag",
+ "Emoji": "toot:Emoji"
+ }
+ ]
+}
diff --git a/test/object_test.exs b/test/object_test.exs
index c6b2bc399..5690bedec 100644
--- a/test/object_test.exs
+++ b/test/object_test.exs
@@ -76,8 +76,43 @@ defmodule Pleroma.ObjectTest do
describe "delete attachments" do
clear_config([Pleroma.Upload])
+ test "Disabled via config" do
+ Pleroma.Config.put([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
+ Pleroma.Config.put([:instance, :cleanup_attachments], false)
+
+ file = %Plug.Upload{
+ content_type: "image/jpg",
+ path: Path.absname("test/fixtures/image.jpg"),
+ filename: "an_image.jpg"
+ }
+
+ user = insert(:user)
+
+ {:ok, %Object{} = attachment} =
+ Pleroma.Web.ActivityPub.ActivityPub.upload(file, actor: user.ap_id)
+
+ %{data: %{"attachment" => [%{"url" => [%{"href" => href}]}]}} =
+ note = insert(:note, %{user: user, data: %{"attachment" => [attachment.data]}})
+
+ uploads_dir = Pleroma.Config.get!([Pleroma.Uploaders.Local, :uploads])
+
+ path = href |> Path.dirname() |> Path.basename()
+
+ assert {:ok, ["an_image.jpg"]} == File.ls("#{uploads_dir}/#{path}")
+
+ Object.delete(note)
+
+ ObanHelpers.perform(all_enqueued(worker: Pleroma.Workers.AttachmentsCleanupWorker))
+
+ assert Object.get_by_id(note.id).data["deleted"]
+ refute Object.get_by_id(attachment.id) == nil
+
+ assert {:ok, ["an_image.jpg"]} == File.ls("#{uploads_dir}/#{path}")
+ end
+
test "in subdirectories" do
Pleroma.Config.put([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
+ Pleroma.Config.put([:instance, :cleanup_attachments], true)
file = %Plug.Upload{
content_type: "image/jpg",
@@ -103,6 +138,7 @@ defmodule Pleroma.ObjectTest do
ObanHelpers.perform(all_enqueued(worker: Pleroma.Workers.AttachmentsCleanupWorker))
+ assert Object.get_by_id(note.id).data["deleted"]
assert Object.get_by_id(attachment.id) == nil
assert {:ok, []} == File.ls("#{uploads_dir}/#{path}")
@@ -111,6 +147,7 @@ defmodule Pleroma.ObjectTest do
test "with dedupe enabled" do
Pleroma.Config.put([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
Pleroma.Config.put([Pleroma.Upload, :filters], [Pleroma.Upload.Filter.Dedupe])
+ Pleroma.Config.put([:instance, :cleanup_attachments], true)
uploads_dir = Pleroma.Config.get!([Pleroma.Uploaders.Local, :uploads])
@@ -139,6 +176,7 @@ defmodule Pleroma.ObjectTest do
ObanHelpers.perform(all_enqueued(worker: Pleroma.Workers.AttachmentsCleanupWorker))
+ assert Object.get_by_id(note.id).data["deleted"]
assert Object.get_by_id(attachment.id) == nil
assert {:ok, files} = File.ls(uploads_dir)
refute filename in files
@@ -146,6 +184,7 @@ defmodule Pleroma.ObjectTest do
test "with objects that have legacy data.url attribute" do
Pleroma.Config.put([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
+ Pleroma.Config.put([:instance, :cleanup_attachments], true)
file = %Plug.Upload{
content_type: "image/jpg",
@@ -173,6 +212,7 @@ defmodule Pleroma.ObjectTest do
ObanHelpers.perform(all_enqueued(worker: Pleroma.Workers.AttachmentsCleanupWorker))
+ assert Object.get_by_id(note.id).data["deleted"]
assert Object.get_by_id(attachment.id) == nil
assert {:ok, []} == File.ls("#{uploads_dir}/#{path}")
@@ -181,6 +221,7 @@ defmodule Pleroma.ObjectTest do
test "With custom base_url" do
Pleroma.Config.put([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local)
Pleroma.Config.put([Pleroma.Upload, :base_url], "https://sub.domain.tld/dir/")
+ Pleroma.Config.put([:instance, :cleanup_attachments], true)
file = %Plug.Upload{
content_type: "image/jpg",
@@ -206,6 +247,7 @@ defmodule Pleroma.ObjectTest do
ObanHelpers.perform(all_enqueued(worker: Pleroma.Workers.AttachmentsCleanupWorker))
+ assert Object.get_by_id(note.id).data["deleted"]
assert Object.get_by_id(attachment.id) == nil
assert {:ok, []} == File.ls("#{uploads_dir}/#{path}")
diff --git a/test/plugs/rate_limiter_test.exs b/test/plugs/rate_limiter_test.exs
index 78f1ea9e4..06ffa7b70 100644
--- a/test/plugs/rate_limiter_test.exs
+++ b/test/plugs/rate_limiter_test.exs
@@ -16,6 +16,7 @@ defmodule Pleroma.Plugs.RateLimiterTest do
test "config is required for plug to work" do
limiter_name = :test_init
Pleroma.Config.put([:rate_limit, limiter_name], {1, 1})
+ Pleroma.Config.put([Pleroma.Web.Endpoint, :http, :ip], {8, 8, 8, 8})
assert %{limits: {1, 1}, name: :test_init, opts: [name: :test_init]} ==
RateLimiter.init(name: limiter_name)
@@ -23,11 +24,39 @@ defmodule Pleroma.Plugs.RateLimiterTest do
assert nil == RateLimiter.init(name: :foo)
end
+ test "it is disabled for localhost" do
+ limiter_name = :test_init
+ Pleroma.Config.put([:rate_limit, limiter_name], {1, 1})
+ Pleroma.Config.put([Pleroma.Web.Endpoint, :http, :ip], {127, 0, 0, 1})
+ Pleroma.Config.put([Pleroma.Plugs.RemoteIp, :enabled], false)
+
+ assert RateLimiter.disabled?() == true
+ end
+
+ test "it is disabled for socket" do
+ limiter_name = :test_init
+ Pleroma.Config.put([:rate_limit, limiter_name], {1, 1})
+ Pleroma.Config.put([Pleroma.Web.Endpoint, :http, :ip], {:local, "/path/to/pleroma.sock"})
+ Pleroma.Config.put([Pleroma.Plugs.RemoteIp, :enabled], false)
+
+ assert RateLimiter.disabled?() == true
+ end
+
+ test "it is enabled for socket when remote ip is enabled" do
+ limiter_name = :test_init
+ Pleroma.Config.put([:rate_limit, limiter_name], {1, 1})
+ Pleroma.Config.put([Pleroma.Web.Endpoint, :http, :ip], {:local, "/path/to/pleroma.sock"})
+ Pleroma.Config.put([Pleroma.Plugs.RemoteIp, :enabled], true)
+
+ assert RateLimiter.disabled?() == false
+ end
+
test "it restricts based on config values" do
limiter_name = :test_opts
scale = 80
limit = 5
+ Pleroma.Config.put([Pleroma.Web.Endpoint, :http, :ip], {8, 8, 8, 8})
Pleroma.Config.put([:rate_limit, limiter_name], {scale, limit})
opts = RateLimiter.init(name: limiter_name)
@@ -61,6 +90,7 @@ defmodule Pleroma.Plugs.RateLimiterTest do
limiter_name = :test_bucket_name
Pleroma.Config.put([:rate_limit, limiter_name], {1000, 5})
+ Pleroma.Config.put([Pleroma.Web.Endpoint, :http, :ip], {8, 8, 8, 8})
base_bucket_name = "#{limiter_name}:group1"
opts = RateLimiter.init(name: limiter_name, bucket_name: base_bucket_name)
@@ -75,6 +105,7 @@ defmodule Pleroma.Plugs.RateLimiterTest do
test "`params` option allows different queries to be tracked independently" do
limiter_name = :test_params
Pleroma.Config.put([:rate_limit, limiter_name], {1000, 5})
+ Pleroma.Config.put([Pleroma.Web.Endpoint, :http, :ip], {8, 8, 8, 8})
opts = RateLimiter.init(name: limiter_name, params: ["id"])
@@ -90,6 +121,7 @@ defmodule Pleroma.Plugs.RateLimiterTest do
test "it supports combination of options modifying bucket name" do
limiter_name = :test_options_combo
Pleroma.Config.put([:rate_limit, limiter_name], {1000, 5})
+ Pleroma.Config.put([Pleroma.Web.Endpoint, :http, :ip], {8, 8, 8, 8})
base_bucket_name = "#{limiter_name}:group1"
opts = RateLimiter.init(name: limiter_name, bucket_name: base_bucket_name, params: ["id"])
@@ -109,6 +141,7 @@ defmodule Pleroma.Plugs.RateLimiterTest do
test "are restricted based on remote IP" do
limiter_name = :test_unauthenticated
Pleroma.Config.put([:rate_limit, limiter_name], [{1000, 5}, {1, 10}])
+ Pleroma.Config.put([Pleroma.Web.Endpoint, :http, :ip], {8, 8, 8, 8})
opts = RateLimiter.init(name: limiter_name)
@@ -147,6 +180,7 @@ defmodule Pleroma.Plugs.RateLimiterTest do
scale = 50
limit = 5
+ Pleroma.Config.put([Pleroma.Web.Endpoint, :http, :ip], {8, 8, 8, 8})
Pleroma.Config.put([:rate_limit, limiter_name], [{1000, 1}, {scale, limit}])
opts = RateLimiter.init(name: limiter_name)
@@ -169,6 +203,7 @@ defmodule Pleroma.Plugs.RateLimiterTest do
test "diffrerent users are counted independently" do
limiter_name = :test_authenticated
Pleroma.Config.put([:rate_limit, limiter_name], [{1, 10}, {1000, 5}])
+ Pleroma.Config.put([Pleroma.Web.Endpoint, :http, :ip], {8, 8, 8, 8})
opts = RateLimiter.init(name: limiter_name)
diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs
index 5da358c43..0829a6ec2 100644
--- a/test/web/activity_pub/transmogrifier_test.exs
+++ b/test/web/activity_pub/transmogrifier_test.exs
@@ -395,6 +395,25 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
assert data["content"] == "👌"
end
+ test "it reject invalid emoji reactions" do
+ user = insert(:user)
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
+
+ data =
+ File.read!("test/fixtures/emoji-reaction-too-long.json")
+ |> Poison.decode!()
+ |> Map.put("object", activity.data["object"])
+
+ assert :error = Transmogrifier.handle_incoming(data)
+
+ data =
+ File.read!("test/fixtures/emoji-reaction-no-emoji.json")
+ |> Poison.decode!()
+ |> Map.put("object", activity.data["object"])
+
+ assert :error = Transmogrifier.handle_incoming(data)
+ end
+
test "it works for incoming emoji reaction undos" do
user = insert(:user)
diff --git a/test/web/admin_api/admin_api_controller_test.exs b/test/web/admin_api/admin_api_controller_test.exs
index 5c767219a..5fbdf96f6 100644
--- a/test/web/admin_api/admin_api_controller_test.exs
+++ b/test/web/admin_api/admin_api_controller_test.exs
@@ -1899,13 +1899,6 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
"To use this endpoint you need to enable configuration from database."
end
- test "without any settings in db", %{conn: conn} do
- conn = get(conn, "/api/pleroma/admin/config")
-
- assert json_response(conn, 400) ==
- "To use configuration from database migrate your settings to database."
- end
-
test "with settings only in db", %{conn: conn} do
config1 = insert(:config)
config2 = insert(:config)
@@ -2043,7 +2036,6 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
Application.delete_env(:pleroma, Pleroma.Captcha.NotReal)
Application.put_env(:pleroma, :http, http)
Application.put_env(:tesla, :adapter, Tesla.Mock)
- :ok = File.rm("config/test.exported_from_db.secret.exs")
end)
end
@@ -2170,7 +2162,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
assert Application.get_env(:idna, :key5) == {"string", Pleroma.Captcha.NotReal, []}
end
- test "save config setting without key", %{conn: conn} do
+ test "save configs setting without explicit key", %{conn: conn} do
level = Application.get_env(:quack, :level)
meta = Application.get_env(:quack, :meta)
webhook_url = Application.get_env(:quack, :webhook_url)
@@ -2256,6 +2248,34 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
}
end
+ test "saving config which need pleroma reboot", %{conn: conn} do
+ chat = Pleroma.Config.get(:chat)
+ on_exit(fn -> Pleroma.Config.put(:chat, chat) end)
+
+ conn =
+ post(
+ conn,
+ "/api/pleroma/admin/config",
+ %{
+ configs: [
+ %{group: ":pleroma", key: ":chat", value: [%{"tuple" => [":enabled", true]}]}
+ ]
+ }
+ )
+
+ assert json_response(conn, 200) == %{
+ "configs" => [
+ %{
+ "db" => [":enabled"],
+ "group" => ":pleroma",
+ "key" => ":chat",
+ "value" => [%{"tuple" => [":enabled", true]}]
+ }
+ ],
+ "need_reboot" => true
+ }
+ end
+
test "saving config with nested merge", %{conn: conn} do
config =
insert(:config, key: ":key1", value: :erlang.term_to_binary(key1: 1, key2: [k1: 1, k2: 2]))
@@ -2957,47 +2977,15 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
end
end
- describe "config mix tasks run" do
- setup do
- Mix.shell(Mix.Shell.Quiet)
-
- on_exit(fn ->
- Mix.shell(Mix.Shell.IO)
- end)
-
- :ok
- end
-
+ describe "GET /api/pleroma/admin/restart" do
clear_config(:configurable_from_database) do
Pleroma.Config.put(:configurable_from_database, true)
end
- clear_config([:feed, :post_title]) do
- Pleroma.Config.put([:feed, :post_title], %{max_length: 100, omission: "…"})
- end
-
- test "transfer settings to DB and to file", %{conn: conn} do
- assert Repo.all(Pleroma.ConfigDB) == []
- Mix.Tasks.Pleroma.Config.migrate_to_db("test/fixtures/config/temp.secret.exs")
- assert Repo.aggregate(Pleroma.ConfigDB, :count, :id) > 0
-
- conn = get(conn, "/api/pleroma/admin/config/migrate_from_db")
-
- assert json_response(conn, 200) == %{}
- assert Repo.all(Pleroma.ConfigDB) == []
- end
-
- test "returns error if configuration from database is off", %{conn: conn} do
- initial = Pleroma.Config.get(:configurable_from_database)
- on_exit(fn -> Pleroma.Config.put(:configurable_from_database, initial) end)
- Pleroma.Config.put(:configurable_from_database, false)
-
- conn = get(conn, "/api/pleroma/admin/config/migrate_from_db")
-
- assert json_response(conn, 400) ==
- "To use this endpoint you need to enable configuration from database."
-
- assert Repo.all(Pleroma.ConfigDB) == []
+ test "pleroma restarts", %{conn: conn} do
+ ExUnit.CaptureLog.capture_log(fn ->
+ assert conn |> get("/api/pleroma/admin/restart") |> json_response(200) == %{}
+ end) =~ "pleroma restarted"
end
end
diff --git a/test/web/common_api/common_api_test.exs b/test/web/common_api/common_api_test.exs
index f8963e42e..214cbdd7c 100644
--- a/test/web/common_api/common_api_test.exs
+++ b/test/web/common_api/common_api_test.exs
@@ -238,7 +238,9 @@ defmodule Pleroma.Web.CommonAPITest do
assert reaction.data["actor"] == user.ap_id
assert reaction.data["content"] == "👍"
- # TODO: test error case.
+ {:ok, activity} = CommonAPI.post(other_user, %{"status" => "cofe"})
+
+ {:error, _} = CommonAPI.react_with_emoji(activity.id, user, ".")
end
test "unreacting to a status with an emoji" do
@@ -322,6 +324,21 @@ defmodule Pleroma.Web.CommonAPITest do
assert %User{pinned_activities: [^id]} = user
end
+ test "pin poll", %{user: user} do
+ {:ok, activity} =
+ CommonAPI.post(user, %{
+ "status" => "How is fediverse today?",
+ "poll" => %{"options" => ["Absolutely outstanding", "Not good"], "expires_in" => 20}
+ })
+
+ assert {:ok, ^activity} = CommonAPI.pin(activity.id, user)
+
+ id = activity.id
+ user = refresh_record(user)
+
+ assert %User{pinned_activities: [^id]} = user
+ end
+
test "unlisted statuses can be pinned", %{user: user} do
{:ok, activity} = CommonAPI.post(user, %{"status" => "HI!!!", "visibility" => "unlisted"})
assert {:ok, ^activity} = CommonAPI.pin(activity.id, user)
diff --git a/test/web/mastodon_api/controllers/account_controller_test.exs b/test/web/mastodon_api/controllers/account_controller_test.exs
index 0d4860a42..ec1e18002 100644
--- a/test/web/mastodon_api/controllers/account_controller_test.exs
+++ b/test/web/mastodon_api/controllers/account_controller_test.exs
@@ -668,6 +668,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
end
test "rate limit", %{conn: conn} do
+ Pleroma.Config.put([Pleroma.Plugs.RemoteIp, :enabled], true)
app_token = insert(:oauth_token, user: nil)
conn =
diff --git a/test/web/mastodon_api/views/status_view_test.exs b/test/web/mastodon_api/views/status_view_test.exs
index 25777b011..fc110417c 100644
--- a/test/web/mastodon_api/views/status_view_test.exs
+++ b/test/web/mastodon_api/views/status_view_test.exs
@@ -37,8 +37,15 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
status = StatusView.render("show.json", activity: activity)
assert status[:pleroma][:emoji_reactions] == [
- %{emoji: "☕", count: 2},
- %{emoji: "🍵", count: 1}
+ %{emoji: "☕", count: 2, reacted: false},
+ %{emoji: "🍵", count: 1, reacted: false}
+ ]
+
+ status = StatusView.render("show.json", activity: activity, for: user)
+
+ assert status[:pleroma][:emoji_reactions] == [
+ %{emoji: "☕", count: 2, reacted: true},
+ %{emoji: "🍵", count: 1, reacted: false}
]
end
diff --git a/test/web/pleroma_api/controllers/emoji_api_controller_test.exs b/test/web/pleroma_api/controllers/emoji_api_controller_test.exs
index 8e76f2f3d..6f1ea78ec 100644
--- a/test/web/pleroma_api/controllers/emoji_api_controller_test.exs
+++ b/test/web/pleroma_api/controllers/emoji_api_controller_test.exs
@@ -6,7 +6,6 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do
use Pleroma.Web.ConnCase
import Tesla.Mock
-
import Pleroma.Factory
@emoji_dir_path Path.join(
diff --git a/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs b/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs
index 3978c2ec5..be5007de5 100644
--- a/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs
+++ b/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs
@@ -25,9 +25,14 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIControllerTest do
|> assign(:user, other_user)
|> assign(:token, insert(:oauth_token, user: other_user, scopes: ["write:statuses"]))
|> post("/api/v1/pleroma/statuses/#{activity.id}/react_with_emoji", %{"emoji" => "☕"})
+ |> json_response(200)
- assert %{"id" => id} = json_response(result, 200)
+ assert %{"id" => id} = result
assert to_string(activity.id) == id
+
+ assert result["pleroma"]["emoji_reactions"] == [
+ %{"emoji" => "☕", "count" => 1, "reacted" => true}
+ ]
end
test "POST /api/v1/pleroma/statuses/:id/unreact_with_emoji", %{conn: conn} do
@@ -54,6 +59,7 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIControllerTest do
test "GET /api/v1/pleroma/statuses/:id/emoji_reactions_by", %{conn: conn} do
user = insert(:user)
other_user = insert(:user)
+ doomed_user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "#cofe"})
@@ -65,14 +71,29 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIControllerTest do
assert result == []
{:ok, _, _} = CommonAPI.react_with_emoji(activity.id, other_user, "🎅")
+ {:ok, _, _} = CommonAPI.react_with_emoji(activity.id, doomed_user, "🎅")
+
+ User.perform(:delete, doomed_user)
result =
conn
|> get("/api/v1/pleroma/statuses/#{activity.id}/emoji_reactions_by")
|> json_response(200)
- [%{"emoji" => "🎅", "count" => 1, "accounts" => [represented_user]}] = result
+ [%{"emoji" => "🎅", "count" => 1, "accounts" => [represented_user], "reacted" => false}] =
+ result
+
assert represented_user["id"] == other_user.id
+
+ result =
+ conn
+ |> assign(:user, other_user)
+ |> assign(:token, insert(:oauth_token, user: other_user, scopes: ["read:statuses"]))
+ |> get("/api/v1/pleroma/statuses/#{activity.id}/emoji_reactions_by")
+ |> json_response(200)
+
+ assert [%{"emoji" => "🎅", "count" => 1, "accounts" => [_represented_user], "reacted" => true}] =
+ result
end
test "/api/v1/pleroma/conversations/:id" do