summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlain <lain@soykaf.club>2020-02-11 13:58:36 +0100
committerlain <lain@soykaf.club>2020-02-11 13:58:36 +0100
commit24c526a0b18b822ae339a481934bfa66b13bba54 (patch)
tree11d7c9bb2bf5503b536ee0ab72533974e9a7b21b
parent57098713c02363aaee78d519726e6f2975f725d8 (diff)
parent2f1c61255ff95a1d21a751cb78da3c031ccdd692 (diff)
Merge remote-tracking branch 'origin/develop' into uguu-uwu-notices-bulge
-rw-r--r--CHANGELOG.md2
-rw-r--r--config/config.exs25
-rw-r--r--config/description.exs7
-rw-r--r--config/test.exs7
-rw-r--r--docs/API/differences_in_mastoapi_responses.md3
-rw-r--r--docs/administration/backup.md34
-rw-r--r--docs/clients.md5
-rw-r--r--docs/configuration/cheatsheet.md13
-rw-r--r--lib/mix/tasks/pleroma/email.ex5
-rw-r--r--lib/pleroma/application.ex12
-rw-r--r--lib/pleroma/daemons/activity_expiration_daemon.ex66
-rw-r--r--lib/pleroma/daemons/digest_email_daemon.ex42
-rw-r--r--lib/pleroma/daemons/scheduled_activity_daemon.ex62
-rw-r--r--lib/pleroma/docs/generator.ex2
-rw-r--r--lib/pleroma/following_relationship.ex2
-rw-r--r--lib/pleroma/plugs/parsers_plug.ex21
-rw-r--r--lib/pleroma/scheduled_activity.ex83
-rw-r--r--lib/pleroma/scheduler.ex7
-rw-r--r--lib/pleroma/stats.ex39
-rw-r--r--lib/pleroma/user.ex43
-rw-r--r--lib/pleroma/web/activity_pub/utils.ex9
-rw-r--r--lib/pleroma/web/common_api/utils.ex6
-rw-r--r--lib/pleroma/web/endpoint.ex12
-rw-r--r--lib/pleroma/web/mastodon_api/controllers/status_controller.ex19
-rw-r--r--lib/pleroma/web/oauth/token/clean_worker.ex34
-rw-r--r--lib/pleroma/workers/activity_expiration_worker.ex18
-rw-r--r--lib/pleroma/workers/background_worker.ex5
-rw-r--r--lib/pleroma/workers/cron/clear_oauth_token_worker.ex21
-rw-r--r--lib/pleroma/workers/cron/digest_emails_worker.ex58
-rw-r--r--lib/pleroma/workers/cron/purge_expired_activities_worker.ex46
-rw-r--r--lib/pleroma/workers/cron/stats_worker.ex16
-rw-r--r--lib/pleroma/workers/digest_emails_worker.ex16
-rw-r--r--lib/pleroma/workers/scheduled_activity_worker.ex36
-rw-r--r--mix.exs7
-rw-r--r--mix.lock10
-rw-r--r--test/activity_expiration_test.exs25
-rw-r--r--test/daemons/activity_expiration_daemon_test.exs17
-rw-r--r--test/daemons/scheduled_activity_daemon_test.exs19
-rw-r--r--test/scheduled_activity_test.exs41
-rw-r--r--test/support/helpers.ex6
-rw-r--r--test/web/activity_pub/activity_pub_test.exs17
-rw-r--r--test/web/common_api/common_api_test.exs44
-rw-r--r--test/web/mastodon_api/controllers/account_controller_test.exs10
-rw-r--r--test/web/mastodon_api/controllers/scheduled_activity_controller_test.exs46
-rw-r--r--test/web/mastodon_api/controllers/status_controller_test.exs5
-rw-r--r--test/web/node_info_test.exs1
-rw-r--r--test/workers/cron/clear_oauth_token_worker_test.exs22
-rw-r--r--test/workers/cron/digest_emails_worker_test.exs (renamed from test/daemons/digest_email_daemon_test.exs)15
-rw-r--r--test/workers/cron/purge_expired_activities_worker_test.exs56
-rw-r--r--test/workers/scheduled_activity_worker_test.exs52
50 files changed, 733 insertions, 436 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ca3bdf8d1..150fd27cd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -121,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
<details>
<summary>API Changes</summary>
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 @@ config :pleroma, Pleroma.Repo,
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 @@ config :pleroma, Oban,
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, Pleroma.ScheduledActivity,
config :pleroma, :email_notifications,
digest: %{
active: false,
- schedule: "0 0 * * 0",
interval: 7,
inactivity_threshold: 7
}
@@ -586,8 +577,7 @@ config :pleroma, :email_notifications,
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, :modules, runtime_dir: "instance/modules"
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 6b912a07e..e5bac9b3f 100644
--- a/config/description.exs
+++ b/config/description.exs
@@ -2519,13 +2519,6 @@ config :pleroma, :config_description, [
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 5c66a36f1..078c46205 100644
--- a/config/test.exs
+++ b/config/test.exs
@@ -66,11 +66,8 @@ config :web_push_encryption, :http_client, Pleroma.Web.WebPushHttpClientMock
config :pleroma, Oban,
queues: false,
- prune: :disabled
-
-config :pleroma, Pleroma.Scheduler,
- jobs: [],
- global: false
+ prune: :disabled,
+ crontab: false
config :pleroma, Pleroma.ScheduledActivity,
daily_user_limit: 2,
diff --git a/docs/API/differences_in_mastoapi_responses.md b/docs/API/differences_in_mastoapi_responses.md
index b822bc037..06de90f71 100644
--- a/docs/API/differences_in_mastoapi_responses.md
+++ b/docs/API/differences_in_mastoapi_responses.md
@@ -88,6 +88,9 @@ Behavior has changed:
- `/api/v1/accounts/search`: Does not require authentication
+## Search (global)
+
+Unlisted posts are available in search results, they are considered to be public posts that shouldn't be shown in local/federated timeline.
## Notifications
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 <pleroma_db> --format=custom -f </path/to/backup_location/pleroma.pgdump>`
+3. Run `sudo -Hu postgres pg_dump -d <pleroma_db> --format=custom -f </path/to/backup_location/pleroma.pgdump>` (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 <pleroma_db> -v -1 </path/to/backup_location/pleroma.pgdump>`
-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 <pleroma_db>;';` `sudo -Hu postgres psql -c 'CREATE DATABASE <pleroma_db>;';`
+6. Run `sudo -Hu postgres pg_restore -d <pleroma_db> -v -1 </path/to/backup_location/pleroma.pgdump>`
+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 <pleroma_db>;';` `sudo -Hu postgres psql -c 'DROP USER <pleroma_db>;';`
+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/clients.md b/docs/clients.md
index 6c6180f7a..8ac9ad3de 100644
--- a/docs/clients.md
+++ b/docs/clients.md
@@ -37,6 +37,11 @@ Feel free to contact us to be added to this list!
- Platforms: Android
- Features: Streaming Ready, Moderation, Text Formatting
+### Kyclos
+- Source Code: <https://git.pleroma.social/pleroma/harbour-kyclos>
+- Platforms: SailfishOS
+- Features: No Streaming
+
### Nekonium
- Homepage: [F-Droid Repository](https://repo.gdgd.jp.net/), [Google Play](https://play.google.com/store/apps/details?id=com.apps.nekonium), [Amazon](https://www.amazon.co.jp/dp/B076FXPRBC/)
- Source: <https://gogs.gdgd.jp.net/lin/nekonium>
diff --git a/docs/configuration/cheatsheet.md b/docs/configuration/cheatsheet.md
index f30aedc01..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
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 @@ defmodule Mix.Tasks.Pleroma.Email 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/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 @@ defmodule Pleroma.Application 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 @@ defmodule Pleroma.Application 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 @@ defmodule Pleroma.Application do
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 <https://pleroma.social/>
-# 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 <https://pleroma.social/>
-# 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 <https://pleroma.social/>
-# 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 @@ defmodule Pleroma.Docs.Generator 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 @@ defmodule Pleroma.FollowingRelationship 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/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 <https://pleroma.social/>
-# 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 @@ defmodule Pleroma.ScheduledActivity 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 @@ defmodule Pleroma.ScheduledActivity 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 @@ defmodule Pleroma.ScheduledActivity 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 <https://pleroma.social/>
-# 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 @@ defmodule Pleroma.Stats do
end
def init(args) do
- Process.send(self(), :run_update, [])
{:ok, args}
end
@@ -45,17 +65,12 @@ defmodule Pleroma.Stats 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 @@ defmodule Pleroma.Stats 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 3c86cdb38..5ea36fea3 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -647,25 +647,48 @@ defmodule Pleroma.User 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/utils.ex b/lib/pleroma/web/activity_pub/utils.ex
index 4bcacc6d1..10ce5eee8 100644
--- a/lib/pleroma/web/activity_pub/utils.ex
+++ b/lib/pleroma/web/activity_pub/utils.ex
@@ -490,6 +490,15 @@ defmodule Pleroma.Web.ActivityPub.Utils 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)
diff --git a/lib/pleroma/web/common_api/utils.ex b/lib/pleroma/web/common_api/utils.ex
index a9b164d9a..ca6c93862 100644
--- a/lib/pleroma/web/common_api/utils.ex
+++ b/lib/pleroma/web/common_api/utils.ex
@@ -179,9 +179,9 @@ defmodule Pleroma.Web.CommonAPI.Utils do
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 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
) 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/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 <https://pleroma.social/>
-# 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 <https://pleroma.social/>
-# 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 @@ defmodule Pleroma.Workers.BackgroundWorker do
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 <https://pleroma.social/>
+# 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 <https://pleroma.social/>
+# 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 <https://pleroma.social/>
+# 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 <https://pleroma.social/>
+# 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 <https://pleroma.social/>
-# 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 f6794f126..3e3eac521 100644
--- a/mix.exs
+++ b/mix.exs
@@ -63,7 +63,7 @@ defmodule Pleroma.Mixfile 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 @@ defmodule Pleroma.Mixfile 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 @@ defmodule Pleroma.Mixfile 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 17b8900e0..69eec5431 100644
--- a/mix.lock
+++ b/mix.lock
@@ -36,9 +36,9 @@
"ex_doc": {:hex, :ex_doc, "0.21.2", "caca5bc28ed7b3bdc0b662f8afe2bee1eedb5c3cf7b322feeeb7c6ebbde089d6", [:mix], [{:earmark, "~> 1.3.3 or ~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"},
"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"},
"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"},
- "fast_html": {:hex, :fast_html, "1.0.1", "5bc7df4dc4607ec2c314c16414e4111d79a209956c4f5df96602d194c61197f9", [:make, :mix], [], "hexpm"},
- "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"},
+ "excoveralls": {:hex, :excoveralls, "0.12.1", "a553c59f6850d0aff3770e4729515762ba7c8e41eedde03208182a8dc9d0ce07", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"},
+ "fast_html": {:hex, :fast_html, "0.99.4", "d80812664f0429607e1d880fba0ef04da87a2e4fa596701bcaae17953535695c", [:make, :mix], [], "hexpm"},
+ "fast_sanitize": {:hex, :fast_sanitize, "0.1.4", "6c2e7203ca2f8275527a3021ba6e9d5d4ee213a47dc214a97c128737c9e56df1", [:mix], [{:fast_html, "~> 0.99", [hex: :fast_html, repo: "hexpm", optional: false]}, {:plug, "~> 1.8", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
"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"},
"floki": {:hex, :floki, "0.23.1", "e100306ce7d8841d70a559748e5091542e2cfc67ffb3ade92b89a8435034dab1", [:mix], [{:html_entities, "~> 0.5.0", [hex: :html_entities, repo: "hexpm", optional: false]}], "hexpm"},
"gen_smtp": {:hex, :gen_smtp, "0.15.0", "9f51960c17769b26833b50df0b96123605a8024738b62db747fece14eb2fbfcc", [:rebar3], [], "hexpm"},
@@ -77,7 +77,7 @@
"phoenix_html": {:hex, :phoenix_html, "2.13.3", "850e292ff6e204257f5f9c4c54a8cb1f6fbc16ed53d360c2b780a3d0ba333867", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
"phoenix_pubsub": {:hex, :phoenix_pubsub, "1.1.2", "496c303bdf1b2e98a9d26e89af5bba3ab487ba3a3735f74bf1f4064d2a845a3e", [:mix], [], "hexpm"},
"phoenix_swoosh": {:hex, :phoenix_swoosh, "0.2.0", "a7e0b32077cd6d2323ae15198839b05d9caddfa20663fd85787479e81f89520e", [:mix], [{:phoenix, "~> 1.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.2", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:swoosh, "~> 0.1", [hex: :swoosh, repo: "hexpm", optional: false]}], "hexpm"},
- "plug": {:hex, :plug, "1.8.3", "12d5f9796dc72e8ac9614e94bda5e51c4c028d0d428e9297650d09e15a684478", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm"},
+ "plug": {:hex, :plug, "1.9.0", "8d7c4e26962283ff9f8f3347bd73838e2413fbc38b7bb5467d5924f68f3a5a4a", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm"},
"plug_cowboy": {:hex, :plug_cowboy, "2.1.0", "b75768153c3a8a9e8039d4b25bb9b14efbc58e9c4a6e6a270abff1cd30cbe320", [:mix], [{:cowboy, "~> 2.5", [hex: :cowboy, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
"plug_crypto": {:hex, :plug_crypto, "1.0.0", "18e49317d3fa343f24620ed22795ec29d4a5e602d52d1513ccea0b07d8ea7d4d", [:mix], [], "hexpm"},
"plug_static_index_html": {:hex, :plug_static_index_html, "1.0.0", "840123d4d3975585133485ea86af73cb2600afd7f2a976f9f5fd8b3808e636a0", [:mix], [{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
@@ -90,12 +90,10 @@
"prometheus_phoenix": {:hex, :prometheus_phoenix, "1.3.0", "c4b527e0b3a9ef1af26bdcfbfad3998f37795b9185d475ca610fe4388fdd3bb5", [:mix], [{:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}, {:prometheus_ex, "~> 1.3 or ~> 2.0 or ~> 3.0", [hex: :prometheus_ex, repo: "hexpm", optional: false]}], "hexpm"},
"prometheus_plugs": {:hex, :prometheus_plugs, "1.1.5", "25933d48f8af3a5941dd7b621c889749894d8a1082a6ff7c67cc99dec26377c5", [:mix], [{:accept, "~> 0.1", [hex: :accept, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}, {:prometheus_ex, "~> 1.1 or ~> 2.0 or ~> 3.0", [hex: :prometheus_ex, repo: "hexpm", optional: false]}, {:prometheus_process_collector, "~> 1.1", [hex: :prometheus_process_collector, repo: "hexpm", optional: true]}], "hexpm"},
"quack": {:hex, :quack, "0.1.1", "cca7b4da1a233757fdb44b3334fce80c94785b3ad5a602053b7a002b5a8967bf", [:mix], [{:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: false]}, {:tesla, "~> 1.2.0", [hex: :tesla, repo: "hexpm", optional: false]}], "hexpm"},
- "quantum": {:hex, :quantum, "2.3.4", "72a0e8855e2adc101459eac8454787cb74ab4169de6ca50f670e72142d4960e9", [:mix], [{:calendar, "~> 0.17", [hex: :calendar, repo: "hexpm", optional: true]}, {:crontab, "~> 1.1", [hex: :crontab, repo: "hexpm", optional: false]}, {:gen_stage, "~> 0.12", [hex: :gen_stage, repo: "hexpm", optional: false]}, {:swarm, "~> 3.3", [hex: :swarm, repo: "hexpm", optional: false]}, {:timex, "~> 3.1", [hex: :timex, repo: "hexpm", optional: true]}], "hexpm"},
"ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm"},
"recon": {:git, "https://github.com/ferd/recon.git", "75d70c7c08926d2f24f1ee6de14ee50fe8a52763", [tag: "2.4.0"]},
"remote_ip": {:git, "https://git.pleroma.social/pleroma/remote_ip.git", "825dc00aaba5a1b7c4202a532b696b595dd3bcb3", [ref: "825dc00aaba5a1b7c4202a532b696b595dd3bcb3"]},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.5", "6eaf7ad16cb568bb01753dbbd7a95ff8b91c7979482b95f38443fe2c8852a79b", [:make, :mix, :rebar3], [], "hexpm"},
- "swarm": {:hex, :swarm, "3.4.0", "64f8b30055d74640d2186c66354b33b999438692a91be275bb89cdc7e401f448", [:mix], [{:gen_state_machine, "~> 2.0", [hex: :gen_state_machine, repo: "hexpm", optional: false]}, {:libring, "~> 1.0", [hex: :libring, repo: "hexpm", optional: false]}], "hexpm"},
"sweet_xml": {:hex, :sweet_xml, "0.6.6", "fc3e91ec5dd7c787b6195757fbcf0abc670cee1e4172687b45183032221b66b8", [:mix], [], "hexpm"},
"swoosh": {:hex, :swoosh, "0.23.5", "bfd9404bbf5069b1be2ffd317923ce57e58b332e25dbca2a35dedd7820dfee5a", [:mix], [{:cowboy, "~> 1.0.1 or ~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm"},
"syslog": {:git, "https://github.com/Vagabond/erlang-syslog.git", "4a6c6f2c996483e86c1320e9553f91d337bcb6aa", [tag: "1.0.5"]},
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 @@ defmodule Pleroma.ActivityExpirationTest 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 <https://pleroma.social/>
-# 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 <https://pleroma.social/>
-# 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/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 @@ defmodule Pleroma.ScheduledActivityTest 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 @@ defmodule Pleroma.Tests.Helpers 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 ea6e79b44..ce68e7d0e 100644
--- a/test/web/activity_pub/activity_pub_test.exs
+++ b/test/web/activity_pub/activity_pub_test.exs
@@ -1174,6 +1174,23 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest 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/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 @@ defmodule Pleroma.Web.CommonAPITest 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_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 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest 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 @@ defmodule Pleroma.Web.MastodonAPI.ScheduledActivityControllerTest 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 @@ defmodule Pleroma.Web.MastodonAPI.ScheduledActivityControllerTest 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 @@ defmodule Pleroma.Web.MastodonAPI.ScheduledActivityControllerTest 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 @@ defmodule Pleroma.Web.MastodonAPI.ScheduledActivityControllerTest 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 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest 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/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 <https://pleroma.social/>
+# 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
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 <https://pleroma.social/>
# 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 @@ defmodule Pleroma.DigestEmailDaemonTest 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 <https://pleroma.social/>
+# 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 <https://pleroma.social/>
+# 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