Merge branch 'bugfix/elixir-1.15' into 'develop'

Elixir 1.15 compatibility

See merge request pleroma/pleroma!3917
This commit is contained in:
feld 2024-06-20 01:07:41 +00:00
commit 9a4cdde5c9
198 changed files with 216 additions and 296 deletions

3
.gitignore vendored
View file

@ -60,3 +60,6 @@ pleroma.iml
*~
*#
*.swp
archive-*
.gitlab-ci-local

View file

@ -86,7 +86,6 @@ build-1.15.8-otp-26:
- .using-ci-base
stage: build
image: git.pleroma.social:5050/pleroma/pleroma/ci-base:elixir-1.15.8-otp-26
allow_failure: true
script:
- mix compile --force
@ -136,7 +135,7 @@ unit-testing-1.13.4-otp-25:
script: &testing_script
- mix ecto.create
- mix ecto.migrate
- mix test --cover --preload-modules
- mix pleroma.test_runner --cover --preload-modules
coverage: '/^Line total: ([^ ]*%)$/'
artifacts:
reports:
@ -150,7 +149,6 @@ unit-testing-1.15.8-otp-26:
- .using-ci-base
stage: test
image: git.pleroma.social:5050/pleroma/pleroma/ci-base:elixir-1.15.8-otp-26
allow_failure: true
cache: *testing_cache_policy
services: *testing_services
script: *testing_script
@ -167,11 +165,11 @@ unit-testing-1.13.4-otp-25-erratic:
script:
- mix ecto.create
- mix ecto.migrate
- mix test --only=erratic
- mix pleroma.test_runner --only=erratic
formatting-1.13:
formatting-1.15:
extends: .build_changes_policy
image: &formatting_elixir elixir:1.13-alpine
image: &formatting_elixir elixir:1.15-alpine
stage: lint
cache: *testing_cache_policy
before_script: &current_bfr_script

View file

@ -0,0 +1 @@
Elixir Logger configuration is now longer permitted through AdminFE and ConfigDB

View file

@ -0,0 +1 @@
Elixir 1.15 compatibility

View file

@ -132,6 +132,8 @@
]
# Configures Elixir's Logger
config :logger, backends: [:console]
config :logger, :console,
level: :debug,
format: "\n$time $metadata[$level] $message\n",

View file

@ -1228,79 +1228,6 @@
}
]
},
%{
group: :logger,
type: :group,
description: "Logger-related settings",
children: [
%{
key: :backends,
type: [:atom, :tuple, :module],
description:
"Where logs will be sent, :console - send logs to stdout, { ExSyslogger, :ex_syslogger } - to syslog, Quack.Logger - to Slack.",
suggestions: [:console, {ExSyslogger, :ex_syslogger}]
}
]
},
%{
group: :logger,
type: :group,
key: :ex_syslogger,
label: "ExSyslogger",
description: "ExSyslogger-related settings",
children: [
%{
key: :level,
type: {:dropdown, :atom},
description: "Log level",
suggestions: [:debug, :info, :warning, :error]
},
%{
key: :ident,
type: :string,
description:
"A string that's prepended to every message, and is typically set to the app name",
suggestions: ["pleroma"]
},
%{
key: :format,
type: :string,
description: "Default: \"$date $time [$level] $levelpad$node $metadata $message\"",
suggestions: ["$metadata[$level] $message"]
},
%{
key: :metadata,
type: {:list, :atom},
suggestions: [:request_id]
}
]
},
%{
group: :logger,
type: :group,
key: :console,
label: "Console Logger",
description: "Console logger settings",
children: [
%{
key: :level,
type: {:dropdown, :atom},
description: "Log level",
suggestions: [:debug, :info, :warning, :error]
},
%{
key: :format,
type: :string,
description: "Default: \"$date $time [$level] $levelpad$node $metadata $message\"",
suggestions: ["$metadata[$level] $message"]
},
%{
key: :metadata,
type: {:list, :atom},
suggestions: [:request_id]
}
]
},
%{
group: :pleroma,
key: :frontend_configurations,

View file

@ -36,7 +36,7 @@
# different ports.
# Do not include timestamps in development logs
config :logger, :console, format: "$metadata[$level] $message\n"
config :logger, Logger.Backends.Console, format: "$metadata[$level] $message\n"
# Set a higher stacktrace during development. Avoid configuring such
# in production as building large stacktraces may be expensive.

View file

@ -20,7 +20,7 @@
config :phoenix, serve_endpoints: true
# Do not print debug messages in production
config :logger, :console, level: :info
config :logger, Logger.Backends.Console, level: :info
config :logger, :ex_syslogger, level: :info
# ## SSL Support

View file

@ -49,7 +49,8 @@
hostname: System.get_env("DB_HOST") || "localhost",
port: System.get_env("DB_PORT") || "5432",
pool: Ecto.Adapters.SQL.Sandbox,
pool_size: System.schedulers_online() * 2
pool_size: System.schedulers_online() * 2,
log: false
config :pleroma, :dangerzone, override_repo_pool_size: true
@ -177,6 +178,10 @@
streamer_registry: false,
test_http_pools: true
config :pleroma, Pleroma.Web.Streaming, sync_streaming: true
config :pleroma, Pleroma.Web.MastodonAPI.StatusView, sync_fetching: true
config :pleroma, Pleroma.Uploaders.Uploader, timeout: 1_000
config :pleroma, Pleroma.Emoji.Loader, test_emoji: true

View file

@ -853,7 +853,7 @@ config :logger,
backends: [{ExSyslogger, :ex_syslogger}]
config :logger, :ex_syslogger,
level: :warn
level: :warning
```
Another example, keeping console output and adding the pid to syslog output:
@ -862,7 +862,7 @@ config :logger,
backends: [:console, {ExSyslogger, :ex_syslogger}]
config :logger, :ex_syslogger,
level: :warn,
level: :warning,
option: [:pid, :ndelay]
```

View file

@ -1,7 +1,7 @@
## Required dependencies
* PostgreSQL >=11.0
* Elixir >=1.13.0 <1.15
* Elixir >=1.13.0 <1.17
* Erlang OTP >=22.2.0 (supported: <27)
* git
* file / libmagic

View file

@ -14,7 +14,8 @@ defmodule Mix.Pleroma do
:swoosh,
:timex,
:fast_html,
:oban
:oban,
:logger_backends
]
@cachex_children ["object", "user", "scrubber", "web_resp"]
@doc "Common functions to be reused in mix tasks"

View file

@ -351,7 +351,7 @@ def run(["set_text_search_config", tsconfig]) do
)
end
shell_info('Done.')
shell_info(~c"Done.")
end
end

View file

@ -0,0 +1,25 @@
defmodule Mix.Tasks.Pleroma.TestRunner do
@shortdoc "Retries tests once if they fail"
use Mix.Task
def run(args \\ []) do
case System.cmd("mix", ["test"] ++ args, into: IO.stream(:stdio, :line)) do
{_, 0} ->
:ok
_ ->
retry(args)
end
end
def retry(args) do
case System.cmd("mix", ["test", "--failed"] ++ args, into: IO.stream(:stdio, :line)) do
{_, 0} ->
:ok
_ ->
exit(1)
end
end
end

View file

@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# Copyright © 2017-2023 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Config.TransferTask do
@ -44,14 +44,9 @@ def load_and_update_env(deleted_settings \\ [], restart_pleroma? \\ true) do
with {_, true} <- {:configurable, Config.get(:configurable_from_database)} do
# We need to restart applications for loaded settings take effect
{logger, other} =
settings =
(Repo.all(ConfigDB) ++ deleted_settings)
|> Enum.map(&merge_with_default/1)
|> Enum.split_with(fn {group, _, _, _} -> group in [:logger] end)
logger
|> Enum.sort()
|> Enum.each(&configure/1)
started_applications = Application.started_applications()
@ -64,7 +59,7 @@ def load_and_update_env(deleted_settings \\ [], restart_pleroma? \\ true) do
[:pleroma | reject]
end
other
settings
|> Enum.map(&update/1)
|> Enum.uniq()
|> Enum.reject(&(&1 in reject))
@ -102,38 +97,6 @@ defp merge_with_default(%{group: group, key: key, value: value} = setting) do
{group, key, value, merged}
end
# change logger configuration in runtime, without restart
defp configure({_, :backends, _, merged}) do
# removing current backends
Enum.each(Application.get_env(:logger, :backends), &Logger.remove_backend/1)
Enum.each(merged, &Logger.add_backend/1)
:ok = update_env(:logger, :backends, merged)
end
defp configure({_, key, _, merged}) when key in [:console, :ex_syslogger] do
merged =
if key == :console do
put_in(merged[:format], merged[:format] <> "\n")
else
merged
end
backend =
if key == :ex_syslogger,
do: {ExSyslogger, :ex_syslogger},
else: key
Logger.configure_backend(backend, merged)
:ok = update_env(:logger, key, merged)
end
defp configure({_, key, _, merged}) do
Logger.configure([{key, merged}])
:ok = update_env(:logger, key, merged)
end
defp update({group, key, value, merged}) do
try do
:ok = update_env(group, key, merged)

