@@ -13,9 +13,11 @@ defmodule Realtime.Tenants.Authorization do
1313
1414 alias DBConnection.ConnectionError
1515 alias Realtime.Api.Message
16+ alias Realtime.Api.Tenant
1617 alias Realtime.Database
17- alias Realtime.Repo
18+ alias Realtime.GenCounter
1819 alias Realtime.GenRpc
20+ alias Realtime.Repo
1921 alias Realtime.Tenants.Authorization.Policies
2022
2123 defstruct [ :tenant_id , :topic , :headers , :jwt , :claims , :role , :sub ]
@@ -60,26 +62,42 @@ defmodule Realtime.Tenants.Authorization do
6062 @ spec get_read_authorizations ( Policies . t ( ) , pid ( ) , t ( ) ) ::
6163 { :ok , Policies . t ( ) } | { :error , any ( ) } | { :error , :rls_policy_error , any ( ) }
6264 def get_read_authorizations ( policies , db_conn , authorization_context ) when node ( ) == node ( db_conn ) do
63- case get_read_policies_for_connection ( db_conn , authorization_context , policies ) do
64- { :ok , % Policies { } = policies } -> { :ok , policies }
65- { :ok , { :error , % Postgrex.Error { } = error } } -> { :error , :rls_policy_error , error }
66- { :error , % ConnectionError { reason: :queue_timeout } } -> { :error , :increase_connection_pool }
67- { :error , error } -> { :error , error }
65+ rate_counter = rate_counter ( authorization_context . tenant_id )
66+
67+ if rate_counter . limit . triggered == false do
68+ db_conn
69+ |> get_read_policies_for_connection ( authorization_context , policies )
70+ |> handle_policies_result ( rate_counter )
71+ else
72+ { :error , :increase_connection_pool }
6873 end
6974 end
7075
7176 # Remote call
7277 def get_read_authorizations ( policies , db_conn , authorization_context ) do
73- case GenRpc . call (
74- node ( db_conn ) ,
75- __MODULE__ ,
76- :get_read_authorizations ,
77- [ policies , db_conn , authorization_context ] ,
78- tenant_id: authorization_context . tenant_id ,
79- key: authorization_context . tenant_id
80- ) do
81- { :error , :rpc_error , reason } -> { :error , reason }
82- response -> response
78+ rate_counter = rate_counter ( authorization_context . tenant_id )
79+
80+ if rate_counter . limit . triggered == false do
81+ case GenRpc . call (
82+ node ( db_conn ) ,
83+ __MODULE__ ,
84+ :get_read_authorizations ,
85+ [ policies , db_conn , authorization_context ] ,
86+ tenant_id: authorization_context . tenant_id ,
87+ key: authorization_context . tenant_id
88+ ) do
89+ { :error , :increase_connection_pool } = error ->
90+ GenCounter . add ( rate_counter . id )
91+ error
92+
93+ { :error , :rpc_error , reason } ->
94+ { :error , reason }
95+
96+ response ->
97+ response
98+ end
99+ else
100+ { :error , :increase_connection_pool }
83101 end
84102 end
85103
@@ -91,33 +109,70 @@ defmodule Realtime.Tenants.Authorization do
91109 @ spec get_write_authorizations ( Policies . t ( ) , pid ( ) , __MODULE__ . t ( ) ) ::
92110 { :ok , Policies . t ( ) } | { :error , any ( ) } | { :error , :rls_policy_error , any ( ) }
93111 def get_write_authorizations ( policies , db_conn , authorization_context ) when node ( ) == node ( db_conn ) do
94- case get_write_policies_for_connection ( db_conn , authorization_context , policies ) do
95- { :ok , % Policies { } = policies } -> { :ok , policies }
96- { :ok , { :error , % Postgrex.Error { } = error } } -> { :error , :rls_policy_error , error }
97- { :error , % ConnectionError { reason: :queue_timeout } } -> { :error , :increase_connection_pool }
98- { :error , error } -> { :error , error }
112+ rate_counter = rate_counter ( authorization_context . tenant_id )
113+
114+ if rate_counter . limit . triggered == false do
115+ db_conn
116+ |> get_write_policies_for_connection ( authorization_context , policies )
117+ |> handle_policies_result ( rate_counter )
118+ else
119+ { :error , :increase_connection_pool }
99120 end
100121 end
101122
102123 # Remote call
103124 def get_write_authorizations ( policies , db_conn , authorization_context ) do
104- case GenRpc . call (
105- node ( db_conn ) ,
106- __MODULE__ ,
107- :get_write_authorizations ,
108- [ policies , db_conn , authorization_context ] ,
109- tenant_id: authorization_context . tenant_id ,
110- key: authorization_context . tenant_id
111- ) do
112- { :error , :rpc_error , reason } -> { :error , reason }
113- response -> response
125+ rate_counter = rate_counter ( authorization_context . tenant_id )
126+
127+ if rate_counter . limit . triggered == false do
128+ case GenRpc . call (
129+ node ( db_conn ) ,
130+ __MODULE__ ,
131+ :get_write_authorizations ,
132+ [ policies , db_conn , authorization_context ] ,
133+ tenant_id: authorization_context . tenant_id ,
134+ key: authorization_context . tenant_id
135+ ) do
136+ { :error , :increase_connection_pool } = error ->
137+ GenCounter . add ( rate_counter . id )
138+ error
139+
140+ { :error , :rpc_error , reason } ->
141+ { :error , reason }
142+
143+ response ->
144+ response
145+ end
146+ else
147+ { :error , :increase_connection_pool }
114148 end
115149 end
116150
117151 def get_write_authorizations ( db_conn , authorization_context ) do
118152 get_write_authorizations ( % Policies { } , db_conn , authorization_context )
119153 end
120154
155+ defp handle_policies_result ( result , rate_counter ) do
156+ case result do
157+ { :ok , % Policies { } = policies } ->
158+ { :ok , policies }
159+
160+ { :ok , { :error , % Postgrex.Error { } = error } } ->
161+ { :error , :rls_policy_error , error }
162+
163+ { :error , % ConnectionError { reason: :queue_timeout } } ->
164+ GenCounter . add ( rate_counter . id )
165+ { :error , :increase_connection_pool }
166+
167+ { :error , { :exit , _ } } ->
168+ GenCounter . add ( rate_counter . id )
169+ { :error , :increase_connection_pool }
170+
171+ { :error , error } ->
172+ { :error , error }
173+ end
174+ end
175+
121176 @ doc """
122177 Sets the current connection configuration with the following config values:
123178 * role: The role of the user
@@ -282,4 +337,11 @@ defmodule Realtime.Tenants.Authorization do
282337 e
283338 end
284339 end
340+
341+ defp rate_counter ( tenant_id ) do
342+ % Tenant { } = tenant = Realtime.Tenants.Cache . get_tenant_by_external_id ( tenant_id )
343+ rate_counter = Realtime.Tenants . authorization_errors_per_second_rate ( tenant )
344+ { :ok , rate_counter } = Realtime.RateCounter . get ( rate_counter )
345+ rate_counter
346+ end
285347end
0 commit comments