summaryrefslogtreecommitdiff
path: root/lib/mix/tasks
diff options
context:
space:
mode:
Diffstat (limited to 'lib/mix/tasks')
-rw-r--r--lib/mix/tasks/migrate_local_uploads.ex97
-rw-r--r--lib/mix/tasks/pleroma/sample_config.eex41
-rw-r--r--lib/mix/tasks/reactivate_user.ex19
-rw-r--r--lib/mix/tasks/relay_follow.ex24
-rw-r--r--lib/mix/tasks/relay_unfollow.ex23
-rw-r--r--lib/mix/tasks/set_admin.ex32
-rw-r--r--lib/mix/tasks/unsubscribe_user.ex38
7 files changed, 274 insertions, 0 deletions
diff --git a/lib/mix/tasks/migrate_local_uploads.ex b/lib/mix/tasks/migrate_local_uploads.ex
new file mode 100644
index 000000000..8f9e210c0
--- /dev/null
+++ b/lib/mix/tasks/migrate_local_uploads.ex
@@ -0,0 +1,97 @@
+defmodule Mix.Tasks.MigrateLocalUploads do
+ use Mix.Task
+ import Mix.Ecto
+ alias Pleroma.{Upload, Uploaders.Local, Uploaders.S3}
+ require Logger
+
+ @log_every 50
+ @shortdoc "Migrate uploads from local to remote storage"
+
+ def run([target_uploader | args]) do
+ delete? = Enum.member?(args, "--delete")
+ Application.ensure_all_started(:pleroma)
+
+ local_path = Pleroma.Config.get!([Local, :uploads])
+ uploader = Module.concat(Pleroma.Uploaders, target_uploader)
+
+ unless Code.ensure_loaded?(uploader) do
+ raise("The uploader #{inspect(uploader)} is not an existing/loaded module.")
+ end
+
+ target_enabled? = Pleroma.Config.get([Upload, :uploader]) == uploader
+
+ unless target_enabled? do
+ Pleroma.Config.put([Upload, :uploader], uploader)
+ end
+
+ Logger.info("Migrating files from local #{local_path} to #{to_string(uploader)}")
+
+ if delete? do
+ Logger.warn(
+ "Attention: uploaded files will be deleted, hope you have backups! (--delete ; cancel with ^C)"
+ )
+
+ :timer.sleep(:timer.seconds(5))
+ end
+
+ uploads =
+ File.ls!(local_path)
+ |> Enum.map(fn id ->
+ root_path = Path.join(local_path, id)
+
+ cond do
+ File.dir?(root_path) ->
+ files = for file <- File.ls!(root_path), do: {id, file, Path.join([root_path, file])}
+
+ case List.first(files) do
+ {id, file, path} ->
+ {%Pleroma.Upload{id: id, name: file, path: id <> "/" <> file, tempfile: path},
+ root_path}
+
+ _ ->
+ nil
+ end
+
+ File.exists?(root_path) ->
+ file = Path.basename(id)
+ [hash, ext] = String.split(id, ".")
+ {%Pleroma.Upload{id: hash, name: file, path: file, tempfile: root_path}, root_path}
+
+ true ->
+ nil
+ end
+ end)
+ |> Enum.filter(& &1)
+
+ total_count = length(uploads)
+ Logger.info("Found #{total_count} uploads")
+
+ uploads
+ |> Task.async_stream(
+ fn {upload, root_path} ->
+ case Upload.store(upload, uploader: uploader, filters: [], size_limit: nil) do
+ {:ok, _} ->
+ if delete?, do: File.rm_rf!(root_path)
+ Logger.debug("uploaded: #{inspect(upload.path)} #{inspect(upload)}")
+ :ok
+
+ error ->
+ Logger.error("failed to upload #{inspect(upload.path)}: #{inspect(error)}")
+ end
+ end,
+ timeout: 150_000
+ )
+ |> Stream.chunk_every(@log_every)
+ |> Enum.reduce(0, fn done, count ->
+ count = count + length(done)
+ Logger.info("Uploaded #{count}/#{total_count} files")
+ count
+ end)
+
+ Logger.info("Done!")
+ end
+
+ def run(_) do
+ Logger.error("Usage: migrate_local_uploads S3|Swift [--delete]")
+ end
+end
diff --git a/lib/mix/tasks/pleroma/sample_config.eex b/lib/mix/tasks/pleroma/sample_config.eex
index 066939981..df9d1ad65 100644
--- a/lib/mix/tasks/pleroma/sample_config.eex
+++ b/lib/mix/tasks/pleroma/sample_config.eex
@@ -28,3 +28,44 @@ config :pleroma, Pleroma.Repo,
database: "<%= dbname %>",
hostname: "<%= dbhost %>",
pool_size: 10
+
+# Enable Strict-Transport-Security once SSL is working:
+# config :pleroma, :http_security,
+# sts: true
+
+# Configure S3 support if desired.
+# The public S3 endpoint is different depending on region and provider,
+# consult your S3 provider's documentation for details on what to use.
+#
+# config :pleroma, Pleroma.Uploaders.S3,
+# bucket: "some-bucket",
+# public_endpoint: "https://s3.amazonaws.com"
+#
+# Configure S3 credentials:
+# config :ex_aws, :s3,
+# access_key_id: "xxxxxxxxxxxxx",
+# secret_access_key: "yyyyyyyyyyyy",
+# region: "us-east-1",
+# scheme: "https://"
+#
+# For using third-party S3 clones like wasabi, also do:
+# config :ex_aws, :s3,
+# host: "s3.wasabisys.com"
+
+
+# Configure Openstack Swift support if desired.
+#
+# Many openstack deployments are different, so config is left very open with
+# no assumptions made on which provider you're using. This should allow very
+# wide support without needing separate handlers for OVH, Rackspace, etc.
+#
+# config :pleroma, Pleroma.Uploaders.Swift,
+# container: "some-container",
+# username: "api-username-yyyy",
+# password: "api-key-xxxx",
+# tenant_id: "<openstack-project/tenant-id>",
+# auth_url: "https://keystone-endpoint.provider.com",
+# storage_url: "https://swift-endpoint.prodider.com/v1/AUTH_<tenant>/<container>",
+# object_url: "https://cdn-endpoint.provider.com/<container>"
+#
+
diff --git a/lib/mix/tasks/reactivate_user.ex b/lib/mix/tasks/reactivate_user.ex
new file mode 100644
index 000000000..a30d3ac8b
--- /dev/null
+++ b/lib/mix/tasks/reactivate_user.ex
@@ -0,0 +1,19 @@
+defmodule Mix.Tasks.ReactivateUser do
+ use Mix.Task
+ alias Pleroma.User
+
+ @moduledoc """
+ Reactivate a user
+
+ Usage: ``mix reactivate_user <nickname>``
+
+ Example: ``mix reactivate_user lain``
+ """
+ def run([nickname]) do
+ Mix.Task.run("app.start")
+
+ with user <- User.get_by_nickname(nickname) do
+ User.deactivate(user, false)
+ end
+ end
+end
diff --git a/lib/mix/tasks/relay_follow.ex b/lib/mix/tasks/relay_follow.ex
new file mode 100644
index 000000000..85b1c024d
--- /dev/null
+++ b/lib/mix/tasks/relay_follow.ex
@@ -0,0 +1,24 @@
+defmodule Mix.Tasks.RelayFollow do
+ use Mix.Task
+ require Logger
+ alias Pleroma.Web.ActivityPub.Relay
+
+ @shortdoc "Follows a remote relay"
+ @moduledoc """
+ Follows a remote relay
+
+ Usage: ``mix relay_follow <relay_url>``
+
+ Example: ``mix relay_follow https://example.org/relay``
+ """
+ def run([target]) do
+ Mix.Task.run("app.start")
+
+ with {:ok, activity} <- Relay.follow(target) do
+ # put this task to sleep to allow the genserver to push out the messages
+ :timer.sleep(500)
+ else
+ {:error, e} -> Mix.shell().error("Error while following #{target}: #{inspect(e)}")
+ end
+ end
+end
diff --git a/lib/mix/tasks/relay_unfollow.ex b/lib/mix/tasks/relay_unfollow.ex
new file mode 100644
index 000000000..237fb771c
--- /dev/null
+++ b/lib/mix/tasks/relay_unfollow.ex
@@ -0,0 +1,23 @@
+defmodule Mix.Tasks.RelayUnfollow do
+ use Mix.Task
+ require Logger
+ alias Pleroma.Web.ActivityPub.Relay
+
+ @moduledoc """
+ Unfollows a remote relay
+
+ Usage: ``mix relay_follow <relay_url>``
+
+ Example: ``mix relay_follow https://example.org/relay``
+ """
+ def run([target]) do
+ Mix.Task.run("app.start")
+
+ with {:ok, activity} <- Relay.follow(target) do
+ # put this task to sleep to allow the genserver to push out the messages
+ :timer.sleep(500)
+ else
+ {:error, e} -> Mix.shell().error("Error while following #{target}: #{inspect(e)}")
+ end
+ end
+end
diff --git a/lib/mix/tasks/set_admin.ex b/lib/mix/tasks/set_admin.ex
new file mode 100644
index 000000000..d5ccf261b
--- /dev/null
+++ b/lib/mix/tasks/set_admin.ex
@@ -0,0 +1,32 @@
+defmodule Mix.Tasks.SetAdmin do
+ use Mix.Task
+ alias Pleroma.User
+
+ @doc """
+ Sets admin status
+ Usage: set_admin nickname [true|false]
+ """
+ def run([nickname | rest]) do
+ Application.ensure_all_started(:pleroma)
+
+ status =
+ case rest do
+ [status] -> status == "true"
+ _ -> true
+ end
+
+ with %User{local: true} = user <- User.get_by_nickname(nickname) do
+ info =
+ user.info
+ |> Map.put("is_admin", !!status)
+
+ cng = User.info_changeset(user, %{info: info})
+ {:ok, user} = User.update_and_set_cache(cng)
+
+ IO.puts("Admin status of #{nickname}: #{user.info["is_admin"]}")
+ else
+ _ ->
+ IO.puts("No local user #{nickname}")
+ end
+ end
+end
diff --git a/lib/mix/tasks/unsubscribe_user.ex b/lib/mix/tasks/unsubscribe_user.ex
new file mode 100644
index 000000000..62ea61a5c
--- /dev/null
+++ b/lib/mix/tasks/unsubscribe_user.ex
@@ -0,0 +1,38 @@
+defmodule Mix.Tasks.UnsubscribeUser do
+ use Mix.Task
+ alias Pleroma.{User, Repo}
+ require Logger
+
+ @moduledoc """
+ Deactivate and Unsubscribe local users from a user
+
+ Usage: ``mix unsubscribe_user <nickname>``
+
+ Example: ``mix unsubscribe_user lain``
+ """
+ def run([nickname]) do
+ Mix.Task.run("app.start")
+
+ with %User{} = user <- User.get_by_nickname(nickname) do
+ Logger.info("Deactivating #{user.nickname}")
+ User.deactivate(user)
+
+ {:ok, friends} = User.get_friends(user)
+
+ Enum.each(friends, fn friend ->
+ user = Repo.get(User, user.id)
+
+ Logger.info("Unsubscribing #{friend.nickname} from #{user.nickname}")
+ User.unfollow(user, friend)
+ end)
+
+ :timer.sleep(500)
+
+ user = Repo.get(User, user.id)
+
+ if length(user.following) == 0 do
+ Logger.info("Successfully unsubscribed all followers from #{user.nickname}")
+ end
+ end
+ end
+end