summaryrefslogtreecommitdiff
path: root/lib/pleroma/web/controller/frontend_controller.ex
blob: 2e9082db1260de8d957bad48de1c62c12d4b9e41 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
defmodule Pleroma.Web.FrontendController do
  use Pleroma.Web, :controller

  defmacro __using__(_opts) do
    quote do
      require Logger
      alias Pleroma.User

      def fallback(conn, _params) do
        conn
        |> put_status(404)
        |> text("Not found")
      end

      def registration_page(conn, params) do
        index(conn, params)
      end

      def api_not_implemented(conn, _params) do
        conn
        |> put_status(404)
        |> json(%{error: "Not implemented"})
      end

      def empty(conn, _params) do
        conn
        |> put_status(204)
        |> text("")
      end

      def index(conn, _params) do
        {:ok, path} = Pleroma.Frontend.file_path("index.html")

        conn
        |> put_resp_content_type("text/html")
        |> send_file(conn.status || 200, path)
      end

      def index_with_preload(conn, %{"path" => ["pleroma", "admin"]}) do
        redirect(conn, to: "/pleroma/admin/")
      end

      def index_with_preload(conn, params) do
        index_with_generated_data(conn, params, [:preload])
      end

      def index_with_meta(conn, %{"maybe_nickname_or_id" => maybe_nickname_or_id} = params) do
        with %User{} = user <- User.get_cached_by_nickname_or_id(maybe_nickname_or_id) do
          index_with_meta(conn, %{user: user})
        else
          nil ->
            index(conn, params)
        end
      end

      def index_with_meta(conn, params) do
        index_with_generated_data(conn, params, [:metadata, :preload])
      end

      defp index_with_generated_data(conn, params, generators) do
        {:ok, path} = Pleroma.Frontend.file_path("index.html")
        {:ok, index_content} = File.read(path)

        generated =
          Enum.reduce(generators, "", fn generator, acc ->
            acc <> generate_data(conn, params, generator)
          end)

        response = String.replace(index_content, "<!--server-generated-meta-->", generated)

        html(conn, response)
      end

      defp generate_data(conn, params, :preload) do
        try do
          Pleroma.Web.Preload.build_tags(conn, params)
        rescue
          e ->
            Logger.error(
              "Preloading for #{conn.request_path} failed.\n" <>
                Exception.format(:error, e, __STACKTRACE__)
            )

            ""
        end
      end

      defp generate_data(conn, params, :metadata) do
        try do
          Pleroma.Web.Metadata.build_tags(params)
        rescue
          e ->
            Logger.error(
              "Metadata rendering for #{conn.request_path} failed.\n" <>
                Exception.format(:error, e, __STACKTRACE__)
            )

            ""
        end
      end

      defoverridable api_not_implemented: 2,
                     empty: 2,
                     fallback: 2,
                     index: 2,
                     index_with_preload: 2,
                     index_with_meta: 2,
                     registration_page: 2
    end
  end

  defp action(conn, _opts) do
    fe_config = conn.private[:frontend] || Pleroma.Frontend.get_config(:primary)

    action_name = action_name(conn)

    {controller, action} =
      cond do
        function_exported?(fe_config["controller"], action_name, 2) ->
          {fe_config["controller"], action_name}

        true ->
          {fe_config["controller"], :fallback}
      end

    conn
    |> put_private(:frontend, fe_config)
    |> put_view(Phoenix.Controller.__view__(controller))
    |> controller.call(controller.init(action))
  end
end