@@ -6,6 +6,20 @@ defmodule EpochtalkServerWeb.Helpers.Validate do
66 """
77 alias EpochtalkServerWeb.CustomErrors.InvalidPayload
88
9+ @ doc """
10+ Ensure that `keys` provided in list are mutually exclusive within `attrs` map.
11+ """
12+ @ spec mutually_exclusive! ( attrs :: map , keys :: [ String . t ( ) ] ) :: :ok | no_return
13+ def mutually_exclusive! ( attrs , keys ) when is_map ( attrs ) and is_list ( keys ) do
14+ if map_contains_any_two_keys_in_list? ( attrs , keys ) ,
15+ do:
16+ raise ( InvalidPayload ,
17+ message:
18+ "The following payload parameters cannot be passed at the same time: #{ Enum . join ( keys , ", " ) } "
19+ ) ,
20+ else: :ok
21+ end
22+
923 @ doc """
1024 Helper used to validate and cast request parameters directly out of the incoming
1125 paylod map (usually a controller function's `attrs` parameter) to the specified type.
@@ -121,6 +135,29 @@ defmodule EpochtalkServerWeb.Helpers.Validate do
121135 end
122136 end
123137
138+ # entrypoint
139+ defp map_contains_any_two_keys_in_list? ( map , list ) ,
140+ do: map_contains_any_two_keys_in_list? ( map , list , false )
141+
142+ # if map is empty, return false
143+ defp map_contains_any_two_keys_in_list? ( map , _list , _key_found? ) when map == % { } , do: false
144+ # if list is empty, return false
145+ defp map_contains_any_two_keys_in_list? ( _map , [ ] , _key_found? ) , do: false
146+ # if key_found? is false
147+ defp map_contains_any_two_keys_in_list? ( map , [ key | keys ] = _list , false = _key_found? ) do
148+ # check next key with updated key_found?
149+ map_contains_any_two_keys_in_list? ( map , keys , Map . has_key? ( map , key ) )
150+ end
151+
152+ # if key_found? is true
153+ defp map_contains_any_two_keys_in_list? ( map , [ key | keys ] = _list , true = key_found? ) do
154+ # if current key is in map, return true
155+ if Map . has_key? ( map , key ) ,
156+ do: true ,
157+ # otherwise, check next key
158+ else: map_contains_any_two_keys_in_list? ( map , keys , key_found? )
159+ end
160+
124161 defp to_bool ( str , opts ) do
125162 case str do
126163 "true" -> true
0 commit comments