File size: 4,202 Bytes
8da2481
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
defmodule PlausibleWeb.Api.Internal.SegmentsController do
  @moduledoc """
  Internal API controller for segments.
  """
  use Plausible
  use PlausibleWeb, :controller
  use PlausibleWeb.Plugs.ErrorHandler
  alias PlausibleWeb.Api.Helpers, as: H
  alias Plausible.ChangesetHelpers
  alias Plausible.Segments

  def create(
        %Plug.Conn{
          assigns: %{
            site: site,
            current_user: %{id: user_id},
            site_role: site_role
          }
        } = conn,
        %{} = params
      ) do
    case Segments.insert_one(user_id, site, site_role, params) do
      {:error, :not_enough_permissions} ->
        H.not_enough_permissions(conn, "Not enough permissions to create segment")

      {:error, :segment_limit_reached} ->
        H.not_enough_permissions(conn, "Segment limit reached")

      {:error, {:invalid_segment, errors}} when is_list(errors) ->
        conn
        |> put_status(400)
        |> json(%{
          error: ChangesetHelpers.serialize_first_error(errors)
        })

      {:ok, segment} ->
        json(conn, Segments.to_response_map(segment, site))
    end
  end

  def create(%Plug.Conn{} = conn, _params), do: invalid_request(conn)

  def update(
        %Plug.Conn{
          assigns: %{
            site: site,
            current_user: %{id: user_id},
            site_role: site_role
          }
        } =
          conn,
        %{} = params
      ) do
    segment_id = normalize_segment_id_param(params["segment_id"])

    case Segments.update_one(user_id, site, site_role, segment_id, params) do
      {:error, :not_enough_permissions} ->
        H.not_enough_permissions(conn, "Not enough permissions to edit segment")

      {:error, :segment_not_found} ->
        segment_not_found(conn, params["segment_id"])

      {:error, {:invalid_segment, errors}} when is_list(errors) ->
        conn
        |> put_status(400)
        |> json(%{
          error: ChangesetHelpers.serialize_first_error(errors)
        })

      {:ok, segment} ->
        json(conn, Segments.to_response_map(segment, site))
    end
  end

  def update(%Plug.Conn{} = conn, _params), do: invalid_request(conn)

  def delete(
        %Plug.Conn{
          assigns: %{
            site: site,
            current_user: %{id: user_id},
            site_role: site_role
          }
        } =
          conn,
        %{} = params
      ) do
    segment_id = normalize_segment_id_param(params["segment_id"])

    case Segments.delete_one(user_id, site, site_role, segment_id) do
      {:error, :not_enough_permissions} ->
        H.not_enough_permissions(conn, "Not enough permissions to delete segment")

      {:error, :segment_not_found} ->
        segment_not_found(conn, params["segment_id"])

      {:ok, segment} ->
        json(conn, Segments.to_response_map(segment, site))
    end
  end

  def delete(%Plug.Conn{} = conn, _params), do: invalid_request(conn)

  def get_related_shared_links(
        %Plug.Conn{
          assigns: %{
            site: site,
            current_user: %{id: _user_id},
            site_role: site_role
          }
        } =
          conn,
        %{} = params
      ) do
    segment_id = normalize_segment_id_param(params["segment_id"])

    case Segments.get_related_shared_links(site, site_role, segment_id) do
      {:error, :not_enough_permissions} ->
        H.not_enough_permissions(conn, "Not enough permissions to get related shared links")

      {:error, :segment_not_found} ->
        segment_not_found(conn, params["segment_id"])

      {:ok, shared_links} ->
        json(conn, shared_links |> Enum.map(& &1.name))
    end
  end

  def get_related_shared_links(%Plug.Conn{} = conn, _params), do: invalid_request(conn)

  @spec normalize_segment_id_param(any()) :: nil | pos_integer()
  defp normalize_segment_id_param(input) do
    case Integer.parse(input) do
      {int_value, ""} when int_value > 0 -> int_value
      _ -> nil
    end
  end

  defp segment_not_found(%Plug.Conn{} = conn, segment_id_param) do
    H.not_found(conn, "Segment not found with ID #{inspect(segment_id_param)}")
  end

  defp invalid_request(%Plug.Conn{} = conn) do
    H.bad_request(conn, "Invalid request")
  end
end