forked from AkkomaGang/akkoma
Merge branch 'frontend-bundles-redux' into 'develop'
Changeable frontends MVP See merge request pleroma/pleroma!2801
This commit is contained in:
commit
165ea038bd
8 changed files with 179 additions and 11 deletions
|
@ -645,6 +645,15 @@
|
||||||
|
|
||||||
config :pleroma, :static_fe, enabled: false
|
config :pleroma, :static_fe, enabled: false
|
||||||
|
|
||||||
|
# Example of frontend configuration
|
||||||
|
# This example will make us serve the primary frontend from the
|
||||||
|
# `/frontends/pleroma/develop` folder in your instance static directory.
|
||||||
|
#
|
||||||
|
# With no frontend configuration, the bundled files from the `static` directory will
|
||||||
|
# be used.
|
||||||
|
#
|
||||||
|
# config :pleroma, :frontends, primary: %{"name" => "pleroma", "ref" => "develop"}
|
||||||
|
|
||||||
config :pleroma, :web_cache_ttl,
|
config :pleroma, :web_cache_ttl,
|
||||||
activity_pub: nil,
|
activity_pub: nil,
|
||||||
activity_pub_question: 30_000
|
activity_pub_question: 30_000
|
||||||
|
|
|
@ -3481,5 +3481,30 @@
|
||||||
suggestions: ["s3.eu-central-1.amazonaws.com"]
|
suggestions: ["s3.eu-central-1.amazonaws.com"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
group: :pleroma,
|
||||||
|
key: :frontends,
|
||||||
|
type: :group,
|
||||||
|
description: "Installed frontends management",
|
||||||
|
children: [
|
||||||
|
%{
|
||||||
|
key: :primary,
|
||||||
|
type: :map,
|
||||||
|
description: "Primary frontend, the one that is served for all pages by default",
|
||||||
|
children: [
|
||||||
|
%{
|
||||||
|
key: "name",
|
||||||
|
type: :string,
|
||||||
|
description: "Name of the installed primary frontend"
|
||||||
|
},
|
||||||
|
%{
|
||||||
|
key: "ref",
|
||||||
|
type: :string,
|
||||||
|
description: "reference of the installed primary frontend to be used"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -1046,3 +1046,25 @@ Note: setting `restrict_unauthenticated/timelines/local` to `true` has no practi
|
||||||
Control favicons for instances.
|
Control favicons for instances.
|
||||||
|
|
||||||
* `enabled`: Allow/disallow displaying and getting instances favicons
|
* `enabled`: Allow/disallow displaying and getting instances favicons
|
||||||
|
|
||||||
|
## Frontend management
|
||||||
|
|
||||||
|
Frontends in Pleroma are swappable - you can specify which one to use here.
|
||||||
|
|
||||||
|
For now, you can set a frontend with the key `primary` and the options of `name` and `ref`. This will then make Pleroma serve the frontend from a folder constructed by concatenating the instance static path, `frontends` and the name and ref.
|
||||||
|
|
||||||
|
The key `primary` refers to the frontend that will be served by default for general requests. In the future, other frontends like the admin frontend will also be configurable here.
|
||||||
|
|
||||||
|
If you don't set anything here, the bundled frontend will be used.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
config :pleroma, :frontends,
|
||||||
|
primary: %{
|
||||||
|
"name" => "pleroma",
|
||||||
|
"ref" => "stable"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This would serve the frontend from the the folder at `$instance_static/frontends/pleroma/stable`. You have to copy the frontend into this folder yourself. You can choose the name and ref any way you like, but they will be used by mix tasks to automate installation in the future, the name referring to the project and the ref referring to a commit.
|
||||||
|
|
54
lib/pleroma/plugs/frontend_static.ex
Normal file
54
lib/pleroma/plugs/frontend_static.ex
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Plugs.FrontendStatic do
|
||||||
|
require Pleroma.Constants
|
||||||
|
|
||||||
|
@moduledoc """
|
||||||
|
This is a shim to call `Plug.Static` but with runtime `from` configuration`. It dispatches to the different frontends.
|
||||||
|
"""
|
||||||
|
@behaviour Plug
|
||||||
|
|
||||||
|
def file_path(path, frontend_type \\ :primary) do
|
||||||
|
if configuration = Pleroma.Config.get([:frontends, frontend_type]) do
|
||||||
|
instance_static_path = Pleroma.Config.get([:instance, :static_dir], "instance/static")
|
||||||
|
|
||||||
|
Path.join([
|
||||||
|
instance_static_path,
|
||||||
|
"frontends",
|
||||||
|
configuration["name"],
|
||||||
|
configuration["ref"],
|
||||||
|
path
|
||||||
|
])
|
||||||
|
else
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def init(opts) do
|
||||||
|
opts
|
||||||
|
|> Keyword.put(:from, "__unconfigured_frontend_static_plug")
|
||||||
|
|> Plug.Static.init()
|
||||||
|
end
|
||||||
|
|
||||||
|
def call(conn, opts) do
|
||||||
|
frontend_type = Map.get(opts, :frontend_type, :primary)
|
||||||
|
path = file_path("", frontend_type)
|
||||||
|
|
||||||
|
if path do
|
||||||
|
conn
|
||||||
|
|> call_static(opts, path)
|
||||||
|
else
|
||||||
|
conn
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp call_static(conn, opts, from) do
|
||||||
|
opts =
|
||||||
|
opts
|
||||||
|
|> Map.put(:from, from)
|
||||||
|
|
||||||
|
Plug.Static.call(conn, opts)
|
||||||
|
end
|
||||||
|
end
|
|
@ -16,28 +16,24 @@ def file_path(path) do
|
||||||
instance_path =
|
instance_path =
|
||||||
Path.join(Pleroma.Config.get([:instance, :static_dir], "instance/static/"), path)
|
Path.join(Pleroma.Config.get([:instance, :static_dir], "instance/static/"), path)
|
||||||
|
|
||||||
if File.exists?(instance_path) do
|
frontend_path = Pleroma.Plugs.FrontendStatic.file_path(path, :primary)
|
||||||
instance_path
|
|
||||||
else
|
(File.exists?(instance_path) && instance_path) ||
|
||||||
|
(frontend_path && File.exists?(frontend_path) && frontend_path) ||
|
||||||
Path.join(Application.app_dir(:pleroma, "priv/static/"), path)
|
Path.join(Application.app_dir(:pleroma, "priv/static/"), path)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def init(opts) do
|
def init(opts) do
|
||||||
opts
|
opts
|
||||||
|> Keyword.put(:from, "__unconfigured_instance_static_plug")
|
|> Keyword.put(:from, "__unconfigured_instance_static_plug")
|
||||||
|> Keyword.put(:at, "/__unconfigured_instance_static_plug")
|
|
||||||
|> Plug.Static.init()
|
|> Plug.Static.init()
|
||||||
end
|
end
|
||||||
|
|
||||||
for only <- Pleroma.Constants.static_only_files() do
|
for only <- Pleroma.Constants.static_only_files() do
|
||||||
at = Plug.Router.Utils.split("/")
|
|
||||||
|
|
||||||
def call(%{request_path: "/" <> unquote(only) <> _} = conn, opts) do
|
def call(%{request_path: "/" <> unquote(only) <> _} = conn, opts) do
|
||||||
call_static(
|
call_static(
|
||||||
conn,
|
conn,
|
||||||
opts,
|
opts,
|
||||||
unquote(at),
|
|
||||||
Pleroma.Config.get([:instance, :static_dir], "instance/static")
|
Pleroma.Config.get([:instance, :static_dir], "instance/static")
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
@ -47,11 +43,10 @@ def call(conn, _) do
|
||||||
conn
|
conn
|
||||||
end
|
end
|
||||||
|
|
||||||
defp call_static(conn, opts, at, from) do
|
defp call_static(conn, opts, from) do
|
||||||
opts =
|
opts =
|
||||||
opts
|
opts
|
||||||
|> Map.put(:from, from)
|
|> Map.put(:from, from)
|
||||||
|> Map.put(:at, at)
|
|
||||||
|
|
||||||
Plug.Static.call(conn, opts)
|
Plug.Static.call(conn, opts)
|
||||||
end
|
end
|
||||||
|
|
|
@ -28,6 +28,17 @@ defmodule Pleroma.Web.Endpoint do
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Careful! No `only` restriction here, as we don't know what frontends contain.
|
||||||
|
plug(Pleroma.Plugs.FrontendStatic,
|
||||||
|
at: "/",
|
||||||
|
frontend_type: :primary,
|
||||||
|
gzip: true,
|
||||||
|
cache_control_for_etags: @static_cache_control,
|
||||||
|
headers: %{
|
||||||
|
"cache-control" => @static_cache_control
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
# Serve at "/" the static files from "priv/static" directory.
|
# Serve at "/" the static files from "priv/static" directory.
|
||||||
#
|
#
|
||||||
# You should set gzip to true if you are running phoenix.digest
|
# You should set gzip to true if you are running phoenix.digest
|
||||||
|
|
30
test/plugs/frontend_static_test.exs
Normal file
30
test/plugs/frontend_static_test.exs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.FrontendStaticPlugTest do
|
||||||
|
use Pleroma.Web.ConnCase
|
||||||
|
|
||||||
|
@dir "test/tmp/instance_static"
|
||||||
|
|
||||||
|
setup do
|
||||||
|
File.mkdir_p!(@dir)
|
||||||
|
on_exit(fn -> File.rm_rf(@dir) end)
|
||||||
|
end
|
||||||
|
|
||||||
|
setup do: clear_config([:instance, :static_dir], @dir)
|
||||||
|
|
||||||
|
test "overrides existing static files", %{conn: conn} do
|
||||||
|
name = "pelmora"
|
||||||
|
ref = "uguu"
|
||||||
|
|
||||||
|
clear_config([:frontends, :primary], %{"name" => name, "ref" => ref})
|
||||||
|
path = "#{@dir}/frontends/#{name}/#{ref}"
|
||||||
|
|
||||||
|
File.mkdir_p!(path)
|
||||||
|
File.write!("#{path}/index.html", "from frontend plug")
|
||||||
|
|
||||||
|
index = get(conn, "/")
|
||||||
|
assert html_response(index, 200) == "from frontend plug"
|
||||||
|
end
|
||||||
|
end
|
|
@ -2,7 +2,7 @@
|
||||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
defmodule Pleroma.Web.RuntimeStaticPlugTest do
|
defmodule Pleroma.Web.InstanceStaticPlugTest do
|
||||||
use Pleroma.Web.ConnCase
|
use Pleroma.Web.ConnCase
|
||||||
|
|
||||||
@dir "test/tmp/instance_static"
|
@dir "test/tmp/instance_static"
|
||||||
|
@ -24,6 +24,28 @@ test "overrides index" do
|
||||||
assert html_response(index, 200) == "hello world"
|
assert html_response(index, 200) == "hello world"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "also overrides frontend files", %{conn: conn} do
|
||||||
|
name = "pelmora"
|
||||||
|
ref = "uguu"
|
||||||
|
|
||||||
|
clear_config([:frontends, :primary], %{"name" => name, "ref" => ref})
|
||||||
|
|
||||||
|
bundled_index = get(conn, "/")
|
||||||
|
refute html_response(bundled_index, 200) == "from frontend plug"
|
||||||
|
|
||||||
|
path = "#{@dir}/frontends/#{name}/#{ref}"
|
||||||
|
File.mkdir_p!(path)
|
||||||
|
File.write!("#{path}/index.html", "from frontend plug")
|
||||||
|
|
||||||
|
index = get(conn, "/")
|
||||||
|
assert html_response(index, 200) == "from frontend plug"
|
||||||
|
|
||||||
|
File.write!(@dir <> "/index.html", "from instance static")
|
||||||
|
|
||||||
|
index = get(conn, "/")
|
||||||
|
assert html_response(index, 200) == "from instance static"
|
||||||
|
end
|
||||||
|
|
||||||
test "overrides any file in static/static" do
|
test "overrides any file in static/static" do
|
||||||
bundled_index = get(build_conn(), "/static/terms-of-service.html")
|
bundled_index = get(build_conn(), "/static/terms-of-service.html")
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue