Page MenuHomePhorge

No OneTemporary

Size
99 KB
Referenced Files
None
Subscribers
None
diff --git a/config/dev.exs b/config/dev.exs
index 71b11f7c3..7e1e3b4be 100644
--- a/config/dev.exs
+++ b/config/dev.exs
@@ -1,64 +1,64 @@
use Mix.Config
# For development, we disable any cache and enable
# debugging and code reloading.
#
# The watchers configuration can be used to run external
# watchers to your application. For example, we use it
# with brunch.io to recompile .js and .css sources.
config :pleroma, Pleroma.Web.Endpoint,
http: [
port: 4000,
protocol_options: [max_request_line_length: 8192, max_header_value_length: 8192]
],
protocol: "http",
debug_errors: true,
code_reloader: true,
check_origin: false,
watchers: [],
secure_cookie_flag: false
config :pleroma, Pleroma.Emails.Mailer, adapter: Swoosh.Adapters.Local
# ## SSL Support
#
# In order to use HTTPS in development, a self-signed
# certificate can be generated by running the following
# command from your terminal:
#
# openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 -subj "/C=US/ST=Denial/L=Springfield/O=Dis/CN=www.example.com" -keyout priv/server.key -out priv/server.pem
#
# The `http:` config above can be replaced with:
#
# https: [port: 4000, keyfile: "priv/server.key", certfile: "priv/server.pem"],
#
# If desired, both `http:` and `https:` keys can be
# configured to run both http and https servers on
# different ports.
# Do not include metadata nor timestamps in development logs
config :logger, :console, format: "[$level] $message\n"
# Set a higher stacktrace during development. Avoid configuring such
# in production as building large stacktraces may be expensive.
config :phoenix, :stacktrace_depth, 20
# Configure your database
config :pleroma, Pleroma.Repo,
adapter: Ecto.Adapters.Postgres,
username: "postgres",
password: "postgres",
database: "pleroma_dev",
hostname: "localhost",
pool_size: 10
if File.exists?("./config/dev.secret.exs") do
import_config "dev.secret.exs"
else
IO.puts(
"!!! RUNNING IN LOCALHOST DEV MODE! !!!\nFEDERATION WON'T WORK UNTIL YOU CONFIGURE A dev.secret.exs"
)
end
-if File.exists?("./config/dev.migrated.secret.exs"),
- do: import_config("./config/dev.migrated.secret.exs")
+if File.exists?("./config/dev.exported_from_db.secret.exs"),
+ do: import_config("dev.exported_from_db.secret.exs")
diff --git a/config/prod.exs b/config/prod.exs
index 42edccf64..9c205cbd2 100644
--- a/config/prod.exs
+++ b/config/prod.exs
@@ -1,68 +1,68 @@
use Mix.Config
# For production, we often load configuration from external
# sources, such as your system environment. For this reason,
# you won't find the :http configuration below, but set inside
# Pleroma.Web.Endpoint.load_from_system_env/1 dynamically.
# Any dynamic configuration should be moved to such function.
#
# Don't forget to configure the url host to something meaningful,
# Phoenix uses this information when generating URLs.
#
# Finally, we also include the path to a cache manifest
# containing the digested version of static files. This
# manifest is generated by the mix phoenix.digest task
# which you typically run after static files are built.
config :pleroma, Pleroma.Web.Endpoint,
http: [port: 4000],
protocol: "http"
config :phoenix, serve_endpoints: true
# Do not print debug messages in production
config :logger, level: :warn
# ## SSL Support
#
# To get SSL working, you will need to add the `https` key
# to the previous section and set your `:url` port to 443:
#
# config :pleroma, Pleroma.Web.Endpoint,
# ...
# url: [host: "example.com", port: 443],
# https: [:inet6,
# port: 443,
# keyfile: System.get_env("SOME_APP_SSL_KEY_PATH"),
# certfile: System.get_env("SOME_APP_SSL_CERT_PATH")]
#
# Where those two env variables return an absolute path to
# the key and cert in disk or a relative path inside priv,
# for example "priv/ssl/server.key".
#
# We also recommend setting `force_ssl`, ensuring no data is
# ever sent via http, always redirecting to https:
#
# config :pleroma, Pleroma.Web.Endpoint,
# force_ssl: [hsts: true]
#
# Check `Plug.SSL` for all available options in `force_ssl`.
# ## Using releases
#
# If you are doing OTP releases, you need to instruct Phoenix
# to start the server for all endpoints:
#
# config :phoenix, :serve_endpoints, true
#
# Alternatively, you can configure exactly which server to
# start per endpoint:
#
# config :pleroma, Pleroma.Web.Endpoint, server: true
#
# Finally import the config/prod.secret.exs
# which should be versioned separately.
import_config "prod.secret.exs"
-if File.exists?("./config/prod.migrated.secret.exs"),
- do: import_config("./config/prod.migrated.secret.exs")
+if File.exists?("./config/prod.exported_from_db.secret.exs"),
+ do: import_config("prod.exported_from_db.secret.exs")
diff --git a/lib/mix/tasks/pleroma/common.ex b/lib/mix/pleroma.ex
similarity index 94%
rename from lib/mix/tasks/pleroma/common.ex
rename to lib/mix/pleroma.ex
index 7d50605af..548c8a0a4 100644
--- a/lib/mix/tasks/pleroma/common.ex
+++ b/lib/mix/pleroma.ex
@@ -1,63 +1,63 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
-defmodule Mix.Tasks.Pleroma.Common do
+defmodule Mix.Pleroma do
@doc "Common functions to be reused in mix tasks"
def start_pleroma do
Application.put_env(:phoenix, :serve_endpoints, false, persistent: true)
{:ok, _} = Application.ensure_all_started(:pleroma)
end
def get_option(options, opt, prompt, defval \\ nil, defname \\ nil) do
Keyword.get(options, opt) || shell_prompt(prompt, defval, defname)
end
def shell_prompt(prompt, defval \\ nil, defname \\ nil) do
- prompt_message = "#{prompt} [#{defname || defval}]"
+ prompt_message = "#{prompt} [#{defname || defval}] "
input =
if mix_shell?(),
do: Mix.shell().prompt(prompt_message),
else: :io.get_line(prompt_message)
case input do
"\n" ->
case defval do
nil ->
shell_prompt(prompt, defval, defname)
defval ->
defval
end
input ->
String.trim(input)
end
end
def shell_yes?(message) do
if mix_shell?(),
do: Mix.shell().yes?("Continue?"),
else: shell_prompt(message, "Continue?") in ~w(Yn Y y)
end
def shell_info(message) do
if mix_shell?(),
do: Mix.shell().info(message),
else: IO.puts(message)
end
def shell_error(message) do
if mix_shell?(),
do: Mix.shell().error(message),
else: IO.puts(:stderr, message)
end
@doc "Performs a safe check whether `Mix.shell/0` is available (does not raise if Mix is not loaded)"
def mix_shell?, do: :erlang.function_exported(Mix, :shell, 0)
def escape_sh_path(path) do
~S(') <> String.replace(path, ~S('), ~S(\')) <> ~S(')
end
end
diff --git a/lib/mix/tasks/benchmark.ex b/lib/mix/tasks/pleroma/benchmark.ex
similarity index 82%
rename from lib/mix/tasks/benchmark.ex
rename to lib/mix/tasks/pleroma/benchmark.ex
index e4b1a638a..d43db7b35 100644
--- a/lib/mix/tasks/benchmark.ex
+++ b/lib/mix/tasks/pleroma/benchmark.ex
@@ -1,25 +1,25 @@
defmodule Mix.Tasks.Pleroma.Benchmark do
+ import Mix.Pleroma
use Mix.Task
- alias Mix.Tasks.Pleroma.Common
def run(["search"]) do
- Common.start_pleroma()
+ start_pleroma()
Benchee.run(%{
"search" => fn ->
Pleroma.Activity.search(nil, "cofe")
end
})
end
def run(["tag"]) do
- Common.start_pleroma()
+ start_pleroma()
Benchee.run(%{
"tag" => fn ->
%{"type" => "Create", "tag" => "cofe"}
|> Pleroma.Web.ActivityPub.ActivityPub.fetch_public_activities()
end
})
end
end
diff --git a/lib/mix/tasks/pleroma/config.ex b/lib/mix/tasks/pleroma/config.ex
index 1fe03088d..cc5425362 100644
--- a/lib/mix/tasks/pleroma/config.ex
+++ b/lib/mix/tasks/pleroma/config.ex
@@ -1,68 +1,69 @@
defmodule Mix.Tasks.Pleroma.Config do
use Mix.Task
- alias Mix.Tasks.Pleroma.Common
+ import Mix.Pleroma
alias Pleroma.Repo
alias Pleroma.Web.AdminAPI.Config
@shortdoc "Manages the location of the config"
@moduledoc """
Manages the location of the config.
## Transfers config from file to DB.
mix pleroma.config migrate_to_db
## Transfers config from DB to file.
mix pleroma.config migrate_from_db ENV
"""
def run(["migrate_to_db"]) do
- Common.start_pleroma()
+ start_pleroma()
if Pleroma.Config.get([:instance, :dynamic_configuration]) do
Application.get_all_env(:pleroma)
|> Enum.reject(fn {k, _v} -> k in [Pleroma.Repo, :env] end)
|> Enum.each(fn {k, v} ->
key = to_string(k) |> String.replace("Elixir.", "")
{:ok, _} = Config.update_or_create(%{key: key, value: v})
Mix.shell().info("#{key} is migrated.")
end)
Mix.shell().info("Settings migrated.")
else
Mix.shell().info(
"Migration is not allowed by config. You can change this behavior in instance settings."
)
end
end
def run(["migrate_from_db", env]) do
- Common.start_pleroma()
+ start_pleroma()
if Pleroma.Config.get([:instance, :dynamic_configuration]) do
- config_path = "config/#{env}.migrated.secret.exs"
+ config_path = "config/#{env}.exported_from_db.secret.exs"
{:ok, file} = File.open(config_path, [:write])
+ IO.write(file, "use Mix.Config\r\n")
Repo.all(Config)
|> Enum.each(fn config ->
mark = if String.starts_with?(config.key, "Pleroma."), do: ",", else: ":"
IO.write(
file,
"config :pleroma, #{config.key}#{mark} #{inspect(Config.from_binary(config.value))}\r\n"
)
{:ok, _} = Repo.delete(config)
Mix.shell().info("#{config.key} deleted from DB.")
end)
File.close(file)
System.cmd("mix", ["format", config_path])
else
Mix.shell().info(
"Migration is not allowed by config. You can change this behavior in instance settings."
)
end
end
end
diff --git a/lib/mix/tasks/pleroma/database.ex b/lib/mix/tasks/pleroma/database.ex
index 4d480ac3f..e91fb31d1 100644
--- a/lib/mix/tasks/pleroma/database.ex
+++ b/lib/mix/tasks/pleroma/database.ex
@@ -1,122 +1,122 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Mix.Tasks.Pleroma.Database do
- alias Mix.Tasks.Pleroma.Common
alias Pleroma.Conversation
alias Pleroma.Object
alias Pleroma.Repo
alias Pleroma.User
require Logger
+ import Mix.Pleroma
use Mix.Task
@shortdoc "A collection of database related tasks"
@moduledoc """
A collection of database related tasks
## Replace embedded objects with their references
Replaces embedded objects with references to them in the `objects` table. Only needs to be ran once. The reason why this is not a migration is because it could significantly increase the database size after being ran, however after this `VACUUM FULL` will be able to reclaim about 20% (really depends on what is in the database, your mileage may vary) of the db size before the migration.
mix pleroma.database remove_embedded_objects
Options:
- `--vacuum` - run `VACUUM FULL` after the embedded objects are replaced with their references
## Prune old objects from the database
mix pleroma.database prune_objects
## Create a conversation for all existing DMs. Can be safely re-run.
mix pleroma.database bump_all_conversations
## Remove duplicated items from following and update followers count for all users
mix pleroma.database update_users_following_followers_counts
"""
def run(["remove_embedded_objects" | args]) do
{options, [], []} =
OptionParser.parse(
args,
strict: [
vacuum: :boolean
]
)
- Common.start_pleroma()
+ start_pleroma()
Logger.info("Removing embedded objects")
Repo.query!(
"update activities set data = jsonb_set(data, '{object}'::text[], data->'object'->'id') where data->'object'->>'id' is not null;",
[],
timeout: :infinity
)
if Keyword.get(options, :vacuum) do
Logger.info("Runnning VACUUM FULL")
Repo.query!(
"vacuum full;",
[],
timeout: :infinity
)
end
end
def run(["bump_all_conversations"]) do
- Common.start_pleroma()
+ start_pleroma()
Conversation.bump_for_all_activities()
end
def run(["update_users_following_followers_counts"]) do
- Common.start_pleroma()
+ start_pleroma()
users = Repo.all(User)
Enum.each(users, &User.remove_duplicated_following/1)
Enum.each(users, &User.update_follower_count/1)
end
def run(["prune_objects" | args]) do
import Ecto.Query
{options, [], []} =
OptionParser.parse(
args,
strict: [
vacuum: :boolean
]
)
- Common.start_pleroma()
+ start_pleroma()
deadline = Pleroma.Config.get([:instance, :remote_post_retention_days])
Logger.info("Pruning objects older than #{deadline} days")
time_deadline =
NaiveDateTime.utc_now()
|> NaiveDateTime.add(-(deadline * 86_400))
public = "https://www.w3.org/ns/activitystreams#Public"
from(o in Object,
where: fragment("?->'to' \\? ? OR ?->'cc' \\? ?", o.data, ^public, o.data, ^public),
where: o.inserted_at < ^time_deadline,
where:
fragment("split_part(?->>'actor', '/', 3) != ?", o.data, ^Pleroma.Web.Endpoint.host())
)
|> Repo.delete_all(timeout: :infinity)
if Keyword.get(options, :vacuum) do
Logger.info("Runnning VACUUM FULL")
Repo.query!(
"vacuum full;",
[],
timeout: :infinity
)
end
end
end
diff --git a/lib/mix/tasks/pleroma/instance.ex b/lib/mix/tasks/pleroma/instance.ex
index 44e49cb69..2c4e414cf 100644
--- a/lib/mix/tasks/pleroma/instance.ex
+++ b/lib/mix/tasks/pleroma/instance.ex
@@ -1,224 +1,243 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Mix.Tasks.Pleroma.Instance do
use Mix.Task
- alias Mix.Tasks.Pleroma.Common
+ import Mix.Pleroma
@shortdoc "Manages Pleroma instance"
@moduledoc """
Manages Pleroma instance.
## Generate a new instance config.
mix pleroma.instance gen [OPTION...]
If any options are left unspecified, you will be prompted interactively
## Options
- `-f`, `--force` - overwrite any output files
- `-o PATH`, `--output PATH` - the output file for the generated configuration
- `--output-psql PATH` - the output file for the generated PostgreSQL setup
- `--domain DOMAIN` - the domain of your instance
- `--instance-name INSTANCE_NAME` - the name of your instance
- `--admin-email ADMIN_EMAIL` - the email address of the instance admin
- `--notify-email NOTIFY_EMAIL` - email address for notifications
- `--dbhost HOSTNAME` - the hostname of the PostgreSQL database to use
- `--dbname DBNAME` - the name of the database to use
- `--dbuser DBUSER` - the user (aka role) to use for the database connection
- `--dbpass DBPASS` - the password to use for the database connection
- `--indexable Y/N` - Allow/disallow indexing site by search engines
- `--db-configurable Y/N` - Allow/disallow configuring instance from admin part
+ - `--uploads-dir` - the directory uploads go in when using a local uploader
+ - `--static-dir` - the directory custom public files should be read from (custom emojis, frontend bundle overrides, robots.txt, etc.)
"""
def run(["gen" | rest]) do
{options, [], []} =
OptionParser.parse(
rest,
strict: [
force: :boolean,
output: :string,
output_psql: :string,
domain: :string,
instance_name: :string,
admin_email: :string,
notify_email: :string,
dbhost: :string,
dbname: :string,
dbuser: :string,
dbpass: :string,
indexable: :string,
- db_configurable: :string
+ db_configurable: :string,
+ uploads_dir: :string,
+ static_dir: :string
],
aliases: [
o: :output,
f: :force
]
)
paths =
[config_path, psql_path] = [
Keyword.get(options, :output, "config/generated_config.exs"),
Keyword.get(options, :output_psql, "config/setup_db.psql")
]
will_overwrite = Enum.filter(paths, &File.exists?/1)
proceed? = Enum.empty?(will_overwrite) or Keyword.get(options, :force, false)
if proceed? do
[domain, port | _] =
String.split(
- Common.get_option(
+ get_option(
options,
:domain,
"What domain will your instance use? (e.g pleroma.soykaf.com)"
),
":"
) ++ [443]
name =
- Common.get_option(
+ get_option(
options,
:instance_name,
"What is the name of your instance? (e.g. Pleroma/Soykaf)"
)
- email = Common.get_option(options, :admin_email, "What is your admin email address?")
+ email = get_option(options, :admin_email, "What is your admin email address?")
notify_email =
- Common.get_option(
+ get_option(
options,
:notify_email,
"What email address do you want to use for sending email notifications?",
email
)
indexable =
- Common.get_option(
+ get_option(
options,
:indexable,
"Do you want search engines to index your site? (y/n)",
"y"
) === "y"
db_configurable? =
- Common.get_option(
+ get_option(
options,
:db_configurable,
- "Do you want to be able to configure instance from admin part? (y/n)",
+ "Do you want to store the configuration in the database (allows controlling it from admin-fe)? (y/n)",
"y"
) === "y"
- dbhost =
- Common.get_option(options, :dbhost, "What is the hostname of your database?", "localhost")
+ dbhost = get_option(options, :dbhost, "What is the hostname of your database?", "localhost")
- dbname =
- Common.get_option(options, :dbname, "What is the name of your database?", "pleroma_dev")
+ dbname = get_option(options, :dbname, "What is the name of your database?", "pleroma_dev")
dbuser =
- Common.get_option(
+ get_option(
options,
:dbuser,
"What is the user used to connect to your database?",
"pleroma"
)
dbpass =
- Common.get_option(
+ get_option(
options,
:dbpass,
"What is the password used to connect to your database?",
:crypto.strong_rand_bytes(64) |> Base.encode64() |> binary_part(0, 64),
"autogenerated"
)
+ uploads_dir =
+ get_option(
+ options,
+ :upload_dir,
+ "What directory should media uploads go in (when using the local uploader)?",
+ Pleroma.Config.get([Pleroma.Uploaders.Local, :uploads])
+ )
+
+ static_dir =
+ get_option(
+ options,
+ :static_dir,
+ "What directory should custom public files be read from (custom emojis, frontend bundle overrides, robots.txt, etc.)?",
+ Pleroma.Config.get([:instance, :static_dir])
+ )
+
secret = :crypto.strong_rand_bytes(64) |> Base.encode64() |> binary_part(0, 64)
signing_salt = :crypto.strong_rand_bytes(8) |> Base.encode64() |> binary_part(0, 8)
{web_push_public_key, web_push_private_key} = :crypto.generate_key(:ecdh, :prime256v1)
result_config =
EEx.eval_file(
"sample_config.eex" |> Path.expand(__DIR__),
domain: domain,
port: port,
email: email,
notify_email: notify_email,
name: name,
dbhost: dbhost,
dbname: dbname,
dbuser: dbuser,
dbpass: dbpass,
- version: Pleroma.Mixfile.project() |> Keyword.get(:version),
secret: secret,
signing_salt: signing_salt,
web_push_public_key: Base.url_encode64(web_push_public_key, padding: false),
web_push_private_key: Base.url_encode64(web_push_private_key, padding: false),
- db_configurable?: db_configurable?
+ db_configurable?: db_configurable?,
+ static_dir: static_dir,
+ uploads_dir: uploads_dir
)
result_psql =
EEx.eval_file(
"sample_psql.eex" |> Path.expand(__DIR__),
dbname: dbname,
dbuser: dbuser,
dbpass: dbpass
)
- Common.shell_info(
+ shell_info(
"Writing config to #{config_path}. You should rename it to config/prod.secret.exs or config/dev.secret.exs."
)
File.write(config_path, result_config)
- Common.shell_info("Writing #{psql_path}.")
+ shell_info("Writing #{psql_path}.")
File.write(psql_path, result_psql)
write_robots_txt(indexable)
- Common.shell_info(
+ shell_info(
"\n" <>
"""
To get started:
1. Verify the contents of the generated files.
- 2. Run `sudo -u postgres psql -f #{Common.escape_sh_path(psql_path)}`.
+ 2. Run `sudo -u postgres psql -f #{escape_sh_path(psql_path)}`.
""" <>
if config_path in ["config/dev.secret.exs", "config/prod.secret.exs"] do
""
else
- "3. Run `mv #{Common.escape_sh_path(config_path)} 'config/prod.secret.exs'`."
+ "3. Run `mv #{escape_sh_path(config_path)} 'config/prod.secret.exs'`."
end
)
else
- Common.shell_error(
+ shell_error(
"The task would have overwritten the following files:\n" <>
(Enum.map(paths, &"- #{&1}\n") |> Enum.join("")) <>
"Rerun with `--force` to overwrite them."
)
end
end
defp write_robots_txt(indexable) do
robots_txt =
EEx.eval_file(
Path.expand("robots_txt.eex", __DIR__),
indexable: indexable
)
static_dir = Pleroma.Config.get([:instance, :static_dir], "instance/static/")
unless File.exists?(static_dir) do
File.mkdir_p!(static_dir)
end
robots_txt_path = Path.join(static_dir, "robots.txt")
if File.exists?(robots_txt_path) do
File.cp!(robots_txt_path, "#{robots_txt_path}.bak")
- Common.shell_info("Backing up existing robots.txt to #{robots_txt_path}.bak")
+ shell_info("Backing up existing robots.txt to #{robots_txt_path}.bak")
end
File.write(robots_txt_path, robots_txt)
- Common.shell_info("Writing #{robots_txt_path}.")
+ shell_info("Writing #{robots_txt_path}.")
end
end
diff --git a/lib/mix/tasks/pleroma/relay.ex b/lib/mix/tasks/pleroma/relay.ex
index 213ae24d2..83ed0ed02 100644
--- a/lib/mix/tasks/pleroma/relay.ex
+++ b/lib/mix/tasks/pleroma/relay.ex
@@ -1,47 +1,47 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Mix.Tasks.Pleroma.Relay do
use Mix.Task
- alias Mix.Tasks.Pleroma.Common
+ import Mix.Pleroma
alias Pleroma.Web.ActivityPub.Relay
@shortdoc "Manages remote relays"
@moduledoc """
Manages remote relays
## Follow a remote relay
``mix pleroma.relay follow <relay_url>``
Example: ``mix pleroma.relay follow https://example.org/relay``
## Unfollow a remote relay
``mix pleroma.relay unfollow <relay_url>``
Example: ``mix pleroma.relay unfollow https://example.org/relay``
"""
def run(["follow", target]) do
- Common.start_pleroma()
+ start_pleroma()
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} -> Common.shell_error("Error while following #{target}: #{inspect(e)}")
+ {:error, e} -> shell_error("Error while following #{target}: #{inspect(e)}")
end
end
def run(["unfollow", target]) do
- Common.start_pleroma()
+ start_pleroma()
with {:ok, _activity} <- Relay.unfollow(target) do
# put this task to sleep to allow the genserver to push out the messages
:timer.sleep(500)
else
- {:error, e} -> Common.shell_error("Error while following #{target}: #{inspect(e)}")
+ {:error, e} -> shell_error("Error while following #{target}: #{inspect(e)}")
end
end
end
diff --git a/lib/mix/tasks/pleroma/sample_config.eex b/lib/mix/tasks/pleroma/sample_config.eex
index 73d9217be..8b45acb05 100644
--- a/lib/mix/tasks/pleroma/sample_config.eex
+++ b/lib/mix/tasks/pleroma/sample_config.eex
@@ -1,79 +1,81 @@
# Pleroma instance configuration
# NOTE: This file should not be committed to a repo or otherwise made public
# without removing sensitive information.
use Mix.Config
config :pleroma, Pleroma.Web.Endpoint,
url: [host: "<%= domain %>", scheme: "https", port: <%= port %>],
secret_key_base: "<%= secret %>",
signing_salt: "<%= signing_salt %>"
config :pleroma, :instance,
name: "<%= name %>",
email: "<%= email %>",
notify_email: "<%= notify_email %>",
limit: 5000,
registrations_open: true,
- dedupe_media: false,
dynamic_configuration: <%= db_configurable? %>
config :pleroma, :media_proxy,
enabled: false,
redirect_on_failure: true
#base_url: "https://cache.pleroma.social"
config :pleroma, Pleroma.Repo,
adapter: Ecto.Adapters.Postgres,
username: "<%= dbuser %>",
password: "<%= dbpass %>",
database: "<%= dbname %>",
hostname: "<%= dbhost %>",
pool_size: 10
# Configure web push notifications
config :web_push_encryption, :vapid_details,
subject: "mailto:<%= email %>",
public_key: "<%= web_push_public_key %>",
private_key: "<%= web_push_private_key %>"
+config :pleroma, :instance, static_dir: "<%= static_dir %>"
+config :pleroma, Pleroma.Uploaders.Local, uploads: "<%= uploads_dir %>"
+
# 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/pleroma/uploads.ex b/lib/mix/tasks/pleroma/uploads.ex
index 8855b5538..be45383ee 100644
--- a/lib/mix/tasks/pleroma/uploads.ex
+++ b/lib/mix/tasks/pleroma/uploads.ex
@@ -1,108 +1,108 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Mix.Tasks.Pleroma.Uploads do
use Mix.Task
- alias Mix.Tasks.Pleroma.Common
+ import Mix.Pleroma
alias Pleroma.Upload
alias Pleroma.Uploaders.Local
require Logger
@log_every 50
@shortdoc "Migrates uploads from local to remote storage"
@moduledoc """
Manages uploads
## Migrate uploads from local to remote storage
mix pleroma.uploads migrate_local TARGET_UPLOADER [OPTIONS...]
Options:
- `--delete` - delete local uploads after migrating them to the target uploader
A list of available uploaders can be seen in config.exs
"""
def run(["migrate_local", target_uploader | args]) do
delete? = Enum.member?(args, "--delete")
- Common.start_pleroma()
+ start_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
- Common.shell_info("Migrating files from local #{local_path} to #{to_string(uploader)}")
+ shell_info("Migrating files from local #{local_path} to #{to_string(uploader)}")
if delete? do
- Common.shell_info(
+ shell_info(
"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 = Path.rootname(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)
- Common.shell_info("Found #{total_count} uploads")
+ shell_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 ->
- Common.shell_error("failed to upload #{inspect(upload.path)}: #{inspect(error)}")
+ shell_error("failed to upload #{inspect(upload.path)}: #{inspect(error)}")
end
end,
timeout: 150_000
)
|> Stream.chunk_every(@log_every)
# credo:disable-for-next-line Credo.Check.Warning.UnusedEnumOperation
|> Enum.reduce(0, fn done, count ->
count = count + length(done)
- Common.shell_info("Uploaded #{count}/#{total_count} files")
+ shell_info("Uploaded #{count}/#{total_count} files")
count
end)
- Common.shell_info("Done!")
+ shell_info("Done!")
end
end
diff --git a/lib/mix/tasks/pleroma/user.ex b/lib/mix/tasks/pleroma/user.ex
index 0efa745e4..ab158f57e 100644
--- a/lib/mix/tasks/pleroma/user.ex
+++ b/lib/mix/tasks/pleroma/user.ex
@@ -1,467 +1,465 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Mix.Tasks.Pleroma.User do
use Mix.Task
import Ecto.Changeset
- alias Mix.Tasks.Pleroma.Common
+ import Mix.Pleroma
alias Pleroma.User
alias Pleroma.UserInviteToken
alias Pleroma.Web.OAuth
@shortdoc "Manages Pleroma users"
@moduledoc """
Manages Pleroma users.
## Create a new user.
mix pleroma.user new NICKNAME EMAIL [OPTION...]
Options:
- `--name NAME` - the user's name (i.e., "Lain Iwakura")
- `--bio BIO` - the user's bio
- `--password PASSWORD` - the user's password
- `--moderator`/`--no-moderator` - whether the user is a moderator
- `--admin`/`--no-admin` - whether the user is an admin
- `-y`, `--assume-yes`/`--no-assume-yes` - whether to assume yes to all questions
## Generate an invite link.
mix pleroma.user invite [OPTION...]
Options:
- `--expires_at DATE` - last day on which token is active (e.g. "2019-04-05")
- `--max_use NUMBER` - maximum numbers of token uses
## List generated invites
mix pleroma.user invites
## Revoke invite
mix pleroma.user revoke_invite TOKEN OR TOKEN_ID
## Delete the user's account.
mix pleroma.user rm NICKNAME
## Delete the user's activities.
mix pleroma.user delete_activities NICKNAME
## Sign user out from all applications (delete user's OAuth tokens and authorizations).
mix pleroma.user sign_out NICKNAME
## Deactivate or activate the user's account.
mix pleroma.user toggle_activated NICKNAME
## Unsubscribe local users from user's account and deactivate it
mix pleroma.user unsubscribe NICKNAME
## Create a password reset link.
mix pleroma.user reset_password NICKNAME
## Set the value of the given user's settings.
mix pleroma.user set NICKNAME [OPTION...]
Options:
- `--locked`/`--no-locked` - whether the user's account is locked
- `--moderator`/`--no-moderator` - whether the user is a moderator
- `--admin`/`--no-admin` - whether the user is an admin
## Add tags to a user.
mix pleroma.user tag NICKNAME TAGS
## Delete tags from a user.
mix pleroma.user untag NICKNAME TAGS
## Toggle confirmation of the user's account.
mix pleroma.user toggle_confirmed NICKNAME
"""
def run(["new", nickname, email | rest]) do
{options, [], []} =
OptionParser.parse(
rest,
strict: [
name: :string,
bio: :string,
password: :string,
moderator: :boolean,
admin: :boolean,
assume_yes: :boolean
],
aliases: [
y: :assume_yes
]
)
name = Keyword.get(options, :name, nickname)
bio = Keyword.get(options, :bio, "")
{password, generated_password?} =
case Keyword.get(options, :password) do
nil ->
{:crypto.strong_rand_bytes(16) |> Base.encode64(), true}
password ->
{password, false}
end
moderator? = Keyword.get(options, :moderator, false)
admin? = Keyword.get(options, :admin, false)
assume_yes? = Keyword.get(options, :assume_yes, false)
- Common.shell_info("""
+ shell_info("""
A user will be created with the following information:
- nickname: #{nickname}
- email: #{email}
- password: #{
if(generated_password?, do: "[generated; a reset link will be created]", else: password)
}
- name: #{name}
- bio: #{bio}
- moderator: #{if(moderator?, do: "true", else: "false")}
- admin: #{if(admin?, do: "true", else: "false")}
""")
- proceed? = assume_yes? or Common.shell_yes?("Continue?")
+ proceed? = assume_yes? or shell_yes?("Continue?")
if proceed? do
- Common.start_pleroma()
+ start_pleroma()
params = %{
nickname: nickname,
email: email,
password: password,
password_confirmation: password,
name: name,
bio: bio
}
changeset = User.register_changeset(%User{}, params, need_confirmation: false)
{:ok, _user} = User.register(changeset)
- Common.shell_info("User #{nickname} created")
+ shell_info("User #{nickname} created")
if moderator? do
run(["set", nickname, "--moderator"])
end
if admin? do
run(["set", nickname, "--admin"])
end
if generated_password? do
run(["reset_password", nickname])
end
else
- Common.shell_info("User will not be created.")
+ shell_info("User will not be created.")
end
end
def run(["rm", nickname]) do
- Common.start_pleroma()
+ start_pleroma()
with %User{local: true} = user <- User.get_cached_by_nickname(nickname) do
User.perform(:delete, user)
- Common.shell_info("User #{nickname} deleted.")
+ shell_info("User #{nickname} deleted.")
else
_ ->
- Common.shell_error("No local user #{nickname}")
+ shell_error("No local user #{nickname}")
end
end
def run(["toggle_activated", nickname]) do
- Common.start_pleroma()
+ start_pleroma()
with %User{} = user <- User.get_cached_by_nickname(nickname) do
{:ok, user} = User.deactivate(user, !user.info.deactivated)
- Common.shell_info(
+ shell_info(
"Activation status of #{nickname}: #{if(user.info.deactivated, do: "de", else: "")}activated"
)
else
_ ->
- Common.shell_error("No user #{nickname}")
+ shell_error("No user #{nickname}")
end
end
def run(["reset_password", nickname]) do
- Common.start_pleroma()
+ start_pleroma()
with %User{local: true} = user <- User.get_cached_by_nickname(nickname),
{:ok, token} <- Pleroma.PasswordResetToken.create_token(user) do
- Common.shell_info("Generated password reset token for #{user.nickname}")
+ shell_info("Generated password reset token for #{user.nickname}")
IO.puts(
"URL: #{
Pleroma.Web.Router.Helpers.util_url(
Pleroma.Web.Endpoint,
:show_password_reset,
token.token
)
}"
)
else
_ ->
- Common.shell_error("No local user #{nickname}")
+ shell_error("No local user #{nickname}")
end
end
def run(["unsubscribe", nickname]) do
- Common.start_pleroma()
+ start_pleroma()
with %User{} = user <- User.get_cached_by_nickname(nickname) do
- Common.shell_info("Deactivating #{user.nickname}")
+ shell_info("Deactivating #{user.nickname}")
User.deactivate(user)
{:ok, friends} = User.get_friends(user)
Enum.each(friends, fn friend ->
user = User.get_cached_by_id(user.id)
- Common.shell_info("Unsubscribing #{friend.nickname} from #{user.nickname}")
+ shell_info("Unsubscribing #{friend.nickname} from #{user.nickname}")
User.unfollow(user, friend)
end)
:timer.sleep(500)
user = User.get_cached_by_id(user.id)
if Enum.empty?(user.following) do
- Common.shell_info("Successfully unsubscribed all followers from #{user.nickname}")
+ shell_info("Successfully unsubscribed all followers from #{user.nickname}")
end
else
_ ->
- Common.shell_error("No user #{nickname}")
+ shell_error("No user #{nickname}")
end
end
def run(["set", nickname | rest]) do
- Common.start_pleroma()
+ start_pleroma()
{options, [], []} =
OptionParser.parse(
rest,
strict: [
moderator: :boolean,
admin: :boolean,
locked: :boolean
]
)
with %User{local: true} = user <- User.get_cached_by_nickname(nickname) do
user =
case Keyword.get(options, :moderator) do
nil -> user
value -> set_moderator(user, value)
end
user =
case Keyword.get(options, :locked) do
nil -> user
value -> set_locked(user, value)
end
_user =
case Keyword.get(options, :admin) do
nil -> user
value -> set_admin(user, value)
end
else
_ ->
- Common.shell_error("No local user #{nickname}")
+ shell_error("No local user #{nickname}")
end
end
def run(["tag", nickname | tags]) do
- Common.start_pleroma()
+ start_pleroma()
with %User{} = user <- User.get_cached_by_nickname(nickname) do
user = user |> User.tag(tags)
- Common.shell_info("Tags of #{user.nickname}: #{inspect(tags)}")
+ shell_info("Tags of #{user.nickname}: #{inspect(tags)}")
else
_ ->
- Common.shell_error("Could not change user tags for #{nickname}")
+ shell_error("Could not change user tags for #{nickname}")
end
end
def run(["untag", nickname | tags]) do
- Common.start_pleroma()
+ start_pleroma()
with %User{} = user <- User.get_cached_by_nickname(nickname) do
user = user |> User.untag(tags)
- Common.shell_info("Tags of #{user.nickname}: #{inspect(tags)}")
+ shell_info("Tags of #{user.nickname}: #{inspect(tags)}")
else
_ ->
- Common.shell_error("Could not change user tags for #{nickname}")
+ shell_error("Could not change user tags for #{nickname}")
end
end
def run(["invite" | rest]) do
{options, [], []} =
OptionParser.parse(rest,
strict: [
expires_at: :string,
max_use: :integer
]
)
options =
options
|> Keyword.update(:expires_at, {:ok, nil}, fn
nil -> {:ok, nil}
val -> Date.from_iso8601(val)
end)
|> Enum.into(%{})
- Common.start_pleroma()
+ start_pleroma()
with {:ok, val} <- options[:expires_at],
options = Map.put(options, :expires_at, val),
{:ok, invite} <- UserInviteToken.create_invite(options) do
- Common.shell_info(
- "Generated user invite token " <> String.replace(invite.invite_type, "_", " ")
- )
+ shell_info("Generated user invite token " <> String.replace(invite.invite_type, "_", " "))
url =
Pleroma.Web.Router.Helpers.redirect_url(
Pleroma.Web.Endpoint,
:registration_page,
invite.token
)
IO.puts(url)
else
error ->
- Common.shell_error("Could not create invite token: #{inspect(error)}")
+ shell_error("Could not create invite token: #{inspect(error)}")
end
end
def run(["invites"]) do
- Common.start_pleroma()
+ start_pleroma()
- Common.shell_info("Invites list:")
+ shell_info("Invites list:")
UserInviteToken.list_invites()
|> Enum.each(fn invite ->
expire_info =
with expires_at when not is_nil(expires_at) <- invite.expires_at do
" | Expires at: #{Date.to_string(expires_at)}"
end
using_info =
with max_use when not is_nil(max_use) <- invite.max_use do
" | Max use: #{max_use} Left use: #{max_use - invite.uses}"
end
- Common.shell_info(
+ shell_info(
"ID: #{invite.id} | Token: #{invite.token} | Token type: #{invite.invite_type} | Used: #{
invite.used
}#{expire_info}#{using_info}"
)
end)
end
def run(["revoke_invite", token]) do
- Common.start_pleroma()
+ start_pleroma()
with {:ok, invite} <- UserInviteToken.find_by_token(token),
{:ok, _} <- UserInviteToken.update_invite(invite, %{used: true}) do
- Common.shell_info("Invite for token #{token} was revoked.")
+ shell_info("Invite for token #{token} was revoked.")
else
- _ -> Common.shell_error("No invite found with token #{token}")
+ _ -> shell_error("No invite found with token #{token}")
end
end
def run(["delete_activities", nickname]) do
- Common.start_pleroma()
+ start_pleroma()
with %User{local: true} = user <- User.get_cached_by_nickname(nickname) do
{:ok, _} = User.delete_user_activities(user)
- Common.shell_info("User #{nickname} statuses deleted.")
+ shell_info("User #{nickname} statuses deleted.")
else
_ ->
- Common.shell_error("No local user #{nickname}")
+ shell_error("No local user #{nickname}")
end
end
def run(["toggle_confirmed", nickname]) do
- Common.start_pleroma()
+ start_pleroma()
with %User{} = user <- User.get_cached_by_nickname(nickname) do
{:ok, user} = User.toggle_confirmation(user)
message = if user.info.confirmation_pending, do: "needs", else: "doesn't need"
- Common.shell_info("#{nickname} #{message} confirmation.")
+ shell_info("#{nickname} #{message} confirmation.")
else
_ ->
- Common.shell_error("No local user #{nickname}")
+ shell_error("No local user #{nickname}")
end
end
def run(["sign_out", nickname]) do
- Common.start_pleroma()
+ start_pleroma()
with %User{local: true} = user <- User.get_cached_by_nickname(nickname) do
OAuth.Token.delete_user_tokens(user)
OAuth.Authorization.delete_user_authorizations(user)
- Common.shell_info("#{nickname} signed out from all apps.")
+ shell_info("#{nickname} signed out from all apps.")
else
_ ->
- Common.shell_error("No local user #{nickname}")
+ shell_error("No local user #{nickname}")
end
end
defp set_moderator(user, value) do
info_cng = User.Info.admin_api_update(user.info, %{is_moderator: value})
user_cng =
Ecto.Changeset.change(user)
|> put_embed(:info, info_cng)
{:ok, user} = User.update_and_set_cache(user_cng)
- Common.shell_info("Moderator status of #{user.nickname}: #{user.info.is_moderator}")
+ shell_info("Moderator status of #{user.nickname}: #{user.info.is_moderator}")
user
end
defp set_admin(user, value) do
info_cng = User.Info.admin_api_update(user.info, %{is_admin: value})
user_cng =
Ecto.Changeset.change(user)
|> put_embed(:info, info_cng)
{:ok, user} = User.update_and_set_cache(user_cng)
- Common.shell_info("Admin status of #{user.nickname}: #{user.info.is_admin}")
+ shell_info("Admin status of #{user.nickname}: #{user.info.is_admin}")
user
end
defp set_locked(user, value) do
info_cng = User.Info.user_upgrade(user.info, %{locked: value})
user_cng =
Ecto.Changeset.change(user)
|> put_embed(:info, info_cng)
{:ok, user} = User.update_and_set_cache(user_cng)
- Common.shell_info("Locked status of #{user.nickname}: #{user.info.locked}")
+ shell_info("Locked status of #{user.nickname}: #{user.info.locked}")
user
end
end
diff --git a/lib/pleroma/release_tasks.ex b/lib/pleroma/release_tasks.ex
index eb6eff61c..d6720cd05 100644
--- a/lib/pleroma/release_tasks.ex
+++ b/lib/pleroma/release_tasks.ex
@@ -1,63 +1,64 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.ReleaseTasks do
@repo Pleroma.Repo
def run(args) do
[task | args] = String.split(args)
case task do
"migrate" -> migrate(args)
"create" -> create()
"rollback" -> rollback(args)
task -> mix_task(task, args)
end
end
defp mix_task(task, args) do
+ Application.load(:pleroma)
{:ok, modules} = :application.get_key(:pleroma, :modules)
module =
Enum.find(modules, fn module ->
module = Module.split(module)
match?(["Mix", "Tasks", "Pleroma" | _], module) and
String.downcase(List.last(module)) == task
end)
if module do
module.run(args)
else
IO.puts("The task #{task} does not exist")
end
end
def migrate(args) do
Mix.Tasks.Pleroma.Ecto.Migrate.run(args)
end
def rollback(args) do
Mix.Tasks.Pleroma.Ecto.Rollback.run(args)
end
def create do
case @repo.__adapter__.storage_up(@repo.config) do
:ok ->
IO.puts("The database for #{inspect(@repo)} has been created")
{:error, :already_up} ->
IO.puts("The database for #{inspect(@repo)} has already been created")
{:error, term} when is_binary(term) ->
IO.puts(:stderr, "The database for #{inspect(@repo)} couldn't be created: #{term}")
{:error, term} ->
IO.puts(
:stderr,
"The database for #{inspect(@repo)} couldn't be created: #{inspect(term)}"
)
end
end
end
diff --git a/rel/files/bin/pleroma_ctl b/rel/files/bin/pleroma_ctl
index 62368115e..b0e1874a9 100755
--- a/rel/files/bin/pleroma_ctl
+++ b/rel/files/bin/pleroma_ctl
@@ -1,118 +1,118 @@
#!/bin/sh
# XXX: This should be removed when elixir's releases get custom command support
detect_flavour() {
arch="$(arch)"
if [ "$arch" = "x86_64" ]; then
arch="amd64"
elif [ "$arch" = "armv7l" ]; then
arch="arm"
elif [ "$arch" = "aarch64" ]; then
arch="arm64"
else
echo "Unsupported arch: $arch" >&2
exit 1
fi
if getconf GNU_LIBC_VERSION >/dev/null; then
libc_postfix=""
elif [ "$(ldd 2>&1 | head -c 9)" = "musl libc" ]; then
libc_postfix="-musl"
elif [ "$(find /lib/libc.musl* | wc -l)" ]; then
libc_postfix="-musl"
else
echo "Unsupported libc" >&2
exit 1
fi
echo "$arch$libc_postfix"
}
detect_branch() {
version="$(cut -d' ' -f2 <"$RELEASE_ROOT"/releases/start_erl.data)"
branch="$(echo "$version" | cut -d'-' -f 4)"
if [ "$branch" = "develop" ]; then
echo "develop"
elif [ "$branch" = "" ]; then
echo "master"
else
echo "Releases are built only for master and develop branches" >&2
exit 1
fi
}
update() {
set -e
RELEASE_ROOT=$(dirname "$SCRIPTPATH")
uri="${PLEROMA_CTL_URI:-https://git.pleroma.social}"
project_id="${PLEROMA_CTL_PROJECT_ID:-2}"
project_branch="$(detect_branch)"
flavour="${PLEROMA_CTL_FLAVOUR:-$(detect_flavour)}"
echo "Detected flavour: $flavour"
tmp="${PLEROMA_CTL_TMP_DIR:-/tmp}"
artifact="$tmp/pleroma.zip"
full_uri="${uri}/api/v4/projects/${project_id}/jobs/artifacts/${project_branch}/download?job=${flavour}"
echo "Downloading the artifact from ${full_uri} to ${artifact}"
curl "$full_uri" -o "${artifact}"
echo "Unpacking ${artifact} to ${tmp}"
unzip -q "$artifact" -d "$tmp"
echo "Copying files over to $RELEASE_ROOT"
if [ "$1" != "--no-rm" ]; then
rm -r "${RELEASE_ROOT:-?}"/*
fi
cp -rf "$tmp/release"/* "$RELEASE_ROOT"
echo "Removing temporary files"
rm -r "$tmp/release"
rm "$artifact"
echo "Done! Please refer to the changelog/release notes for changes and update instructions"
set +e
}
if [ -z "$1" ] || [ "$1" = "help" ]; then
# TODO: Just list the commands on `pleroma_ctl help` and output help for the individual command on `pleroma_ctl help $COMMAND`
echo "Usage: $(basename "$0") COMMAND [ARGS]
The known commands are:
create
Create database schema (needs to be executed only once)
migrate
Execute database migrations (needs to be done after updates)
rollback [VERSION]
Rollback database migrations (needs to be done before downgrading)
update [OPTIONS]
Update the instance using the latest CI artifact for the current branch.
The only supported option is --no-rm, when set the script won't delete the whole directory, but
just force copy over files from the new release. This wastes more space, but may be useful if
some files are stored inside of the release directories (although you really shouldn't store them
there), or if you want to be able to quickly revert a broken update.
The script will try to detect your architecture and ABI and set a flavour automatically,
but if it is wrong, you can overwrite it by setting PLEROMA_CTL_FLAVOUR to the desired flavour.
By default the artifact will be downloaded from https://git.pleroma.social for pleroma/pleroma (project id: 2)
to /tmp/, you can overwrite these settings by setting PLEROMA_CTL_URI, PLEROMA_CTL_PROJECT_ID and PLEROMA_CTL_TMP_DIR
respectively.
and any mix tasks under Pleroma namespace, for example \`mix pleroma.user COMMAND\` is
equivalent to \`$(basename "$0") user COMMAND\`
By default pleroma_ctl will try calling into a running instance to execute non migration-related commands,
if for some reason this is undesired, set PLEROMA_CTL_RPC_DISABLED environment variable
"
else
SCRIPT=$(readlink -f "$0")
SCRIPTPATH=$(dirname "$SCRIPT")
if [ "$1" = "update" ]; then
update "$2"
- elif [ "$1" = "migrate" ] || [ "$1" = "rollback" ] || [ "$1" = "create" ] || [ -n "$PLEROMA_CTL_RPC_DISABLED" ]; then
+ elif [ "$1" = "migrate" ] || [ "$1" = "rollback" ] || [ "$1" = "create" ] || [ "$1 $2" = "instance gen" ] || [ -n "$PLEROMA_CTL_RPC_DISABLED" ]; then
"$SCRIPTPATH"/pleroma eval 'Pleroma.ReleaseTasks.run("'"$*"'")'
else
"$SCRIPTPATH"/pleroma rpc 'Pleroma.ReleaseTasks.run("'"$*"'")'
fi
fi
diff --git a/test/tasks/config_test.exs b/test/tasks/config_test.exs
index 7d3b1860c..d448b0444 100644
--- a/test/tasks/config_test.exs
+++ b/test/tasks/config_test.exs
@@ -1,54 +1,54 @@
defmodule Mix.Tasks.Pleroma.ConfigTest do
use Pleroma.DataCase
alias Pleroma.Repo
alias Pleroma.Web.AdminAPI.Config
setup_all do
Mix.shell(Mix.Shell.Process)
- temp_file = "config/temp.migrated.secret.exs"
+ temp_file = "config/temp.exported_from_db.secret.exs"
dynamic = Pleroma.Config.get([:instance, :dynamic_configuration])
Pleroma.Config.put([:instance, :dynamic_configuration], true)
on_exit(fn ->
Mix.shell(Mix.Shell.IO)
Application.delete_env(:pleroma, :first_setting)
Application.delete_env(:pleroma, :second_setting)
Pleroma.Config.put([:instance, :dynamic_configuration], dynamic)
:ok = File.rm(temp_file)
end)
{:ok, temp_file: temp_file}
end
test "settings are migrated to db" do
assert Repo.all(Config) == []
Application.put_env(:pleroma, :first_setting, key: "value", key2: [Pleroma.Repo])
Application.put_env(:pleroma, :second_setting, key: "value2", key2: [Pleroma.Activity])
Mix.Tasks.Pleroma.Config.run(["migrate_to_db"])
first_db = Config.get_by_key("first_setting")
second_db = Config.get_by_key("second_setting")
refute Config.get_by_key("Pleroma.Repo")
assert Config.from_binary(first_db.value) == [key: "value", key2: [Pleroma.Repo]]
assert Config.from_binary(second_db.value) == [key: "value2", key2: [Pleroma.Activity]]
end
test "settings are migrated to file and deleted from db", %{temp_file: temp_file} do
Config.create(%{key: "setting_first", value: [key: "value", key2: [Pleroma.Activity]]})
Config.create(%{key: "setting_second", value: [key: "valu2", key2: [Pleroma.Repo]]})
Mix.Tasks.Pleroma.Config.run(["migrate_from_db", "temp"])
assert Repo.all(Config) == []
assert File.exists?(temp_file)
{:ok, file} = File.read(temp_file)
assert file =~ "config :pleroma, setting_first:"
assert file =~ "config :pleroma, setting_second:"
end
end
diff --git a/test/web/admin_api/admin_api_controller_test.exs b/test/web/admin_api/admin_api_controller_test.exs
index 18f64f2b7..2a5912645 100644
--- a/test/web/admin_api/admin_api_controller_test.exs
+++ b/test/web/admin_api/admin_api_controller_test.exs
@@ -1,1467 +1,1467 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
use Pleroma.Web.ConnCase
alias Pleroma.Activity
alias Pleroma.User
alias Pleroma.UserInviteToken
alias Pleroma.Web.CommonAPI
import Pleroma.Factory
describe "/api/pleroma/admin/users" do
test "Delete" do
admin = insert(:user, info: %{is_admin: true})
user = insert(:user)
conn =
build_conn()
|> assign(:user, admin)
|> put_req_header("accept", "application/json")
|> delete("/api/pleroma/admin/users?nickname=#{user.nickname}")
assert json_response(conn, 200) == user.nickname
end
test "Create" do
admin = insert(:user, info: %{is_admin: true})
conn =
build_conn()
|> assign(:user, admin)
|> put_req_header("accept", "application/json")
|> post("/api/pleroma/admin/users", %{
"nickname" => "lain",
"email" => "lain@example.org",
"password" => "test"
})
assert json_response(conn, 200) == "lain"
end
end
describe "/api/pleroma/admin/users/:nickname" do
test "Show", %{conn: conn} do
admin = insert(:user, info: %{is_admin: true})
user = insert(:user)
conn =
conn
|> assign(:user, admin)
|> get("/api/pleroma/admin/users/#{user.nickname}")
expected = %{
"deactivated" => false,
"id" => to_string(user.id),
"local" => true,
"nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false},
"tags" => []
}
assert expected == json_response(conn, 200)
end
test "when the user doesn't exist", %{conn: conn} do
admin = insert(:user, info: %{is_admin: true})
user = build(:user)
conn =
conn
|> assign(:user, admin)
|> get("/api/pleroma/admin/users/#{user.nickname}")
assert "Not found" == json_response(conn, 404)
end
end
describe "/api/pleroma/admin/users/follow" do
test "allows to force-follow another user" do
admin = insert(:user, info: %{is_admin: true})
user = insert(:user)
follower = insert(:user)
build_conn()
|> assign(:user, admin)
|> put_req_header("accept", "application/json")
|> post("/api/pleroma/admin/users/follow", %{
"follower" => follower.nickname,
"followed" => user.nickname
})
user = User.get_cached_by_id(user.id)
follower = User.get_cached_by_id(follower.id)
assert User.following?(follower, user)
end
end
describe "/api/pleroma/admin/users/unfollow" do
test "allows to force-unfollow another user" do
admin = insert(:user, info: %{is_admin: true})
user = insert(:user)
follower = insert(:user)
User.follow(follower, user)
build_conn()
|> assign(:user, admin)
|> put_req_header("accept", "application/json")
|> post("/api/pleroma/admin/users/unfollow", %{
"follower" => follower.nickname,
"followed" => user.nickname
})
user = User.get_cached_by_id(user.id)
follower = User.get_cached_by_id(follower.id)
refute User.following?(follower, user)
end
end
describe "PUT /api/pleroma/admin/users/tag" do
setup do
admin = insert(:user, info: %{is_admin: true})
user1 = insert(:user, %{tags: ["x"]})
user2 = insert(:user, %{tags: ["y"]})
user3 = insert(:user, %{tags: ["unchanged"]})
conn =
build_conn()
|> assign(:user, admin)
|> put_req_header("accept", "application/json")
|> put(
"/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=#{
user2.nickname
}&tags[]=foo&tags[]=bar"
)
%{conn: conn, user1: user1, user2: user2, user3: user3}
end
test "it appends specified tags to users with specified nicknames", %{
conn: conn,
user1: user1,
user2: user2
} do
assert json_response(conn, :no_content)
assert User.get_cached_by_id(user1.id).tags == ["x", "foo", "bar"]
assert User.get_cached_by_id(user2.id).tags == ["y", "foo", "bar"]
end
test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
assert json_response(conn, :no_content)
assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
end
end
describe "DELETE /api/pleroma/admin/users/tag" do
setup do
admin = insert(:user, info: %{is_admin: true})
user1 = insert(:user, %{tags: ["x"]})
user2 = insert(:user, %{tags: ["y", "z"]})
user3 = insert(:user, %{tags: ["unchanged"]})
conn =
build_conn()
|> assign(:user, admin)
|> put_req_header("accept", "application/json")
|> delete(
"/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=#{
user2.nickname
}&tags[]=x&tags[]=z"
)
%{conn: conn, user1: user1, user2: user2, user3: user3}
end
test "it removes specified tags from users with specified nicknames", %{
conn: conn,
user1: user1,
user2: user2
} do
assert json_response(conn, :no_content)
assert User.get_cached_by_id(user1.id).tags == []
assert User.get_cached_by_id(user2.id).tags == ["y"]
end
test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
assert json_response(conn, :no_content)
assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
end
end
describe "/api/pleroma/admin/users/:nickname/permission_group" do
test "GET is giving user_info" do
admin = insert(:user, info: %{is_admin: true})
conn =
build_conn()
|> assign(:user, admin)
|> put_req_header("accept", "application/json")
|> get("/api/pleroma/admin/users/#{admin.nickname}/permission_group/")
assert json_response(conn, 200) == %{
"is_admin" => true,
"is_moderator" => false
}
end
test "/:right POST, can add to a permission group" do
admin = insert(:user, info: %{is_admin: true})
user = insert(:user)
conn =
build_conn()
|> assign(:user, admin)
|> put_req_header("accept", "application/json")
|> post("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin")
assert json_response(conn, 200) == %{
"is_admin" => true
}
end
test "/:right DELETE, can remove from a permission group" do
admin = insert(:user, info: %{is_admin: true})
user = insert(:user, info: %{is_admin: true})
conn =
build_conn()
|> assign(:user, admin)
|> put_req_header("accept", "application/json")
|> delete("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin")
assert json_response(conn, 200) == %{
"is_admin" => false
}
end
end
describe "PUT /api/pleroma/admin/users/:nickname/activation_status" do
setup %{conn: conn} do
admin = insert(:user, info: %{is_admin: true})
conn =
conn
|> assign(:user, admin)
|> put_req_header("accept", "application/json")
%{conn: conn}
end
test "deactivates the user", %{conn: conn} do
user = insert(:user)
conn =
conn
|> put("/api/pleroma/admin/users/#{user.nickname}/activation_status", %{status: false})
user = User.get_cached_by_id(user.id)
assert user.info.deactivated == true
assert json_response(conn, :no_content)
end
test "activates the user", %{conn: conn} do
user = insert(:user, info: %{deactivated: true})
conn =
conn
|> put("/api/pleroma/admin/users/#{user.nickname}/activation_status", %{status: true})
user = User.get_cached_by_id(user.id)
assert user.info.deactivated == false
assert json_response(conn, :no_content)
end
test "returns 403 when requested by a non-admin", %{conn: conn} do
user = insert(:user)
conn =
conn
|> assign(:user, user)
|> put("/api/pleroma/admin/users/#{user.nickname}/activation_status", %{status: false})
assert json_response(conn, :forbidden)
end
end
describe "POST /api/pleroma/admin/email_invite, with valid config" do
setup do
registrations_open = Pleroma.Config.get([:instance, :registrations_open])
invites_enabled = Pleroma.Config.get([:instance, :invites_enabled])
Pleroma.Config.put([:instance, :registrations_open], false)
Pleroma.Config.put([:instance, :invites_enabled], true)
on_exit(fn ->
Pleroma.Config.put([:instance, :registrations_open], registrations_open)
Pleroma.Config.put([:instance, :invites_enabled], invites_enabled)
:ok
end)
[user: insert(:user, info: %{is_admin: true})]
end
test "sends invitation and returns 204", %{conn: conn, user: user} do
recipient_email = "foo@bar.com"
recipient_name = "J. D."
conn =
conn
|> assign(:user, user)
|> post(
"/api/pleroma/admin/users/email_invite?email=#{recipient_email}&name=#{recipient_name}"
)
assert json_response(conn, :no_content)
token_record = List.last(Pleroma.Repo.all(Pleroma.UserInviteToken))
assert token_record
refute token_record.used
notify_email = Pleroma.Config.get([:instance, :notify_email])
instance_name = Pleroma.Config.get([:instance, :name])
email =
Pleroma.Emails.UserEmail.user_invitation_email(
user,
token_record,
recipient_email,
recipient_name
)
Swoosh.TestAssertions.assert_email_sent(
from: {instance_name, notify_email},
to: {recipient_name, recipient_email},
html_body: email.html_body
)
end
test "it returns 403 if requested by a non-admin", %{conn: conn} do
non_admin_user = insert(:user)
conn =
conn
|> assign(:user, non_admin_user)
|> post("/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
assert json_response(conn, :forbidden)
end
end
describe "POST /api/pleroma/admin/users/email_invite, with invalid config" do
setup do
[user: insert(:user, info: %{is_admin: true})]
end
test "it returns 500 if `invites_enabled` is not enabled", %{conn: conn, user: user} do
registrations_open = Pleroma.Config.get([:instance, :registrations_open])
invites_enabled = Pleroma.Config.get([:instance, :invites_enabled])
Pleroma.Config.put([:instance, :registrations_open], false)
Pleroma.Config.put([:instance, :invites_enabled], false)
on_exit(fn ->
Pleroma.Config.put([:instance, :registrations_open], registrations_open)
Pleroma.Config.put([:instance, :invites_enabled], invites_enabled)
:ok
end)
conn =
conn
|> assign(:user, user)
|> post("/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
assert json_response(conn, :internal_server_error)
end
test "it returns 500 if `registrations_open` is enabled", %{conn: conn, user: user} do
registrations_open = Pleroma.Config.get([:instance, :registrations_open])
invites_enabled = Pleroma.Config.get([:instance, :invites_enabled])
Pleroma.Config.put([:instance, :registrations_open], true)
Pleroma.Config.put([:instance, :invites_enabled], true)
on_exit(fn ->
Pleroma.Config.put([:instance, :registrations_open], registrations_open)
Pleroma.Config.put([:instance, :invites_enabled], invites_enabled)
:ok
end)
conn =
conn
|> assign(:user, user)
|> post("/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
assert json_response(conn, :internal_server_error)
end
end
test "/api/pleroma/admin/users/invite_token" do
admin = insert(:user, info: %{is_admin: true})
conn =
build_conn()
|> assign(:user, admin)
|> put_req_header("accept", "application/json")
|> get("/api/pleroma/admin/users/invite_token")
assert conn.status == 200
end
test "/api/pleroma/admin/users/:nickname/password_reset" do
admin = insert(:user, info: %{is_admin: true})
user = insert(:user)
conn =
build_conn()
|> assign(:user, admin)
|> put_req_header("accept", "application/json")
|> get("/api/pleroma/admin/users/#{user.nickname}/password_reset")
assert conn.status == 200
end
describe "GET /api/pleroma/admin/users" do
setup do
admin = insert(:user, info: %{is_admin: true})
conn =
build_conn()
|> assign(:user, admin)
{:ok, conn: conn, admin: admin}
end
test "renders users array for the first page", %{conn: conn, admin: admin} do
user = insert(:user, local: false, tags: ["foo", "bar"])
conn = get(conn, "/api/pleroma/admin/users?page=1")
users =
[
%{
"deactivated" => admin.info.deactivated,
"id" => admin.id,
"nickname" => admin.nickname,
"roles" => %{"admin" => true, "moderator" => false},
"local" => true,
"tags" => []
},
%{
"deactivated" => user.info.deactivated,
"id" => user.id,
"nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false},
"local" => false,
"tags" => ["foo", "bar"]
}
]
|> Enum.sort_by(& &1["nickname"])
assert json_response(conn, 200) == %{
"count" => 2,
"page_size" => 50,
"users" => users
}
end
test "renders empty array for the second page", %{conn: conn} do
insert(:user)
conn = get(conn, "/api/pleroma/admin/users?page=2")
assert json_response(conn, 200) == %{
"count" => 2,
"page_size" => 50,
"users" => []
}
end
test "regular search", %{conn: conn} do
user = insert(:user, nickname: "bob")
conn = get(conn, "/api/pleroma/admin/users?query=bo")
assert json_response(conn, 200) == %{
"count" => 1,
"page_size" => 50,
"users" => [
%{
"deactivated" => user.info.deactivated,
"id" => user.id,
"nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false},
"local" => true,
"tags" => []
}
]
}
end
test "search by domain", %{conn: conn} do
user = insert(:user, nickname: "nickname@domain.com")
insert(:user)
conn = get(conn, "/api/pleroma/admin/users?query=domain.com")
assert json_response(conn, 200) == %{
"count" => 1,
"page_size" => 50,
"users" => [
%{
"deactivated" => user.info.deactivated,
"id" => user.id,
"nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false},
"local" => true,
"tags" => []
}
]
}
end
test "search by full nickname", %{conn: conn} do
user = insert(:user, nickname: "nickname@domain.com")
insert(:user)
conn = get(conn, "/api/pleroma/admin/users?query=nickname@domain.com")
assert json_response(conn, 200) == %{
"count" => 1,
"page_size" => 50,
"users" => [
%{
"deactivated" => user.info.deactivated,
"id" => user.id,
"nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false},
"local" => true,
"tags" => []
}
]
}
end
test "search by display name", %{conn: conn} do
user = insert(:user, name: "Display name")
insert(:user)
conn = get(conn, "/api/pleroma/admin/users?name=display")
assert json_response(conn, 200) == %{
"count" => 1,
"page_size" => 50,
"users" => [
%{
"deactivated" => user.info.deactivated,
"id" => user.id,
"nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false},
"local" => true,
"tags" => []
}
]
}
end
test "search by email", %{conn: conn} do
user = insert(:user, email: "email@example.com")
insert(:user)
conn = get(conn, "/api/pleroma/admin/users?email=email@example.com")
assert json_response(conn, 200) == %{
"count" => 1,
"page_size" => 50,
"users" => [
%{
"deactivated" => user.info.deactivated,
"id" => user.id,
"nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false},
"local" => true,
"tags" => []
}
]
}
end
test "regular search with page size", %{conn: conn} do
user = insert(:user, nickname: "aalice")
user2 = insert(:user, nickname: "alice")
conn1 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=1")
assert json_response(conn1, 200) == %{
"count" => 2,
"page_size" => 1,
"users" => [
%{
"deactivated" => user.info.deactivated,
"id" => user.id,
"nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false},
"local" => true,
"tags" => []
}
]
}
conn2 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=2")
assert json_response(conn2, 200) == %{
"count" => 2,
"page_size" => 1,
"users" => [
%{
"deactivated" => user2.info.deactivated,
"id" => user2.id,
"nickname" => user2.nickname,
"roles" => %{"admin" => false, "moderator" => false},
"local" => true,
"tags" => []
}
]
}
end
test "only local users" do
admin = insert(:user, info: %{is_admin: true}, nickname: "john")
user = insert(:user, nickname: "bob")
insert(:user, nickname: "bobb", local: false)
conn =
build_conn()
|> assign(:user, admin)
|> get("/api/pleroma/admin/users?query=bo&filters=local")
assert json_response(conn, 200) == %{
"count" => 1,
"page_size" => 50,
"users" => [
%{
"deactivated" => user.info.deactivated,
"id" => user.id,
"nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false},
"local" => true,
"tags" => []
}
]
}
end
test "only local users with no query", %{admin: old_admin} do
admin = insert(:user, info: %{is_admin: true}, nickname: "john")
user = insert(:user, nickname: "bob")
insert(:user, nickname: "bobb", local: false)
conn =
build_conn()
|> assign(:user, admin)
|> get("/api/pleroma/admin/users?filters=local")
users =
[
%{
"deactivated" => user.info.deactivated,
"id" => user.id,
"nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false},
"local" => true,
"tags" => []
},
%{
"deactivated" => admin.info.deactivated,
"id" => admin.id,
"nickname" => admin.nickname,
"roles" => %{"admin" => true, "moderator" => false},
"local" => true,
"tags" => []
},
%{
"deactivated" => false,
"id" => old_admin.id,
"local" => true,
"nickname" => old_admin.nickname,
"roles" => %{"admin" => true, "moderator" => false},
"tags" => []
}
]
|> Enum.sort_by(& &1["nickname"])
assert json_response(conn, 200) == %{
"count" => 3,
"page_size" => 50,
"users" => users
}
end
test "load only admins", %{conn: conn, admin: admin} do
second_admin = insert(:user, info: %{is_admin: true})
insert(:user)
insert(:user)
conn = get(conn, "/api/pleroma/admin/users?filters=is_admin")
users =
[
%{
"deactivated" => false,
"id" => admin.id,
"nickname" => admin.nickname,
"roles" => %{"admin" => true, "moderator" => false},
"local" => admin.local,
"tags" => []
},
%{
"deactivated" => false,
"id" => second_admin.id,
"nickname" => second_admin.nickname,
"roles" => %{"admin" => true, "moderator" => false},
"local" => second_admin.local,
"tags" => []
}
]
|> Enum.sort_by(& &1["nickname"])
assert json_response(conn, 200) == %{
"count" => 2,
"page_size" => 50,
"users" => users
}
end
test "load only moderators", %{conn: conn} do
moderator = insert(:user, info: %{is_moderator: true})
insert(:user)
insert(:user)
conn = get(conn, "/api/pleroma/admin/users?filters=is_moderator")
assert json_response(conn, 200) == %{
"count" => 1,
"page_size" => 50,
"users" => [
%{
"deactivated" => false,
"id" => moderator.id,
"nickname" => moderator.nickname,
"roles" => %{"admin" => false, "moderator" => true},
"local" => moderator.local,
"tags" => []
}
]
}
end
test "load users with tags list", %{conn: conn} do
user1 = insert(:user, tags: ["first"])
user2 = insert(:user, tags: ["second"])
insert(:user)
insert(:user)
conn = get(conn, "/api/pleroma/admin/users?tags[]=first&tags[]=second")
users =
[
%{
"deactivated" => false,
"id" => user1.id,
"nickname" => user1.nickname,
"roles" => %{"admin" => false, "moderator" => false},
"local" => user1.local,
"tags" => ["first"]
},
%{
"deactivated" => false,
"id" => user2.id,
"nickname" => user2.nickname,
"roles" => %{"admin" => false, "moderator" => false},
"local" => user2.local,
"tags" => ["second"]
}
]
|> Enum.sort_by(& &1["nickname"])
assert json_response(conn, 200) == %{
"count" => 2,
"page_size" => 50,
"users" => users
}
end
test "it works with multiple filters" do
admin = insert(:user, nickname: "john", info: %{is_admin: true})
user = insert(:user, nickname: "bob", local: false, info: %{deactivated: true})
insert(:user, nickname: "ken", local: true, info: %{deactivated: true})
insert(:user, nickname: "bobb", local: false, info: %{deactivated: false})
conn =
build_conn()
|> assign(:user, admin)
|> get("/api/pleroma/admin/users?filters=deactivated,external")
assert json_response(conn, 200) == %{
"count" => 1,
"page_size" => 50,
"users" => [
%{
"deactivated" => user.info.deactivated,
"id" => user.id,
"nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false},
"local" => user.local,
"tags" => []
}
]
}
end
end
test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation" do
admin = insert(:user, info: %{is_admin: true})
user = insert(:user)
conn =
build_conn()
|> assign(:user, admin)
|> patch("/api/pleroma/admin/users/#{user.nickname}/toggle_activation")
assert json_response(conn, 200) ==
%{
"deactivated" => !user.info.deactivated,
"id" => user.id,
"nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false},
"local" => true,
"tags" => []
}
end
describe "GET /api/pleroma/admin/users/invite_token" do
setup do
admin = insert(:user, info: %{is_admin: true})
conn =
build_conn()
|> assign(:user, admin)
{:ok, conn: conn}
end
test "without options", %{conn: conn} do
conn = get(conn, "/api/pleroma/admin/users/invite_token")
token = json_response(conn, 200)
invite = UserInviteToken.find_by_token!(token)
refute invite.used
refute invite.expires_at
refute invite.max_use
assert invite.invite_type == "one_time"
end
test "with expires_at", %{conn: conn} do
conn =
get(conn, "/api/pleroma/admin/users/invite_token", %{
"invite" => %{"expires_at" => Date.to_string(Date.utc_today())}
})
token = json_response(conn, 200)
invite = UserInviteToken.find_by_token!(token)
refute invite.used
assert invite.expires_at == Date.utc_today()
refute invite.max_use
assert invite.invite_type == "date_limited"
end
test "with max_use", %{conn: conn} do
conn =
get(conn, "/api/pleroma/admin/users/invite_token", %{
"invite" => %{"max_use" => 150}
})
token = json_response(conn, 200)
invite = UserInviteToken.find_by_token!(token)
refute invite.used
refute invite.expires_at
assert invite.max_use == 150
assert invite.invite_type == "reusable"
end
test "with max use and expires_at", %{conn: conn} do
conn =
get(conn, "/api/pleroma/admin/users/invite_token", %{
"invite" => %{"max_use" => 150, "expires_at" => Date.to_string(Date.utc_today())}
})
token = json_response(conn, 200)
invite = UserInviteToken.find_by_token!(token)
refute invite.used
assert invite.expires_at == Date.utc_today()
assert invite.max_use == 150
assert invite.invite_type == "reusable_date_limited"
end
end
describe "GET /api/pleroma/admin/users/invites" do
setup do
admin = insert(:user, info: %{is_admin: true})
conn =
build_conn()
|> assign(:user, admin)
{:ok, conn: conn}
end
test "no invites", %{conn: conn} do
conn = get(conn, "/api/pleroma/admin/users/invites")
assert json_response(conn, 200) == %{"invites" => []}
end
test "with invite", %{conn: conn} do
{:ok, invite} = UserInviteToken.create_invite()
conn = get(conn, "/api/pleroma/admin/users/invites")
assert json_response(conn, 200) == %{
"invites" => [
%{
"expires_at" => nil,
"id" => invite.id,
"invite_type" => "one_time",
"max_use" => nil,
"token" => invite.token,
"used" => false,
"uses" => 0
}
]
}
end
end
describe "POST /api/pleroma/admin/users/revoke_invite" do
test "with token" do
admin = insert(:user, info: %{is_admin: true})
{:ok, invite} = UserInviteToken.create_invite()
conn =
build_conn()
|> assign(:user, admin)
|> post("/api/pleroma/admin/users/revoke_invite", %{"token" => invite.token})
assert json_response(conn, 200) == %{
"expires_at" => nil,
"id" => invite.id,
"invite_type" => "one_time",
"max_use" => nil,
"token" => invite.token,
"used" => true,
"uses" => 0
}
end
end
describe "GET /api/pleroma/admin/reports/:id" do
setup %{conn: conn} do
admin = insert(:user, info: %{is_admin: true})
%{conn: assign(conn, :user, admin)}
end
test "returns report by its id", %{conn: conn} do
[reporter, target_user] = insert_pair(:user)
activity = insert(:note_activity, user: target_user)
{:ok, %{id: report_id}} =
CommonAPI.report(reporter, %{
"account_id" => target_user.id,
"comment" => "I feel offended",
"status_ids" => [activity.id]
})
response =
conn
|> get("/api/pleroma/admin/reports/#{report_id}")
|> json_response(:ok)
assert response["id"] == report_id
end
test "returns 404 when report id is invalid", %{conn: conn} do
conn = get(conn, "/api/pleroma/admin/reports/test")
assert json_response(conn, :not_found) == "Not found"
end
end
describe "PUT /api/pleroma/admin/reports/:id" do
setup %{conn: conn} do
admin = insert(:user, info: %{is_admin: true})
[reporter, target_user] = insert_pair(:user)
activity = insert(:note_activity, user: target_user)
{:ok, %{id: report_id}} =
CommonAPI.report(reporter, %{
"account_id" => target_user.id,
"comment" => "I feel offended",
"status_ids" => [activity.id]
})
%{conn: assign(conn, :user, admin), id: report_id}
end
test "mark report as resolved", %{conn: conn, id: id} do
response =
conn
|> put("/api/pleroma/admin/reports/#{id}", %{"state" => "resolved"})
|> json_response(:ok)
assert response["state"] == "resolved"
end
test "closes report", %{conn: conn, id: id} do
response =
conn
|> put("/api/pleroma/admin/reports/#{id}", %{"state" => "closed"})
|> json_response(:ok)
assert response["state"] == "closed"
end
test "returns 400 when state is unknown", %{conn: conn, id: id} do
conn =
conn
|> put("/api/pleroma/admin/reports/#{id}", %{"state" => "test"})
assert json_response(conn, :bad_request) == "Unsupported state"
end
test "returns 404 when report is not exist", %{conn: conn} do
conn =
conn
|> put("/api/pleroma/admin/reports/test", %{"state" => "closed"})
assert json_response(conn, :not_found) == "Not found"
end
end
describe "GET /api/pleroma/admin/reports" do
setup %{conn: conn} do
admin = insert(:user, info: %{is_admin: true})
%{conn: assign(conn, :user, admin)}
end
test "returns empty response when no reports created", %{conn: conn} do
response =
conn
|> get("/api/pleroma/admin/reports")
|> json_response(:ok)
assert Enum.empty?(response["reports"])
end
test "returns reports", %{conn: conn} do
[reporter, target_user] = insert_pair(:user)
activity = insert(:note_activity, user: target_user)
{:ok, %{id: report_id}} =
CommonAPI.report(reporter, %{
"account_id" => target_user.id,
"comment" => "I feel offended",
"status_ids" => [activity.id]
})
response =
conn
|> get("/api/pleroma/admin/reports")
|> json_response(:ok)
[report] = response["reports"]
assert length(response["reports"]) == 1
assert report["id"] == report_id
end
test "returns reports with specified state", %{conn: conn} do
[reporter, target_user] = insert_pair(:user)
activity = insert(:note_activity, user: target_user)
{:ok, %{id: first_report_id}} =
CommonAPI.report(reporter, %{
"account_id" => target_user.id,
"comment" => "I feel offended",
"status_ids" => [activity.id]
})
{:ok, %{id: second_report_id}} =
CommonAPI.report(reporter, %{
"account_id" => target_user.id,
"comment" => "I don't like this user"
})
CommonAPI.update_report_state(second_report_id, "closed")
response =
conn
|> get("/api/pleroma/admin/reports", %{
"state" => "open"
})
|> json_response(:ok)
[open_report] = response["reports"]
assert length(response["reports"]) == 1
assert open_report["id"] == first_report_id
response =
conn
|> get("/api/pleroma/admin/reports", %{
"state" => "closed"
})
|> json_response(:ok)
[closed_report] = response["reports"]
assert length(response["reports"]) == 1
assert closed_report["id"] == second_report_id
response =
conn
|> get("/api/pleroma/admin/reports", %{
"state" => "resolved"
})
|> json_response(:ok)
assert Enum.empty?(response["reports"])
end
test "returns 403 when requested by a non-admin" do
user = insert(:user)
conn =
build_conn()
|> assign(:user, user)
|> get("/api/pleroma/admin/reports")
assert json_response(conn, :forbidden) == %{"error" => "User is not admin."}
end
test "returns 403 when requested by anonymous" do
conn =
build_conn()
|> get("/api/pleroma/admin/reports")
assert json_response(conn, :forbidden) == %{"error" => "Invalid credentials."}
end
end
describe "POST /api/pleroma/admin/reports/:id/respond" do
setup %{conn: conn} do
admin = insert(:user, info: %{is_admin: true})
%{conn: assign(conn, :user, admin)}
end
test "returns created dm", %{conn: conn} do
[reporter, target_user] = insert_pair(:user)
activity = insert(:note_activity, user: target_user)
{:ok, %{id: report_id}} =
CommonAPI.report(reporter, %{
"account_id" => target_user.id,
"comment" => "I feel offended",
"status_ids" => [activity.id]
})
response =
conn
|> post("/api/pleroma/admin/reports/#{report_id}/respond", %{
"status" => "I will check it out"
})
|> json_response(:ok)
recipients = Enum.map(response["mentions"], & &1["username"])
assert conn.assigns[:user].nickname in recipients
assert reporter.nickname in recipients
assert response["content"] == "I will check it out"
assert response["visibility"] == "direct"
end
test "returns 400 when status is missing", %{conn: conn} do
conn = post(conn, "/api/pleroma/admin/reports/test/respond")
assert json_response(conn, :bad_request) == "Invalid parameters"
end
test "returns 404 when report id is invalid", %{conn: conn} do
conn =
post(conn, "/api/pleroma/admin/reports/test/respond", %{
"status" => "foo"
})
assert json_response(conn, :not_found) == "Not found"
end
end
describe "PUT /api/pleroma/admin/statuses/:id" do
setup %{conn: conn} do
admin = insert(:user, info: %{is_admin: true})
activity = insert(:note_activity)
%{conn: assign(conn, :user, admin), id: activity.id}
end
test "toggle sensitive flag", %{conn: conn, id: id} do
response =
conn
|> put("/api/pleroma/admin/statuses/#{id}", %{"sensitive" => "true"})
|> json_response(:ok)
assert response["sensitive"]
response =
conn
|> put("/api/pleroma/admin/statuses/#{id}", %{"sensitive" => "false"})
|> json_response(:ok)
refute response["sensitive"]
end
test "change visibility flag", %{conn: conn, id: id} do
response =
conn
|> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "public"})
|> json_response(:ok)
assert response["visibility"] == "public"
response =
conn
|> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "private"})
|> json_response(:ok)
assert response["visibility"] == "private"
response =
conn
|> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "unlisted"})
|> json_response(:ok)
assert response["visibility"] == "unlisted"
end
test "returns 400 when visibility is unknown", %{conn: conn, id: id} do
conn =
conn
|> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "test"})
assert json_response(conn, :bad_request) == "Unsupported visibility"
end
end
describe "DELETE /api/pleroma/admin/statuses/:id" do
setup %{conn: conn} do
admin = insert(:user, info: %{is_admin: true})
activity = insert(:note_activity)
%{conn: assign(conn, :user, admin), id: activity.id}
end
test "deletes status", %{conn: conn, id: id} do
conn
|> delete("/api/pleroma/admin/statuses/#{id}")
|> json_response(:ok)
refute Activity.get_by_id(id)
end
test "returns error when status is not exist", %{conn: conn} do
conn =
conn
|> delete("/api/pleroma/admin/statuses/test")
assert json_response(conn, :bad_request) == "Could not delete"
end
end
describe "GET /api/pleroma/admin/config" do
setup %{conn: conn} do
admin = insert(:user, info: %{is_admin: true})
%{conn: assign(conn, :user, admin)}
end
test "without any settings in db", %{conn: conn} do
conn = get(conn, "/api/pleroma/admin/config")
assert json_response(conn, 200) == %{"configs" => []}
end
test "with settings in db", %{conn: conn} do
config1 = insert(:config)
config2 = insert(:config)
conn = get(conn, "/api/pleroma/admin/config")
%{
"configs" => [
%{
"key" => key1,
"value" => _
},
%{
"key" => key2,
"value" => _
}
]
} = json_response(conn, 200)
assert key1 == config1.key
assert key2 == config2.key
end
end
describe "POST /api/pleroma/admin/config" do
setup %{conn: conn} do
admin = insert(:user, info: %{is_admin: true})
- temp_file = "config/test.migrated.secret.exs"
+ temp_file = "config/test.exported_from_db.secret.exs"
on_exit(fn ->
Application.delete_env(:pleroma, :key1)
Application.delete_env(:pleroma, :key2)
Application.delete_env(:pleroma, :key3)
Application.delete_env(:pleroma, :key4)
Application.delete_env(:pleroma, :keyaa1)
Application.delete_env(:pleroma, :keyaa2)
:ok = File.rm(temp_file)
end)
dynamic = Pleroma.Config.get([:instance, :dynamic_configuration])
Pleroma.Config.put([:instance, :dynamic_configuration], true)
on_exit(fn ->
Pleroma.Config.put([:instance, :dynamic_configuration], dynamic)
end)
%{conn: assign(conn, :user, admin)}
end
test "create new config setting in db", %{conn: conn} do
conn =
post(conn, "/api/pleroma/admin/config", %{
configs: [
%{key: "key1", value: "value1"},
%{
key: "key2",
value: %{
"nested_1" => "nested_value1",
"nested_2" => [
%{"nested_22" => "nested_value222"},
%{"nested_33" => %{"nested_44" => "nested_444"}}
]
}
},
%{
key: "key3",
value: [
%{"nested_3" => ":nested_3", "nested_33" => "nested_33"},
%{"nested_4" => ":true"}
]
},
%{
key: "key4",
value: %{"nested_5" => ":upload", "endpoint" => "https://example.com"}
}
]
})
assert json_response(conn, 200) == %{
"configs" => [
%{
"key" => "key1",
"value" => "value1"
},
%{
"key" => "key2",
"value" => [
%{"nested_1" => "nested_value1"},
%{
"nested_2" => [
%{"nested_22" => "nested_value222"},
%{"nested_33" => %{"nested_44" => "nested_444"}}
]
}
]
},
%{
"key" => "key3",
"value" => [
[%{"nested_3" => "nested_3"}, %{"nested_33" => "nested_33"}],
%{"nested_4" => true}
]
},
%{
"key" => "key4",
"value" => [%{"endpoint" => "https://example.com"}, %{"nested_5" => "upload"}]
}
]
}
assert Application.get_env(:pleroma, :key1) == "value1"
assert Application.get_env(:pleroma, :key2) == [
nested_1: "nested_value1",
nested_2: [
[nested_22: "nested_value222"],
[nested_33: [nested_44: "nested_444"]]
]
]
assert Application.get_env(:pleroma, :key3) == [
[nested_3: :nested_3, nested_33: "nested_33"],
[nested_4: true]
]
assert Application.get_env(:pleroma, :key4) == [
endpoint: "https://example.com",
nested_5: :upload
]
end
test "update config setting & delete", %{conn: conn} do
config1 = insert(:config, key: "keyaa1")
config2 = insert(:config, key: "keyaa2")
conn =
post(conn, "/api/pleroma/admin/config", %{
configs: [
%{key: config1.key, value: "another_value"},
%{key: config2.key, delete: "true"}
]
})
assert json_response(conn, 200) == %{
"configs" => [
%{
"key" => config1.key,
"value" => "another_value"
}
]
}
assert Application.get_env(:pleroma, :keyaa1) == "another_value"
refute Application.get_env(:pleroma, :keyaa2)
end
end
end

File Metadata

Mime Type
text/x-diff
Expires
Sat, Aug 8, 6:18 AM (14 h, 34 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1722942
Default Alt Text
(99 KB)

Event Timeline