View file

@ -165,8 +165,7 @@ defp only_full_update?(%ConfigDB{group: group, key: key}) do
{:pleroma, :ecto_repos},
{:mime, :types},
{:cors_plug, [:max_age, :methods, :expose, :headers]},
{:swarm, :node_blacklist},
{:logger, :backends}
{:swarm, :node_blacklist}
]
Enum.any?(full_key_update, fn
@ -385,7 +384,12 @@ defp find_valid_delimiter([delimiter | others], pattern, regex_delimiter) do
@spec module_name?(String.t()) :: boolean()
def module_name?(string) do
Regex.match?(~r/^(Pleroma|Phoenix|Tesla|Ueberauth|Swoosh)\./, string) or
string in ["Oban", "Ueberauth", "ExSyslogger", "ConcurrentLimiter"]
if String.contains?(string, ".") do
[name | _] = String.split(string, ".", parts: 2)
name in ~w[Pleroma Phoenix Tesla Ueberauth Swoosh Logger LoggerBackends]
else
string in ~w[Oban Ueberauth ExSyslogger ConcurrentLimiter]
end
end
end

View file

@ -416,10 +416,10 @@ defp downloadable?(pack) do
end
defp create_archive_and_cache(pack, hash) do
files = ['pack.json' | Enum.map(pack.files, fn {_, file} -> to_charlist(file) end)]
files = [~c"pack.json" | Enum.map(pack.files, fn {_, file} -> to_charlist(file) end)]
{:ok, {_, result}} =
:zip.zip('#{pack.name}.zip', files, [:memory, cwd: to_charlist(pack.path)])
:zip.zip(~c"#{pack.name}.zip", files, [:memory, cwd: to_charlist(pack.path)])
ttl_per_file = Pleroma.Config.get!([:emoji, :shared_pack_cache_seconds_per_file])
overall_ttl = :timer.seconds(ttl_per_file * Enum.count(files))
@ -586,7 +586,7 @@ defp unzip(archive, pack_info, remote_pack, local_pack) do
with :ok <- File.mkdir_p!(local_pack.path) do
files = Enum.map(remote_pack["files"], fn {_, path} -> to_charlist(path) end)
# Fallback cannot contain a pack.json file
files = if pack_info[:fallback], do: files, else: ['pack.json' | files]
files = if pack_info[:fallback], do: files, else: [~c"pack.json" | files]
:zip.unzip(archive, cwd: to_charlist(local_pack.path), file_list: files)
end

View file

@ -134,7 +134,10 @@ def make_update_object_data(original_data, new_data, date) do
else
%{updated_object: updated_data} =
updated_data
|> maybe_update_history(original_data, updated: updated, use_history_in_new_object?: false)
|> maybe_update_history(original_data,
updated: updated,
use_history_in_new_object?: false
)
updated_data
|> Map.put("updated", date)

View file

@ -249,14 +249,16 @@ defp url_from_spec(%__MODULE__{name: name}, base_url, {:file, path}) do
defp url_from_spec(_upload, _base_url, {:url, url}), do: url
@spec base_url() :: binary
def base_url do
uploader = @config_impl.get([Pleroma.Upload, :uploader])
upload_base_url = @config_impl.get([Pleroma.Upload, :base_url])
upload_fallback_url = Pleroma.Web.Endpoint.url() <> "/media/"
upload_base_url = @config_impl.get([Pleroma.Upload, :base_url]) || upload_fallback_url
public_endpoint = @config_impl.get([uploader, :public_endpoint])
case uploader do
Pleroma.Uploaders.Local ->
upload_base_url || Pleroma.Web.Endpoint.url() <> "/media/"
upload_base_url
Pleroma.Uploaders.S3 ->
bucket = @config_impl.get([Pleroma.Uploaders.S3, :bucket])
@ -268,11 +270,14 @@ def base_url do
!is_nil(truncated_namespace) ->
truncated_namespace
!is_nil(namespace) ->
!is_nil(namespace) and !is_nil(bucket) ->
namespace <> ":" <> bucket
true ->
!is_nil(bucket) ->
bucket
true ->
""
end
if public_endpoint do
@ -285,7 +290,7 @@ def base_url do
@config_impl.get([Pleroma.Uploaders.IPFS, :get_gateway_url])
_ ->
public_endpoint || upload_base_url || Pleroma.Web.Endpoint.url() <> "/media/"
public_endpoint || upload_base_url
end
end
end

View file

@ -197,12 +197,12 @@ defp wait_backup(backup, current_processed, task) do
end
@files [
'actor.json',
'outbox.json',
'likes.json',
'bookmarks.json',
'followers.json',
'following.json'
~c"actor.json",
~c"outbox.json",
~c"likes.json",
~c"bookmarks.json",
~c"followers.json",
~c"following.json"
]
@spec export(Pleroma.User.Backup.t(), pid()) :: {:ok, String.t()} | :error
def export(%__MODULE__{} = backup, caller_pid) do

View file

@ -79,7 +79,9 @@ def search_operation do
%Schema{type: :string, enum: ["accounts", "hashtags", "statuses"]},
"Search type"
),
Operation.parameter(:q, :query, %Schema{type: :string}, "The search query", required: true),
Operation.parameter(:q, :query, %Schema{type: :string}, "The search query",
required: true
),
Operation.parameter(
:resolve,
:query,

View file

@ -110,7 +110,7 @@ defp register_user(connection, base, uid, name) do
}
params =
case List.keyfind(attributes, 'mail', 0) do
case List.keyfind(attributes, ~c"mail", 0) do
{_, [mail]} -> Map.put_new(params, :email, :erlang.list_to_binary(mail))
_ -> params
end

View file

@ -8,6 +8,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
require Pleroma.Constants
alias Pleroma.Activity
alias Pleroma.Config
alias Pleroma.HTML
alias Pleroma.Maps
alias Pleroma.Object
@ -30,7 +31,13 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
# pagination is restricted to 40 activities at a time
defp fetch_rich_media_for_activities(activities) do
Enum.each(activities, fn activity ->
spawn(fn -> Card.get_by_activity(activity) end)
fun = fn -> Card.get_by_activity(activity) end
if Config.get([__MODULE__, :sync_fetching], false) do
fun.()
else
spawn(fun)
end
end)
end

View file

@ -104,7 +104,7 @@ def handle_info(:ping, state) do
end
def handle_info(:close, state) do
{:stop, {:closed, 'connection closed by server'}, state}
{:stop, {:closed, ~c"connection closed by server"}, state}
end
def handle_info(msg, state) do

View file

@ -75,8 +75,7 @@ def whitelisted?(url) do
%{host: domain} = URI.parse(url)
mediaproxy_whitelist_domains =
[:media_proxy, :whitelist]
|> Config.get()
Config.get([:media_proxy, :whitelist], [])
|> Kernel.++(["#{Upload.base_url()}"])
|> Enum.map(&maybe_get_domain_from_url/1)

View file

@ -34,7 +34,9 @@ def perform(%Plug.Conn{assigns: assigns} = conn, %{scopes: scopes} = options) do
permissions = Enum.join(missing_scopes, " #{op} ")
error_message =
dgettext("errors", "Insufficient permissions: %{permissions}.", permissions: permissions)
dgettext("errors", "Insufficient permissions: %{permissions}.",
permissions: permissions
)
conn
|> put_resp_content_type("application/json")

