forked from AkkomaGang/akkoma
Add an API endpoint to install a new frontend
This commit is contained in:
parent
2f7401806b
commit
03e306785b
10 changed files with 448 additions and 107 deletions
|
@ -560,7 +560,8 @@
|
||||||
background: 5,
|
background: 5,
|
||||||
remote_fetcher: 2,
|
remote_fetcher: 2,
|
||||||
attachments_cleanup: 5,
|
attachments_cleanup: 5,
|
||||||
new_users_digest: 1
|
new_users_digest: 1,
|
||||||
|
frontend_installer: 1
|
||||||
],
|
],
|
||||||
plugins: [Oban.Plugins.Pruner],
|
plugins: [Oban.Plugins.Pruner],
|
||||||
crontab: [
|
crontab: [
|
||||||
|
|
|
@ -17,8 +17,6 @@ def run(["install", "none" | _args]) do
|
||||||
end
|
end
|
||||||
|
|
||||||
def run(["install", frontend | args]) do
|
def run(["install", frontend | args]) do
|
||||||
log_level = Logger.level()
|
|
||||||
Logger.configure(level: :warn)
|
|
||||||
start_pleroma()
|
start_pleroma()
|
||||||
|
|
||||||
{options, [], []} =
|
{options, [], []} =
|
||||||
|
@ -33,109 +31,6 @@ def run(["install", frontend | args]) do
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
instance_static_dir =
|
Pleroma.Frontend.install(frontend, options)
|
||||||
with nil <- options[:static_dir] do
|
|
||||||
Pleroma.Config.get!([:instance, :static_dir])
|
|
||||||
end
|
|
||||||
|
|
||||||
cmd_frontend_info = %{
|
|
||||||
"name" => frontend,
|
|
||||||
"ref" => options[:ref],
|
|
||||||
"build_url" => options[:build_url],
|
|
||||||
"build_dir" => options[:build_dir]
|
|
||||||
}
|
|
||||||
|
|
||||||
config_frontend_info = Pleroma.Config.get([:frontends, :available, frontend], %{})
|
|
||||||
|
|
||||||
frontend_info =
|
|
||||||
Map.merge(config_frontend_info, cmd_frontend_info, fn _key, config, cmd ->
|
|
||||||
# This only overrides things that are actually set
|
|
||||||
cmd || config
|
|
||||||
end)
|
|
||||||
|
|
||||||
ref = frontend_info["ref"]
|
|
||||||
|
|
||||||
unless ref do
|
|
||||||
raise "No ref given or configured"
|
|
||||||
end
|
|
||||||
|
|
||||||
dest =
|
|
||||||
Path.join([
|
|
||||||
instance_static_dir,
|
|
||||||
"frontends",
|
|
||||||
frontend,
|
|
||||||
ref
|
|
||||||
])
|
|
||||||
|
|
||||||
fe_label = "#{frontend} (#{ref})"
|
|
||||||
|
|
||||||
tmp_dir = Path.join([instance_static_dir, "frontends", "tmp"])
|
|
||||||
|
|
||||||
with {_, :ok} <-
|
|
||||||
{:download_or_unzip, download_or_unzip(frontend_info, tmp_dir, options[:file])},
|
|
||||||
shell_info("Installing #{fe_label} to #{dest}"),
|
|
||||||
:ok <- install_frontend(frontend_info, tmp_dir, dest) do
|
|
||||||
File.rm_rf!(tmp_dir)
|
|
||||||
shell_info("Frontend #{fe_label} installed to #{dest}")
|
|
||||||
|
|
||||||
Logger.configure(level: log_level)
|
|
||||||
else
|
|
||||||
{:download_or_unzip, _} ->
|
|
||||||
shell_info("Could not download or unzip the frontend")
|
|
||||||
|
|
||||||
_e ->
|
|
||||||
shell_info("Could not install the frontend")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defp download_or_unzip(frontend_info, temp_dir, file) do
|
|
||||||
if file do
|
|
||||||
with {:ok, zip} <- File.read(Path.expand(file)) do
|
|
||||||
unzip(zip, temp_dir)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
download_build(frontend_info, temp_dir)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def unzip(zip, dest) do
|
|
||||||
with {:ok, unzipped} <- :zip.unzip(zip, [:memory]) do
|
|
||||||
File.rm_rf!(dest)
|
|
||||||
File.mkdir_p!(dest)
|
|
||||||
|
|
||||||
Enum.each(unzipped, fn {filename, data} ->
|
|
||||||
path = filename
|
|
||||||
|
|
||||||
new_file_path = Path.join(dest, path)
|
|
||||||
|
|
||||||
new_file_path
|
|
||||||
|> Path.dirname()
|
|
||||||
|> File.mkdir_p!()
|
|
||||||
|
|
||||||
File.write!(new_file_path, data)
|
|
||||||
end)
|
|
||||||
|
|
||||||
:ok
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defp download_build(frontend_info, dest) do
|
|
||||||
shell_info("Downloading pre-built bundle for #{frontend_info["name"]}")
|
|
||||||
url = String.replace(frontend_info["build_url"], "${ref}", frontend_info["ref"])
|
|
||||||
|
|
||||||
with {:ok, %{status: 200, body: zip_body}} <-
|
|
||||||
Pleroma.HTTP.get(url, [], pool: :media, recv_timeout: 120_000) do
|
|
||||||
unzip(zip_body, dest)
|
|
||||||
else
|
|
||||||
e -> {:error, e}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defp install_frontend(frontend_info, source, dest) do
|
|
||||||
from = frontend_info["build_dir"] || "dist"
|
|
||||||
File.rm_rf!(dest)
|
|
||||||
File.mkdir_p!(dest)
|
|
||||||
File.cp_r!(Path.join([source, from]), dest)
|
|
||||||
:ok
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
108
lib/pleroma/frontend.ex
Normal file
108
lib/pleroma/frontend.ex
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Frontend do
|
||||||
|
alias Pleroma.Config
|
||||||
|
|
||||||
|
require Logger
|
||||||
|
|
||||||
|
def install(name, opts \\ []) do
|
||||||
|
cmd_frontend_info = %{
|
||||||
|
"ref" => opts[:ref],
|
||||||
|
"build_url" => opts[:build_url],
|
||||||
|
"build_dir" => opts[:build_dir]
|
||||||
|
}
|
||||||
|
|
||||||
|
config_frontend_info = Config.get([:frontends, :available, name], %{})
|
||||||
|
|
||||||
|
frontend_info =
|
||||||
|
Map.merge(config_frontend_info, cmd_frontend_info, fn _key, config, cmd ->
|
||||||
|
# This only overrides things that are actually set
|
||||||
|
cmd || config
|
||||||
|
end)
|
||||||
|
|
||||||
|
ref = frontend_info["ref"]
|
||||||
|
|
||||||
|
unless ref do
|
||||||
|
raise "No ref given or configured"
|
||||||
|
end
|
||||||
|
|
||||||
|
dest = Path.join([dir(), name, ref])
|
||||||
|
|
||||||
|
label = "#{name} (#{ref})"
|
||||||
|
tmp_dir = Path.join(dir(), "tmp")
|
||||||
|
|
||||||
|
with {_, :ok} <-
|
||||||
|
{:download_or_unzip, download_or_unzip(frontend_info, tmp_dir, opts[:file])},
|
||||||
|
Logger.info("Installing #{label} to #{dest}"),
|
||||||
|
:ok <- install_frontend(frontend_info, tmp_dir, dest) do
|
||||||
|
File.rm_rf!(tmp_dir)
|
||||||
|
Logger.info("Frontend #{label} installed to #{dest}")
|
||||||
|
else
|
||||||
|
{:download_or_unzip, _} ->
|
||||||
|
Logger.info("Could not download or unzip the frontend")
|
||||||
|
|
||||||
|
_e ->
|
||||||
|
Logger.info("Could not install the frontend")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def dir(opts \\ []) do
|
||||||
|
if is_nil(opts[:static_dir]) do
|
||||||
|
Pleroma.Config.get!([:instance, :static_dir])
|
||||||
|
else
|
||||||
|
opts[:static_dir]
|
||||||
|
end
|
||||||
|
|> Path.join("frontends")
|
||||||
|
end
|
||||||
|
|
||||||
|
defp download_or_unzip(frontend_info, temp_dir, nil),
|
||||||
|
do: download_build(frontend_info, temp_dir)
|
||||||
|
|
||||||
|
defp download_or_unzip(_frontend_info, temp_dir, file) do
|
||||||
|
with {:ok, zip} <- File.read(Path.expand(file)) do
|
||||||
|
unzip(zip, temp_dir)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def unzip(zip, dest) do
|
||||||
|
with {:ok, unzipped} <- :zip.unzip(zip, [:memory]) do
|
||||||
|
File.rm_rf!(dest)
|
||||||
|
File.mkdir_p!(dest)
|
||||||
|
|
||||||
|
Enum.each(unzipped, fn {filename, data} ->
|
||||||
|
path = filename
|
||||||
|
|
||||||
|
new_file_path = Path.join(dest, path)
|
||||||
|
|
||||||
|
new_file_path
|
||||||
|
|> Path.dirname()
|
||||||
|
|> File.mkdir_p!()
|
||||||
|
|
||||||
|
File.write!(new_file_path, data)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp download_build(frontend_info, dest) do
|
||||||
|
Logger.info("Downloading pre-built bundle for #{frontend_info["name"]}")
|
||||||
|
url = String.replace(frontend_info["build_url"], "${ref}", frontend_info["ref"])
|
||||||
|
|
||||||
|
with {:ok, %{status: 200, body: zip_body}} <-
|
||||||
|
Pleroma.HTTP.get(url, [], pool: :media, recv_timeout: 120_000) do
|
||||||
|
unzip(zip_body, dest)
|
||||||
|
else
|
||||||
|
{:error, e} -> {:error, e}
|
||||||
|
e -> {:error, e}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp install_frontend(frontend_info, source, dest) do
|
||||||
|
from = frontend_info["build_dir"] || "dist"
|
||||||
|
File.rm_rf!(dest)
|
||||||
|
File.mkdir_p!(dest)
|
||||||
|
File.cp_r!(Path.join([source, from]), dest)
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
end
|
41
lib/pleroma/web/admin_api/controllers/frontend_controller.ex
Normal file
41
lib/pleroma/web/admin_api/controllers/frontend_controller.ex
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.AdminAPI.FrontendController do
|
||||||
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
|
alias Pleroma.Config
|
||||||
|
alias Pleroma.Web.Plugs.OAuthScopesPlug
|
||||||
|
alias Pleroma.Workers.FrontendInstallerWorker
|
||||||
|
|
||||||
|
plug(Pleroma.Web.ApiSpec.CastAndValidate)
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["write"], admin: true} when action == :install)
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["read"], admin: true} when action == :index)
|
||||||
|
action_fallback(Pleroma.Web.AdminAPI.FallbackController)
|
||||||
|
|
||||||
|
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.Admin.FrontendOperation
|
||||||
|
|
||||||
|
def index(conn, _params) do
|
||||||
|
installed = installed()
|
||||||
|
|
||||||
|
frontends =
|
||||||
|
[:frontends, :available]
|
||||||
|
|> Config.get([])
|
||||||
|
|> Enum.map(fn {name, desc} ->
|
||||||
|
Map.put(desc, "installed", name in installed)
|
||||||
|
end)
|
||||||
|
|
||||||
|
render(conn, "index.json", frontends: frontends)
|
||||||
|
end
|
||||||
|
|
||||||
|
def install(%{body_params: params} = conn, _params) do
|
||||||
|
FrontendInstallerWorker.install(params.name, Map.delete(params, :name))
|
||||||
|
|
||||||
|
index(conn, %{})
|
||||||
|
end
|
||||||
|
|
||||||
|
defp installed do
|
||||||
|
File.ls!(Pleroma.Frontend.dir())
|
||||||
|
end
|
||||||
|
end
|
21
lib/pleroma/web/admin_api/views/frontend_view.ex
Normal file
21
lib/pleroma/web/admin_api/views/frontend_view.ex
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.AdminAPI.FrontendView do
|
||||||
|
use Pleroma.Web, :view
|
||||||
|
|
||||||
|
def render("index.json", %{frontends: frontends}) do
|
||||||
|
render_many(frontends, __MODULE__, "show.json")
|
||||||
|
end
|
||||||
|
|
||||||
|
def render("show.json", %{frontend: frontend}) do
|
||||||
|
%{
|
||||||
|
name: frontend["name"],
|
||||||
|
git: frontend["git"],
|
||||||
|
build_url: frontend["build_url"],
|
||||||
|
ref: frontend["ref"],
|
||||||
|
installed: frontend["installed"]
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,77 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.ApiSpec.Admin.FrontendOperation do
|
||||||
|
alias OpenApiSpex.Operation
|
||||||
|
alias OpenApiSpex.Schema
|
||||||
|
alias Pleroma.Web.ApiSpec.Schemas.ApiError
|
||||||
|
|
||||||
|
import Pleroma.Web.ApiSpec.Helpers
|
||||||
|
|
||||||
|
def open_api_operation(action) do
|
||||||
|
operation = String.to_existing_atom("#{action}_operation")
|
||||||
|
apply(__MODULE__, operation, [])
|
||||||
|
end
|
||||||
|
|
||||||
|
def index_operation do
|
||||||
|
%Operation{
|
||||||
|
tags: ["Admin", "Reports"],
|
||||||
|
summary: "Get a list of available frontends",
|
||||||
|
operationId: "AdminAPI.FrontendController.index",
|
||||||
|
security: [%{"oAuth" => ["read"]}],
|
||||||
|
responses: %{
|
||||||
|
200 => Operation.response("Response", "application/json", list_of_frontends()),
|
||||||
|
403 => Operation.response("Forbidden", "application/json", ApiError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def install_operation do
|
||||||
|
%Operation{
|
||||||
|
tags: ["Admin", "Reports"],
|
||||||
|
summary: "Install a frontend",
|
||||||
|
operationId: "AdminAPI.FrontendController.install",
|
||||||
|
security: [%{"oAuth" => ["read"]}],
|
||||||
|
requestBody: request_body("Parameters", install_request(), required: true),
|
||||||
|
responses: %{
|
||||||
|
200 => Operation.response("Response", "application/json", list_of_frontends()),
|
||||||
|
403 => Operation.response("Forbidden", "application/json", ApiError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp list_of_frontends do
|
||||||
|
%Schema{
|
||||||
|
type: :array,
|
||||||
|
items: %Schema{
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
name: %Schema{type: :string},
|
||||||
|
git: %Schema{type: :string, format: :uri, nullable: true},
|
||||||
|
build_url: %Schema{type: :string, format: :uri},
|
||||||
|
ref: %Schema{type: :string},
|
||||||
|
installed: %Schema{type: :boolean}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp install_request do
|
||||||
|
%Schema{
|
||||||
|
title: "FrontendInstallRequest",
|
||||||
|
type: :object,
|
||||||
|
required: [:name],
|
||||||
|
properties: %{
|
||||||
|
name: %Schema{
|
||||||
|
type: :string,
|
||||||
|
nullable: false
|
||||||
|
},
|
||||||
|
ref: %Schema{
|
||||||
|
type: :string,
|
||||||
|
nullable: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
|
@ -223,6 +223,9 @@ defmodule Pleroma.Web.Router do
|
||||||
get("/chats/:id", ChatController, :show)
|
get("/chats/:id", ChatController, :show)
|
||||||
get("/chats/:id/messages", ChatController, :messages)
|
get("/chats/:id/messages", ChatController, :messages)
|
||||||
delete("/chats/:id/messages/:message_id", ChatController, :delete_message)
|
delete("/chats/:id/messages/:message_id", ChatController, :delete_message)
|
||||||
|
|
||||||
|
get("/frontends", FrontendController, :index)
|
||||||
|
post("/frontends", FrontendController, :install)
|
||||||
end
|
end
|
||||||
|
|
||||||
scope "/api/pleroma/emoji", Pleroma.Web.PleromaAPI do
|
scope "/api/pleroma/emoji", Pleroma.Web.PleromaAPI do
|
||||||
|
|
21
lib/pleroma/workers/frontend_installer_worker.ex
Normal file
21
lib/pleroma/workers/frontend_installer_worker.ex
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Workers.FrontendInstallerWorker do
|
||||||
|
use Oban.Worker, queue: :frontend_installer, max_attempts: 1
|
||||||
|
|
||||||
|
alias Oban.Job
|
||||||
|
alias Pleroma.Frontend
|
||||||
|
|
||||||
|
def install(name, opts \\ []) do
|
||||||
|
%{"name" => name, "opts" => Map.new(opts)}
|
||||||
|
|> new()
|
||||||
|
|> Oban.insert()
|
||||||
|
end
|
||||||
|
|
||||||
|
def perform(%Job{args: %{"name" => name, "opts" => opts}}) do
|
||||||
|
opts = Keyword.new(opts, fn {key, value} -> {String.to_existing_atom(key), value} end)
|
||||||
|
Frontend.install(name, opts)
|
||||||
|
end
|
||||||
|
end
|
80
test/pleroma/frontend_test.exs
Normal file
80
test/pleroma/frontend_test.exs
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.FrontendTest do
|
||||||
|
use Pleroma.DataCase
|
||||||
|
alias Pleroma.Frontend
|
||||||
|
|
||||||
|
import ExUnit.CaptureIO, only: [capture_io: 1]
|
||||||
|
|
||||||
|
@dir "test/frontend_static_test"
|
||||||
|
|
||||||
|
setup do
|
||||||
|
File.mkdir_p!(@dir)
|
||||||
|
clear_config([:instance, :static_dir], @dir)
|
||||||
|
|
||||||
|
on_exit(fn ->
|
||||||
|
File.rm_rf(@dir)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it downloads and unzips a known frontend" do
|
||||||
|
clear_config([:frontends, :available], %{
|
||||||
|
"pleroma" => %{
|
||||||
|
"ref" => "fantasy",
|
||||||
|
"name" => "pleroma",
|
||||||
|
"build_url" => "http://gensokyo.2hu/builds/${ref}"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
Tesla.Mock.mock(fn %{url: "http://gensokyo.2hu/builds/fantasy"} ->
|
||||||
|
%Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/frontend_dist.zip")}
|
||||||
|
end)
|
||||||
|
|
||||||
|
capture_io(fn ->
|
||||||
|
Frontend.install("pleroma")
|
||||||
|
end)
|
||||||
|
|
||||||
|
assert File.exists?(Path.join([@dir, "frontends", "pleroma", "fantasy", "test.txt"]))
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it also works given a file" do
|
||||||
|
clear_config([:frontends, :available], %{
|
||||||
|
"pleroma" => %{
|
||||||
|
"ref" => "fantasy",
|
||||||
|
"name" => "pleroma",
|
||||||
|
"build_dir" => ""
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
folder = Path.join([@dir, "frontends", "pleroma", "fantasy"])
|
||||||
|
previously_existing = Path.join([folder, "temp"])
|
||||||
|
File.mkdir_p!(folder)
|
||||||
|
File.write!(previously_existing, "yey")
|
||||||
|
assert File.exists?(previously_existing)
|
||||||
|
|
||||||
|
capture_io(fn ->
|
||||||
|
Frontend.install("pleroma", file: "test/fixtures/tesla_mock/frontend.zip")
|
||||||
|
end)
|
||||||
|
|
||||||
|
assert File.exists?(Path.join([folder, "test.txt"]))
|
||||||
|
refute File.exists?(previously_existing)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it downloads and unzips unknown frontends" do
|
||||||
|
Tesla.Mock.mock(fn %{url: "http://gensokyo.2hu/madeup.zip"} ->
|
||||||
|
%Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/frontend.zip")}
|
||||||
|
end)
|
||||||
|
|
||||||
|
capture_io(fn ->
|
||||||
|
Frontend.install("unknown",
|
||||||
|
ref: "baka",
|
||||||
|
build_url: "http://gensokyo.2hu/madeup.zip",
|
||||||
|
build_dir: ""
|
||||||
|
)
|
||||||
|
end)
|
||||||
|
|
||||||
|
assert File.exists?(Path.join([@dir, "frontends", "unknown", "baka", "test.txt"]))
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,94 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.AdminAPI.FrontendControllerTest do
|
||||||
|
use Pleroma.Web.ConnCase
|
||||||
|
use Oban.Testing, repo: Pleroma.Repo
|
||||||
|
|
||||||
|
import Pleroma.Factory
|
||||||
|
|
||||||
|
alias Pleroma.Config
|
||||||
|
alias Pleroma.Tests.ObanHelpers
|
||||||
|
alias Pleroma.Workers.FrontendInstallerWorker
|
||||||
|
|
||||||
|
@dir "test/frontend_static_test"
|
||||||
|
|
||||||
|
setup do
|
||||||
|
clear_config([:instance, :static_dir], @dir)
|
||||||
|
File.mkdir_p!(Pleroma.Frontend.dir())
|
||||||
|
|
||||||
|
on_exit(fn ->
|
||||||
|
File.rm_rf(@dir)
|
||||||
|
end)
|
||||||
|
|
||||||
|
admin = insert(:user, is_admin: true)
|
||||||
|
token = insert(:oauth_admin_token, user: admin)
|
||||||
|
|
||||||
|
conn =
|
||||||
|
build_conn()
|
||||||
|
|> assign(:user, admin)
|
||||||
|
|> assign(:token, token)
|
||||||
|
|
||||||
|
{:ok, %{admin: admin, token: token, conn: conn}}
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "GET /api/pleroma/admin/frontends" do
|
||||||
|
test "it lists available frontends", %{conn: conn} do
|
||||||
|
response =
|
||||||
|
conn
|
||||||
|
|> get("/api/pleroma/admin/frontends")
|
||||||
|
|> json_response_and_validate_schema(:ok)
|
||||||
|
|
||||||
|
assert Enum.map(response, & &1["name"]) ==
|
||||||
|
Enum.map(Config.get([:frontends, :available]), fn {_, map} -> map["name"] end)
|
||||||
|
|
||||||
|
refute Enum.any?(response, fn frontend -> frontend["installed"] == true end)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "POST /api/pleroma/admin/frontends" do
|
||||||
|
test "it installs a frontend", %{conn: conn} do
|
||||||
|
clear_config([:frontends, :available], %{
|
||||||
|
"pleroma" => %{
|
||||||
|
"ref" => "fantasy",
|
||||||
|
"name" => "pleroma",
|
||||||
|
"build_url" => "http://gensokyo.2hu/builds/${ref}"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
Tesla.Mock.mock(fn %{url: "http://gensokyo.2hu/builds/fantasy"} ->
|
||||||
|
%Tesla.Env{status: 200, body: File.read!("test/fixtures/tesla_mock/frontend_dist.zip")}
|
||||||
|
end)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|
|> post("/api/pleroma/admin/frontends", %{name: "pleroma"})
|
||||||
|
|> json_response_and_validate_schema(:ok)
|
||||||
|
|
||||||
|
assert_enqueued(
|
||||||
|
worker: FrontendInstallerWorker,
|
||||||
|
args: %{"name" => "pleroma", "opts" => %{}}
|
||||||
|
)
|
||||||
|
|
||||||
|
ObanHelpers.perform(all_enqueued(worker: FrontendInstallerWorker))
|
||||||
|
|
||||||
|
assert File.exists?(Path.join([@dir, "frontends", "pleroma", "fantasy", "test.txt"]))
|
||||||
|
|
||||||
|
response =
|
||||||
|
conn
|
||||||
|
|> get("/api/pleroma/admin/frontends")
|
||||||
|
|> json_response_and_validate_schema(:ok)
|
||||||
|
|
||||||
|
assert response == [
|
||||||
|
%{
|
||||||
|
"build_url" => "http://gensokyo.2hu/builds/${ref}",
|
||||||
|
"git" => nil,
|
||||||
|
"installed" => true,
|
||||||
|
"name" => "pleroma",
|
||||||
|
"ref" => "fantasy"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue