mirror of
https://github.com/apache/superset.git
synced 2026-04-19 08:04:53 +00:00
[SIP-29] Add support for row-level security (#8699)
* Support and apply filters. * Added the UI for row level security, and moved it all under SQLA in order to access the Table model more easily. * Added a row level security filter documentation entry. * Accidentally added two new lines to this file. * Blacked and iSorted, hopefully. Also, sometimes g.user may not be set. * Another isort, and handling g not having a user attribute another way. * Let's try this again #CI tests. * Adjusted import order for isort; I was sure I'd already done this.. * Row level filters should be wrapped in parentheses in case one contains an OR. * Oops, did not think that would change Black's formatting. * Changes as per @mistercrunch. * RLS filters are now many-to-many with Roles. * Updated documentation to reflect RLS filters supporting multiple rows. * Let's see what happens when I set it to the previous revision ID * Updated from upstream. * There was a pylint error. * Added RLS ids to the cache keys; modified documentation; added template processing to RLS filters. * A new migration was merged in. * Removed RLS cache key from query_object. * RLS added to the cache_key from query_context. * Changes as per @etr2460. * Updating entry for RLS pull request. * Another migration to skip. * Changes as per @serenajiang. * Blacked. * Blacked and added some attributes to check for. * Changed to a manual query as per @mistercrunch. * Blacked. * Another migration in the meantime. * Black wanted some whitespace changes. * AttributeError: 'AnonymousUserMixin' object has no attribute 'id'. * Oops, did hasattr backwards. * Changes as per @mistercrunch. * Doesn't look like text us required here anymore. * Changes as per @dpgaspar * Two RLS tests. * Row level security is now disabled by default via the feature flag ENABLE_ROW_LEVEL_SECURITY. * New head to revise. * Changed the comment.
This commit is contained in:
@@ -20,11 +20,12 @@ import unittest
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
import prison
|
||||
from flask import g
|
||||
|
||||
import tests.test_app
|
||||
from superset import app, appbuilder, db, security_manager, viz
|
||||
from superset.connectors.druid.models import DruidCluster, DruidDatasource
|
||||
from superset.connectors.sqla.models import SqlaTable
|
||||
from superset.connectors.sqla.models import RowLevelSecurityFilter, SqlaTable
|
||||
from superset.exceptions import SupersetSecurityException
|
||||
from superset.models.core import Database
|
||||
from superset.models.slice import Slice
|
||||
@@ -815,3 +816,71 @@ class SecurityManagerTests(SupersetTestCase):
|
||||
|
||||
with self.assertRaises(SupersetSecurityException):
|
||||
security_manager.assert_viz_permission(test_viz)
|
||||
|
||||
|
||||
class RowLevelSecurityTests(SupersetTestCase):
|
||||
"""
|
||||
Testing Row Level Security
|
||||
"""
|
||||
|
||||
rls_entry = None
|
||||
|
||||
def setUp(self):
|
||||
session = db.session
|
||||
|
||||
# Create the RowLevelSecurityFilter
|
||||
self.rls_entry = RowLevelSecurityFilter()
|
||||
self.rls_entry.table = (
|
||||
session.query(SqlaTable).filter_by(table_name="birth_names").first()
|
||||
)
|
||||
self.rls_entry.clause = "gender = 'male'"
|
||||
self.rls_entry.roles.append(
|
||||
security_manager.find_role("Gamma")
|
||||
) # db.session.query(Role).filter_by(name="Gamma").first())
|
||||
db.session.add(self.rls_entry)
|
||||
|
||||
db.session.commit()
|
||||
|
||||
def tearDown(self):
|
||||
session = db.session
|
||||
session.delete(self.rls_entry)
|
||||
session.commit()
|
||||
|
||||
# Do another test to make sure it doesn't alter another query
|
||||
def test_rls_filter_alters_query(self):
|
||||
g.user = self.get_user(
|
||||
username="gamma"
|
||||
) # self.login() doesn't actually set the user
|
||||
tbl = self.get_table_by_name("birth_names")
|
||||
query_obj = dict(
|
||||
groupby=[],
|
||||
metrics=[],
|
||||
filter=[],
|
||||
is_timeseries=False,
|
||||
columns=["name"],
|
||||
granularity=None,
|
||||
from_dttm=None,
|
||||
to_dttm=None,
|
||||
extras={},
|
||||
)
|
||||
sql = tbl.get_query_str(query_obj)
|
||||
self.assertIn("gender = 'male'", sql)
|
||||
|
||||
def test_rls_filter_doesnt_alter_query(self):
|
||||
g.user = self.get_user(
|
||||
username="admin"
|
||||
) # self.login() doesn't actually set the user
|
||||
tbl = self.get_table_by_name("birth_names")
|
||||
query_obj = dict(
|
||||
groupby=[],
|
||||
metrics=[],
|
||||
filter=[],
|
||||
is_timeseries=False,
|
||||
columns=["name"],
|
||||
granularity=None,
|
||||
from_dttm=None,
|
||||
to_dttm=None,
|
||||
extras={},
|
||||
)
|
||||
sql = tbl.get_query_str(query_obj)
|
||||
self.assertNotIn("gender = 'male'", sql)
|
||||
|
||||
Reference in New Issue
Block a user