Merge branch 'preload-data' into 'develop'
authorfeld <feld@feld.me>
Thu, 25 Jun 2020 21:35:39 +0000 (21:35 +0000)
committerfeld <feld@feld.me>
Thu, 25 Jun 2020 21:35:39 +0000 (21:35 +0000)
Preload data into index.html

Closes #1660

See merge request pleroma/pleroma!2381

20 files changed:
config/config.exs
lib/pleroma/web/fallback_redirect_controller.ex
lib/pleroma/web/nodeinfo/nodeinfo.ex [new file with mode: 0644]
lib/pleroma/web/nodeinfo/nodeinfo_controller.ex
lib/pleroma/web/preload.ex [new file with mode: 0644]
lib/pleroma/web/preload/instance.ex [new file with mode: 0644]
lib/pleroma/web/preload/provider.ex [new file with mode: 0644]
lib/pleroma/web/preload/status_net.ex [new file with mode: 0644]
lib/pleroma/web/preload/timelines.ex [new file with mode: 0644]
lib/pleroma/web/preload/user.ex [new file with mode: 0644]
lib/pleroma/web/router.ex
lib/pleroma/web/twitter_api/controllers/util_controller.ex
lib/pleroma/web/twitter_api/views/util_view.ex
test/plugs/instance_static_test.exs
test/web/fallback_test.exs
test/web/node_info_test.exs
test/web/preload/instance_test.exs [new file with mode: 0644]
test/web/preload/status_net_test.exs [new file with mode: 0644]
test/web/preload/timeline_test.exs [new file with mode: 0644]
test/web/preload/user_test.exs [new file with mode: 0644]

index 5aad26e95806411c600b02ae58ed4371c4e6521e..5b1c576e7a5edcf7aba348817ee7f6d38502beb4 100644 (file)
@@ -434,6 +434,14 @@ config :pleroma, Pleroma.Web.Metadata,
   ],
   unfurl_nsfw: false
 
+config :pleroma, Pleroma.Web.Preload,
+  providers: [
+    Pleroma.Web.Preload.Providers.Instance,
+    Pleroma.Web.Preload.Providers.User,
+    Pleroma.Web.Preload.Providers.Timelines,
+    Pleroma.Web.Preload.Providers.StatusNet
+  ]
+
 config :pleroma, :http_security,
   enabled: true,
   sts: false,
index 0d9d578fcc2895f9e0690e8f4a28abeef98e4e01..431ad5485b2371fbf267692ab12dd54c90fc7198 100644 (file)
@@ -9,6 +9,7 @@ defmodule Fallback.RedirectController do
 
   alias Pleroma.User
   alias Pleroma.Web.Metadata
+  alias Pleroma.Web.Preload
 
   def api_not_implemented(conn, _params) do
     conn
@@ -16,16 +17,7 @@ defmodule Fallback.RedirectController do
     |> json(%{error: "Not implemented"})
   end
 
-  def redirector(conn, _params, code \\ 200)
-
-  # 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
+  def redirector(conn, _params, code \\ 200) do
     conn
     |> put_resp_content_type("text/html")
     |> send_file(code, index_file_path())
@@ -43,28 +35,33 @@ defmodule Fallback.RedirectController do
   def redirector_with_meta(conn, params) do
     {:ok, index_content} = File.read(index_file_path())
 
-    tags =
-      try do
-        Metadata.build_tags(params)
-      rescue
-        e ->
-          Logger.error(
-            "Metadata rendering for #{conn.request_path} failed.\n" <>
-              Exception.format(:error, e, __STACKTRACE__)
-          )
-
-          ""
-      end
+    tags = build_tags(conn, params)
+    preloads = preload_data(conn, params)
 
-    response = String.replace(index_content, "<!--server-generated-meta-->", tags)
+    response =
+      index_content
+      |> String.replace("<!--server-generated-meta-->", tags <> preloads)
 
     conn
     |> put_resp_content_type("text/html")
     |> send_resp(200, response)
   end
 
-  def index_file_path do
-    Pleroma.Plugs.InstanceStatic.file_path("index.html")
+  def redirector_with_preload(conn, %{"path" => ["pleroma", "admin"]}) do
+    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-meta-->", preloads)
+
+    conn
+    |> put_resp_content_type("text/html")
+    |> send_resp(200, response)
   end
 
   def registration_page(conn, params) do