View file

@ -172,7 +172,13 @@ def remove_socket(topic) do
def stream(topics, items) do
if should_env_send?() do
for topic <- List.wrap(topics), item <- List.wrap(items) do
spawn(fn -> do_stream(topic, item) end)
fun = fn -> do_stream(topic, item) end
if Config.get([__MODULE__, :sync_streaming], false) do
fun.()
else
spawn(fun)
end
end
end
end

View file

@ -9,7 +9,7 @@ def string_from_xpath(_, :error), do: nil
def string_from_xpath(xpath, doc) do
try do
{:xmlObj, :string, res} = :xmerl_xpath.string('string(#{xpath})', doc)
{:xmlObj, :string, res} = :xmerl_xpath.string(~c"string(#{xpath})", doc)
res =
res

37
mix.exs
View file

@ -8,7 +8,7 @@ def project do
elixir: "~> 1.13",
elixirc_paths: elixirc_paths(Mix.env()),
compilers: Mix.compilers(),
elixirc_options: [warnings_as_errors: warnings_as_errors()],
elixirc_options: [warnings_as_errors: warnings_as_errors(), prune_code_paths: false],
xref: [exclude: [:eldap]],
dialyzer: [plt_add_apps: [:mix, :eldap]],
start_permanent: Mix.env() == :prod,
@ -73,14 +73,15 @@ def copy_nginx_config(%{path: target_path} = release) do
def application do
[
mod: {Pleroma.Application, []},
extra_applications: [
:logger,
:runtime_tools,
:comeonin,
:fast_sanitize,
:os_mon,
:ssl
],
extra_applications:
[
:logger,
:runtime_tools,
:comeonin,
:fast_sanitize,
:os_mon,
:ssl
] ++ logger_application(),
included_applications: [:ex_syslogger]
]
end
@ -109,6 +110,22 @@ defp oauth_deps do
for s <- oauth_strategy_packages, do: {String.to_atom(s), ">= 0.0.0"}
end
defp logger_application do
if Version.match?(System.version(), "<1.15.0-rc.0") do
[]
else
[:logger_backends]
end
end
defp logger_deps do
if Version.match?(System.version(), "<1.15.0-rc.0") do
[]
else
[{:logger_backends, "~> 1.0"}]
end
end
# Specifies your project dependencies.
#
# Type `mix help deps` for examples and options.
@ -197,7 +214,7 @@ defp deps do
{:websockex, "~> 0.4.3", only: :test},
{:benchee, "~> 1.0", only: :benchmark},
{:dialyxir, "~> 1.4", only: [:dev, :test], runtime: false}
] ++ oauth_deps()
] ++ oauth_deps() ++ logger_deps()
end
# Aliases are shortcuts or tasks specific to the current project.

View file

