forked from AkkomaGang/akkoma
preload data into index.html
This commit is contained in:
parent
d6693a9102
commit
29ae5bb771
15 changed files with 532 additions and 156 deletions
|
@ -241,18 +241,7 @@
|
||||||
account_field_value_length: 2048,
|
account_field_value_length: 2048,
|
||||||
external_user_synchronization: true,
|
external_user_synchronization: true,
|
||||||
extended_nickname_format: true,
|
extended_nickname_format: true,
|
||||||
cleanup_attachments: false,
|
cleanup_attachments: false
|
||||||
multi_factor_authentication: [
|
|
||||||
totp: [
|
|
||||||
# digits 6 or 8
|
|
||||||
digits: 6,
|
|
||||||
period: 30
|
|
||||||
],
|
|
||||||
backup_codes: [
|
|
||||||
number: 5,
|
|
||||||
length: 16
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
config :pleroma, :feed,
|
config :pleroma, :feed,
|
||||||
post_title: %{
|
post_title: %{
|
||||||
|
@ -361,8 +350,7 @@
|
||||||
reject: [],
|
reject: [],
|
||||||
accept: [],
|
accept: [],
|
||||||
avatar_removal: [],
|
avatar_removal: [],
|
||||||
banner_removal: [],
|
banner_removal: []
|
||||||
reject_deletes: []
|
|
||||||
|
|
||||||
config :pleroma, :mrf_keyword,
|
config :pleroma, :mrf_keyword,
|
||||||
reject: [],
|
reject: [],
|
||||||
|
@ -428,6 +416,13 @@
|
||||||
],
|
],
|
||||||
unfurl_nsfw: false
|
unfurl_nsfw: false
|
||||||
|
|
||||||
|
config :pleroma, Pleroma.Web.Preload,
|
||||||
|
providers: [
|
||||||
|
Pleroma.Web.Preload.Providers.Instance,
|
||||||
|
Pleroma.Web.Preload.Providers.User,
|
||||||
|
Pleroma.Web.Preload.Providers.Timelines
|
||||||
|
]
|
||||||
|
|
||||||
config :pleroma, :http_security,
|
config :pleroma, :http_security,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
sts: false,
|
sts: false,
|
||||||
|
@ -682,8 +677,6 @@
|
||||||
profiles: %{local: false, remote: false},
|
profiles: %{local: false, remote: false},
|
||||||
activities: %{local: false, remote: false}
|
activities: %{local: false, remote: false}
|
||||||
|
|
||||||
config :pleroma, Pleroma.Web.ApiSpec.CastAndValidate, strict: false
|
|
||||||
|
|
||||||
# Import environment specific config. This must remain at the bottom
|
# Import environment specific config. This must remain at the bottom
|
||||||
# of this file so it overrides the configuration defined above.
|
# of this file so it overrides the configuration defined above.
|
||||||
import_config "#{Mix.env()}.exs"
|
import_config "#{Mix.env()}.exs"
|
||||||
|
|
|
@ -4,11 +4,10 @@
|
||||||
|
|
||||||
defmodule Fallback.RedirectController do
|
defmodule Fallback.RedirectController do
|
||||||
use Pleroma.Web, :controller
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.Metadata
|
alias Pleroma.Web.Metadata
|
||||||
|
alias Pleroma.Web.Preload
|
||||||
|
|
||||||
def api_not_implemented(conn, _params) do
|
def api_not_implemented(conn, _params) do
|
||||||
conn
|
conn
|
||||||
|
@ -16,16 +15,7 @@ def api_not_implemented(conn, _params) do
|
||||||
|> json(%{error: "Not implemented"})
|
|> json(%{error: "Not implemented"})
|
||||||
end
|
end
|
||||||
|
|
||||||
def redirector(conn, _params, code \\ 200)
|
def redirector(conn, _params, code \\ 200) do
|
||||||
|
|
||||||
# redirect to admin section
|
|
||||||
# /pleroma/admin -> /pleroma/admin/
|
|
||||||
#
|
|
||||||
def redirector(conn, %{"path" => ["pleroma", "admin"]} = _, _code) do
|
|
||||||
redirect(conn, to: "/pleroma/admin/")
|
|
||||||
end
|
|
||||||
|
|
||||||
def redirector(conn, _params, code) do
|
|
||||||
conn
|
conn
|
||||||
|> put_resp_content_type("text/html")
|
|> put_resp_content_type("text/html")
|
||||||
|> send_file(code, index_file_path())
|
|> send_file(code, index_file_path())
|
||||||
|
@ -43,28 +33,34 @@ def redirector_with_meta(conn, %{"maybe_nickname_or_id" => maybe_nickname_or_id}
|
||||||
def redirector_with_meta(conn, params) do
|
def redirector_with_meta(conn, params) do
|
||||||
{:ok, index_content} = File.read(index_file_path())
|
{:ok, index_content} = File.read(index_file_path())
|
||||||
|
|
||||||
tags =
|
tags = build_tags(conn, params)
|
||||||
try do
|
preloads = preload_data(conn, params)
|
||||||
Metadata.build_tags(params)
|
|
||||||
rescue
|
|
||||||
e ->
|
|
||||||
Logger.error(
|
|
||||||
"Metadata rendering for #{conn.request_path} failed.\n" <>
|
|
||||||
Exception.format(:error, e, __STACKTRACE__)
|
|
||||||
)
|
|
||||||
|
|
||||||
""
|
response =
|
||||||
end
|
index_content
|
||||||
|
|> String.replace("<!--server-generated-meta-->", tags)
|
||||||
response = String.replace(index_content, "<!--server-generated-meta-->", tags)
|
|> String.replace("<!--server-generated-initial-data-->", preloads)
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_resp_content_type("text/html")
|
|> put_resp_content_type("text/html")
|
||||||
|> send_resp(200, response)
|
|> send_resp(200, response)
|
||||||
end
|
end
|
||||||
|
|
||||||
def index_file_path do
|
def redirector_with_preload(conn, %{"path" => ["pleroma", "admin"]}) do
|
||||||
Pleroma.Plugs.InstanceStatic.file_path("index.html")
|
redirect(conn, to: "/pleroma/admin/")
|
||||||
|
end
|
||||||
|
|
||||||
|
def redirector_with_preload(conn, params) do
|
||||||
|
{:ok, index_content} = File.read(index_file_path())
|
||||||
|
preloads = preload_data(conn, params)
|
||||||
|
|
||||||
|
response =
|
||||||
|
index_content
|
||||||
|
|> String.replace("<!--server-generated-initial-data-->", preloads)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_resp_content_type("text/html")
|
||||||
|
|> send_resp(200, response)
|
||||||
end
|
end
|
||||||
|
|
||||||
def registration_page(conn, params) do
|
def registration_page(conn, params) do
|
||||||
|
@ -76,4 +72,36 @@ def empty(conn, _params) do
|
||||||
|> put_status(204)
|
|> put_status(204)
|
||||||
|> text("")
|
|> text("")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp index_file_path do
|
||||||
|
Pleroma.Plugs.InstanceStatic.file_path("index.html")
|
||||||
|
end
|
||||||
|
|
||||||
|
defp build_tags(conn, params) do
|
||||||
|
try do
|
||||||
|
Metadata.build_tags(params)
|
||||||
|
rescue
|
||||||
|
e ->
|
||||||
|
Logger.error(
|
||||||
|
"Metadata rendering for #{conn.request_path} failed.\n" <>
|
||||||
|
Exception.format(:error, e, __STACKTRACE__)
|
||||||
|
)
|
||||||
|
|
||||||
|
""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp preload_data(conn, params) do
|
||||||
|
try do
|
||||||
|
Preload.build_tags(conn, params)
|
||||||
|
rescue
|
||||||
|
e ->
|
||||||
|
Logger.error(
|
||||||
|
"Preloading for #{conn.request_path} failed.\n" <>
|
||||||
|
Exception.format(:error, e, __STACKTRACE__)
|
||||||
|
)
|
||||||
|
|
||||||
|
""
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
130
lib/pleroma/web/nodeinfo/nodeinfo.ex
Normal file
130
lib/pleroma/web/nodeinfo/nodeinfo.ex
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.Nodeinfo.Nodeinfo do
|
||||||
|
alias Pleroma.Config
|
||||||
|
alias Pleroma.Stats
|
||||||
|
alias Pleroma.User
|
||||||
|
alias Pleroma.Web.ActivityPub.MRF
|
||||||
|
alias Pleroma.Web.Federator.Publisher
|
||||||
|
|
||||||
|
# returns a nodeinfo 2.0 map, since 2.1 just adds a repository field
|
||||||
|
# under software.
|
||||||
|
def get_nodeinfo("2.0") do
|
||||||
|
stats = Stats.get_stats()
|
||||||
|
|
||||||
|
quarantined = Config.get([:instance, :quarantined_instances], [])
|
||||||
|
|
||||||
|
staff_accounts =
|
||||||
|
User.all_superusers()
|
||||||
|
|> Enum.map(fn u -> u.ap_id end)
|
||||||
|
|
||||||
|
federation_response =
|
||||||
|
if Config.get([:instance, :mrf_transparency]) do
|
||||||
|
{:ok, data} = MRF.describe()
|
||||||
|
|
||||||
|
data
|
||||||
|
|> Map.merge(%{quarantined_instances: quarantined})
|
||||||
|
else
|
||||||
|
%{}
|
||||||
|
end
|
||||||
|
|> Map.put(:enabled, Config.get([:instance, :federating]))
|
||||||
|
|
||||||
|
features =
|
||||||
|
[
|
||||||
|
"pleroma_api",
|
||||||
|
"mastodon_api",
|
||||||
|
"mastodon_api_streaming",
|
||||||
|
"polls",
|
||||||
|
"pleroma_explicit_addressing",
|
||||||
|
"shareable_emoji_packs",
|
||||||
|
"multifetch",
|
||||||
|
"pleroma:api/v1/notifications:include_types_filter",
|
||||||
|
if Config.get([:media_proxy, :enabled]) do
|
||||||
|
"media_proxy"
|
||||||
|
end,
|
||||||
|
if Config.get([:gopher, :enabled]) do
|
||||||
|
"gopher"
|
||||||
|
end,
|
||||||
|
if Config.get([:chat, :enabled]) do
|
||||||
|
"chat"
|
||||||
|
end,
|
||||||
|
if Config.get([:instance, :allow_relay]) do
|
||||||
|
"relay"
|
||||||
|
end,
|
||||||
|
if Config.get([:instance, :safe_dm_mentions]) do
|
||||||
|
"safe_dm_mentions"
|
||||||
|
end,
|
||||||
|
"pleroma_emoji_reactions"
|
||||||
|
]
|
||||||
|
|> Enum.filter(& &1)
|
||||||
|
|
||||||
|
%{
|
||||||
|
version: "2.0",
|
||||||
|
software: %{
|
||||||
|
name: Pleroma.Application.name() |> String.downcase(),
|
||||||
|
version: Pleroma.Application.version()
|
||||||
|
},
|
||||||
|
protocols: Publisher.gather_nodeinfo_protocol_names(),
|
||||||
|
services: %{
|
||||||
|
inbound: [],
|
||||||
|
outbound: []
|
||||||
|
},
|
||||||
|
openRegistrations: Config.get([:instance, :registrations_open]),
|
||||||
|
usage: %{
|
||||||
|
users: %{
|
||||||
|
total: Map.get(stats, :user_count, 0)
|
||||||
|
},
|
||||||
|
localPosts: Map.get(stats, :status_count, 0)
|
||||||
|
},
|
||||||
|
metadata: %{
|
||||||
|
nodeName: Config.get([:instance, :name]),
|
||||||
|
nodeDescription: Config.get([:instance, :description]),
|
||||||
|
private: !Config.get([:instance, :public], true),
|
||||||
|
suggestions: %{
|
||||||
|
enabled: false
|
||||||
|
},
|
||||||
|
staffAccounts: staff_accounts,
|
||||||
|
federation: federation_response,
|
||||||
|
pollLimits: Config.get([:instance, :poll_limits]),
|
||||||
|
postFormats: Config.get([:instance, :allowed_post_formats]),
|
||||||
|
uploadLimits: %{
|
||||||
|
general: Config.get([:instance, :upload_limit]),
|
||||||
|
avatar: Config.get([:instance, :avatar_upload_limit]),
|
||||||
|
banner: Config.get([:instance, :banner_upload_limit]),
|
||||||
|
background: Config.get([:instance, :background_upload_limit])
|
||||||
|
},
|
||||||
|
fieldsLimits: %{
|
||||||
|
maxFields: Config.get([:instance, :max_account_fields]),
|
||||||
|
maxRemoteFields: Config.get([:instance, :max_remote_account_fields]),
|
||||||
|
nameLength: Config.get([:instance, :account_field_name_length]),
|
||||||
|
valueLength: Config.get([:instance, :account_field_value_length])
|
||||||
|
},
|
||||||
|
accountActivationRequired: Config.get([:instance, :account_activation_required], false),
|
||||||
|
invitesEnabled: Config.get([:instance, :invites_enabled], false),
|
||||||
|
mailerEnabled: Config.get([Pleroma.Emails.Mailer, :enabled], false),
|
||||||
|
features: features,
|
||||||
|
restrictedNicknames: Config.get([Pleroma.User, :restricted_nicknames]),
|
||||||
|
skipThreadContainment: Config.get([:instance, :skip_thread_containment], false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_nodeinfo("2.1") do
|
||||||
|
raw_response = get_nodeinfo("2.0")
|
||||||
|
|
||||||
|
updated_software =
|
||||||
|
raw_response
|
||||||
|
|> Map.get(:software)
|
||||||
|
|> Map.put(:repository, Pleroma.Application.repository())
|
||||||
|
|
||||||
|
raw_response
|
||||||
|
|> Map.put(:software, updated_software)
|
||||||
|
|> Map.put(:version, "2.1")
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_nodeinfo(_version) do
|
||||||
|
{:error, :missing}
|
||||||
|
end
|
||||||
|
end
|
|
@ -5,12 +5,8 @@
|
||||||
defmodule Pleroma.Web.Nodeinfo.NodeinfoController do
|
defmodule Pleroma.Web.Nodeinfo.NodeinfoController do
|
||||||
use Pleroma.Web, :controller
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
alias Pleroma.Config
|
|
||||||
alias Pleroma.Stats
|
|
||||||
alias Pleroma.User
|
|
||||||
alias Pleroma.Web
|
alias Pleroma.Web
|
||||||
alias Pleroma.Web.Federator.Publisher
|
alias Pleroma.Web.Nodeinfo.Nodeinfo
|
||||||
alias Pleroma.Web.MastodonAPI.InstanceView
|
|
||||||
|
|
||||||
def schemas(conn, _params) do
|
def schemas(conn, _params) do
|
||||||
response = %{
|
response = %{
|
||||||
|
@ -29,102 +25,20 @@ def schemas(conn, _params) do
|
||||||
json(conn, response)
|
json(conn, response)
|
||||||
end
|
end
|
||||||
|
|
||||||
# returns a nodeinfo 2.0 map, since 2.1 just adds a repository field
|
|
||||||
# under software.
|
|
||||||
def raw_nodeinfo do
|
|
||||||
stats = Stats.get_stats()
|
|
||||||
|
|
||||||
staff_accounts =
|
|
||||||
User.all_superusers()
|
|
||||||
|> Enum.map(fn u -> u.ap_id end)
|
|
||||||
|
|
||||||
features = InstanceView.features()
|
|
||||||
federation = InstanceView.federation()
|
|
||||||
|
|
||||||
%{
|
|
||||||
version: "2.0",
|
|
||||||
software: %{
|
|
||||||
name: Pleroma.Application.name() |> String.downcase(),
|
|
||||||
version: Pleroma.Application.version()
|
|
||||||
},
|
|
||||||
protocols: Publisher.gather_nodeinfo_protocol_names(),
|
|
||||||
services: %{
|
|
||||||
inbound: [],
|
|
||||||
outbound: []
|
|
||||||
},
|
|
||||||
openRegistrations: Config.get([:instance, :registrations_open]),
|
|
||||||
usage: %{
|
|
||||||
users: %{
|
|
||||||
total: Map.get(stats, :user_count, 0)
|
|
||||||
},
|
|
||||||
localPosts: Map.get(stats, :status_count, 0)
|
|
||||||
},
|
|
||||||
metadata: %{
|
|
||||||
nodeName: Config.get([:instance, :name]),
|
|
||||||
nodeDescription: Config.get([:instance, :description]),
|
|
||||||
private: !Config.get([:instance, :public], true),
|
|
||||||
suggestions: %{
|
|
||||||
enabled: false
|
|
||||||
},
|
|
||||||
staffAccounts: staff_accounts,
|
|
||||||
federation: federation,
|
|
||||||
pollLimits: Config.get([:instance, :poll_limits]),
|
|
||||||
postFormats: Config.get([:instance, :allowed_post_formats]),
|
|
||||||
uploadLimits: %{
|
|
||||||
general: Config.get([:instance, :upload_limit]),
|
|
||||||
avatar: Config.get([:instance, :avatar_upload_limit]),
|
|
||||||
banner: Config.get([:instance, :banner_upload_limit]),
|
|
||||||
background: Config.get([:instance, :background_upload_limit])
|
|
||||||
},
|
|
||||||
fieldsLimits: %{
|
|
||||||
maxFields: Config.get([:instance, :max_account_fields]),
|
|
||||||
maxRemoteFields: Config.get([:instance, :max_remote_account_fields]),
|
|
||||||
nameLength: Config.get([:instance, :account_field_name_length]),
|
|
||||||
valueLength: Config.get([:instance, :account_field_value_length])
|
|
||||||
},
|
|
||||||
accountActivationRequired: Config.get([:instance, :account_activation_required], false),
|
|
||||||
invitesEnabled: Config.get([:instance, :invites_enabled], false),
|
|
||||||
mailerEnabled: Config.get([Pleroma.Emails.Mailer, :enabled], false),
|
|
||||||
features: features,
|
|
||||||
restrictedNicknames: Config.get([Pleroma.User, :restricted_nicknames]),
|
|
||||||
skipThreadContainment: Config.get([:instance, :skip_thread_containment], false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
# Schema definition: https://github.com/jhass/nodeinfo/blob/master/schemas/2.0/schema.json
|
# Schema definition: https://github.com/jhass/nodeinfo/blob/master/schemas/2.0/schema.json
|
||||||
# and https://github.com/jhass/nodeinfo/blob/master/schemas/2.1/schema.json
|
# and https://github.com/jhass/nodeinfo/blob/master/schemas/2.1/schema.json
|
||||||
def nodeinfo(conn, %{"version" => "2.0"}) do
|
def nodeinfo(conn, %{"version" => version}) do
|
||||||
conn
|
case Nodeinfo.get_nodeinfo(version) do
|
||||||
|> put_resp_header(
|
{:error, :missing} ->
|
||||||
"content-type",
|
render_error(conn, :not_found, "Nodeinfo schema version not handled")
|
||||||
"application/json; profile=http://nodeinfo.diaspora.software/ns/schema/2.0#; charset=utf-8"
|
|
||||||
)
|
|
||||||
|> json(raw_nodeinfo())
|
|
||||||
end
|
|
||||||
|
|
||||||
def nodeinfo(conn, %{"version" => "2.1"}) do
|
node_info ->
|
||||||
raw_response = raw_nodeinfo()
|
conn
|
||||||
|
|> put_resp_header(
|
||||||
updated_software =
|
"content-type",
|
||||||
raw_response
|
"application/json; profile=http://nodeinfo.diaspora.software/ns/schema/2.0#; charset=utf-8"
|
||||||
|> Map.get(:software)
|
)
|
||||||
|> Map.put(:repository, Pleroma.Application.repository())
|
|> json(node_info)
|
||||||
|
end
|
||||||
response =
|
|
||||||
raw_response
|
|
||||||
|> Map.put(:software, updated_software)
|
|
||||||
|> Map.put(:version, "2.1")
|
|
||||||
|
|
||||||
conn
|
|
||||||
|> put_resp_header(
|
|
||||||
"content-type",
|
|
||||||
"application/json; profile=http://nodeinfo.diaspora.software/ns/schema/2.1#; charset=utf-8"
|
|
||||||
)
|
|
||||||
|> json(response)
|
|
||||||
end
|
|
||||||
|
|
||||||
def nodeinfo(conn, _) do
|
|
||||||
render_error(conn, :not_found, "Nodeinfo schema version not handled")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
30
lib/pleroma/web/preload.ex
Normal file
30
lib/pleroma/web/preload.ex
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.Preload do
|
||||||
|
alias Phoenix.HTML
|
||||||
|
require Logger
|
||||||
|
|
||||||
|
def build_tags(_conn, params) do
|
||||||
|
preload_data =
|
||||||
|
Enum.reduce(Pleroma.Config.get([__MODULE__, :providers], []), %{}, fn parser, acc ->
|
||||||
|
Map.merge(acc, parser.generate_terms(params))
|
||||||
|
end)
|
||||||
|
|
||||||
|
rendered_html =
|
||||||
|
preload_data
|
||||||
|
|> Jason.encode!()
|
||||||
|
|> build_script_tag()
|
||||||
|
|> HTML.safe_to_string()
|
||||||
|
|
||||||
|
rendered_html
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_script_tag(content) do
|
||||||
|
HTML.Tag.content_tag(:script, HTML.raw(content),
|
||||||
|
id: "initial-results",
|
||||||
|
type: "application/json"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
49
lib/pleroma/web/preload/instance.ex
Normal file
49
lib/pleroma/web/preload/instance.ex
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.Preload.Providers.Instance do
|
||||||
|
alias Pleroma.Web.MastodonAPI.InstanceView
|
||||||
|
alias Pleroma.Web.Nodeinfo.Nodeinfo
|
||||||
|
alias Pleroma.Web.Preload.Providers.Provider
|
||||||
|
|
||||||
|
@behaviour Provider
|
||||||
|
@instance_url :"/api/v1/instance"
|
||||||
|
@panel_url :"/instance/panel.html"
|
||||||
|
@nodeinfo_url :"/nodeinfo/2.0"
|
||||||
|
|
||||||
|
@impl Provider
|
||||||
|
def generate_terms(_params) do
|
||||||
|
%{}
|
||||||
|
|> build_info_tag()
|
||||||
|
|> build_panel_tag()
|
||||||
|
|> build_nodeinfo_tag()
|
||||||
|
end
|
||||||
|
|
||||||
|
defp build_info_tag(acc) do
|
||||||
|
info_data = InstanceView.render("show.json", %{})
|
||||||
|
|
||||||
|
Map.put(acc, @instance_url, info_data)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp build_panel_tag(acc) do
|
||||||
|
instance_path = Path.join(:code.priv_dir(:pleroma), "static/instance/panel.html")
|
||||||
|
|
||||||
|
if File.exists?(instance_path) do
|
||||||
|
panel_data = File.read!(instance_path)
|
||||||
|
Map.put(acc, @panel_url, panel_data)
|
||||||
|
else
|
||||||
|
acc
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp build_nodeinfo_tag(acc) do
|
||||||
|
case Nodeinfo.get_nodeinfo("2.0") do
|
||||||
|
{:error, _} ->
|
||||||
|
acc
|
||||||
|
|
||||||
|
nodeinfo_data ->
|
||||||
|
Map.put(acc, @nodeinfo_url, nodeinfo_data)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
7
lib/pleroma/web/preload/provider.ex
Normal file
7
lib/pleroma/web/preload/provider.ex
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.Preload.Providers.Provider do
|
||||||
|
@callback generate_terms(map()) :: map()
|
||||||
|
end
|
42
lib/pleroma/web/preload/timelines.ex
Normal file
42
lib/pleroma/web/preload/timelines.ex
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.Preload.Providers.Timelines do
|
||||||
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
|
alias Pleroma.Web.MastodonAPI.StatusView
|
||||||
|
alias Pleroma.Web.Preload.Providers.Provider
|
||||||
|
|
||||||
|
@behaviour Provider
|
||||||
|
@public_url :"/api/v1/timelines/public"
|
||||||
|
|
||||||
|
@impl Provider
|
||||||
|
def generate_terms(_params) do
|
||||||
|
build_public_tag(%{})
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_public_tag(acc) do
|
||||||
|
if Pleroma.Config.get([:restrict_unauthenticated, :timelines, :federated], true) do
|
||||||
|
acc
|
||||||
|
else
|
||||||
|
Map.put(acc, @public_url, public_timeline(nil))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp public_timeline(user) do
|
||||||
|
activities =
|
||||||
|
create_timeline_params(user)
|
||||||
|
|> Map.put("local_only", false)
|
||||||
|
|> ActivityPub.fetch_public_activities()
|
||||||
|
|
||||||
|
StatusView.render("index.json", activities: activities, for: user, as: :activity)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp create_timeline_params(user) do
|
||||||
|
%{}
|
||||||
|
|> Map.put("type", ["Create", "Announce"])
|
||||||
|
|> Map.put("blocking_user", user)
|
||||||
|
|> Map.put("muting_user", user)
|
||||||
|
|> Map.put("user", user)
|
||||||
|
end
|
||||||
|
end
|
25
lib/pleroma/web/preload/user.ex
Normal file
25
lib/pleroma/web/preload/user.ex
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.Preload.Providers.User do
|
||||||
|
alias Pleroma.Web.MastodonAPI.AccountView
|
||||||
|
alias Pleroma.Web.Preload.Providers.Provider
|
||||||
|
|
||||||
|
@behaviour Provider
|
||||||
|
@account_url :"/api/v1/accounts"
|
||||||
|
|
||||||
|
@impl Provider
|
||||||
|
def generate_terms(%{user: user}) do
|
||||||
|
build_accounts_tag(%{}, user)
|
||||||
|
end
|
||||||
|
|
||||||
|
def generate_terms(_params), do: %{}
|
||||||
|
|
||||||
|
def build_accounts_tag(acc, nil), do: acc
|
||||||
|
|
||||||
|
def build_accounts_tag(acc, user) do
|
||||||
|
account_data = AccountView.render("show.json", %{user: user, for: user})
|
||||||
|
Map.put(acc, @account_url, account_data)
|
||||||
|
end
|
||||||
|
end
|
|
@ -718,7 +718,7 @@ defmodule Pleroma.Web.Router do
|
||||||
get("/registration/:token", RedirectController, :registration_page)
|
get("/registration/:token", RedirectController, :registration_page)
|
||||||
get("/:maybe_nickname_or_id", RedirectController, :redirector_with_meta)
|
get("/:maybe_nickname_or_id", RedirectController, :redirector_with_meta)
|
||||||
get("/api*path", RedirectController, :api_not_implemented)
|
get("/api*path", RedirectController, :api_not_implemented)
|
||||||
get("/*path", RedirectController, :redirector)
|
get("/*path", RedirectController, :redirector_with_preload)
|
||||||
|
|
||||||
options("/*path", RedirectController, :empty)
|
options("/*path", RedirectController, :empty)
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,7 +16,7 @@ defmodule Pleroma.Web.RuntimeStaticPlugTest do
|
||||||
|
|
||||||
test "overrides index" do
|
test "overrides index" do
|
||||||
bundled_index = get(build_conn(), "/")
|
bundled_index = get(build_conn(), "/")
|
||||||
assert html_response(bundled_index, 200) == File.read!("priv/static/index.html")
|
refute html_response(bundled_index, 200) == "hello world"
|
||||||
|
|
||||||
File.write!(@dir <> "/index.html", "hello world")
|
File.write!(@dir <> "/index.html", "hello world")
|
||||||
|
|
||||||
|
|
|
@ -6,22 +6,36 @@ defmodule Pleroma.Web.FallbackTest do
|
||||||
use Pleroma.Web.ConnCase
|
use Pleroma.Web.ConnCase
|
||||||
import Pleroma.Factory
|
import Pleroma.Factory
|
||||||
|
|
||||||
test "GET /registration/:token", %{conn: conn} do
|
describe "neither preloaded data nor metadata attached to" do
|
||||||
assert conn
|
test "GET /registration/:token", %{conn: conn} do
|
||||||
|> get("/registration/foo")
|
response = get(conn, "/registration/foo")
|
||||||
|> html_response(200) =~ "<!--server-generated-meta-->"
|
|
||||||
|
assert html_response(response, 200) =~ "<!--server-generated-meta-->"
|
||||||
|
assert html_response(response, 200) =~ "<!--server-generated-initial-data-->"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "GET /:maybe_nickname_or_id", %{conn: conn} do
|
describe "preloaded data and metadata attached to" do
|
||||||
user = insert(:user)
|
test "GET /:maybe_nickname_or_id", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
user_missing = get(conn, "/foo")
|
||||||
|
user_present = get(conn, "/#{user.nickname}")
|
||||||
|
|
||||||
assert conn
|
assert html_response(user_missing, 200) =~ "<!--server-generated-meta-->"
|
||||||
|> get("/foo")
|
refute html_response(user_present, 200) =~ "<!--server-generated-meta-->"
|
||||||
|> html_response(200) =~ "<!--server-generated-meta-->"
|
|
||||||
|
|
||||||
refute conn
|
assert html_response(user_missing, 200) =~ "<!--server-generated-initial-data-->"
|
||||||
|> get("/" <> user.nickname)
|
refute html_response(user_present, 200) =~ "<!--server-generated-initial-data-->"
|
||||||
|> html_response(200) =~ "<!--server-generated-meta-->"
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "preloaded data only attached to" do
|
||||||
|
test "GET /*path", %{conn: conn} do
|
||||||
|
public_page = get(conn, "/main/public")
|
||||||
|
|
||||||
|
assert html_response(public_page, 200) =~ "<!--server-generated-meta-->"
|
||||||
|
refute html_response(public_page, 200) =~ "<!--server-generated-initial-data-->"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "GET /api*path", %{conn: conn} do
|
test "GET /api*path", %{conn: conn} do
|
||||||
|
|
37
test/web/preload/instance_test.exs
Normal file
37
test/web/preload/instance_test.exs
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.Preload.Providers.InstanceTest do
|
||||||
|
use Pleroma.DataCase
|
||||||
|
alias Pleroma.Web.Preload.Providers.Instance
|
||||||
|
|
||||||
|
setup do: {:ok, Instance.generate_terms(nil)}
|
||||||
|
|
||||||
|
test "it renders the info", %{"/api/v1/instance": info} do
|
||||||
|
assert %{
|
||||||
|
description: description,
|
||||||
|
email: "admin@example.com",
|
||||||
|
registrations: true
|
||||||
|
} = info
|
||||||
|
|
||||||
|
assert String.equivalent?(description, "A Pleroma instance, an alternative fediverse server")
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it renders the panel", %{"/instance/panel.html": panel} do
|
||||||
|
assert String.contains?(
|
||||||
|
panel,
|
||||||
|
"<p>Welcome to <a href=\"https://pleroma.social\" target=\"_blank\">Pleroma!</a></p>"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it renders the node_info", %{"/nodeinfo/2.0": nodeinfo} do
|
||||||
|
%{
|
||||||
|
metadata: metadata,
|
||||||
|
version: "2.0"
|
||||||
|
} = nodeinfo
|
||||||
|
|
||||||
|
assert metadata.private == false
|
||||||
|
assert metadata.suggestions == %{enabled: false}
|
||||||
|
end
|
||||||
|
end
|
74
test/web/preload/timeline_test.exs
Normal file
74
test/web/preload/timeline_test.exs
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.Preload.Providers.TimelineTest do
|
||||||
|
use Pleroma.DataCase
|
||||||
|
import Pleroma.Factory
|
||||||
|
|
||||||
|
alias Pleroma.Web.CommonAPI
|
||||||
|
alias Pleroma.Web.Preload.Providers.Timelines
|
||||||
|
|
||||||
|
@public_url :"/api/v1/timelines/public"
|
||||||
|
|
||||||
|
describe "unauthenticated timeliness when restricted" do
|
||||||
|
setup do
|
||||||
|
svd_config = Pleroma.Config.get([:restrict_unauthenticated, :timelines])
|
||||||
|
Pleroma.Config.put([:restrict_unauthenticated, :timelines], %{local: true, federated: true})
|
||||||
|
|
||||||
|
on_exit(fn ->
|
||||||
|
Pleroma.Config.put([:restrict_unauthenticated, :timelines], svd_config)
|
||||||
|
end)
|
||||||
|
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
|
||||||
|
test "return nothing" do
|
||||||
|
tl_data = Timelines.generate_terms(%{})
|
||||||
|
|
||||||
|
refute Map.has_key?(tl_data, "/api/v1/timelines/public")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "unauthenticated timeliness when unrestricted" do
|
||||||
|
setup do
|
||||||
|
svd_config = Pleroma.Config.get([:restrict_unauthenticated, :timelines])
|
||||||
|
|
||||||
|
Pleroma.Config.put([:restrict_unauthenticated, :timelines], %{
|
||||||
|
local: false,
|
||||||
|
federated: false
|
||||||
|
})
|
||||||
|
|
||||||
|
on_exit(fn ->
|
||||||
|
Pleroma.Config.put([:restrict_unauthenticated, :timelines], svd_config)
|
||||||
|
end)
|
||||||
|
|
||||||
|
{:ok, user: insert(:user)}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "returns the timeline when not restricted" do
|
||||||
|
assert Timelines.generate_terms(%{})
|
||||||
|
|> Map.has_key?(@public_url)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "returns public items", %{user: user} do
|
||||||
|
{:ok, _} = CommonAPI.post(user, %{"status" => "it's post 1!"})
|
||||||
|
{:ok, _} = CommonAPI.post(user, %{"status" => "it's post 2!"})
|
||||||
|
{:ok, _} = CommonAPI.post(user, %{"status" => "it's post 3!"})
|
||||||
|
|
||||||
|
assert Timelines.generate_terms(%{})
|
||||||
|
|> Map.fetch!(@public_url)
|
||||||
|
|> Enum.count() == 3
|
||||||
|
end
|
||||||
|
|
||||||
|
test "does not return non-public items", %{user: user} do
|
||||||
|
{:ok, _} = CommonAPI.post(user, %{"status" => "it's post 1!", "visibility" => "unlisted"})
|
||||||
|
{:ok, _} = CommonAPI.post(user, %{"status" => "it's post 2!", "visibility" => "direct"})
|
||||||
|
{:ok, _} = CommonAPI.post(user, %{"status" => "it's post 3!"})
|
||||||
|
|
||||||
|
assert Timelines.generate_terms(%{})
|
||||||
|
|> Map.fetch!(@public_url)
|
||||||
|
|> Enum.count() == 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
33
test/web/preload/user_test.exs
Normal file
33
test/web/preload/user_test.exs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.Preload.Providers.UserTest do
|
||||||
|
use Pleroma.DataCase
|
||||||
|
import Pleroma.Factory
|
||||||
|
alias Pleroma.Web.Preload.Providers.User
|
||||||
|
|
||||||
|
describe "returns empty when user doesn't exist" do
|
||||||
|
test "nil user specified" do
|
||||||
|
refute User.generate_terms(%{user: nil})
|
||||||
|
|> Map.has_key?("/api/v1/accounts")
|
||||||
|
end
|
||||||
|
|
||||||
|
test "missing user specified" do
|
||||||
|
refute User.generate_terms(%{user: :not_a_user})
|
||||||
|
|> Map.has_key?("/api/v1/accounts")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "specified user exists" do
|
||||||
|
setup do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
{:ok, User.generate_terms(%{user: user})}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "account is rendered", %{"/api/v1/accounts": accounts} do
|
||||||
|
assert %{acct: user, username: user} = accounts
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue