From 9a768429a3a79faacad47aa19ff2742dacdf245d Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 14 Jun 2021 17:27:29 -0500 Subject: [PATCH] Frontend: enable CLI task --- docs/administration/CLI_tasks/frontend.md | 21 ++++++++++- lib/mix/tasks/pleroma/frontend.ex | 63 +++++++++++++++++++++++++++++-- lib/pleroma/frontend.ex | 38 +++++++++++++++++++ test/mix/tasks/pleroma/frontend_test.exs | 25 ++++++++++++ test/pleroma/frontend_test.exs | 26 +++++++++++++ 5 files changed, 167 insertions(+), 6 deletions(-) diff --git a/docs/administration/CLI_tasks/frontend.md b/docs/administration/CLI_tasks/frontend.md index d4a48cb56..6a330975d 100644 --- a/docs/administration/CLI_tasks/frontend.md +++ b/docs/administration/CLI_tasks/frontend.md @@ -3,13 +3,15 @@ === "OTP" ```sh - ./bin/pleroma_ctl frontend install [--ref ] [--file ] [--build-url ] [--path ] [--build-dir ] + ./bin/pleroma_ctl frontend install [--ref ] [--file ] [--build-url ] [--path ] [--build-dir ] [--primary] [--admin] + ./bin/pleroma_ctl frontend enable [--ref ] [--file ] [--build-url ] [--path ] [--build-dir ] [--primary] [--admin] ``` === "From Source" ```sh - mix pleroma.frontend install [--ref ] [--file ] [--build-url ] [--path ] [--build-dir ] + mix pleroma.frontend install [--ref ] [--file ] [--build-url ] [--path ] [--build-dir ] [--primary] [--admin] + mix pleroma.frontend enable [--ref ] [--file ] [--build-url ] [--path ] [--build-dir ] [--primary] [--admin] ``` Frontend can be installed either from local zip file, or automatically downloaded from the web. @@ -94,3 +96,18 @@ The installation process is the same, but you will have to give all the needed o If you don't have a zip file but just want to install a frontend from a local path, you can simply copy the files over a folder of this template: `${instance_static}/frontends/${name}/${ref}`. +## Enabling a frontend + +Once installed, a frontend can be enabled with the `enable` command: + +=== "OTP" + + ```sh + ./bin/pleroma_ctl frontend enable gensokyo --primary + ``` + +=== "From Source" + + ```sh + mix pleroma.frontend enable gensokyo --primary + ``` diff --git a/lib/mix/tasks/pleroma/frontend.ex b/lib/mix/tasks/pleroma/frontend.ex index 9b151c3bd..819cd9f6a 100644 --- a/lib/mix/tasks/pleroma/frontend.ex +++ b/lib/mix/tasks/pleroma/frontend.ex @@ -32,13 +32,68 @@ defmodule Mix.Tasks.Pleroma.Frontend do ] ) - options - |> Keyword.put(:name, name) - |> opts_to_frontend() - |> Frontend.install() + shell_info("Installing frontend #{name}...") + + with %Frontend{} = fe <- + options + |> Keyword.put(:name, name) + |> opts_to_frontend() + |> Frontend.install() do + shell_info("Frontend #{fe.name} installed") + else + error -> + shell_error("Failed to install frontend") + exit(inspect(error)) + end + end + + def run(["enable", name | args]) do + start_pleroma() + + {options, [], []} = + OptionParser.parse( + args, + strict: [ + ref: :string, + build_url: :string, + build_dir: :string, + file: :string, + admin: :boolean, + primary: :boolean + ] + ) + + frontend_type = get_frontend_type(options) + + shell_info("Enabling frontend #{name}...") + + with %Frontend{} = fe <- + options + |> Keyword.put(:name, name) + |> opts_to_frontend() + |> Frontend.enable(frontend_type) do + shell_info("Frontend #{fe.name} enabled") + else + error -> + shell_error("Failed to enable frontend") + exit(inspect(error)) + end end defp opts_to_frontend(opts) do struct(Frontend, opts) end + + defp get_frontend_type(opts) do + case Enum.into(opts, %{}) do + %{admin: true, primary: true} -> + raise "Invalid command. Only one frontend type may be selected." + + %{admin: true} -> + :admin + + _ -> + :primary + end + end end diff --git a/lib/pleroma/frontend.ex b/lib/pleroma/frontend.ex index a0d496193..cd49a4899 100644 --- a/lib/pleroma/frontend.ex +++ b/lib/pleroma/frontend.ex @@ -4,11 +4,13 @@ defmodule Pleroma.Frontend do alias Pleroma.Config + alias Pleroma.ConfigDB alias Pleroma.Frontend require Logger @unknown_name "unknown" + @frontend_types [:admin, :primary] defstruct [:name, :ref, :git, :build_url, :build_dir, :file, :"custom-http-headers"] @@ -40,6 +42,7 @@ defmodule Pleroma.Frontend do :ok <- install_frontend(frontend, tmp_dir, dest) do File.rm_rf!(tmp_dir) Logger.info("Frontend #{label} installed to #{dest}") + frontend else {:download_or_unzip, _} -> Logger.info("Could not download or unzip the frontend") @@ -51,6 +54,41 @@ defmodule Pleroma.Frontend do end end + def enable(%Frontend{} = frontend, frontend_type) when frontend_type in @frontend_types do + with {:config_db, true} <- {:config_db, Config.get(:configurable_from_database)} do + frontend + |> maybe_put_name() + |> hydrate() + |> validate!() + |> do_enable(frontend_type) + else + {:config_db, _} -> + map = to_map(frontend) + + raise """ + Can't enable frontend; database configuration is disabled. + Enable the frontend by manually adding this line to your config: + + config :pleroma, :frontends, #{to_string(frontend_type)}: #{inspect(map)} + + Alternatively, enable database configuration: + + config :pleroma, configurable_from_database: true + """ + end + end + + def do_enable(%Frontend{name: name} = frontend, frontend_type) do + value = Keyword.put([], frontend_type, to_map(frontend)) + params = %{group: :pleroma, key: :frontends, value: value} + + with {:ok, _} <- ConfigDB.update_or_create(params), + :ok <- Config.TransferTask.load_and_update_env([], false) do + Logger.info("Frontend #{name} successfully enabled") + frontend + end + end + def dir do Config.get!([:instance, :static_dir]) |> Path.join("frontends") diff --git a/test/mix/tasks/pleroma/frontend_test.exs b/test/mix/tasks/pleroma/frontend_test.exs index aa4b25ebb..db6a8a4dd 100644 --- a/test/mix/tasks/pleroma/frontend_test.exs +++ b/test/mix/tasks/pleroma/frontend_test.exs @@ -82,4 +82,29 @@ defmodule Mix.Tasks.Pleroma.FrontendTest do assert File.exists?(Path.join([@dir, "frontends", "unknown", "baka", "test.txt"])) end + + describe "enable" do + setup do + clear_config(:configurable_from_database, true) + end + + test "enabling a primary frontend" do + capture_io(fn -> Frontend.run(["enable", "soapbox-fe"]) end) + + primary = Pleroma.Config.get([:frontends, :primary]) + assert primary["name"] == "soapbox-fe" + end + + test "enabling an admin frontend" do + capture_io(fn -> Frontend.run(["enable", "soapbox-fe", "--admin"]) end) + + primary = Pleroma.Config.get([:frontends, :admin]) + assert primary["name"] == "soapbox-fe" + end + + test "raise if configurable_from_database is disabled" do + clear_config(:configurable_from_database, false) + assert_raise(RuntimeError, fn -> Frontend.run(["enable", "soapbox-fe"]) end) + end + end end diff --git a/test/pleroma/frontend_test.exs b/test/pleroma/frontend_test.exs index 634487844..3cd30d121 100644 --- a/test/pleroma/frontend_test.exs +++ b/test/pleroma/frontend_test.exs @@ -133,4 +133,30 @@ defmodule Pleroma.FrontendTest do assert Frontend.get_named_frontend("pleroma") == frontend end + + describe "enable/2" do + setup do + clear_config(:configurable_from_database, true) + end + + test "enables a primary frontend" do + frontend = %Frontend{name: "soapbox", ref: "v1.2.3"} + map = Frontend.to_map(frontend) + + clear_config([:frontends, :available], %{"soapbox" => map}) + Frontend.enable(frontend, :primary) + + assert Pleroma.Config.get([:frontends, :primary]) == map + end + + test "enables an admin frontend" do + frontend = %Frontend{name: "admin-fe", ref: "develop"} + map = Frontend.to_map(frontend) + + clear_config([:frontends, :available], %{"admin-fe" => map}) + Frontend.enable(frontend, :admin) + + assert Pleroma.Config.get([:frontends, :admin]) == map + end + end end