Merge branch 'develop' into feature/new-registrations-digest
This commit is contained in:
commit
e151dea276
35 changed files with 3635 additions and 1416 deletions
|
|
@ -4,7 +4,11 @@
|
|||
|
||||
defmodule Pleroma.Web.AdminAPI.AdminAPIController do
|
||||
use Pleroma.Web, :controller
|
||||
|
||||
import Pleroma.Web.ControllerHelper, only: [json_response: 3]
|
||||
|
||||
alias Pleroma.Activity
|
||||
alias Pleroma.ConfigDB
|
||||
alias Pleroma.ModerationLog
|
||||
alias Pleroma.Plugs.OAuthScopesPlug
|
||||
alias Pleroma.ReportNote
|
||||
|
|
@ -14,7 +18,6 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
|
|||
alias Pleroma.Web.ActivityPub.Relay
|
||||
alias Pleroma.Web.ActivityPub.Utils
|
||||
alias Pleroma.Web.AdminAPI.AccountView
|
||||
alias Pleroma.Web.AdminAPI.Config
|
||||
alias Pleroma.Web.AdminAPI.ConfigView
|
||||
alias Pleroma.Web.AdminAPI.ModerationLogView
|
||||
alias Pleroma.Web.AdminAPI.Report
|
||||
|
|
@ -25,10 +28,11 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
|
|||
alias Pleroma.Web.MastodonAPI.StatusView
|
||||
alias Pleroma.Web.Router
|
||||
|
||||
import Pleroma.Web.ControllerHelper, only: [json_response: 3]
|
||||
|
||||
require Logger
|
||||
|
||||
@descriptions_json Pleroma.Docs.JSON.compile()
|
||||
@users_page_size 50
|
||||
|
||||
plug(
|
||||
OAuthScopesPlug,
|
||||
%{scopes: ["read:accounts"], admin: true}
|
||||
|
|
@ -93,7 +97,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
|
|||
plug(
|
||||
OAuthScopesPlug,
|
||||
%{scopes: ["read"], admin: true}
|
||||
when action in [:config_show, :migrate_to_db, :migrate_from_db, :list_log]
|
||||
when action in [:config_show, :migrate_from_db, :list_log]
|
||||
)
|
||||
|
||||
plug(
|
||||
|
|
@ -102,8 +106,6 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
|
|||
when action == :config_update
|
||||
)
|
||||
|
||||
@users_page_size 50
|
||||
|
||||
action_fallback(:errors)
|
||||
|
||||
def user_delete(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname}) do
|
||||
|
|
@ -785,49 +787,132 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
|
|||
|> render("index.json", %{log: log})
|
||||
end
|
||||
|
||||
def migrate_to_db(conn, _params) do
|
||||
Mix.Tasks.Pleroma.Config.run(["migrate_to_db"])
|
||||
json(conn, %{})
|
||||
def config_descriptions(conn, _params) do
|
||||
conn
|
||||
|> Plug.Conn.put_resp_content_type("application/json")
|
||||
|> Plug.Conn.send_resp(200, @descriptions_json)
|
||||
end
|
||||
|
||||
def migrate_from_db(conn, _params) do
|
||||
Mix.Tasks.Pleroma.Config.run(["migrate_from_db", Pleroma.Config.get(:env), "true"])
|
||||
json(conn, %{})
|
||||
with :ok <- configurable_from_database(conn) do
|
||||
Mix.Tasks.Pleroma.Config.run([
|
||||
"migrate_from_db",
|
||||
"--env",
|
||||
to_string(Pleroma.Config.get(:env)),
|
||||
"-d"
|
||||
])
|
||||
|
||||
json(conn, %{})
|
||||
end
|
||||
end
|
||||
|
||||
def config_show(conn, %{"only_db" => true}) do
|
||||
with :ok <- configurable_from_database(conn) do
|
||||
configs = Pleroma.Repo.all(ConfigDB)
|
||||
|
||||
if configs == [] do
|
||||
errors(
|
||||
conn,
|
||||
{:error, "To use configuration from database migrate your settings to database."}
|
||||
)
|
||||
else
|
||||
conn
|
||||
|> put_view(ConfigView)
|
||||
|> render("index.json", %{configs: configs})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def config_show(conn, _params) do
|
||||
configs = Pleroma.Repo.all(Config)
|
||||
with :ok <- configurable_from_database(conn) do
|
||||
configs = ConfigDB.get_all_as_keyword()
|
||||
|
||||
conn
|
||||
|> put_view(ConfigView)
|
||||
|> render("index.json", %{configs: configs})
|
||||
if configs == [] do
|
||||
errors(
|
||||
conn,
|
||||
{:error, "To use configuration from database migrate your settings to database."}
|
||||
)
|
||||
else
|
||||
merged =
|
||||
Pleroma.Config.Holder.config()
|
||||
|> ConfigDB.merge(configs)
|
||||
|> Enum.map(fn {group, values} ->
|
||||
Enum.map(values, fn {key, value} ->
|
||||
db =
|
||||
if configs[group][key] do
|
||||
ConfigDB.get_db_keys(configs[group][key], key)
|
||||
end
|
||||
|
||||
db_value = configs[group][key]
|
||||
|
||||
merged_value =
|
||||
if !is_nil(db_value) and Keyword.keyword?(db_value) and
|
||||
ConfigDB.sub_key_full_update?(group, key, Keyword.keys(db_value)) do
|
||||
ConfigDB.merge_group(group, key, value, db_value)
|
||||
else
|
||||
value
|
||||
end
|
||||
|
||||
setting = %{
|
||||
group: ConfigDB.convert(group),
|
||||
key: ConfigDB.convert(key),
|
||||
value: ConfigDB.convert(merged_value)
|
||||
}
|
||||
|
||||
if db, do: Map.put(setting, :db, db), else: setting
|
||||
end)
|
||||
end)
|
||||
|> List.flatten()
|
||||
|
||||
json(conn, %{configs: merged})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def config_update(conn, %{"configs" => configs}) do
|
||||
updated =
|
||||
if Pleroma.Config.get([:instance, :dynamic_configuration]) do
|
||||
updated =
|
||||
Enum.map(configs, fn
|
||||
%{"group" => group, "key" => key, "delete" => "true"} = params ->
|
||||
{:ok, config} = Config.delete(%{group: group, key: key, subkeys: params["subkeys"]})
|
||||
config
|
||||
with :ok <- configurable_from_database(conn) do
|
||||
{_errors, results} =
|
||||
Enum.map(configs, fn
|
||||
%{"group" => group, "key" => key, "delete" => true} = params ->
|
||||
ConfigDB.delete(%{group: group, key: key, subkeys: params["subkeys"]})
|
||||
|
||||
%{"group" => group, "key" => key, "value" => value} ->
|
||||
{:ok, config} = Config.update_or_create(%{group: group, key: key, value: value})
|
||||
config
|
||||
end)
|
||||
|> Enum.reject(&is_nil(&1))
|
||||
%{"group" => group, "key" => key, "value" => value} ->
|
||||
ConfigDB.update_or_create(%{group: group, key: key, value: value})
|
||||
end)
|
||||
|> Enum.split_with(fn result -> elem(result, 0) == :error end)
|
||||
|
||||
Pleroma.Config.TransferTask.load_and_update_env()
|
||||
Mix.Tasks.Pleroma.Config.run(["migrate_from_db", Pleroma.Config.get(:env), "false"])
|
||||
updated
|
||||
else
|
||||
[]
|
||||
end
|
||||
{deleted, updated} =
|
||||
results
|
||||
|> Enum.map(fn {:ok, config} ->
|
||||
Map.put(config, :db, ConfigDB.get_db_keys(config))
|
||||
end)
|
||||
|> Enum.split_with(fn config ->
|
||||
Ecto.get_meta(config, :state) == :deleted
|
||||
end)
|
||||
|
||||
conn
|
||||
|> put_view(ConfigView)
|
||||
|> render("index.json", %{configs: updated})
|
||||
Pleroma.Config.TransferTask.load_and_update_env(deleted)
|
||||
|
||||
Mix.Tasks.Pleroma.Config.run([
|
||||
"migrate_from_db",
|
||||
"--env",
|
||||
to_string(Pleroma.Config.get(:env))
|
||||
])
|
||||
|
||||
conn
|
||||
|> put_view(ConfigView)
|
||||
|> render("index.json", %{configs: updated})
|
||||
end
|
||||
end
|
||||
|
||||
defp configurable_from_database(conn) do
|
||||
if Pleroma.Config.get(:configurable_from_database) do
|
||||
:ok
|
||||
else
|
||||
errors(
|
||||
conn,
|
||||
{:error, "To use this endpoint you need to enable configuration from database."}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def reload_emoji(conn, _params) do
|
||||
|
|
|
|||
|
|
@ -1,182 +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.AdminAPI.Config do
|
||||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
import Pleroma.Web.Gettext
|
||||
alias __MODULE__
|
||||
alias Pleroma.Repo
|
||||
|
||||
@type t :: %__MODULE__{}
|
||||
|
||||
schema "config" do
|
||||
field(:key, :string)
|
||||
field(:group, :string)
|
||||
field(:value, :binary)
|
||||
|
||||
timestamps()
|
||||
end
|
||||
|
||||
@spec get_by_params(map()) :: Config.t() | nil
|
||||
def get_by_params(params), do: Repo.get_by(Config, params)
|
||||
|
||||
@spec changeset(Config.t(), map()) :: Changeset.t()
|
||||
def changeset(config, params \\ %{}) do
|
||||
config
|
||||
|> cast(params, [:key, :group, :value])
|
||||
|> validate_required([:key, :group, :value])
|
||||
|> unique_constraint(:key, name: :config_group_key_index)
|
||||
end
|
||||
|
||||
@spec create(map()) :: {:ok, Config.t()} | {:error, Changeset.t()}
|
||||
def create(params) do
|
||||
%Config{}
|
||||
|> changeset(Map.put(params, :value, transform(params[:value])))
|
||||
|> Repo.insert()
|
||||
end
|
||||
|
||||
@spec update(Config.t(), map()) :: {:ok, Config} | {:error, Changeset.t()}
|
||||
def update(%Config{} = config, %{value: value}) do
|
||||
config
|
||||
|> change(value: transform(value))
|
||||
|> Repo.update()
|
||||
end
|
||||
|
||||
@spec update_or_create(map()) :: {:ok, Config.t()} | {:error, Changeset.t()}
|
||||
def update_or_create(params) do
|
||||
with %Config{} = config <- Config.get_by_params(Map.take(params, [:group, :key])) do
|
||||
Config.update(config, params)
|
||||
else
|
||||
nil -> Config.create(params)
|
||||
end
|
||||
end
|
||||
|
||||
@spec delete(map()) :: {:ok, Config.t()} | {:error, Changeset.t()}
|
||||
def delete(params) do
|
||||
with %Config{} = config <- Config.get_by_params(Map.delete(params, :subkeys)) do
|
||||
if params[:subkeys] do
|
||||
updated_value =
|
||||
Keyword.drop(
|
||||
:erlang.binary_to_term(config.value),
|
||||
Enum.map(params[:subkeys], &do_transform_string(&1))
|
||||
)
|
||||
|
||||
Config.update(config, %{value: updated_value})
|
||||
else
|
||||
Repo.delete(config)
|
||||
{:ok, nil}
|
||||
end
|
||||
else
|
||||
nil ->
|
||||
err =
|
||||
dgettext("errors", "Config with params %{params} not found", params: inspect(params))
|
||||
|
||||
{:error, err}
|
||||
end
|
||||
end
|
||||
|
||||
@spec from_binary(binary()) :: term()
|
||||
def from_binary(binary), do: :erlang.binary_to_term(binary)
|
||||
|
||||
@spec from_binary_with_convert(binary()) :: any()
|
||||
def from_binary_with_convert(binary) do
|
||||
from_binary(binary)
|
||||
|> do_convert()
|
||||
end
|
||||
|
||||
defp do_convert(entity) when is_list(entity) do
|
||||
for v <- entity, into: [], do: do_convert(v)
|
||||
end
|
||||
|
||||
defp do_convert(%Regex{} = entity), do: inspect(entity)
|
||||
|
||||
defp do_convert(entity) when is_map(entity) do
|
||||
for {k, v} <- entity, into: %{}, do: {do_convert(k), do_convert(v)}
|
||||
end
|
||||
|
||||
defp do_convert({:dispatch, [entity]}), do: %{"tuple" => [":dispatch", [inspect(entity)]]}
|
||||
defp do_convert({:partial_chain, entity}), do: %{"tuple" => [":partial_chain", inspect(entity)]}
|
||||
|
||||
defp do_convert(entity) when is_tuple(entity),
|
||||
do: %{"tuple" => do_convert(Tuple.to_list(entity))}
|
||||
|
||||
defp do_convert(entity) when is_boolean(entity) or is_number(entity) or is_nil(entity),
|
||||
do: entity
|
||||
|
||||
defp do_convert(entity) when is_atom(entity) do
|
||||
string = to_string(entity)
|
||||
|
||||
if String.starts_with?(string, "Elixir."),
|
||||
do: do_convert(string),
|
||||
else: ":" <> string
|
||||
end
|
||||
|
||||
defp do_convert("Elixir." <> module_name), do: module_name
|
||||
|
||||
defp do_convert(entity) when is_binary(entity), do: entity
|
||||
|
||||
@spec transform(any()) :: binary()
|
||||
def transform(entity) when is_binary(entity) or is_map(entity) or is_list(entity) do
|
||||
:erlang.term_to_binary(do_transform(entity))
|
||||
end
|
||||
|
||||
def transform(entity), do: :erlang.term_to_binary(entity)
|
||||
|
||||
defp do_transform(%Regex{} = entity), do: entity
|
||||
|
||||
defp do_transform(%{"tuple" => [":dispatch", [entity]]}) do
|
||||
{dispatch_settings, []} = do_eval(entity)
|
||||
{:dispatch, [dispatch_settings]}
|
||||
end
|
||||
|
||||
defp do_transform(%{"tuple" => [":partial_chain", entity]}) do
|
||||
{partial_chain, []} = do_eval(entity)
|
||||
{:partial_chain, partial_chain}
|
||||
end
|
||||
|
||||
defp do_transform(%{"tuple" => entity}) do
|
||||
Enum.reduce(entity, {}, fn val, acc -> Tuple.append(acc, do_transform(val)) end)
|
||||
end
|
||||
|
||||
defp do_transform(entity) when is_map(entity) do
|
||||
for {k, v} <- entity, into: %{}, do: {do_transform(k), do_transform(v)}
|
||||
end
|
||||
|
||||
defp do_transform(entity) when is_list(entity) do
|
||||
for v <- entity, into: [], do: do_transform(v)
|
||||
end
|
||||
|
||||
defp do_transform(entity) when is_binary(entity) do
|
||||
String.trim(entity)
|
||||
|> do_transform_string()
|
||||
end
|
||||
|
||||
defp do_transform(entity), do: entity
|
||||
|
||||
defp do_transform_string("~r/" <> pattern) do
|
||||
modificator = String.split(pattern, "/") |> List.last()
|
||||
pattern = String.trim_trailing(pattern, "/" <> modificator)
|
||||
|
||||
case modificator do
|
||||
"" -> ~r/#{pattern}/
|
||||
"i" -> ~r/#{pattern}/i
|
||||
"u" -> ~r/#{pattern}/u
|
||||
"s" -> ~r/#{pattern}/s
|
||||
end
|
||||
end
|
||||
|
||||
defp do_transform_string(":" <> atom), do: String.to_atom(atom)
|
||||
|
||||
defp do_transform_string(value) do
|
||||
if String.starts_with?(value, "Pleroma") or String.starts_with?(value, "Phoenix"),
|
||||
do: String.to_existing_atom("Elixir." <> value),
|
||||
else: value
|
||||
end
|
||||
|
||||
defp do_eval(entity) do
|
||||
cleaned_string = String.replace(entity, ~r/[^\w|^{:,[|^,|^[|^\]^}|^\/|^\.|^"]^\s/, "")
|
||||
Code.eval_string(cleaned_string, [], requires: [], macros: [])
|
||||
end
|
||||
end
|
||||
|
|
@ -12,10 +12,16 @@ defmodule Pleroma.Web.AdminAPI.ConfigView do
|
|||
end
|
||||
|
||||
def render("show.json", %{config: config}) do
|
||||
%{
|
||||
map = %{
|
||||
key: config.key,
|
||||
group: config.group,
|
||||
value: Pleroma.Web.AdminAPI.Config.from_binary_with_convert(config.value)
|
||||
value: Pleroma.ConfigDB.from_binary_with_convert(config.value)
|
||||
}
|
||||
|
||||
if config.db != [] do
|
||||
Map.put(map, :db, config.db)
|
||||
else
|
||||
map
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -195,7 +195,7 @@ defmodule Pleroma.Web.Router do
|
|||
|
||||
get("/config", AdminAPIController, :config_show)
|
||||
post("/config", AdminAPIController, :config_update)
|
||||
get("/config/migrate_to_db", AdminAPIController, :migrate_to_db)
|
||||
get("/config/descriptions", AdminAPIController, :config_descriptions)
|
||||
get("/config/migrate_from_db", AdminAPIController, :migrate_from_db)
|
||||
|
||||
get("/moderation_log", AdminAPIController, :list_log)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue