summaryrefslogtreecommitdiff
path: root/lib/web/context_plug.ex
blob: aca04311fd2294bad054406511762f594152bbc7 (plain) (blame)
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
defmodule NolaWeb.ContextPlug do
  import Plug.Conn
  import Phoenix.Controller

  def init(opts \\ []) do
    opts || []
  end

  def get_account(conn) do
    cond do
      get_session(conn, :account) ->
        get_session(conn, :account)

      get_session(conn, :oidc_id) ->
        if account = Nola.Account.find_meta_account("identity-id", get_session(conn, :oidc_id)),
          do: account.id

      true ->
        nil
    end
  end

  def call(conn, opts) do
    account =
      with {:account, account_id} when is_binary(account_id) <- {:account, get_account(conn)},
           {:account, account} when not is_nil(account) <-
             {:account, Nola.Account.get(account_id)} do
        account
      else
        _ -> nil
      end

    network = Map.get(conn.params, "network")
    network = if network == "-", do: nil, else: network

    oidc_account = Nola.Account.find_meta_account("identity-id", get_session(conn, :oidc_id))

    conns = Nola.Irc.Connection.get_network(network)

    chan =
      if c = Map.get(conn.params, "chan") do
        NolaWeb.reformat_chan(c)
      end

    chan_conn = Nola.Irc.Connection.get_network(network, chan)

    memberships =
      if account do
        Nola.Membership.of_account(account)
      end

    auth_required =
      cond do
        Keyword.get(opts, :restrict) == :public ->
          false

        account == nil ->
          true

        network == nil ->
          false

        Keyword.get(opts, :restrict) == :logged_in ->
          false

        network && chan ->
          !Enum.member?(memberships, {network, chan})

        network ->
          !Enum.any?(memberships, fn {n, _} -> n == network end)
      end

    bot =
      cond do
        network && chan && chan_conn -> chan_conn.nick
        network && conns -> conns.nick
        true -> nil
      end

    cond do
      account && auth_required ->
        conn
        |> put_status(404)
        |> text("Page not found")
        |> halt()

      auth_required ->
        conn
        |> put_status(403)
        |> render(NolaWeb.AlcoologView, "auth.html", bot: bot, no_header: true, network: network)
        |> halt()

      network && !conns ->
        conn
        |> put_status(404)
        |> text("Page not found")
        |> halt()

      chan && !chan_conn ->
        conn
        |> put_status(404)
        |> text("Page not found")
        |> halt()

      true ->
        conn =
          conn
          |> assign(:network, network)
          |> assign(:chan, chan)
          |> assign(:bot, bot)
          |> assign(:account, account)
          |> assign(:oidc_account, oidc_account)
          |> assign(:memberships, memberships)
    end
  end
end