-
-
Notifications
You must be signed in to change notification settings - Fork 315
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: Improve Authz performance by reducing queries required (#1239)
* Removes set_config for jwt token which is not used * Reduces read check to single query instead of 2 queries * Streamlines overall code to be leaner
- Loading branch information
1 parent
93fb070
commit 4eaa930
Showing
8 changed files
with
88 additions
and
579 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
70 changes: 0 additions & 70 deletions
70
lib/realtime/tenants/authorization/policies/broadcast_policies.ex
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,83 +1,13 @@ | ||
defmodule Realtime.Tenants.Authorization.Policies.BroadcastPolicies do | ||
@moduledoc """ | ||
BroadcastPolicies structure that holds the required authorization information for a given connection within the scope of a sending / receiving broadcasts messages | ||
Uses the Realtime.Api.Broadcast to try reads and writes on the database to determine authorization for a given connection. | ||
Implements Realtime.Tenants.Authorization behaviour | ||
""" | ||
require Logger | ||
import Ecto.Query | ||
import Realtime.Logs | ||
|
||
alias Realtime.Api.Message | ||
alias Realtime.Repo | ||
alias Realtime.Tenants.Authorization | ||
alias Realtime.Tenants.Authorization.Policies | ||
defstruct read: false, write: false | ||
|
||
@behaviour Realtime.Tenants.Authorization.Policies | ||
|
||
@type t :: %__MODULE__{ | ||
read: boolean(), | ||
write: boolean() | ||
} | ||
@impl true | ||
def check_read_policies(_conn, _, policies, %Authorization{topic: nil}) do | ||
{:ok, Policies.update_policies(policies, :broadcast, :read, false)} | ||
end | ||
|
||
def check_read_policies(conn, %{broadcast_id: id}, %Policies{} = policies, %Authorization{ | ||
topic: topic | ||
}) do | ||
query = | ||
from(m in Message, | ||
where: m.topic == ^topic, | ||
where: m.extension == :broadcast, | ||
where: m.id == ^id | ||
) | ||
|
||
case Repo.all(conn, query, Message, mode: :savepoint) do | ||
{:ok, []} -> | ||
{:ok, Policies.update_policies(policies, :broadcast, :read, false)} | ||
|
||
{:ok, [%Message{}]} -> | ||
{:ok, Policies.update_policies(policies, :broadcast, :read, true)} | ||
|
||
{:error, %Postgrex.Error{postgres: %{code: :insufficient_privilege}}} -> | ||
{:ok, Policies.update_policies(policies, :broadcast, :read, false)} | ||
|
||
{:error, error} -> | ||
log_error( | ||
"UnableToSetPolicies", | ||
"Error getting policies for connection: #{to_log(error)}" | ||
) | ||
|
||
Postgrex.rollback(conn, error) | ||
end | ||
end | ||
|
||
@impl true | ||
def check_write_policies(_conn, policies, %Authorization{topic: nil}) do | ||
{:ok, Policies.update_policies(policies, :broadcast, :write, false)} | ||
end | ||
|
||
def check_write_policies(conn, policies, %Authorization{topic: topic}) do | ||
changeset = | ||
Message.changeset(%Message{}, %{topic: topic, extension: :broadcast}) | ||
|
||
case Repo.insert(conn, changeset, Message, mode: :savepoint) do | ||
{:ok, %Message{}} -> | ||
{:ok, Policies.update_policies(policies, :broadcast, :write, true)} | ||
|
||
{:error, %Postgrex.Error{postgres: %{code: :insufficient_privilege}}} -> | ||
{:ok, Policies.update_policies(policies, :broadcast, :write, false)} | ||
|
||
{:error, error} -> | ||
log_error( | ||
"UnableToSetPolicies", | ||
"Error getting policies for connection: #{to_log(error)}" | ||
) | ||
end | ||
end | ||
end |
72 changes: 0 additions & 72 deletions
72
lib/realtime/tenants/authorization/policies/presence_policies.ex
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,85 +1,13 @@ | ||
defmodule Realtime.Tenants.Authorization.Policies.PresencePolicies do | ||
@moduledoc """ | ||
PresencePolicies structure that holds the required authorization information for a given connection within the scope of a tracking / receiving presence messages | ||
Uses the Realtime.Api.Presence to try reads and writes on the database to determine authorization for a given connection. | ||
Implements Realtime.Tenants.Authorization behaviour | ||
""" | ||
require Logger | ||
import Ecto.Query | ||
import Realtime.Logs | ||
|
||
alias Realtime.Api.Message | ||
alias Realtime.Repo | ||
alias Realtime.Tenants.Authorization | ||
alias Realtime.Tenants.Authorization.Policies | ||
|
||
defstruct read: false, write: false | ||
|
||
@behaviour Realtime.Tenants.Authorization.Policies | ||
|
||
@type t :: %__MODULE__{ | ||
read: boolean(), | ||
write: boolean() | ||
} | ||
@impl true | ||
def check_read_policies(_conn, _, policies, %Authorization{topic: nil}) do | ||
{:ok, Policies.update_policies(policies, :presence, :read, false)} | ||
end | ||
|
||
def check_read_policies(conn, %{presence_id: id}, %Policies{} = policies, %Authorization{ | ||
topic: topic | ||
}) do | ||
query = | ||
from(m in Message, | ||
where: m.topic == ^topic, | ||
where: m.extension == :presence, | ||
where: m.id == ^id | ||
) | ||
|
||
case Repo.all(conn, query, Message, mode: :savepoint) do | ||
{:ok, []} -> | ||
{:ok, Policies.update_policies(policies, :presence, :read, false)} | ||
|
||
{:ok, [%Message{}]} -> | ||
{:ok, Policies.update_policies(policies, :presence, :read, true)} | ||
|
||
{:error, %Postgrex.Error{postgres: %{code: :insufficient_privilege}}} -> | ||
{:ok, Policies.update_policies(policies, :presence, :read, false)} | ||
|
||
{:error, error} -> | ||
log_error( | ||
"UnableToSetPolicies", | ||
"Error getting policies for connection: #{to_log(error)}" | ||
) | ||
|
||
Postgrex.rollback(conn, error) | ||
end | ||
end | ||
|
||
@impl true | ||
def check_write_policies(_conn, policies, %Authorization{topic: nil}) do | ||
{:ok, Policies.update_policies(policies, :presence, :write, false)} | ||
end | ||
|
||
def check_write_policies(conn, policies, %Authorization{topic: topic}) do | ||
changeset = Message.changeset(%Message{}, %{topic: topic, extension: :presence}) | ||
|
||
case Repo.insert(conn, changeset, Message, mode: :savepoint) do | ||
{:ok, %Message{}} -> | ||
{:ok, Policies.update_policies(policies, :presence, :write, true)} | ||
|
||
{:error, %Postgrex.Error{postgres: %{code: :insufficient_privilege}}} -> | ||
{:ok, Policies.update_policies(policies, :presence, :write, false)} | ||
|
||
{:error, error} -> | ||
log_error( | ||
"UnableToSetPolicies", | ||
"Error getting policies for connection: #{to_log(error)}" | ||
) | ||
|
||
Postgrex.rollback(conn, error) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.