forked from explorerhq/sql-explorer
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Issue explorerhq#456: Use of Django connection name rather than alias…
… as lookup This commit changes connection behavior from storing the database connection name to using the database alias mapped by SQL Explorer instead. The reason for this change is two-fold: 1) Views take the connection name as input, allowing anyone who knows Django connection names to query those databases, even if SQL does not expose the connection directly. 2) `Query` stores the connection name, which means that if the Django connection name changes or a different connection should be used (for example, one with reduced permissions) the stored Query will either stop working or at least continue using the old connection This change modifies `ExplorerConnections` from being a dictionary that proxies the Django connection dictionary to a dictionary-like object that uses `EXPLORER_CONNECTIONS` to lookup and validate the requested connection alias. In addition all code that used to the `EXPLORER_CONNECTIONS` value now uses the key instead. For backwards compatibility, a migration will back-populate the alias into `Query` instances (and fail if the mapping no longer exists), `EXPLORER_DEFAULT_CONNECTION` is re-written on start-up to use the alias in case it still uses the Django Connection name and `ExplorerConnections` will still accept a Django Connection name as long as that name is exposed by some alias in `EXPLORER_CONNECTIONS`.
- Loading branch information
Showing
18 changed files
with
256 additions
and
95 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
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
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,24 +1,61 @@ | ||
import importlib | ||
import logging | ||
|
||
from django.db import connections as djcs | ||
|
||
from explorer.app_settings import EXPLORER_CONNECTIONS | ||
from explorer.utils import InvalidExplorerConnectionException | ||
|
||
|
||
# We export valid SQL connections here so that consuming code never has to | ||
# deal with django.db.connections directly, and risk accessing a connection | ||
# that hasn't been registered to Explorer. | ||
|
||
# Django insists that connections that are created in a thread are only accessed | ||
# by that thread, so here we create a dictionary-like collection of the valid | ||
# connections, but does a 'live' lookup of the connection on each item access. | ||
logger = logging.getLogger(__name__) | ||
|
||
|
||
_connections = {c: c for c in djcs if c in EXPLORER_CONNECTIONS.values()} | ||
class ExplorerConnections: | ||
|
||
|
||
class ExplorerConnections(dict): | ||
def get(self, item, default=None): | ||
try: | ||
return self[item] | ||
except InvalidExplorerConnectionException: | ||
return default | ||
|
||
def __getitem__(self, item): | ||
return djcs[item] | ||
|
||
|
||
connections = ExplorerConnections(_connections) | ||
conn = EXPLORER_CONNECTIONS.get(item) | ||
if not conn: | ||
if item in djcs: | ||
# Original connection handling did lookups by the django names not the explorer | ||
# alias. To support stored uses of URLs accessing connections by the old name | ||
# (such as schema), we support the django db connectin name as long as it is | ||
# mapped by some alias in EXPLORER_CONNECTIONS, so as to prevent access to | ||
# Django DB connections never meant to be exposed by Explorer | ||
if item not in EXPLORER_CONNECTIONS.values(): | ||
raise InvalidExplorerConnectionException( | ||
f"Attempted to access connection {item} which is " | ||
f"not a Django DB connection exposed by Explorer" | ||
) | ||
logger.info(f"using legacy lookup by django connection name for '{item}'") | ||
conn = item | ||
else: | ||
raise InvalidExplorerConnectionException( | ||
f'Attempted to access connection {item}, ' | ||
f'but that is not a registered Explorer connection.' | ||
) | ||
# Django insists that connections that are created in a thread are only accessed | ||
# by that thread, so we do a 'live' lookup of the connection on each item access. | ||
return djcs[conn] | ||
|
||
def __contains__(self, item): | ||
return item in EXPLORER_CONNECTIONS | ||
|
||
def __len__(self): | ||
return len(EXPLORER_CONNECTIONS) | ||
|
||
def keys(self): | ||
return EXPLORER_CONNECTIONS.keys() | ||
|
||
def values(self): | ||
return [self[v] for v in EXPLORER_CONNECTIONS.values()] | ||
|
||
def items(self): | ||
return [(k, self[v]) for k, v in EXPLORER_CONNECTIONS.items()] | ||
|
||
|
||
connections = ExplorerConnections() |
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.