@@ -76,4 +73,36 @@ defmodule Fallback.RedirectController do
     |> put_status(204)
     |> text("")
   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
diff --git a/lib/pleroma/web/nodeinfo/nodeinfo.ex b/lib/pleroma/web/nodeinfo/nodeinfo.ex
new file mode 100644 (file)
index 0000000..d26b7c9
--- /dev/null
@@ -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
index 721b599d4b0df32a3d318e6e6cc68dcc28efc47b..8c7a9e56510d1f8ba80f7456963d7f971fe27682 100644 (file)
@@ -5,12 +5,8 @@
 defmodule Pleroma.Web.Nodeinfo.NodeinfoController do
   use Pleroma.Web, :controller
 
-  alias Pleroma.Config
-  alias Pleroma.Stats
-  alias Pleroma.User
   alias Pleroma.Web
-  alias Pleroma.Web.Federator.Publisher
-  alias Pleroma.Web.MastodonAPI.InstanceView
+  alias Pleroma.Web.Nodeinfo.Nodeinfo
 
   def schemas(conn, _params) do
     response = %{
@@ -29,102 +25,20 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do
     json(conn, response)
   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
   # and https://github.com/jhass/nodeinfo/blob/master/schemas/2.1/schema.json
-  def nodeinfo(conn, %{"version" => "2.0"}) do
-    conn
-    |> put_resp_header(
-      "content-type",
-      "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
-    raw_response = raw_nodeinfo()
-
-    updated_software =
-      raw_response
-      |> Map.get(:software)
-      |> Map.put(:repository, Pleroma.Application.repository())
-
-    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")
+  def nodeinfo(conn, %{"version" => version}) do
+    case Nodeinfo.get_nodeinfo(version) do
+      {:error, :missing} ->
+        render_error(conn, :not_found, "Nodeinfo schema version not handled")
+
+      node_info ->
+        conn
+        |> put_resp_header(
+          "content-type",
+          "application/json; profile=http://nodeinfo.diaspora.software/ns/schema/2.0#; charset=utf-8"
+        )
+        |> json(node_info)
+    end
   end
 end
diff --git a/lib/pleroma/web/preload.ex b/lib/pleroma/web/preload.ex
new file mode 100644 (file)
index 0000000..90e4544
--- /dev/null
@@ -0,0 +1,36 @@
+# 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 ->
+        terms =
+          params
+          |> parser.generate_terms()
+          |> Enum.map(fn {k, v} -> {k, Base.encode64(Jason.encode!(v))} end)
+          |> Enum.into(%{})
+
+        Map.merge(acc, terms)
+      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
diff --git a/lib/pleroma/web/preload/instance.ex b/lib/pleroma/web/preload/instance.ex
new file mode 100644 (file)
index 0000000..0b6fd33
--- /dev/null
@@ -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
diff --git a/lib/pleroma/web/preload/provider.ex b/lib/pleroma/web/preload/provider.ex
new file mode 100644 (file)
index 0000000..7ef595a
--- /dev/null
@@ -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
diff --git a/lib/pleroma/web/preload/status_net.ex b/lib/pleroma/web/preload/status_net.ex
new file mode 100644 (file)
index 0000000..367442d
--- /dev/null
@@ -0,0 +1,24 @@
+# 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.StatusNet do
+  alias Pleroma.Web.Preload.Providers.Provider
+  alias Pleroma.Web.TwitterAPI.UtilView
+
+  @behaviour Provider
+  @config_url :"/api/statusnet/config.json"
+
+  @impl Provider
+  def generate_terms(_params) do
+    %{}
+    |> build_config_tag()
+  end
+
+  defp build_config_tag(acc) do
+    instance = Pleroma.Config.get(:instance)
+    info_data = UtilView.status_net_config(instance)
+
+    Map.put(acc, @config_url, info_data)
+  end
+end
diff --git a/lib/pleroma/web/preload/timelines.ex b/lib/pleroma/web/preload/timelines.ex
new file mode 100644 (file)
index 0000000..e531b89
--- /dev/null
@@ -0,0 +1,39 @@
+# 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(%{}, params)
+  end
+
+  def build_public_tag(acc, params) do
+    if Pleroma.Config.get([:restrict_unauthenticated, :timelines, :federated], true) do
+      acc
+    else
+      Map.put(acc, @public_url, public_timeline(params))
+    end
+  end
+
+  defp public_timeline(%{"path" => ["main", "all"]}), do: get_public_timeline(false)
+
+  defp public_timeline(_params), do: get_public_timeline(true)
+
+  defp get_public_timeline(local_only) do
+    activities =
+      ActivityPub.fetch_public_activities(%{
+        type: ["Create"],
+        local_only: local_only
+      })
+
+    StatusView.render("index.json", activities: activities, for: nil, as: :activity)
+  end
+end
diff --git a/lib/pleroma/web/preload/user.ex b/lib/pleroma/web/preload/user.ex
new file mode 100644 (file)
index 0000000..3a24484
--- /dev/null
@@ -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
index 419aa55e4589d76882e5d65832c1e2d958eaf4b8..9e457848e5a574abf0193f06ac99525e5162e660 100644 (file)
@@ -726,7 +726,7 @@ defmodule Pleroma.Web.Router do
     get("/registration/:token", RedirectController, :registration_page)
     get("/:maybe_nickname_or_id", RedirectController, :redirector_with_meta)
     get("/api*path", RedirectController, :api_not_implemented)
-    get("/*path", RedirectController, :redirector)
+    get("/*path", RedirectController, :redirector_with_preload)
 
     options("/*path", RedirectController, :empty)
   end
index fd2aee17569c241ca4d715349f27e0a65a8ad40c..aaca182ecc1ac5c194abfdb4e86a501585cddc5a 100644 (file)
@@ -15,6 +15,7 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
   alias Pleroma.User
   alias Pleroma.Web
   alias Pleroma.Web.CommonAPI
+  alias Pleroma.Web.TwitterAPI.UtilView
   alias Pleroma.Web.WebFinger
 
   plug(Pleroma.Web.FederatingPlug when action == :remote_subscribe)
@@ -90,17 +91,7 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
 
   def config(%{assigns: %{format: "xml"}} = conn, _params) do
     instance = Pleroma.Config.get(:instance)
-
-    response = """
-    <config>
-    <site>
-    <name>#{Keyword.get(instance, :name)}</name>
-    <site>#{Web.base_url()}</site>
-    <textlimit>#{Keyword.get(instance, :limit)}</textlimit>
-    <closed>#{!Keyword.get(instance, :registrations_open)}</closed>
-    </site>
-    </config>
-    """
+    response = UtilView.status_net_config(instance)
 
     conn
     |> put_resp_content_type("application/xml")
index 52054e020dbeda1a4ef53df39e366e74a879b58f..d3bdb4f6230662f7cf62e57672dc352729ebc145 100644 (file)
@@ -5,4 +5,18 @@
 defmodule Pleroma.Web.TwitterAPI.UtilView do
   use Pleroma.Web, :view
   import Phoenix.HTML.Form
+  alias Pleroma.Web
+
+  def status_net_config(instance) do
+    """
+    <config>
+    <site>
+    <name>#{Keyword.get(instance, :name)}</name>
+    <site>#{Web.base_url()}</site>
+    <textlimit>#{Keyword.get(instance, :limit)}</textlimit>
+    <closed>#{!Keyword.get(instance, :registrations_open)}</closed>
+    </site>
+    </config>
+    """
+  end
 end
index b8f070d6ad6f7b7742b15ab27b2df56db54abc51..be2613ad098ce0907345679811639017a7a91b30 100644 (file)
@@ -16,7 +16,7 @@ defmodule Pleroma.Web.RuntimeStaticPlugTest do
 
   test "overrides index" do
     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")
 
index 3919ef93a35db61b212e48d423e5e62fbbedc1f6..a658658603fcb0efce803a0bf52b92f5a5285d31 100644 (file)
@@ -6,22 +6,56 @@ defmodule Pleroma.Web.FallbackTest do
   use Pleroma.Web.ConnCase
   import Pleroma.Factory
 
-  test "GET /registration/:token", %{conn: conn} do
-    assert conn
-           |> get("/registration/foo")
-           |> html_response(200) =~ "<!--server-generated-meta-->"
+  describe "neither preloaded data nor metadata attached to" do
+    test "GET /registration/:token", %{conn: conn} do
+      response = get(conn, "/registration/foo")
+
+      assert html_response(response, 200) =~ "<!--server-generated-meta-->"
+    end
+
+    test "GET /*path", %{conn: conn} do
+      assert conn
+             |> get("/foo")
+             |> html_response(200) =~ "<!--server-generated-meta-->"
+    end
   end
 
-  test "GET /:maybe_nickname_or_id", %{conn: conn} do
-    user = insert(:user)
+  describe "preloaded data and metadata attached to" do
+    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
-           |> get("/foo")
-           |> html_response(200) =~ "<!--server-generated-meta-->"
+      assert(html_response(user_missing, 200) =~ "<!--server-generated-meta-->")
+      refute html_response(user_present, 200) =~ "<!--server-generated-meta-->"
+      assert html_response(user_present, 200) =~ "initial-results"
+    end
 
-    refute conn
-           |> get("/" <> user.nickname)
-           |> html_response(200) =~ "<!--server-generated-meta-->"
+    test "GET /*path", %{conn: conn} do
+      assert conn
+             |> get("/foo")
+             |> html_response(200) =~ "<!--server-generated-meta-->"
+
+      refute conn
+             |> get("/foo/bar")
+             |> html_response(200) =~ "<!--server-generated-meta-->"
+    end
+  end
+
+  describe "preloaded data is attached to" do
+    test "GET /main/public", %{conn: conn} do
+      public_page = get(conn, "/main/public")
+
+      refute html_response(public_page, 200) =~ "<!--server-generated-meta-->"
+      assert html_response(public_page, 200) =~ "initial-results"
+    end
+
+    test "GET /main/all", %{conn: conn} do
+      public_page = get(conn, "/main/all")
+
+      refute html_response(public_page, 200) =~ "<!--server-generated-meta-->"
+      assert html_response(public_page, 200) =~ "initial-results"
+    end
   end
 
   test "GET /api*path", %{conn: conn} do
@@ -34,16 +68,6 @@ defmodule Pleroma.Web.FallbackTest do
     assert redirected_to(get(conn, "/pleroma/admin")) =~ "/pleroma/admin/"
   end
 
-  test "GET /*path", %{conn: conn} do
-    assert conn
-           |> get("/foo")
-           |> html_response(200) =~ "<!--server-generated-meta-->"
-
-    assert conn
-           |> get("/foo/bar")
-           |> html_response(200) =~ "<!--server-generated-meta-->"
-  end
-
   test "OPTIONS /*path", %{conn: conn} do
     assert conn
            |> options("/foo")
index 06b33607fb4ace57cfe545e8976e6285a6c2aa8b..8b3b6177daf92cbf3be4849ae4d859aba0a8e458 100644 (file)
@@ -142,8 +142,7 @@ defmodule Pleroma.Web.NodeInfoTest do
       "shareable_emoji_packs",
       "multifetch",
       "pleroma_emoji_reactions",
-      "pleroma:api/v1/notifications:include_types_filter",
-      "pleroma_chat_messages"
+      "pleroma:api/v1/notifications:include_types_filter"
     ]
 
     assert MapSet.subset?(
diff --git a/test/web/preload/instance_test.exs b/test/web/preload/instance_test.exs
new file mode 100644 (file)
index 0000000..42a0d87
--- /dev/null
@@ -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, "Pleroma: An efficient and flexible 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
diff --git a/test/web/preload/status_net_test.exs b/test/web/preload/status_net_test.exs
new file mode 100644 (file)
index 0000000..ab6823a
--- /dev/null
@@ -0,0 +1,14 @@
+# 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.StatusNetTest do
+  use Pleroma.DataCase
+  alias Pleroma.Web.Preload.Providers.StatusNet
+
+  setup do: {:ok, StatusNet.generate_terms(nil)}
+
+  test "it renders the info", %{"/api/statusnet/config.json": info} do
+    assert info =~ "<name>Pleroma</name>"
+  end
+end
diff --git a/test/web/preload/timeline_test.exs b/test/web/preload/timeline_test.exs
new file mode 100644 (file)
index 0000000..da6a3ad
--- /dev/null
@@ -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
diff --git a/test/web/preload/user_test.exs b/test/web/preload/user_test.exs
new file mode 100644 (file)
index 0000000..99232cd
--- /dev/null
@@ -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