@ -70,6 +70,7 @@
"jose": {:hex, :jose, "1.11.6", "613fda82552128aa6fb804682e3a616f4bc15565a048dabd05b1ebd5827ed965", [:mix, :rebar3], [], "hexpm", "6275cb75504f9c1e60eeacb771adfeee4905a9e182103aa59b53fed651ff9738"},
"jumper": {:hex, :jumper, "1.0.2", "68cdcd84472a00ac596b4e6459a41b3062d4427cbd4f1e8c8793c5b54f1406a7", [:mix], [], "hexpm", "9b7782409021e01ab3c08270e26f36eb62976a38c1aa64b2eaf6348422f165e1"},
"linkify": {:hex, :linkify, "0.5.3", "5f8143d8f61f5ff08d3aeeff47ef6509492b4948d8f08007fbf66e4d2246a7f2", [:mix], [], "hexpm", "3ef35a1377d47c25506e07c1c005ea9d38d700699d92ee92825f024434258177"},
"logger_backends": {:hex, :logger_backends, "1.0.0", "09c4fad6202e08cb0fbd37f328282f16539aca380f512523ce9472b28edc6bdf", [:mix], [], "hexpm", "1faceb3e7ec3ef66a8f5746c5afd020e63996df6fd4eb8cdb789e5665ae6c9ce"},
"majic": {:hex, :majic, "1.0.0", "37e50648db5f5c2ff0c9fb46454d034d11596c03683807b9fb3850676ffdaab3", [:make, :mix], [{:elixir_make, "~> 0.6.1", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "7905858f76650d49695f14ea55cd9aaaee0c6654fa391671d4cf305c275a0a9e"},
"makeup": {:hex, :makeup, "1.0.5", "d5a830bc42c9800ce07dd97fa94669dfb93d3bf5fcf6ea7a0c67b2e0e4a7f26c", [:mix], [{:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cfa158c02d3f5c0c665d0af11512fed3fba0144cf1aadee0f2ce17747fba2ca9"},
"makeup_elixir": {:hex, :makeup_elixir, "0.14.1", "4f0e96847c63c17841d42c08107405a005a2680eb9c7ccadfd757bd31dabccfb", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f2438b1a80eaec9ede832b5c41cd4f373b38fd7aa33e3b22d9db79e640cbde11"},

View file

@ -7,7 +7,10 @@ defmodule Pleroma.Repo.Migrations.CreateUserTrigramIndex do
def change do
create_if_not_exists(
index(:users, ["(nickname || name) gist_trgm_ops"], name: :users_trigram_index, using: :gist)
index(:users, ["(nickname || name) gist_trgm_ops"],
name: :users_trigram_index,
using: :gist
)
)
end
end

View file

@ -20,7 +20,10 @@ def down do
drop_if_exists(index(:users, [], name: :users_trigram_index))
create_if_not_exists(
index(:users, ["(nickname || name) gist_trgm_ops"], name: :users_trigram_index, using: :gist)
index(:users, ["(nickname || name) gist_trgm_ops"],
name: :users_trigram_index,
using: :gist
)
)
end
end

View file

@ -7,7 +7,10 @@ defmodule Pleroma.Repo.Migrations.AddTagIndexToObjects do
def change do
drop_if_exists(
index(:activities, ["(data #> '{\"object\",\"tag\"}')"], using: :gin, name: :activities_tags)
index(:activities, ["(data #> '{\"object\",\"tag\"}')"],
using: :gin,
name: :activities_tags
)
)
create_if_not_exists(index(:objects, ["(data->'tag')"], using: :gin, name: :objects_tags))

View file

@ -9,7 +9,9 @@ defmodule Pleroma.Repo.Migrations.RemoteipPlugRename do
def up do
config =
from(c in Pleroma.ConfigDB, where: c.group == ^:pleroma and c.key == ^Pleroma.Plugs.RemoteIp)
from(c in Pleroma.ConfigDB,
where: c.group == ^:pleroma and c.key == ^Pleroma.Plugs.RemoteIp
)
|> Pleroma.Repo.one()
if config do

View file

@ -0,0 +1,7 @@
defmodule Pleroma.Repo.Migrations.DeprecateConfigDBLogger do
use Ecto.Migration
def change do
execute("DELETE FROM config WHERE config.group = ':logger'")
end
end

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1 +1 @@
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1"><meta name=renderer content=webkit><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><title>Admin FE</title><link rel="shortcut icon" href=favicon.ico><link href=chunk-elementUI.852ab1db.css rel=stylesheet><link href=chunk-libs.0b4a26df.css rel=stylesheet><link href=app.147d87e8.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=static/js/runtime.f1a41c33.js></script><script type=text/javascript src=static/js/chunk-elementUI.bec6fa77.js></script><script type=text/javascript src=static/js/chunk-libs.eb232bda.js></script><script type=text/javascript src=static/js/app.c3e187df.js></script></body></html>
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1"><meta name=renderer content=webkit><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><title>Admin FE</title><link rel="shortcut icon" href=favicon.ico><link href=chunk-elementUI.9644454c.css rel=stylesheet><link href=chunk-libs.3c625040.css rel=stylesheet><link href=app.a10ad7b9.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=static/js/runtime.26323110.js></script><script type=text/javascript src=static/js/chunk-elementUI.d02c484d.js></script><script type=text/javascript src=static/js/chunk-libs.c8fc8a3a.js></script><script type=text/javascript src=static/js/app.85d71fab.js></script></body></html>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show more