diff --git a/CHANGELOG.md b/CHANGELOG.md index 2114589af..3169fb83e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - **Breaking:** Admin API: `PUT /api/pleroma/admin/reports/:id` is now `PATCH /api/pleroma/admin/reports`, see admin_api.md for details - **Breaking:** `/api/pleroma/admin/users/invite_token` now uses `POST`, changed accepted params and returns full invite in json instead of only token string. - **Breaking** replying to reports is now "report notes", enpoint changed from `POST /api/pleroma/admin/reports/:id/respond` to `POST /api/pleroma/admin/reports/:id/notes` +- Mastodon API: stopped sanitizing display names, field names and subject fields since they are supposed to be treated as plaintext - Admin API: Return `total` when querying for reports - Mastodon API: Return `pleroma.direct_conversation_id` when creating a direct message (`POST /api/v1/statuses`) - Admin API: Return link alongside with token on password reset @@ -120,7 +121,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - MRF: `Delete` activities being exempt from MRF policies - OTP releases: Not being able to configure OAuth expired token cleanup interval - OTP releases: Not being able to configure HTML sanitization policy +- OTP releases: Not being able to change upload limit (again) - Favorites timeline now ordered by favorite date instead of post date +- Support for cancellation of a follow request
API Changes diff --git a/config/config.exs b/config/config.exs index 34716cf37..41c1ff637 100644 --- a/config/config.exs +++ b/config/config.exs @@ -51,20 +51,6 @@ telemetry_event: [Pleroma.Repo.Instrumenter], migration_lock: nil -scheduled_jobs = - with digest_config <- Application.get_env(:pleroma, :email_notifications)[:digest], - true <- digest_config[:active] do - [{digest_config[:schedule], {Pleroma.Daemons.DigestEmailDaemon, :perform, []}}] - else - _ -> [] - end - -config :pleroma, Pleroma.Scheduler, - global: true, - overlap: true, - timezone: :utc, - jobs: scheduled_jobs - config :pleroma, Pleroma.Captcha, enabled: true, seconds_valid: 300, @@ -495,6 +481,12 @@ scheduled_activities: 10, background: 5, attachments_cleanup: 5 + ], + crontab: [ + {"0 0 * * *", Pleroma.Workers.Cron.ClearOauthTokenWorker}, + {"0 * * * *", Pleroma.Workers.Cron.StatsWorker}, + {"* * * * *", Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker}, + {"0 0 * * 0", Pleroma.Workers.Cron.DigestEmailsWorker} ] config :pleroma, :workers, @@ -578,7 +570,6 @@ config :pleroma, :email_notifications, digest: %{ active: false, - schedule: "0 0 * * 0", interval: 7, inactivity_threshold: 7 } @@ -586,8 +577,7 @@ config :pleroma, :oauth2, token_expires_in: 600, issue_new_refresh_token: true, - clean_expired_tokens: false, - clean_expired_tokens_interval: 86_400_000 + clean_expired_tokens: false config :pleroma, :database, rum_enabled: false @@ -622,7 +612,6 @@ config :pleroma, configurable_from_database: false -config :swarm, node_blacklist: [~r/myhtml_.*$/] # Import environment specific config. This must remain at the bottom # of this file so it overrides the configuration defined above. import_config "#{Mix.env()}.exs" diff --git a/config/description.exs b/config/description.exs index a4d1a74a7..e5bac9b3f 100644 --- a/config/description.exs +++ b/config/description.exs @@ -871,7 +871,7 @@ }, %{ 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: [ @@ -942,7 +942,7 @@ children: [ %{ key: :level, - type: :atom, + type: {:dropdown, :atom}, description: "Log level", suggestions: [:debug, :info, :warn, :error] }, @@ -974,7 +974,7 @@ children: [ %{ key: :level, - type: :atom, + type: {:dropdown, :atom}, description: "Log level", suggestions: [:debug, :info, :warn, :error] }, @@ -998,7 +998,7 @@ children: [ %{ key: :level, - type: :atom, + type: {:dropdown, :atom}, description: "Log level", suggestions: [:debug, :info, :warn, :error] }, @@ -1969,7 +1969,7 @@ }, %{ key: :verbose, - type: [:atom, false], + type: {:dropdown, :atom}, description: "Logs verbose mode", suggestions: [false, :error, :warn, :info, :debug] }, @@ -2178,7 +2178,7 @@ %{ key: :new_window, type: :boolean, - description: "Set to `false` to remove target='_blank' attribute" + description: "Link urls will open in new window/tab" }, %{ key: :truncate, @@ -2519,13 +2519,6 @@ key: :clean_expired_tokens, type: :boolean, description: "Enable a background job to clean expired oauth tokens. Default: `false`." - }, - %{ - key: :clean_expired_tokens_interval, - type: :integer, - description: - "Interval to run the job to clean expired tokens. Default: 86_400_000 (24 hours).", - suggestions: [86_400_000] } ] }, diff --git a/config/test.exs b/config/test.exs index e48a8df5a..3af9a30d1 100644 --- a/config/test.exs +++ b/config/test.exs @@ -69,10 +69,6 @@ queues: false, prune: :disabled -config :pleroma, Pleroma.Scheduler, - jobs: [], - global: false - config :pleroma, Pleroma.ScheduledActivity, daily_user_limit: 2, total_user_limit: 3, diff --git a/docs/API/admin_api.md b/docs/API/admin_api.md index e445583cb..fb6dfcb08 100644 --- a/docs/API/admin_api.md +++ b/docs/API/admin_api.md @@ -689,7 +689,6 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret - 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 82d967e4d..89245261c 100644 --- a/docs/API/differences_in_mastoapi_responses.md +++ b/docs/API/differences_in_mastoapi_responses.md @@ -101,7 +101,7 @@ The `type` value is `move`. Has an additional field: - `target`: new account -### EmojiReaction Notification +### EmojiReact Notification The `type` value is `pleroma:emoji_reaction`. Has these fields: diff --git a/docs/admin/config.md b/docs/admin/config.md deleted file mode 100644 index b39a73961..000000000 --- a/docs/admin/config.md +++ /dev/null @@ -1,84 +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. - -## 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. If `reboot time` settings were changed, pleroma must be rebooted. - -**ATTENTION** - -**Be careful while changing the settings. Every inaccurate configuration change can break the federation or the instance load.** - -*Compile time settings, which require instance reboot and can break instance loading:* -- all settings inside these keys: - - `:hackney_pools` - - `:chat` - - `Oban` - - `:rate_limit` - - `:markup` - - `:streamer` -- partially settings inside these keys: - - `:seconds_valid` in `Pleroma.Captcha` - - `:proxy_remote` in `Pleroma.Upload` - - `:upload_limit` in `:instance` - - `:digest` in `:email_notifications` - - `:clean_expired_tokens` in `:oauth2` - - `:enabled` in `Pleroma.ActivityExpiration` - - `:enabled` in `Pleroma.ScheduledActivity` - - `:enabled` in `:gopher` - -## 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. If migrate_from_db task was runned, backup and 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..cc32bf859 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` -To delete transfered settings from database optional flag `-d` can be used. is `prod` by default. +!!! 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. `` is `prod` by default. + ```sh tab="OTP" ./bin/pleroma_ctl config migrate_from_db [--env=] [-d] ``` diff --git a/docs/administration/backup.md b/docs/administration/backup.md index 2c70e7bf8..685c45128 100644 --- a/docs/administration/backup.md +++ b/docs/administration/backup.md @@ -1,17 +1,35 @@ -# Backup/Restore your instance +# Backup/Restore/Move/Remove your instance ## Backup 1. Stop the Pleroma service. 2. Go to the working directory of Pleroma (default is `/opt/pleroma`) -3. Run `sudo -Hu postgres pg_dump -d --format=custom -f ` +3. Run `sudo -Hu postgres pg_dump -d --format=custom -f ` (make sure the postgres user has write access to the destination file) 4. Copy `pleroma.pgdump`, `config/prod.secret.exs` and the `uploads` folder to your backup destination. If you have other modifications, copy those changes too. 5. Restart the Pleroma service. -## Restore +## Restore/Move -1. Stop the Pleroma service. -2. Go to the working directory of Pleroma (default is `/opt/pleroma`) -3. Copy the above mentioned files back to their original position. -4. Run `sudo -Hu postgres pg_restore -d -v -1 ` -5. Restart the Pleroma service. +1. Optionally reinstall Pleroma (either on the same server or on another server if you want to move servers). Try to use the same database name. +2. Stop the Pleroma service. +3. Go to the working directory of Pleroma (default is `/opt/pleroma`) +4. Copy the above mentioned files back to their original position. +5. Drop the existing database and recreate an empty one `sudo -Hu postgres psql -c 'DROP DATABASE ;';` `sudo -Hu postgres psql -c 'CREATE DATABASE ;';` +6. Run `sudo -Hu postgres pg_restore -d -v -1 ` +7. If you installed a newer Pleroma version, you should run `mix ecto.migrate`[^1]. This task performs database migrations, if there were any. +8. Restart the Pleroma service. + +[^1]: Prefix with `MIX_ENV=prod` to run it using the production config file. + +## Remove + +1. Optionally you can remove the users of your instance. This will trigger delete requests for their accounts and posts. Note that this is 'best effort' and doesn't mean that all traces of your instance will be gone from the fediverse. + * You can do this from the admin-FE where you can select all local users and delete the accounts using the *Moderate multiple users* dropdown. + * You can also list local users and delete them individualy using the CLI tasks for [Managing users](./CLI_tasks/user.md). +2. Stop the Pleroma service `systemctl stop pleroma` +3. Disable pleroma from systemd `systemctl disable pleroma` +4. Remove the files and folders you created during installation (see installation guide). This includes the pleroma, nginx and systemd files and folders. +5. Reload nginx now that the configuration is removed `systemctl reload nginx` +6. Remove the database and database user `sudo -Hu postgres psql -c 'DROP DATABASE ;';` `sudo -Hu postgres psql -c 'DROP USER ;';` +7. Remove the system user `userdel pleroma` +8. Remove the dependencies that you don't need anymore (see installation guide). Make sure you don't remove packages that are still needed for other software that you have running! diff --git a/docs/configuration/cheatsheet.md b/docs/configuration/cheatsheet.md index ed9049a8d..2bd935983 100644 --- a/docs/configuration/cheatsheet.md +++ b/docs/configuration/cheatsheet.md @@ -513,6 +513,7 @@ Configuration options described in [Oban readme](https://github.com/sorentwo/oba * `verbose` - logs verbosity * `prune` - non-retryable jobs [pruning settings](https://github.com/sorentwo/oban#pruning) (`:disabled` / `{:maxlen, value}` / `{:maxage, value}`) * `queues` - job queues (see below) +* `crontab` - periodic jobs, see [`Oban.Cron`](#obancron) Pleroma has the following queues: @@ -524,6 +525,12 @@ Pleroma has the following queues: * `web_push` - Web push notifications * `scheduled_activities` - Scheduled activities, see [`Pleroma.ScheduledActivity`](#pleromascheduledactivity) +#### Oban.Cron + +Pleroma has these periodic job workers: + +`Pleroma.Workers.Cron.ClearOauthTokenWorker` - a job worker to cleanup expired oauth tokens. + Example: ```elixir @@ -534,6 +541,9 @@ config :pleroma, Oban, queues: [ federator_incoming: 50, federator_outgoing: 50 + ], + crontab: [ + {"0 0 * * *", Pleroma.Workers.Cron.ClearOauthTokenWorker} ] ``` @@ -816,8 +826,7 @@ Configure OAuth 2 provider capabilities: * `token_expires_in` - The lifetime in seconds of the access token. * `issue_new_refresh_token` - Keeps old refresh token or generate new refresh token when to obtain an access token. -* `clean_expired_tokens` - Enable a background job to clean expired oauth tokens. Defaults to `false`. -* `clean_expired_tokens_interval` - Interval to run the job to clean expired tokens. Defaults to `86_400_000` (24 hours). +* `clean_expired_tokens` - Enable a background job to clean expired oauth tokens. Defaults to `false`. Interval settings sets in configuration periodic jobs [`Oban.Cron`](#obancron) ## Link parsing @@ -856,4 +865,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/mix/tasks/pleroma/email.ex b/lib/mix/tasks/pleroma/email.ex index 2c3801429..d3fac6ec8 100644 --- a/lib/mix/tasks/pleroma/email.ex +++ b/lib/mix/tasks/pleroma/email.ex @@ -1,5 +1,6 @@ defmodule Mix.Tasks.Pleroma.Email do use Mix.Task + import Mix.Pleroma @shortdoc "Simple Email test" @moduledoc File.read!("docs/administration/CLI_tasks/email.md") @@ -18,8 +19,6 @@ def run(["test" | args]) do email = Pleroma.Emails.AdminEmail.test_email(options[:to]) {:ok, _} = Pleroma.Emails.Mailer.deliver(email) - Mix.shell().info( - "Test email has been sent to #{inspect(email.to)} from #{inspect(email.from)}" - ) + shell_info("Test email has been sent to #{inspect(email.to)} from #{inspect(email.from)}") end end diff --git a/lib/pleroma/activity.ex b/lib/pleroma/activity.ex index 0f8fce774..72e2256ea 100644 --- a/lib/pleroma/activity.ex +++ b/lib/pleroma/activity.ex @@ -31,7 +31,7 @@ defmodule Pleroma.Activity do "Announce" => "reblog", "Like" => "favourite", "Move" => "move", - "EmojiReaction" => "pleroma:emoji_reaction" + "EmojiReact" => "pleroma:emoji_reaction" } @mastodon_to_ap_notification_types for {k, v} <- @mastodon_notification_types, diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex index 2c8889ce5..27758cf94 100644 --- a/lib/pleroma/application.ex +++ b/lib/pleroma/application.ex @@ -42,12 +42,9 @@ def start(_type, _args) do children = [ Pleroma.Repo, - Pleroma.Scheduler, Pleroma.Config.TransferTask, Pleroma.Emoji, Pleroma.Captcha, - Pleroma.Daemons.ScheduledActivityDaemon, - Pleroma.Daemons.ActivityExpirationDaemon, Pleroma.Plugs.RateLimiter.Supervisor ] ++ cachex_children() ++ @@ -58,7 +55,6 @@ def start(_type, _args) do {Oban, Pleroma.Config.get(Oban)} ] ++ task_children(@env) ++ - oauth_cleanup_child(oauth_cleanup_enabled?()) ++ streamer_child(@env) ++ chat_child(@env, chat_enabled?()) ++ [ @@ -160,20 +156,12 @@ defp build_cachex(type, opts), defp chat_enabled?, do: Pleroma.Config.get([:chat, :enabled]) - defp oauth_cleanup_enabled?, - do: Pleroma.Config.get([:oauth2, :clean_expired_tokens], false) - defp streamer_child(:test), do: [] defp streamer_child(_) do [Pleroma.Web.Streamer.supervisor()] end - defp oauth_cleanup_child(true), - do: [Pleroma.Web.OAuth.Token.CleanWorker] - - defp oauth_cleanup_child(_), do: [] - defp chat_child(_env, true) do [Pleroma.Web.ChatChannel.ChatChannelState] end diff --git a/lib/pleroma/daemons/activity_expiration_daemon.ex b/lib/pleroma/daemons/activity_expiration_daemon.ex deleted file mode 100644 index cab7628c4..000000000 --- a/lib/pleroma/daemons/activity_expiration_daemon.ex +++ /dev/null @@ -1,66 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2019 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Daemons.ActivityExpirationDaemon do - alias Pleroma.Activity - alias Pleroma.ActivityExpiration - alias Pleroma.Config - alias Pleroma.Repo - alias Pleroma.User - alias Pleroma.Web.CommonAPI - - require Logger - use GenServer - import Ecto.Query - - @schedule_interval :timer.minutes(1) - - def start_link(_) do - GenServer.start_link(__MODULE__, nil) - end - - @impl true - def init(_) do - if Config.get([ActivityExpiration, :enabled]) do - schedule_next() - {:ok, nil} - else - :ignore - end - end - - def perform(:execute, expiration_id) do - try do - expiration = - ActivityExpiration - |> where([e], e.id == ^expiration_id) - |> Repo.one!() - - activity = Activity.get_by_id_with_object(expiration.activity_id) - user = User.get_by_ap_id(activity.object.data["actor"]) - CommonAPI.delete(activity.id, user) - rescue - error -> - Logger.error("#{__MODULE__} Couldn't delete expired activity: #{inspect(error)}") - end - end - - @impl true - def handle_info(:perform, state) do - ActivityExpiration.due_expirations(@schedule_interval) - |> Enum.each(fn expiration -> - Pleroma.Workers.ActivityExpirationWorker.enqueue( - "activity_expiration", - %{"activity_expiration_id" => expiration.id} - ) - end) - - schedule_next() - {:noreply, state} - end - - defp schedule_next do - Process.send_after(self(), :perform, @schedule_interval) - end -end diff --git a/lib/pleroma/daemons/digest_email_daemon.ex b/lib/pleroma/daemons/digest_email_daemon.ex deleted file mode 100644 index b4c8eaad9..000000000 --- a/lib/pleroma/daemons/digest_email_daemon.ex +++ /dev/null @@ -1,42 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Daemons.DigestEmailDaemon do - alias Pleroma.Repo - alias Pleroma.Workers.DigestEmailsWorker - - import Ecto.Query - - def perform do - config = Pleroma.Config.get([:email_notifications, :digest]) - negative_interval = -Map.fetch!(config, :interval) - inactivity_threshold = Map.fetch!(config, :inactivity_threshold) - inactive_users_query = Pleroma.User.list_inactive_users_query(inactivity_threshold) - - now = NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second) - - from(u in inactive_users_query, - where: fragment(~s(? ->'digest' @> 'true'), u.email_notifications), - where: u.last_digest_emailed_at < datetime_add(^now, ^negative_interval, "day"), - select: u - ) - |> Repo.all() - |> Enum.each(fn user -> - DigestEmailsWorker.enqueue("digest_email", %{"user_id" => user.id}) - end) - end - - @doc """ - Send digest email to the given user. - Updates `last_digest_emailed_at` field for the user and returns the updated user. - """ - @spec perform(Pleroma.User.t()) :: Pleroma.User.t() - def perform(user) do - with %Swoosh.Email{} = email <- Pleroma.Emails.UserEmail.digest_email(user) do - Pleroma.Emails.Mailer.deliver_async(email) - end - - Pleroma.User.touch_last_digest_emailed_at(user) - end -end diff --git a/lib/pleroma/daemons/scheduled_activity_daemon.ex b/lib/pleroma/daemons/scheduled_activity_daemon.ex deleted file mode 100644 index aee5f723a..000000000 --- a/lib/pleroma/daemons/scheduled_activity_daemon.ex +++ /dev/null @@ -1,62 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Daemons.ScheduledActivityDaemon do - @moduledoc """ - Sends scheduled activities to the job queue. - """ - - alias Pleroma.Config - alias Pleroma.ScheduledActivity - alias Pleroma.User - alias Pleroma.Web.CommonAPI - - use GenServer - require Logger - - @schedule_interval :timer.minutes(1) - - def start_link(_) do - GenServer.start_link(__MODULE__, nil) - end - - def init(_) do - if Config.get([ScheduledActivity, :enabled]) do - schedule_next() - {:ok, nil} - else - :ignore - end - end - - def perform(:execute, scheduled_activity_id) do - try do - {:ok, scheduled_activity} = ScheduledActivity.delete(scheduled_activity_id) - %User{} = user = User.get_cached_by_id(scheduled_activity.user_id) - {:ok, _result} = CommonAPI.post(user, scheduled_activity.params) - rescue - error -> - Logger.error( - "#{__MODULE__} Couldn't create a status from the scheduled activity: #{inspect(error)}" - ) - end - end - - def handle_info(:perform, state) do - ScheduledActivity.due_activities(@schedule_interval) - |> Enum.each(fn scheduled_activity -> - Pleroma.Workers.ScheduledActivityWorker.enqueue( - "execute", - %{"activity_id" => scheduled_activity.id} - ) - end) - - schedule_next() - {:noreply, state} - end - - defp schedule_next do - Process.send_after(self(), :perform, @schedule_interval) - end -end diff --git a/lib/pleroma/docs/generator.ex b/lib/pleroma/docs/generator.ex index 6b12dcdd9..e0fc8cd02 100644 --- a/lib/pleroma/docs/generator.ex +++ b/lib/pleroma/docs/generator.ex @@ -13,7 +13,7 @@ def list_modules_in_dir(dir, start) do |> Enum.filter(&String.ends_with?(&1, ".ex")) |> Enum.map(fn filename -> module = filename |> String.trim_trailing(".ex") |> Macro.camelize() - String.to_existing_atom(start <> module) + String.to_atom(start <> module) end) end end diff --git a/lib/pleroma/following_relationship.ex b/lib/pleroma/following_relationship.ex index 0b0219b82..b8cb3bf03 100644 --- a/lib/pleroma/following_relationship.ex +++ b/lib/pleroma/following_relationship.ex @@ -58,8 +58,8 @@ def follow(%User{} = follower, %User{} = following, state \\ "accept") do def unfollow(%User{} = follower, %User{} = following) do case get(follower, following) do - nil -> {:ok, nil} %__MODULE__{} = following_relationship -> Repo.delete(following_relationship) + _ -> {:ok, nil} end end diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex index d04a65a1e..66e91fcef 100644 --- a/lib/pleroma/notification.ex +++ b/lib/pleroma/notification.ex @@ -294,7 +294,7 @@ def create_notifications(%Activity{data: %{"to" => _, "type" => "Create"}} = act end def create_notifications(%Activity{data: %{"type" => type}} = activity) - when type in ["Like", "Announce", "Follow", "Move", "EmojiReaction"] do + when type in ["Like", "Announce", "Follow", "Move", "EmojiReact"] do notifications = activity |> get_notified_from_activity() @@ -322,7 +322,7 @@ def create_notification(%Activity{} = activity, %User{} = user) do def get_notified_from_activity(activity, local_only \\ true) def get_notified_from_activity(%Activity{data: %{"type" => type}} = activity, local_only) - when type in ["Create", "Like", "Announce", "Follow", "Move", "EmojiReaction"] do + when type in ["Create", "Like", "Announce", "Follow", "Move", "EmojiReact"] do [] |> Utils.maybe_notify_to_recipients(activity) |> Utils.maybe_notify_mentioned_recipients(activity) diff --git a/lib/pleroma/plugs/parsers_plug.ex b/lib/pleroma/plugs/parsers_plug.ex deleted file mode 100644 index 2e493ce0e..000000000 --- a/lib/pleroma/plugs/parsers_plug.ex +++ /dev/null @@ -1,21 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Plugs.Parsers do - @moduledoc "Initializes Plug.Parsers with upload limit set at boot time" - - @behaviour Plug - - def init(_opts) do - Plug.Parsers.init( - parsers: [:urlencoded, :multipart, :json], - pass: ["*/*"], - json_decoder: Jason, - length: Pleroma.Config.get([:instance, :upload_limit]), - body_reader: {Pleroma.Web.Plugs.DigestPlug, :read_body, []} - ) - end - - defdelegate call(conn, opts), to: Plug.Parsers -end diff --git a/lib/pleroma/scheduled_activity.ex b/lib/pleroma/scheduled_activity.ex index fea2cf3ff..e81bfcd7d 100644 --- a/lib/pleroma/scheduled_activity.ex +++ b/lib/pleroma/scheduled_activity.ex @@ -5,15 +5,19 @@ defmodule Pleroma.ScheduledActivity do use Ecto.Schema + alias Ecto.Multi alias Pleroma.Config alias Pleroma.Repo alias Pleroma.ScheduledActivity alias Pleroma.User alias Pleroma.Web.CommonAPI.Utils + alias Pleroma.Workers.ScheduledActivityWorker import Ecto.Query import Ecto.Changeset + @type t :: %__MODULE__{} + @min_offset :timer.minutes(5) schema "scheduled_activities" do @@ -105,16 +109,32 @@ def far_enough?(scheduled_at) do end def new(%User{} = user, attrs) do - %ScheduledActivity{user_id: user.id} - |> changeset(attrs) + changeset(%ScheduledActivity{user_id: user.id}, attrs) end + @doc """ + Creates ScheduledActivity and add to queue to perform at scheduled_at date + """ + @spec create(User.t(), map()) :: {:ok, ScheduledActivity.t()} | {:error, Ecto.Changeset.t()} def create(%User{} = user, attrs) do - user - |> new(attrs) - |> Repo.insert() + Multi.new() + |> Multi.insert(:scheduled_activity, new(user, attrs)) + |> maybe_add_jobs(Config.get([ScheduledActivity, :enabled])) + |> Repo.transaction() + |> transaction_response end + defp maybe_add_jobs(multi, true) do + multi + |> Multi.run(:scheduled_activity_job, fn _repo, %{scheduled_activity: activity} -> + %{activity_id: activity.id} + |> ScheduledActivityWorker.new(scheduled_at: activity.scheduled_at) + |> Oban.insert() + end) + end + + defp maybe_add_jobs(multi, _), do: multi + def get(%User{} = user, scheduled_activity_id) do ScheduledActivity |> where(user_id: ^user.id) @@ -122,25 +142,43 @@ def get(%User{} = user, scheduled_activity_id) do |> Repo.one() end - def update(%ScheduledActivity{} = scheduled_activity, attrs) do - scheduled_activity - |> update_changeset(attrs) - |> Repo.update() + @spec update(ScheduledActivity.t(), map()) :: + {:ok, ScheduledActivity.t()} | {:error, Ecto.Changeset.t()} + def update(%ScheduledActivity{id: id} = scheduled_activity, attrs) do + with {:error, %Ecto.Changeset{valid?: true} = changeset} <- + {:error, update_changeset(scheduled_activity, attrs)} do + Multi.new() + |> Multi.update(:scheduled_activity, changeset) + |> Multi.update_all(:scheduled_job, job_query(id), + set: [scheduled_at: get_field(changeset, :scheduled_at)] + ) + |> Repo.transaction() + |> transaction_response + end end - def delete(%ScheduledActivity{} = scheduled_activity) do - scheduled_activity - |> Repo.delete() + @doc "Deletes a ScheduledActivity and linked jobs." + @spec delete(ScheduledActivity.t() | binary() | integer) :: + {:ok, ScheduledActivity.t()} | {:error, Ecto.Changeset.t()} + def delete(%ScheduledActivity{id: id} = scheduled_activity) do + Multi.new() + |> Multi.delete(:scheduled_activity, scheduled_activity, stale_error_field: :id) + |> Multi.delete_all(:jobs, job_query(id)) + |> Repo.transaction() + |> transaction_response end def delete(id) when is_binary(id) or is_integer(id) do - ScheduledActivity - |> where(id: ^id) - |> select([sa], sa) - |> Repo.delete_all() - |> case do - {1, [scheduled_activity]} -> {:ok, scheduled_activity} - _ -> :error + delete(%__MODULE__{id: id}) + end + + defp transaction_response(result) do + case result do + {:ok, %{scheduled_activity: scheduled_activity}} -> + {:ok, scheduled_activity} + + {:error, _, changeset, _} -> + {:error, changeset} end end @@ -158,4 +196,11 @@ def due_activities(offset \\ 0) do |> where([sa], sa.scheduled_at < ^naive_datetime) |> Repo.all() end + + def job_query(scheduled_activity_id) do + from(j in Oban.Job, + where: j.queue == "scheduled_activities", + where: fragment("args ->> 'activity_id' = ?::text", ^to_string(scheduled_activity_id)) + ) + end end diff --git a/lib/pleroma/scheduler.ex b/lib/pleroma/scheduler.ex deleted file mode 100644 index d84cd99ad..000000000 --- a/lib/pleroma/scheduler.ex +++ /dev/null @@ -1,7 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Scheduler do - use Quantum.Scheduler, otp_app: :pleroma -end diff --git a/lib/pleroma/stats.ex b/lib/pleroma/stats.ex index 8154a09b7..cf590fb01 100644 --- a/lib/pleroma/stats.ex +++ b/lib/pleroma/stats.ex @@ -9,22 +9,43 @@ defmodule Pleroma.Stats do use GenServer - @interval 1000 * 60 * 60 + @init_state %{ + peers: [], + stats: %{ + domain_count: 0, + status_count: 0, + user_count: 0 + } + } def start_link(_) do - GenServer.start_link(__MODULE__, initial_data(), name: __MODULE__) + GenServer.start_link( + __MODULE__, + @init_state, + name: __MODULE__ + ) end + @doc "Performs update stats" def force_update do GenServer.call(__MODULE__, :force_update) end + @doc "Performs collect stats" + def do_collect do + GenServer.cast(__MODULE__, :run_update) + end + + @doc "Returns stats data" + @spec get_stats() :: %{domain_count: integer(), status_count: integer(), user_count: integer()} def get_stats do %{stats: stats} = GenServer.call(__MODULE__, :get_state) stats end + @doc "Returns list peers" + @spec get_peers() :: list(String.t()) def get_peers do %{peers: peers} = GenServer.call(__MODULE__, :get_state) @@ -32,7 +53,6 @@ def get_peers do end def init(args) do - Process.send(self(), :run_update, []) {:ok, args} end @@ -45,17 +65,12 @@ def handle_call(:get_state, _from, state) do {:reply, state, state} end - def handle_info(:run_update, _state) do + def handle_cast(:run_update, _state) do new_stats = get_stat_data() - Process.send_after(self(), :run_update, @interval) {:noreply, new_stats} end - defp initial_data do - %{peers: [], stats: %{}} - end - defp get_stat_data do peers = from( @@ -74,7 +89,11 @@ defp get_stat_data do %{ peers: peers, - stats: %{domain_count: domain_count, status_count: status_count, user_count: user_count} + stats: %{ + domain_count: domain_count, + status_count: status_count, + user_count: user_count + } } end end diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 89cba3e5e..44c15ee9d 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -647,25 +647,48 @@ def follow(%User{} = follower, %User{} = followed, state \\ "accept") do end end + def unfollow(%User{ap_id: ap_id}, %User{ap_id: ap_id}) do + {:error, "Not subscribed!"} + end + def unfollow(%User{} = follower, %User{} = followed) do - if following?(follower, followed) and follower.ap_id != followed.ap_id do - FollowingRelationship.unfollow(follower, followed) + case get_follow_state(follower, followed) do + state when state in ["accept", "pending"] -> + FollowingRelationship.unfollow(follower, followed) + {:ok, followed} = update_follower_count(followed) - {:ok, followed} = update_follower_count(followed) + {:ok, follower} = + follower + |> update_following_count() + |> set_cache() - {:ok, follower} = - follower - |> update_following_count() - |> set_cache() + {:ok, follower, Utils.fetch_latest_follow(follower, followed)} - {:ok, follower, Utils.fetch_latest_follow(follower, followed)} - else - {:error, "Not subscribed!"} + nil -> + {:error, "Not subscribed!"} end end defdelegate following?(follower, followed), to: FollowingRelationship + def get_follow_state(%User{} = follower, %User{} = following) do + following_relationship = FollowingRelationship.get(follower, following) + + case {following_relationship, following.local} do + {nil, false} -> + case Utils.fetch_latest_follow(follower, following) do + %{data: %{"state" => state}} when state in ["pending", "accept"] -> state + _ -> nil + end + + {%{state: state}, _} -> + state + + {nil, _} -> + nil + end + end + def locked?(%User{} = user) do user.locked || false end diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 73acfe02e..7bd405d90 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -581,7 +581,7 @@ def handle_incoming( "star" => "⭐" } - @doc "Rewrite misskey likes into EmojiReactions" + @doc "Rewrite misskey likes into EmojiReacts" def handle_incoming( %{ "type" => "Like", @@ -590,7 +590,7 @@ def handle_incoming( options ) do data - |> Map.put("type", "EmojiReaction") + |> Map.put("type", "EmojiReact") |> Map.put("content", @misskey_reactions[reaction] || reaction) |> handle_incoming(options) end @@ -611,7 +611,7 @@ def handle_incoming( def handle_incoming( %{ - "type" => "EmojiReaction", + "type" => "EmojiReact", "object" => object_id, "actor" => _actor, "id" => id, @@ -752,7 +752,7 @@ def handle_incoming( def handle_incoming( %{ "type" => "Undo", - "object" => %{"type" => "EmojiReaction", "id" => reaction_activity_id}, + "object" => %{"type" => "EmojiReact", "id" => reaction_activity_id}, "actor" => _actor, "id" => id } = data, diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index 4f7fdaf38..10ce5eee8 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -308,7 +308,7 @@ def make_like_data( def make_emoji_reaction_data(user, object, emoji, activity_id) do make_like_data(user, object, activity_id) - |> Map.put("type", "EmojiReaction") + |> Map.put("type", "EmojiReact") |> Map.put("content", emoji) end @@ -490,10 +490,19 @@ def fetch_latest_follow(%User{ap_id: follower_id}, %User{ap_id: followed_id}) do |> Repo.one() end + def fetch_latest_undo(%User{ap_id: ap_id}) do + "Undo" + |> Activity.Queries.by_type() + |> where(actor: ^ap_id) + |> order_by([activity], fragment("? desc nulls last", activity.id)) + |> limit(1) + |> Repo.one() + end + def get_latest_reaction(internal_activity_id, %{ap_id: ap_id}, emoji) do %{data: %{"object" => object_ap_id}} = Activity.get_by_id(internal_activity_id) - "EmojiReaction" + "EmojiReact" |> Activity.Queries.by_type() |> where(actor: ^ap_id) |> where([activity], fragment("?->>'content' = ?", activity.data, ^emoji)) diff --git a/lib/pleroma/web/admin_api/admin_api_controller.ex b/lib/pleroma/web/admin_api/admin_api_controller.ex index 293f1befc..c95cd182d 100644 --- a/lib/pleroma/web/admin_api/admin_api_controller.ex +++ b/lib/pleroma/web/admin_api/admin_api_controller.ex @@ -797,16 +797,9 @@ 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 @@ -814,45 +807,38 @@ def config_show(conn, _params) 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 + 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] + 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 + 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) - } + 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) + 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 diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex index f80cd04ec..e844de536 100644 --- a/lib/pleroma/web/common_api/utils.ex +++ b/lib/pleroma/web/common_api/utils.ex @@ -179,9 +179,9 @@ def make_poll_data(%{"poll" => %{"options" => options, "expires_in" => expires_i end) end_time = - NaiveDateTime.utc_now() - |> NaiveDateTime.add(expires_in) - |> NaiveDateTime.to_iso8601() + DateTime.utc_now() + |> DateTime.add(expires_in) + |> DateTime.to_iso8601() key = if truthy_param?(data["poll"]["multiple"]), do: "anyOf", else: "oneOf" poll = %{"type" => "Question", key => option_notes, "closed" => end_time} diff --git a/lib/pleroma/web/endpoint.ex b/lib/pleroma/web/endpoint.ex index d32c38a05..a77b73109 100644 --- a/lib/pleroma/web/endpoint.ex +++ b/lib/pleroma/web/endpoint.ex @@ -61,7 +61,17 @@ defmodule Pleroma.Web.Endpoint do plug(Plug.RequestId) plug(Plug.Logger, log: :debug) - plug(Pleroma.Plugs.Parsers) + plug(Plug.Parsers, + parsers: [ + :urlencoded, + {:multipart, length: {Pleroma.Config, :get, [[:instance, :upload_limit]]}}, + :json + ], + pass: ["*/*"], + json_decoder: Jason, + length: Pleroma.Config.get([:instance, :upload_limit]), + body_reader: {Pleroma.Web.Plugs.DigestPlug, :read_body, []} + ) plug(Plug.MethodOverride) plug(Plug.Head) diff --git a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex index 1149fb469..287d1631c 100644 --- a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex @@ -124,15 +124,18 @@ def create( ) do params = Map.put(params, "in_reply_to_status_id", params["in_reply_to_id"]) - if ScheduledActivity.far_enough?(scheduled_at) do - with {:ok, scheduled_activity} <- - ScheduledActivity.create(user, %{"params" => params, "scheduled_at" => scheduled_at}) do - conn - |> put_view(ScheduledActivityView) - |> render("show.json", scheduled_activity: scheduled_activity) - end + with {:far_enough, true} <- {:far_enough, ScheduledActivity.far_enough?(scheduled_at)}, + attrs <- %{"params" => params, "scheduled_at" => scheduled_at}, + {:ok, scheduled_activity} <- ScheduledActivity.create(user, attrs) do + conn + |> put_view(ScheduledActivityView) + |> render("show.json", scheduled_activity: scheduled_activity) else - create(conn, Map.drop(params, ["scheduled_at"])) + {:far_enough, _} -> + create(conn, Map.drop(params, ["scheduled_at"])) + + error -> + error end end diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex index a5420f480..c6d37ead7 100644 --- a/lib/pleroma/web/mastodon_api/views/account_view.ex +++ b/lib/pleroma/web/mastodon_api/views/account_view.ex @@ -67,7 +67,7 @@ def render("relationships.json", %{user: user, targets: targets}) do end defp do_render("show.json", %{user: user} = opts) do - display_name = HTML.strip_tags(user.name || user.nickname) + display_name = user.name || user.nickname image = User.avatar_url(user) |> MediaProxy.url() header = User.banner_url(user) |> MediaProxy.url() @@ -105,7 +105,7 @@ defp do_render("show.json", %{user: user} = opts) do |> User.fields() |> Enum.map(fn %{"name" => name, "value" => value} -> %{ - "name" => Pleroma.HTML.strip_tags(name), + "name" => name, "value" => Pleroma.HTML.filter_tags(value, Pleroma.HTML.Scrubber.LinksOnly) } end) diff --git a/lib/pleroma/web/mastodon_api/views/poll_view.ex b/lib/pleroma/web/mastodon_api/views/poll_view.ex index 753039da3..6bb3652fb 100644 --- a/lib/pleroma/web/mastodon_api/views/poll_view.ex +++ b/lib/pleroma/web/mastodon_api/views/poll_view.ex @@ -5,7 +5,6 @@ defmodule Pleroma.Web.MastodonAPI.PollView do use Pleroma.Web, :view - alias Pleroma.HTML alias Pleroma.Web.CommonAPI.Utils def render("show.json", %{object: object, multiple: multiple, options: options} = params) do @@ -57,7 +56,7 @@ defp options_and_votes_count(options) do current_count = option["replies"]["totalItems"] || 0 {%{ - title: HTML.strip_tags(name), + title: name, votes_count: current_count }, current_count + count} end) diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex index 5df29d93f..6cb158bbf 100644 --- a/lib/pleroma/web/mastodon_api/views/status_view.ex +++ b/lib/pleroma/web/mastodon_api/views/status_view.ex @@ -216,21 +216,6 @@ def render("show.json", %{activity: %{data: %{"object" => _object}} = activity} summary = object.data["summary"] || "" - summary_html = - summary - |> HTML.get_cached_scrubbed_html_for_activity( - User.html_filter_policy(opts[:for]), - activity, - "mastoapi:summary" - ) - - summary_plaintext = - summary - |> HTML.get_cached_stripped_html_for_activity( - activity, - "mastoapi:summary" - ) - card = render("card.json", Pleroma.Web.RichMedia.Helpers.fetch_data_for_activity(activity)) url = @@ -286,7 +271,7 @@ def render("show.json", %{activity: %{data: %{"object" => _object}} = activity} muted: thread_muted? || User.mutes?(opts[:for], user), pinned: pinned?(activity, user), sensitive: sensitive, - spoiler_text: summary_html, + spoiler_text: summary, visibility: get_visibility(object), media_attachments: attachments, poll: render(PollView, "show.json", object: object, for: opts[:for]), @@ -303,7 +288,7 @@ def render("show.json", %{activity: %{data: %{"object" => _object}} = activity} conversation_id: get_context_id(activity), in_reply_to_account_acct: reply_to_user && reply_to_user.nickname, content: %{"text/plain" => content_plaintext}, - spoiler_text: %{"text/plain" => summary_plaintext}, + spoiler_text: %{"text/plain" => summary}, expires_at: expires_at, direct_conversation_id: direct_conversation_id, thread_muted: thread_muted?, diff --git a/lib/pleroma/web/oauth/token/clean_worker.ex b/lib/pleroma/web/oauth/token/clean_worker.ex deleted file mode 100644 index 3c9c580d5..000000000 --- a/lib/pleroma/web/oauth/token/clean_worker.ex +++ /dev/null @@ -1,34 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Web.OAuth.Token.CleanWorker do - @moduledoc """ - The module represents functions to clean an expired oauth tokens. - """ - use GenServer - - @ten_seconds 10_000 - @one_day 86_400_000 - - alias Pleroma.Web.OAuth.Token - alias Pleroma.Workers.BackgroundWorker - - def start_link(_), do: GenServer.start_link(__MODULE__, %{}) - - def init(_) do - Process.send_after(self(), :perform, @ten_seconds) - {:ok, nil} - end - - @doc false - def handle_info(:perform, state) do - BackgroundWorker.enqueue("clean_expired_tokens", %{}) - interval = Pleroma.Config.get([:oauth2, :clean_expired_tokens_interval], @one_day) - - Process.send_after(self(), :perform, interval) - {:noreply, state} - end - - def perform(:clean), do: Token.delete_expired_tokens() -end diff --git a/lib/pleroma/workers/activity_expiration_worker.ex b/lib/pleroma/workers/activity_expiration_worker.ex deleted file mode 100644 index 4e3e4195f..000000000 --- a/lib/pleroma/workers/activity_expiration_worker.ex +++ /dev/null @@ -1,18 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Workers.ActivityExpirationWorker do - use Pleroma.Workers.WorkerHelper, queue: "activity_expiration" - - @impl Oban.Worker - def perform( - %{ - "op" => "activity_expiration", - "activity_expiration_id" => activity_expiration_id - }, - _job - ) do - Pleroma.Daemons.ActivityExpirationDaemon.perform(:execute, activity_expiration_id) - end -end diff --git a/lib/pleroma/workers/background_worker.ex b/lib/pleroma/workers/background_worker.ex index 323a4da1e..ac2fe6946 100644 --- a/lib/pleroma/workers/background_worker.ex +++ b/lib/pleroma/workers/background_worker.ex @@ -6,7 +6,6 @@ defmodule Pleroma.Workers.BackgroundWorker do alias Pleroma.Activity alias Pleroma.User alias Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy - alias Pleroma.Web.OAuth.Token.CleanWorker use Pleroma.Workers.WorkerHelper, queue: "background" @@ -55,10 +54,6 @@ def perform( User.perform(:follow_import, follower, followed_identifiers) end - def perform(%{"op" => "clean_expired_tokens"}, _job) do - CleanWorker.perform(:clean) - end - def perform(%{"op" => "media_proxy_preload", "message" => message}, _job) do MediaProxyWarmingPolicy.perform(:preload, message) end diff --git a/lib/pleroma/workers/cron/clear_oauth_token_worker.ex b/lib/pleroma/workers/cron/clear_oauth_token_worker.ex new file mode 100644 index 000000000..a24407874 --- /dev/null +++ b/lib/pleroma/workers/cron/clear_oauth_token_worker.ex @@ -0,0 +1,21 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Workers.Cron.ClearOauthTokenWorker do + @moduledoc """ + The worker to cleanup expired oAuth tokens. + """ + + use Oban.Worker, queue: "background" + + alias Pleroma.Config + alias Pleroma.Web.OAuth.Token + + @impl Oban.Worker + def perform(_opts, _job) do + if Config.get([:oauth2, :clean_expired_tokens], false) do + Token.delete_expired_tokens() + end + end +end diff --git a/lib/pleroma/workers/cron/digest_emails_worker.ex b/lib/pleroma/workers/cron/digest_emails_worker.ex new file mode 100644 index 000000000..0a00129df --- /dev/null +++ b/lib/pleroma/workers/cron/digest_emails_worker.ex @@ -0,0 +1,58 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Workers.Cron.DigestEmailsWorker do + @moduledoc """ + The worker to send digest emails. + """ + + use Oban.Worker, queue: "digest_emails" + + alias Pleroma.Config + alias Pleroma.Emails + alias Pleroma.Repo + alias Pleroma.User + + import Ecto.Query + + require Logger + + @impl Oban.Worker + def perform(_opts, _job) do + config = Config.get([:email_notifications, :digest]) + + if config[:active] do + negative_interval = -Map.fetch!(config, :interval) + inactivity_threshold = Map.fetch!(config, :inactivity_threshold) + inactive_users_query = User.list_inactive_users_query(inactivity_threshold) + + now = NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second) + + from(u in inactive_users_query, + where: fragment(~s(? ->'digest' @> 'true'), u.email_notifications), + where: u.last_digest_emailed_at < datetime_add(^now, ^negative_interval, "day"), + select: u + ) + |> Repo.all() + |> send_emails + end + end + + def send_emails(users) do + Enum.each(users, &send_email/1) + end + + @doc """ + Send digest email to the given user. + Updates `last_digest_emailed_at` field for the user and returns the updated user. + """ + @spec send_email(User.t()) :: User.t() + def send_email(user) do + with %Swoosh.Email{} = email <- Emails.UserEmail.digest_email(user) do + Emails.Mailer.deliver_async(email) + end + + User.touch_last_digest_emailed_at(user) + end +end diff --git a/lib/pleroma/workers/cron/purge_expired_activities_worker.ex b/lib/pleroma/workers/cron/purge_expired_activities_worker.ex new file mode 100644 index 000000000..7a52860a9 --- /dev/null +++ b/lib/pleroma/workers/cron/purge_expired_activities_worker.ex @@ -0,0 +1,46 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker do + @moduledoc """ + The worker to purge expired activities. + """ + + use Oban.Worker, queue: "activity_expiration" + + alias Pleroma.Activity + alias Pleroma.ActivityExpiration + alias Pleroma.Config + alias Pleroma.User + alias Pleroma.Web.CommonAPI + + require Logger + + @interval :timer.minutes(1) + + @impl Oban.Worker + def perform(_opts, _job) do + if Config.get([ActivityExpiration, :enabled]) do + Enum.each(ActivityExpiration.due_expirations(@interval), &delete_activity/1) + end + end + + def delete_activity(%ActivityExpiration{activity_id: activity_id}) do + with {:activity, %Activity{} = activity} <- + {:activity, Activity.get_by_id_with_object(activity_id)}, + {:user, %User{} = user} <- {:user, User.get_by_ap_id(activity.object.data["actor"])} do + CommonAPI.delete(activity.id, user) + else + {:activity, _} -> + Logger.error( + "#{__MODULE__} Couldn't delete expired activity: not found activity ##{activity_id}" + ) + + {:user, _} -> + Logger.error( + "#{__MODULE__} Couldn't delete expired activity: not found actorof ##{activity_id}" + ) + end + end +end diff --git a/lib/pleroma/workers/cron/stats_worker.ex b/lib/pleroma/workers/cron/stats_worker.ex new file mode 100644 index 000000000..425ad41ca --- /dev/null +++ b/lib/pleroma/workers/cron/stats_worker.ex @@ -0,0 +1,16 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Workers.Cron.StatsWorker do + @moduledoc """ + The worker to update peers statistics. + """ + + use Oban.Worker, queue: "background" + + @impl Oban.Worker + def perform(_opts, _job) do + Pleroma.Stats.do_collect() + end +end diff --git a/lib/pleroma/workers/digest_emails_worker.ex b/lib/pleroma/workers/digest_emails_worker.ex deleted file mode 100644 index 3e5a836d0..000000000 --- a/lib/pleroma/workers/digest_emails_worker.ex +++ /dev/null @@ -1,16 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.Workers.DigestEmailsWorker do - alias Pleroma.User - - use Pleroma.Workers.WorkerHelper, queue: "digest_emails" - - @impl Oban.Worker - def perform(%{"op" => "digest_email", "user_id" => user_id}, _job) do - user_id - |> User.get_cached_by_id() - |> Pleroma.Daemons.DigestEmailDaemon.perform() - end -end diff --git a/lib/pleroma/workers/scheduled_activity_worker.ex b/lib/pleroma/workers/scheduled_activity_worker.ex index ca7d53af1..bd41ab4ce 100644 --- a/lib/pleroma/workers/scheduled_activity_worker.ex +++ b/lib/pleroma/workers/scheduled_activity_worker.ex @@ -3,10 +3,42 @@ # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Workers.ScheduledActivityWorker do + @moduledoc """ + The worker to post scheduled activity. + """ + use Pleroma.Workers.WorkerHelper, queue: "scheduled_activities" + alias Pleroma.Config + alias Pleroma.ScheduledActivity + alias Pleroma.User + alias Pleroma.Web.CommonAPI + + require Logger + @impl Oban.Worker - def perform(%{"op" => "execute", "activity_id" => activity_id}, _job) do - Pleroma.Daemons.ScheduledActivityDaemon.perform(:execute, activity_id) + def perform(%{"activity_id" => activity_id}, _job) do + if Config.get([ScheduledActivity, :enabled]) do + case Pleroma.Repo.get(ScheduledActivity, activity_id) do + %ScheduledActivity{} = scheduled_activity -> + post_activity(scheduled_activity) + + _ -> + Logger.error("#{__MODULE__} Couldn't find scheduled activity: #{activity_id}") + end + end + end + + defp post_activity(%ScheduledActivity{user_id: user_id, params: params} = scheduled_activity) do + with {:delete, {:ok, _}} <- {:delete, ScheduledActivity.delete(scheduled_activity)}, + {:user, %User{} = user} <- {:user, User.get_cached_by_id(user_id)}, + {:post, {:ok, _}} <- {:post, CommonAPI.post(user, params)} do + :ok + else + error -> + Logger.error( + "#{__MODULE__} Couldn't create a status from the scheduled activity: #{inspect(error)}" + ) + end end end diff --git a/mix.exs b/mix.exs index 64768d0c7..fae47296a 100644 --- a/mix.exs +++ b/mix.exs @@ -63,7 +63,7 @@ def copy_nginx_config(%{path: target_path} = release) do def application do [ mod: {Pleroma.Application, []}, - extra_applications: [:logger, :runtime_tools, :comeonin, :quack, :fast_sanitize, :swarm], + extra_applications: [:logger, :runtime_tools, :comeonin, :quack, :fast_sanitize], included_applications: [:ex_syslogger] ] end @@ -108,8 +108,7 @@ defp deps do {:ecto_enum, "~> 1.4"}, {:ecto_sql, "~> 3.3.2"}, {:postgrex, ">= 0.13.5"}, - {:oban, "~> 0.12.0"}, - {:quantum, "~> 2.3"}, + {:oban, "~> 0.12.1"}, {:gettext, "~> 0.15"}, {:comeonin, "~> 4.1.1"}, {:pbkdf2_elixir, "~> 0.12.3"}, @@ -163,7 +162,7 @@ defp deps do {:esshd, "~> 0.1.0", runtime: Application.get_env(:esshd, :enabled, false)}, {:ex_const, "~> 0.2"}, {:plug_static_index_html, "~> 1.0.0"}, - {:excoveralls, "~> 0.11.1", only: :test}, + {:excoveralls, "~> 0.12.1", only: :test}, {:flake_id, "~> 0.1.0"}, {:remote_ip, git: "https://git.pleroma.social/pleroma/remote_ip.git", diff --git a/mix.lock b/mix.lock index a6590346c..f748b4047 100644 --- a/mix.lock +++ b/mix.lock @@ -34,7 +34,7 @@ "ex_doc": {:hex, :ex_doc, "0.21.3", "857ec876b35a587c5d9148a2512e952e24c24345552259464b98bfbb883c7b42", [:mix], [{:earmark, "~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "0db1ee8d1547ab4877c5b5dffc6604ef9454e189928d5ba8967d4a58a801f161"}, "ex_machina": {:hex, :ex_machina, "2.3.0", "92a5ad0a8b10ea6314b876a99c8c9e3f25f4dde71a2a835845b136b9adaf199a", [: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", "b84f6af156264530b312a8ab98ac6088f6b77ae5fe2058305c81434aa01fbaf9"}, "ex_syslogger": {:git, "https://github.com/slashmili/ex_syslogger.git", "f3963399047af17e038897c69e20d552e6899e1d", [tag: "1.4.0"]}, - "excoveralls": {:hex, :excoveralls, "0.11.2", "0c6f2c8db7683b0caa9d490fb8125709c54580b4255ffa7ad35f3264b075a643", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "e11a4490976aabeed3eb9dc70ec94a4f2d11fed5c9d4b5dc5d89bfa0a215abb5"}, + "excoveralls": {:hex, :excoveralls, "0.12.2", "a513defac45c59e310ac42fcf2b8ae96f1f85746410f30b1ff2b710a4b6cd44b", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "151c476331d49b45601ffc45f43cb3a8beb396b02a34e3777fea0ad34ae57d89"}, "fast_html": {:hex, :fast_html, "1.0.1", "5bc7df4dc4607ec2c314c16414e4111d79a209956c4f5df96602d194c61197f9", [:make, :mix], [], "hexpm", "18e627dd62051a375ef94b197f41e8027c3e8eef0180ab8f81e0543b3dc6900a"}, "fast_sanitize": {:hex, :fast_sanitize, "0.1.6", "60a5ae96879956dea409a91a77f5dd2994c24cc10f80eefd8f9892ee4c0c7b25", [:mix], [{:fast_html, "~> 1.0", [hex: :fast_html, repo: "hexpm", optional: false]}, {:plug, "~> 1.8", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "b73f50f0cb522dd0331ea8e8c90b408de42c50f37641219d6364f0e3e7efd22c"}, "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"}, diff --git a/priv/static/font/fontello.1575660578688.eot b/priv/static/font/fontello.1575660578688.eot new file mode 100644 index 000000000..31a66127f Binary files /dev/null and b/priv/static/font/fontello.1575660578688.eot differ diff --git a/priv/static/font/fontello.1575660578688.svg b/priv/static/font/fontello.1575660578688.svg new file mode 100644 index 000000000..19fa56ba4 --- /dev/null +++ b/priv/static/font/fontello.1575660578688.svg @@ -0,0 +1,126 @@ + + + +Copyright (C) 2019 by original authors @ fontello.com + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/priv/static/font/fontello.1575660578688.ttf b/priv/static/font/fontello.1575660578688.ttf new file mode 100644 index 000000000..7e990495e Binary files /dev/null and b/priv/static/font/fontello.1575660578688.ttf differ diff --git a/priv/static/font/fontello.1575660578688.woff b/priv/static/font/fontello.1575660578688.woff new file mode 100644 index 000000000..239190cba Binary files /dev/null and b/priv/static/font/fontello.1575660578688.woff differ diff --git a/priv/static/font/fontello.1575660578688.woff2 b/priv/static/font/fontello.1575660578688.woff2 new file mode 100644 index 000000000..b4d3537c5 Binary files /dev/null and b/priv/static/font/fontello.1575660578688.woff2 differ diff --git a/priv/static/font/fontello.1575662648966.eot b/priv/static/font/fontello.1575662648966.eot new file mode 100644 index 000000000..a5cb925ad Binary files /dev/null and b/priv/static/font/fontello.1575662648966.eot differ diff --git a/priv/static/font/fontello.1575662648966.svg b/priv/static/font/fontello.1575662648966.svg new file mode 100644 index 000000000..19fa56ba4 --- /dev/null +++ b/priv/static/font/fontello.1575662648966.svg @@ -0,0 +1,126 @@ + + + +Copyright (C) 2019 by original authors @ fontello.com + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/priv/static/font/fontello.1575662648966.ttf b/priv/static/font/fontello.1575662648966.ttf new file mode 100644 index 000000000..ec67a3d00 Binary files /dev/null and b/priv/static/font/fontello.1575662648966.ttf differ diff --git a/priv/static/font/fontello.1575662648966.woff b/priv/static/font/fontello.1575662648966.woff new file mode 100644 index 000000000..feee99308 Binary files /dev/null and b/priv/static/font/fontello.1575662648966.woff differ diff --git a/priv/static/font/fontello.1575662648966.woff2 b/priv/static/font/fontello.1575662648966.woff2 new file mode 100644 index 000000000..a126c585f Binary files /dev/null and b/priv/static/font/fontello.1575662648966.woff2 differ diff --git a/priv/static/static/fontello.1580232989700.css b/priv/static/fontello.1575660578688.css similarity index 75% rename from priv/static/static/fontello.1580232989700.css rename to priv/static/fontello.1575660578688.css index a9cbcb04d..f232f5600 100644 Binary files a/priv/static/static/fontello.1580232989700.css and b/priv/static/fontello.1575660578688.css differ diff --git a/priv/static/fontello.1575662648966.css b/priv/static/fontello.1575662648966.css new file mode 100644 index 000000000..a47f73e3a Binary files /dev/null and b/priv/static/fontello.1575662648966.css differ diff --git a/priv/static/index.html b/priv/static/index.html index 2fc0d5349..bf7ee958b 100644 --- a/priv/static/index.html +++ b/priv/static/index.html @@ -1 +1 @@ -Pleroma
\ No newline at end of file +Pleroma
\ No newline at end of file diff --git a/priv/static/schemas/litepub-0.1.jsonld b/priv/static/schemas/litepub-0.1.jsonld index e7ebf72be..278ad2f96 100644 --- a/priv/static/schemas/litepub-0.1.jsonld +++ b/priv/static/schemas/litepub-0.1.jsonld @@ -29,7 +29,7 @@ "@id": "litepub:oauthRegistrationEndpoint", "@type": "@id" }, - "EmojiReaction": "litepub:EmojiReaction", + "EmojiReact": "litepub:EmojiReact", "alsoKnownAs": { "@id": "as:alsoKnownAs", "@type": "@id" diff --git a/priv/static/static/font/fontello.1580232989700.woff2 b/priv/static/static/font/fontello.1580232989700.woff2 deleted file mode 100644 index 73acac54f..000000000 Binary files a/priv/static/static/font/fontello.1580232989700.woff2 and /dev/null differ diff --git a/priv/static/static/font/fontello.1580232989700.eot b/priv/static/static/font/fontello.1581007281335.eot similarity index 99% rename from priv/static/static/font/fontello.1580232989700.eot rename to priv/static/static/font/fontello.1581007281335.eot index 6be901301..3aae7d472 100644 Binary files a/priv/static/static/font/fontello.1580232989700.eot and b/priv/static/static/font/fontello.1581007281335.eot differ diff --git a/priv/static/static/font/fontello.1580232989700.svg b/priv/static/static/font/fontello.1581007281335.svg similarity index 100% rename from priv/static/static/font/fontello.1580232989700.svg rename to priv/static/static/font/fontello.1581007281335.svg diff --git a/priv/static/static/font/fontello.1580232989700.ttf b/priv/static/static/font/fontello.1581007281335.ttf similarity index 99% rename from priv/static/static/font/fontello.1580232989700.ttf rename to priv/static/static/font/fontello.1581007281335.ttf index 51d3f1e08..d3d19affe 100644 Binary files a/priv/static/static/font/fontello.1580232989700.ttf and b/priv/static/static/font/fontello.1581007281335.ttf differ diff --git a/priv/static/static/font/fontello.1580232989700.woff b/priv/static/static/font/fontello.1581007281335.woff similarity index 98% rename from priv/static/static/font/fontello.1580232989700.woff rename to priv/static/static/font/fontello.1581007281335.woff index c70e7fb7e..f6e0f80fc 100644 Binary files a/priv/static/static/font/fontello.1580232989700.woff and b/priv/static/static/font/fontello.1581007281335.woff differ diff --git a/priv/static/static/font/fontello.1581007281335.woff2 b/priv/static/static/font/fontello.1581007281335.woff2 new file mode 100644 index 000000000..5bd824c7d Binary files /dev/null and b/priv/static/static/font/fontello.1581007281335.woff2 differ diff --git a/priv/static/static/fontello.1579102213354.css b/priv/static/static/fontello.1581007281335.css similarity index 89% rename from priv/static/static/fontello.1579102213354.css rename to priv/static/static/fontello.1581007281335.css index 0f81954a5..2c747b4ae 100644 Binary files a/priv/static/static/fontello.1579102213354.css and b/priv/static/static/fontello.1581007281335.css differ diff --git a/priv/static/static/js/2.59b096781ddca107175d.js b/priv/static/static/js/2.9be9f9ec29f7536c73c3.js similarity index 82% rename from priv/static/static/js/2.59b096781ddca107175d.js rename to priv/static/static/js/2.9be9f9ec29f7536c73c3.js index f47e92efa..d464dbf74 100644 Binary files a/priv/static/static/js/2.59b096781ddca107175d.js and b/priv/static/static/js/2.9be9f9ec29f7536c73c3.js differ diff --git a/priv/static/static/js/2.59b096781ddca107175d.js.map b/priv/static/static/js/2.9be9f9ec29f7536c73c3.js.map similarity index 99% rename from priv/static/static/js/2.59b096781ddca107175d.js.map rename to priv/static/static/js/2.9be9f9ec29f7536c73c3.js.map index f13a48804..21efd7ec8 100644 Binary files a/priv/static/static/js/2.59b096781ddca107175d.js.map and b/priv/static/static/js/2.9be9f9ec29f7536c73c3.js.map differ diff --git a/priv/static/static/js/app.0aac253187b2af873849.js b/priv/static/static/js/app.0aac253187b2af873849.js new file mode 100644 index 000000000..3f2f39e83 Binary files /dev/null and b/priv/static/static/js/app.0aac253187b2af873849.js differ diff --git a/priv/static/static/js/app.0aac253187b2af873849.js.map b/priv/static/static/js/app.0aac253187b2af873849.js.map new file mode 100644 index 000000000..b2503292e Binary files /dev/null and b/priv/static/static/js/app.0aac253187b2af873849.js.map differ diff --git a/priv/static/static/js/app.9cfed8f3d06c299128ea.js b/priv/static/static/js/app.9cfed8f3d06c299128ea.js deleted file mode 100644 index d373c2a07..000000000 Binary files a/priv/static/static/js/app.9cfed8f3d06c299128ea.js and /dev/null differ diff --git a/priv/static/static/js/app.9cfed8f3d06c299128ea.js.map b/priv/static/static/js/app.9cfed8f3d06c299128ea.js.map deleted file mode 100644 index a7a943e15..000000000 Binary files a/priv/static/static/js/app.9cfed8f3d06c299128ea.js.map and /dev/null differ diff --git a/priv/static/static/js/vendors~app.9ab182239f3a2abee89f.js.map b/priv/static/static/js/vendors~app.9ab182239f3a2abee89f.js.map deleted file mode 100644 index f551dfa51..000000000 Binary files a/priv/static/static/js/vendors~app.9ab182239f3a2abee89f.js.map and /dev/null differ diff --git a/priv/static/static/js/vendors~app.9ab182239f3a2abee89f.js b/priv/static/static/js/vendors~app.c26cf2fc57e9c1975e8d.js similarity index 97% rename from priv/static/static/js/vendors~app.9ab182239f3a2abee89f.js rename to priv/static/static/js/vendors~app.c26cf2fc57e9c1975e8d.js index 0812cdba7..bffb28fa7 100644 Binary files a/priv/static/static/js/vendors~app.9ab182239f3a2abee89f.js and b/priv/static/static/js/vendors~app.c26cf2fc57e9c1975e8d.js differ diff --git a/priv/static/static/js/vendors~app.c26cf2fc57e9c1975e8d.js.map b/priv/static/static/js/vendors~app.c26cf2fc57e9c1975e8d.js.map new file mode 100644 index 000000000..044d577a6 Binary files /dev/null and b/priv/static/static/js/vendors~app.c26cf2fc57e9c1975e8d.js.map differ diff --git a/priv/static/sw-pleroma.js b/priv/static/sw-pleroma.js index 64bde2024..f55ef0112 100644 Binary files a/priv/static/sw-pleroma.js and b/priv/static/sw-pleroma.js differ diff --git a/test/activity_expiration_test.exs b/test/activity_expiration_test.exs index 4948fae16..2fc593b8c 100644 --- a/test/activity_expiration_test.exs +++ b/test/activity_expiration_test.exs @@ -7,6 +7,8 @@ defmodule Pleroma.ActivityExpirationTest do alias Pleroma.ActivityExpiration import Pleroma.Factory + clear_config([ActivityExpiration, :enabled]) + test "finds activities due to be deleted only" do activity = insert(:note_activity) expiration_due = insert(:expiration_in_the_past, %{activity_id: activity.id}) @@ -24,4 +26,27 @@ test "denies expirations that don't live long enough" do now = NaiveDateTime.utc_now() assert {:error, _} = ActivityExpiration.create(activity, now) end + + test "deletes an expiration activity" do + Pleroma.Config.put([ActivityExpiration, :enabled], true) + activity = insert(:note_activity) + + naive_datetime = + NaiveDateTime.add( + NaiveDateTime.utc_now(), + -:timer.minutes(2), + :millisecond + ) + + expiration = + insert( + :expiration_in_the_past, + %{activity_id: activity.id, scheduled_at: naive_datetime} + ) + + Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker.perform(:ops, :pid) + + refute Pleroma.Repo.get(Pleroma.Activity, activity.id) + refute Pleroma.Repo.get(Pleroma.ActivityExpiration, expiration.id) + end end diff --git a/test/daemons/activity_expiration_daemon_test.exs b/test/daemons/activity_expiration_daemon_test.exs deleted file mode 100644 index b51132fb0..000000000 --- a/test/daemons/activity_expiration_daemon_test.exs +++ /dev/null @@ -1,17 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.ActivityExpirationWorkerTest do - use Pleroma.DataCase - alias Pleroma.Activity - import Pleroma.Factory - - test "deletes an activity" do - activity = insert(:note_activity) - expiration = insert(:expiration_in_the_past, %{activity_id: activity.id}) - Pleroma.Daemons.ActivityExpirationDaemon.perform(:execute, expiration.id) - - refute Repo.get(Activity, activity.id) - end -end diff --git a/test/daemons/scheduled_activity_daemon_test.exs b/test/daemons/scheduled_activity_daemon_test.exs deleted file mode 100644 index c8e464491..000000000 --- a/test/daemons/scheduled_activity_daemon_test.exs +++ /dev/null @@ -1,19 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.ScheduledActivityDaemonTest do - use Pleroma.DataCase - alias Pleroma.ScheduledActivity - import Pleroma.Factory - - test "creates a status from the scheduled activity" do - user = insert(:user) - scheduled_activity = insert(:scheduled_activity, user: user, params: %{status: "hi"}) - Pleroma.Daemons.ScheduledActivityDaemon.perform(:execute, scheduled_activity.id) - - refute Repo.get(ScheduledActivity, scheduled_activity.id) - activity = Repo.all(Pleroma.Activity) |> Enum.find(&(&1.actor == user.ap_id)) - assert Pleroma.Object.normalize(activity).data["content"] == "hi" - end -end diff --git a/test/fixtures/emoji-reaction-no-emoji.json b/test/fixtures/emoji-reaction-no-emoji.json index fff77b29b..ef3bbe55c 100644 --- a/test/fixtures/emoji-reaction-no-emoji.json +++ b/test/fixtures/emoji-reaction-no-emoji.json @@ -1,5 +1,5 @@ { - "type": "EmojiReaction", + "type": "EmojiReact", "signature": { "type": "RsaSignature2017", "signatureValue": "fdxMfQSMwbC6wP6sh6neS/vM5879K67yQkHTbiT5Npr5wAac0y6+o3Ij+41tN3rL6wfuGTosSBTHOtta6R4GCOOhCaCSLMZKypnp1VltCzLDoyrZELnYQIC8gpUXVmIycZbREk22qWUe/w7DAFaKK4UscBlHDzeDVcA0K3Se5Sluqi9/Zh+ldAnEzj/rSEPDjrtvf5wGNf3fHxbKSRKFt90JvKK6hS+vxKUhlRFDf6/SMETw+EhwJSNW4d10yMUakqUWsFv4Acq5LW7l+HpYMvlYY1FZhNde1+uonnCyuQDyvzkff8zwtEJmAXC4RivO/VVLa17SmqheJZfI8oluVg==", diff --git a/test/fixtures/emoji-reaction-too-long.json b/test/fixtures/emoji-reaction-too-long.json index 31830d90c..e917c9a68 100644 --- a/test/fixtures/emoji-reaction-too-long.json +++ b/test/fixtures/emoji-reaction-too-long.json @@ -1,5 +1,5 @@ { - "type": "EmojiReaction", + "type": "EmojiReact", "signature": { "type": "RsaSignature2017", "signatureValue": "fdxMfQSMwbC6wP6sh6neS/vM5879K67yQkHTbiT5Npr5wAac0y6+o3Ij+41tN3rL6wfuGTosSBTHOtta6R4GCOOhCaCSLMZKypnp1VltCzLDoyrZELnYQIC8gpUXVmIycZbREk22qWUe/w7DAFaKK4UscBlHDzeDVcA0K3Se5Sluqi9/Zh+ldAnEzj/rSEPDjrtvf5wGNf3fHxbKSRKFt90JvKK6hS+vxKUhlRFDf6/SMETw+EhwJSNW4d10yMUakqUWsFv4Acq5LW7l+HpYMvlYY1FZhNde1+uonnCyuQDyvzkff8zwtEJmAXC4RivO/VVLa17SmqheJZfI8oluVg==", diff --git a/test/fixtures/emoji-reaction.json b/test/fixtures/emoji-reaction.json index 3812e43ad..fe1fecddb 100644 --- a/test/fixtures/emoji-reaction.json +++ b/test/fixtures/emoji-reaction.json @@ -1,5 +1,5 @@ { - "type": "EmojiReaction", + "type": "EmojiReact", "signature": { "type": "RsaSignature2017", "signatureValue": "fdxMfQSMwbC6wP6sh6neS/vM5879K67yQkHTbiT5Npr5wAac0y6+o3Ij+41tN3rL6wfuGTosSBTHOtta6R4GCOOhCaCSLMZKypnp1VltCzLDoyrZELnYQIC8gpUXVmIycZbREk22qWUe/w7DAFaKK4UscBlHDzeDVcA0K3Se5Sluqi9/Zh+ldAnEzj/rSEPDjrtvf5wGNf3fHxbKSRKFt90JvKK6hS+vxKUhlRFDf6/SMETw+EhwJSNW4d10yMUakqUWsFv4Acq5LW7l+HpYMvlYY1FZhNde1+uonnCyuQDyvzkff8zwtEJmAXC4RivO/VVLa17SmqheJZfI8oluVg==", diff --git a/test/scheduled_activity_test.exs b/test/scheduled_activity_test.exs index dcf12fb49..6c13d300a 100644 --- a/test/scheduled_activity_test.exs +++ b/test/scheduled_activity_test.exs @@ -8,11 +8,51 @@ defmodule Pleroma.ScheduledActivityTest do alias Pleroma.ScheduledActivity import Pleroma.Factory + clear_config([ScheduledActivity, :enabled]) + setup context do DataCase.ensure_local_uploader(context) end describe "creation" do + test "scheduled activities with jobs when ScheduledActivity enabled" do + Pleroma.Config.put([ScheduledActivity, :enabled], true) + user = insert(:user) + + today = + NaiveDateTime.utc_now() + |> NaiveDateTime.add(:timer.minutes(6), :millisecond) + |> NaiveDateTime.to_iso8601() + + attrs = %{params: %{}, scheduled_at: today} + {:ok, sa1} = ScheduledActivity.create(user, attrs) + {:ok, sa2} = ScheduledActivity.create(user, attrs) + + jobs = + Repo.all(from(j in Oban.Job, where: j.queue == "scheduled_activities", select: j.args)) + + assert jobs == [%{"activity_id" => sa1.id}, %{"activity_id" => sa2.id}] + end + + test "scheduled activities without jobs when ScheduledActivity disabled" do + Pleroma.Config.put([ScheduledActivity, :enabled], false) + user = insert(:user) + + today = + NaiveDateTime.utc_now() + |> NaiveDateTime.add(:timer.minutes(6), :millisecond) + |> NaiveDateTime.to_iso8601() + + attrs = %{params: %{}, scheduled_at: today} + {:ok, _sa1} = ScheduledActivity.create(user, attrs) + {:ok, _sa2} = ScheduledActivity.create(user, attrs) + + jobs = + Repo.all(from(j in Oban.Job, where: j.queue == "scheduled_activities", select: j.args)) + + assert jobs == [] + end + test "when daily user limit is exceeded" do user = insert(:user) @@ -24,6 +64,7 @@ test "when daily user limit is exceeded" do attrs = %{params: %{}, scheduled_at: today} {:ok, _} = ScheduledActivity.create(user, attrs) {:ok, _} = ScheduledActivity.create(user, attrs) + {:error, changeset} = ScheduledActivity.create(user, attrs) assert changeset.errors == [scheduled_at: {"daily limit exceeded", []}] end diff --git a/test/support/helpers.ex b/test/support/helpers.ex index 9f817622d..d36c29cef 100644 --- a/test/support/helpers.ex +++ b/test/support/helpers.ex @@ -54,6 +54,12 @@ defmacro __using__(_opts) do clear_config_all: 2 ] + def to_datetime(naive_datetime) do + naive_datetime + |> DateTime.from_naive!("Etc/UTC") + |> DateTime.truncate(:second) + end + def collect_ids(collection) do collection |> Enum.map(& &1.id) diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs index ff4604a52..ce68e7d0e 100644 --- a/test/web/activity_pub/activity_pub_test.exs +++ b/test/web/activity_pub/activity_pub_test.exs @@ -877,7 +877,7 @@ test "adds an emoji reaction activity to the db" do assert reaction_activity assert reaction_activity.data["actor"] == reactor.ap_id - assert reaction_activity.data["type"] == "EmojiReaction" + assert reaction_activity.data["type"] == "EmojiReact" assert reaction_activity.data["content"] == "🔥" assert reaction_activity.data["object"] == object.data["id"] assert reaction_activity.data["to"] == [User.ap_followers(reactor), activity.data["actor"]] @@ -1174,6 +1174,23 @@ test "creates an undo activity for the last follow" do assert embedded_object["object"] == followed.ap_id assert embedded_object["id"] == follow_activity.data["id"] end + + test "creates an undo activity for a pending follow request" do + follower = insert(:user) + followed = insert(:user, %{locked: true}) + + {:ok, follow_activity} = ActivityPub.follow(follower, followed) + {:ok, activity} = ActivityPub.unfollow(follower, followed) + + assert activity.data["type"] == "Undo" + assert activity.data["actor"] == follower.ap_id + + embedded_object = activity.data["object"] + assert is_map(embedded_object) + assert embedded_object["type"] == "Follow" + assert embedded_object["object"] == followed.ap_id + assert embedded_object["id"] == follow_activity.data["id"] + end end describe "blocking / unblocking" do diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs index 0829a6ec2..1b12ee3a9 100644 --- a/test/web/activity_pub/transmogrifier_test.exs +++ b/test/web/activity_pub/transmogrifier_test.exs @@ -340,7 +340,7 @@ test "it works for incoming likes" do assert data["object"] == activity.data["object"] end - test "it works for incoming misskey likes, turning them into EmojiReactions" do + test "it works for incoming misskey likes, turning them into EmojiReacts" do user = insert(:user) {:ok, activity} = CommonAPI.post(user, %{"status" => "hello"}) @@ -352,13 +352,13 @@ test "it works for incoming misskey likes, turning them into EmojiReactions" do {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) assert data["actor"] == data["actor"] - assert data["type"] == "EmojiReaction" + assert data["type"] == "EmojiReact" assert data["id"] == data["id"] assert data["object"] == activity.data["object"] assert data["content"] == "🍮" end - test "it works for incoming misskey likes that contain unicode emojis, turning them into EmojiReactions" do + test "it works for incoming misskey likes that contain unicode emojis, turning them into EmojiReacts" do user = insert(:user) {:ok, activity} = CommonAPI.post(user, %{"status" => "hello"}) @@ -371,7 +371,7 @@ test "it works for incoming misskey likes that contain unicode emojis, turning t {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) assert data["actor"] == data["actor"] - assert data["type"] == "EmojiReaction" + assert data["type"] == "EmojiReact" assert data["id"] == data["id"] assert data["object"] == activity.data["object"] assert data["content"] == "⭐" @@ -389,7 +389,7 @@ test "it works for incoming emoji reactions" do {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data) assert data["actor"] == "http://mastodon.example.org/users/admin" - assert data["type"] == "EmojiReaction" + assert data["type"] == "EmojiReact" assert data["id"] == "http://mastodon.example.org/users/admin#reactions/2" assert data["object"] == activity.data["object"] assert data["content"] == "👌" diff --git a/test/web/admin_api/admin_api_controller_test.exs b/test/web/admin_api/admin_api_controller_test.exs index 87f1366a4..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 @@ test "when configuration from database is off", %{conn: conn} 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) diff --git a/test/web/common_api/common_api_test.exs b/test/web/common_api/common_api_test.exs index 214cbdd7c..11f7c068f 100644 --- a/test/web/common_api/common_api_test.exs +++ b/test/web/common_api/common_api_test.exs @@ -551,6 +551,50 @@ test "also unsubscribes a user" do refute User.subscribed_to?(follower, followed) end + + test "cancels a pending follow for a local user" do + follower = insert(:user) + followed = insert(:user, locked: true) + + assert {:ok, follower, followed, %{id: activity_id, data: %{"state" => "pending"}}} = + CommonAPI.follow(follower, followed) + + assert User.get_follow_state(follower, followed) == "pending" + assert {:ok, follower} = CommonAPI.unfollow(follower, followed) + assert User.get_follow_state(follower, followed) == nil + + assert %{id: ^activity_id, data: %{"state" => "cancelled"}} = + Pleroma.Web.ActivityPub.Utils.fetch_latest_follow(follower, followed) + + assert %{ + data: %{ + "type" => "Undo", + "object" => %{"type" => "Follow", "state" => "cancelled"} + } + } = Pleroma.Web.ActivityPub.Utils.fetch_latest_undo(follower) + end + + test "cancels a pending follow for a remote user" do + follower = insert(:user) + followed = insert(:user, locked: true, local: false, ap_enabled: true) + + assert {:ok, follower, followed, %{id: activity_id, data: %{"state" => "pending"}}} = + CommonAPI.follow(follower, followed) + + assert User.get_follow_state(follower, followed) == "pending" + assert {:ok, follower} = CommonAPI.unfollow(follower, followed) + assert User.get_follow_state(follower, followed) == nil + + assert %{id: ^activity_id, data: %{"state" => "cancelled"}} = + Pleroma.Web.ActivityPub.Utils.fetch_latest_follow(follower, followed) + + assert %{ + data: %{ + "type" => "Undo", + "object" => %{"type" => "Follow", "state" => "cancelled"} + } + } = Pleroma.Web.ActivityPub.Utils.fetch_latest_undo(follower) + end end describe "accept_follow_request/2" do diff --git a/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs b/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs index 09bdc46e0..82d9e7d2f 100644 --- a/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs +++ b/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs @@ -269,7 +269,7 @@ test "update fields", %{conn: conn} do |> json_response(200) assert account_data["fields"] == [ - %{"name" => "foo", "value" => "bar"}, + %{"name" => "foo", "value" => "bar"}, %{"name" => "link", "value" => ~S(cofe.io)} ] @@ -297,7 +297,7 @@ test "update fields", %{conn: conn} do |> json_response(200) assert account["fields"] == [ - %{"name" => "foo", "value" => "bar"}, + %{"name" => "foo", "value" => "bar"}, %{"name" => "link", "value" => ~S(cofe.io)} ] diff --git a/test/web/mastodon_api/controllers/account_controller_test.exs b/test/web/mastodon_api/controllers/account_controller_test.exs index ec1e18002..e2abcd7c5 100644 --- a/test/web/mastodon_api/controllers/account_controller_test.exs +++ b/test/web/mastodon_api/controllers/account_controller_test.exs @@ -457,6 +457,16 @@ test "following / unfollowing a user", %{conn: conn} do assert id == to_string(other_user.id) end + test "cancelling follow request", %{conn: conn} do + %{id: other_user_id} = insert(:user, %{locked: true}) + + assert %{"id" => ^other_user_id, "following" => false, "requested" => true} = + conn |> post("/api/v1/accounts/#{other_user_id}/follow") |> json_response(:ok) + + assert %{"id" => ^other_user_id, "following" => false, "requested" => false} = + conn |> post("/api/v1/accounts/#{other_user_id}/unfollow") |> json_response(:ok) + end + test "following without reblogs" do %{conn: conn} = oauth_access(["follow", "read:statuses"]) followed = insert(:user) diff --git a/test/web/mastodon_api/controllers/scheduled_activity_controller_test.exs b/test/web/mastodon_api/controllers/scheduled_activity_controller_test.exs index 9666a7f2e..6317d1b47 100644 --- a/test/web/mastodon_api/controllers/scheduled_activity_controller_test.exs +++ b/test/web/mastodon_api/controllers/scheduled_activity_controller_test.exs @@ -9,6 +9,9 @@ defmodule Pleroma.Web.MastodonAPI.ScheduledActivityControllerTest do alias Pleroma.ScheduledActivity import Pleroma.Factory + import Ecto.Query + + clear_config([ScheduledActivity, :enabled]) test "shows scheduled activities" do %{user: user, conn: conn} = oauth_access(["read:statuses"]) @@ -52,11 +55,26 @@ test "shows a scheduled activity" do end test "updates a scheduled activity" do + Pleroma.Config.put([ScheduledActivity, :enabled], true) %{user: user, conn: conn} = oauth_access(["write:statuses"]) - scheduled_activity = insert(:scheduled_activity, user: user) - new_scheduled_at = - NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond) + scheduled_at = Timex.shift(NaiveDateTime.utc_now(), minutes: 60) + + {:ok, scheduled_activity} = + ScheduledActivity.create( + user, + %{ + scheduled_at: scheduled_at, + params: build(:note).data + } + ) + + job = Repo.one(from(j in Oban.Job, where: j.queue == "scheduled_activities")) + + assert job.args == %{"activity_id" => scheduled_activity.id} + assert DateTime.truncate(job.scheduled_at, :second) == to_datetime(scheduled_at) + + new_scheduled_at = Timex.shift(NaiveDateTime.utc_now(), minutes: 120) res_conn = put(conn, "/api/v1/scheduled_statuses/#{scheduled_activity.id}", %{ @@ -65,6 +83,9 @@ test "updates a scheduled activity" do assert %{"scheduled_at" => expected_scheduled_at} = json_response(res_conn, 200) assert expected_scheduled_at == Pleroma.Web.CommonAPI.Utils.to_masto_date(new_scheduled_at) + job = refresh_record(job) + + assert DateTime.truncate(job.scheduled_at, :second) == to_datetime(new_scheduled_at) res_conn = put(conn, "/api/v1/scheduled_statuses/404", %{scheduled_at: new_scheduled_at}) @@ -72,8 +93,22 @@ test "updates a scheduled activity" do end test "deletes a scheduled activity" do + Pleroma.Config.put([ScheduledActivity, :enabled], true) %{user: user, conn: conn} = oauth_access(["write:statuses"]) - scheduled_activity = insert(:scheduled_activity, user: user) + scheduled_at = Timex.shift(NaiveDateTime.utc_now(), minutes: 60) + + {:ok, scheduled_activity} = + ScheduledActivity.create( + user, + %{ + scheduled_at: scheduled_at, + params: build(:note).data + } + ) + + job = Repo.one(from(j in Oban.Job, where: j.queue == "scheduled_activities")) + + assert job.args == %{"activity_id" => scheduled_activity.id} res_conn = conn @@ -81,7 +116,8 @@ test "deletes a scheduled activity" do |> delete("/api/v1/scheduled_statuses/#{scheduled_activity.id}") assert %{} = json_response(res_conn, 200) - assert nil == Repo.get(ScheduledActivity, scheduled_activity.id) + refute Repo.get(ScheduledActivity, scheduled_activity.id) + refute Repo.get(Oban.Job, job.id) res_conn = conn diff --git a/test/web/mastodon_api/controllers/status_controller_test.exs b/test/web/mastodon_api/controllers/status_controller_test.exs index b03b4b344..83138d7ef 100644 --- a/test/web/mastodon_api/controllers/status_controller_test.exs +++ b/test/web/mastodon_api/controllers/status_controller_test.exs @@ -370,6 +370,11 @@ test "posting a poll", %{conn: conn} do assert NaiveDateTime.diff(NaiveDateTime.from_iso8601!(response["poll"]["expires_at"]), time) in 420..430 refute response["poll"]["expred"] + + question = Object.get_by_id(response["poll"]["id"]) + + # closed contains utc timezone + assert question.data["closed"] =~ "Z" end test "option limit is enforced", %{conn: conn} do diff --git a/test/web/mastodon_api/views/account_view_test.exs b/test/web/mastodon_api/views/account_view_test.exs index 2107bb85c..00c294845 100644 --- a/test/web/mastodon_api/views/account_view_test.exs +++ b/test/web/mastodon_api/views/account_view_test.exs @@ -368,10 +368,10 @@ test "returns the settings store if the requesting user is the represented user assert result.pleroma[:settings_store] == nil end - test "sanitizes display names" do + test "doesn't sanitize display names" do user = insert(:user, name: " username ") result = AccountView.render("show.json", %{user: user}) - refute result.display_name == " username " + assert result.display_name == " username " end test "never display nil user follow counts" do diff --git a/test/web/mastodon_api/views/notification_view_test.exs b/test/web/mastodon_api/views/notification_view_test.exs index 1fe83cb2c..2ac75c2ff 100644 --- a/test/web/mastodon_api/views/notification_view_test.exs +++ b/test/web/mastodon_api/views/notification_view_test.exs @@ -135,7 +135,7 @@ test "Move notification" do NotificationView.render("index.json", %{notifications: [notification], for: follower}) end - test "EmojiReaction notification" do + test "EmojiReact notification" do user = insert(:user) other_user = insert(:user) diff --git a/test/web/node_info_test.exs b/test/web/node_info_test.exs index 9a574a38d..39dd72cec 100644 --- a/test/web/node_info_test.exs +++ b/test/web/node_info_test.exs @@ -6,6 +6,7 @@ defmodule Pleroma.Web.NodeInfoTest do use Pleroma.Web.ConnCase import Pleroma.Factory + clear_config([:mrf_simple]) test "GET /.well-known/nodeinfo", %{conn: conn} do links = diff --git a/test/workers/cron/clear_oauth_token_worker_test.exs b/test/workers/cron/clear_oauth_token_worker_test.exs new file mode 100644 index 000000000..adea47326 --- /dev/null +++ b/test/workers/cron/clear_oauth_token_worker_test.exs @@ -0,0 +1,22 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Workers.Cron.ClearOauthTokenWorkerTest do + use Pleroma.DataCase + + import Pleroma.Factory + alias Pleroma.Workers.Cron.ClearOauthTokenWorker + + clear_config([:oauth2, :clean_expired_tokens]) + + test "deletes expired tokens" do + insert(:oauth_token, + valid_until: NaiveDateTime.add(NaiveDateTime.utc_now(), -60 * 10) + ) + + Pleroma.Config.put([:oauth2, :clean_expired_tokens], true) + ClearOauthTokenWorker.perform(:opts, :job) + assert Pleroma.Repo.all(Pleroma.Web.OAuth.Token) == [] + end +end diff --git a/test/daemons/digest_email_daemon_test.exs b/test/workers/cron/digest_emails_worker_test.exs similarity index 74% rename from test/daemons/digest_email_daemon_test.exs rename to test/workers/cron/digest_emails_worker_test.exs index faf592d5f..073615d9e 100644 --- a/test/daemons/digest_email_daemon_test.exs +++ b/test/workers/cron/digest_emails_worker_test.exs @@ -2,16 +2,24 @@ # Copyright © 2017-2019 Pleroma Authors # SPDX-License-Identifier: AGPL-3.0-only -defmodule Pleroma.DigestEmailDaemonTest do +defmodule Pleroma.Workers.Cron.DigestEmailsWorkerTest do use Pleroma.DataCase + import Pleroma.Factory - alias Pleroma.Daemons.DigestEmailDaemon alias Pleroma.Tests.ObanHelpers alias Pleroma.User alias Pleroma.Web.CommonAPI + clear_config([:email_notifications, :digest]) + test "it sends digest emails" do + Pleroma.Config.put([:email_notifications, :digest], %{ + active: true, + inactivity_threshold: 7, + interval: 7 + }) + user = insert(:user) date = @@ -23,8 +31,7 @@ test "it sends digest emails" do {:ok, _} = User.switch_email_notifications(user2, "digest", true) CommonAPI.post(user, %{"status" => "hey @#{user2.nickname}!"}) - DigestEmailDaemon.perform() - ObanHelpers.perform_all() + Pleroma.Workers.Cron.DigestEmailsWorker.perform(:opts, :pid) # Performing job(s) enqueued at previous step ObanHelpers.perform_all() diff --git a/test/workers/cron/purge_expired_activities_worker_test.exs b/test/workers/cron/purge_expired_activities_worker_test.exs new file mode 100644 index 000000000..c2561683e --- /dev/null +++ b/test/workers/cron/purge_expired_activities_worker_test.exs @@ -0,0 +1,56 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Workers.Cron.PurgeExpiredActivitiesWorkerTest do + use Pleroma.DataCase + + alias Pleroma.ActivityExpiration + alias Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker + + import Pleroma.Factory + import ExUnit.CaptureLog + + clear_config([ActivityExpiration, :enabled]) + + test "deletes an expiration activity" do + Pleroma.Config.put([ActivityExpiration, :enabled], true) + activity = insert(:note_activity) + + naive_datetime = + NaiveDateTime.add( + NaiveDateTime.utc_now(), + -:timer.minutes(2), + :millisecond + ) + + expiration = + insert( + :expiration_in_the_past, + %{activity_id: activity.id, scheduled_at: naive_datetime} + ) + + Pleroma.Workers.Cron.PurgeExpiredActivitiesWorker.perform(:ops, :pid) + + refute Pleroma.Repo.get(Pleroma.Activity, activity.id) + refute Pleroma.Repo.get(Pleroma.ActivityExpiration, expiration.id) + end + + describe "delete_activity/1" do + test "adds log message if activity isn't find" do + assert capture_log([level: :error], fn -> + PurgeExpiredActivitiesWorker.delete_activity(%ActivityExpiration{ + activity_id: "test-activity" + }) + end) =~ "Couldn't delete expired activity: not found activity" + end + + test "adds log message if actor isn't find" do + assert capture_log([level: :error], fn -> + PurgeExpiredActivitiesWorker.delete_activity(%ActivityExpiration{ + activity_id: "test-activity" + }) + end) =~ "Couldn't delete expired activity: not found activity" + end + end +end diff --git a/test/workers/scheduled_activity_worker_test.exs b/test/workers/scheduled_activity_worker_test.exs new file mode 100644 index 000000000..1405d7142 --- /dev/null +++ b/test/workers/scheduled_activity_worker_test.exs @@ -0,0 +1,52 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Workers.ScheduledActivityWorkerTest do + use Pleroma.DataCase + + alias Pleroma.ScheduledActivity + alias Pleroma.Workers.ScheduledActivityWorker + + import Pleroma.Factory + import ExUnit.CaptureLog + + clear_config([ScheduledActivity, :enabled]) + + test "creates a status from the scheduled activity" do + Pleroma.Config.put([ScheduledActivity, :enabled], true) + user = insert(:user) + + naive_datetime = + NaiveDateTime.add( + NaiveDateTime.utc_now(), + -:timer.minutes(2), + :millisecond + ) + + scheduled_activity = + insert( + :scheduled_activity, + scheduled_at: naive_datetime, + user: user, + params: %{status: "hi"} + ) + + ScheduledActivityWorker.perform( + %{"activity_id" => scheduled_activity.id}, + :pid + ) + + refute Repo.get(ScheduledActivity, scheduled_activity.id) + activity = Repo.all(Pleroma.Activity) |> Enum.find(&(&1.actor == user.ap_id)) + assert Pleroma.Object.normalize(activity).data["content"] == "hi" + end + + test "adds log message if ScheduledActivity isn't find" do + Pleroma.Config.put([ScheduledActivity, :enabled], true) + + assert capture_log([level: :error], fn -> + ScheduledActivityWorker.perform(%{"activity_id" => 42}, :pid) + end) =~ "Couldn't find scheduled activity" + end +end