Permissions refactoring, optimizations and unit testing. (#1798)

* Refactor and speed up superset init

* Add unit tests.

* Test fixes.

* More test updates.

* Fix read only perms

* Address comments.
This commit is contained in:
Bogdan 2016-12-15 08:38:34 -05:00 committed by GitHub
parent 733ab8014b
commit 92aa1a6124
9 changed files with 327 additions and 175 deletions

View File

@ -52,7 +52,6 @@ from sqlalchemy_utils import EncryptedType
from werkzeug.datastructures import ImmutableMultiDict from werkzeug.datastructures import ImmutableMultiDict
import superset
from superset import app, db, db_engine_specs, get_session, utils, sm from superset import app, db, db_engine_specs, get_session, utils, sm
from superset.source_registry import SourceRegistry from superset.source_registry import SourceRegistry
from superset.viz import viz_types from superset.viz import viz_types
@ -70,24 +69,13 @@ FillterPattern = re.compile(r'''((?:[^,"']|"[^"]*"|'[^']*')+)''')
def set_perm(mapper, connection, target): # noqa def set_perm(mapper, connection, target): # noqa
target.perm = target.get_perm() if target.perm != target.get_perm():
link_table = target.__table__
connection.execute(
def init_metrics_perm(metrics=None): link_table.update()
"""Create permissions for restricted metrics .where(link_table.c.id == target.id)
.values(perm=target.get_perm())
:param metrics: a list of metrics to be processed, if not specified, )
all metrics are processed
:type metrics: models.SqlMetric or models.DruidMetric
"""
if not metrics:
metrics = []
for model in [SqlMetric, DruidMetric]:
metrics += list(db.session.query(model).all())
for metric in metrics:
if metric.is_restricted and metric.perm:
sm.add_permission_view_menu('metric_access', metric.perm)
class JavascriptPostAggregator(Postaggregator): class JavascriptPostAggregator(Postaggregator):
@ -860,8 +848,8 @@ class Database(Model, AuditMixinNullable):
return ( return (
"[{obj.database_name}].(id:{obj.id})").format(obj=self) "[{obj.database_name}].(id:{obj.id})").format(obj=self)
sqla.event.listen(Database, 'before_insert', set_perm) sqla.event.listen(Database, 'after_insert', set_perm)
sqla.event.listen(Database, 'before_update', set_perm) sqla.event.listen(Database, 'after_update', set_perm)
class SqlaTable(Model, Queryable, AuditMixinNullable, ImportMixin): class SqlaTable(Model, Queryable, AuditMixinNullable, ImportMixin):
@ -1340,8 +1328,8 @@ class SqlaTable(Model, Queryable, AuditMixinNullable, ImportMixin):
return datasource.id return datasource.id
sqla.event.listen(SqlaTable, 'before_insert', set_perm) sqla.event.listen(SqlaTable, 'after_insert', set_perm)
sqla.event.listen(SqlaTable, 'before_update', set_perm) sqla.event.listen(SqlaTable, 'after_update', set_perm)
class SqlMetric(Model, AuditMixinNullable, ImportMixin): class SqlMetric(Model, AuditMixinNullable, ImportMixin):
@ -2238,8 +2226,8 @@ class DruidDatasource(Model, AuditMixinNullable, Queryable):
filters = cond filters = cond
return filters return filters
sqla.event.listen(DruidDatasource, 'before_insert', set_perm) sqla.event.listen(DruidDatasource, 'after_insert', set_perm)
sqla.event.listen(DruidDatasource, 'before_update', set_perm) sqla.event.listen(DruidDatasource, 'after_update', set_perm)
class Log(Model): class Log(Model):
@ -2466,8 +2454,6 @@ class DruidColumn(Model, AuditMixinNullable):
session.add(metric) session.add(metric)
session.flush() session.flush()
init_metrics_perm(new_metrics)
class FavStar(Model): class FavStar(Model):
__tablename__ = 'favstar' __tablename__ = 'favstar'

View File

@ -3,11 +3,10 @@ from __future__ import division
from __future__ import print_function from __future__ import print_function
from __future__ import unicode_literals from __future__ import unicode_literals
from itertools import product
import logging import logging
from flask_appbuilder.security.sqla import models as ab_models from flask_appbuilder.security.sqla import models as ab_models
from superset import conf, db, models, sm from superset import conf, db, models, sm, source_registry
READ_ONLY_MODELVIEWS = { READ_ONLY_MODELVIEWS = {
@ -17,13 +16,10 @@ READ_ONLY_MODELVIEWS = {
} }
GAMMA_READ_ONLY_MODELVIEWS = { GAMMA_READ_ONLY_MODELVIEWS = {
'ColumnInlineView',
'SqlMetricInlineView', 'SqlMetricInlineView',
'TableColumnInlineView', 'TableColumnInlineView',
'TableModelView', 'TableModelView',
'DatasourceModelView',
'DruidColumnInlineView', 'DruidColumnInlineView',
'MetricInlineView',
'DruidDatasourceModelView', 'DruidDatasourceModelView',
'DruidMetricInlineView', 'DruidMetricInlineView',
} | READ_ONLY_MODELVIEWS } | READ_ONLY_MODELVIEWS
@ -38,13 +34,11 @@ ADMIN_ONLY_VIEW_MENUES = {
'RoleModelView', 'RoleModelView',
'Security', 'Security',
'UserDBModelView', 'UserDBModelView',
} | READ_ONLY_MODELVIEWS }
ADMIN_ONLY_PERMISSIONS = { ADMIN_ONLY_PERMISSIONS = {
'all_database_access', 'all_database_access',
'datasource_access', # TODO: move can_sql_json to sql_lab role
'schema_access',
'database_access',
'can_sql_json', 'can_sql_json',
'can_override_role_permissions', 'can_override_role_permissions',
'can_sync_druid_source', 'can_sync_druid_source',
@ -52,24 +46,16 @@ ADMIN_ONLY_PERMISSIONS = {
'can_approve', 'can_approve',
'can_update_role', 'can_update_role',
} }
READ_ONLY_PERMISSION = { READ_ONLY_PERMISSION = {
'can_show', 'can_show',
'can_list', 'can_list',
} }
ALPHA_ONLY_PERMISSIONS = set([ ALPHA_ONLY_PERMISSIONS = set([
'datasource_access',
'schema_access',
'database_access',
'muldelete', 'muldelete',
'all_datasource_access', 'all_datasource_access',
]) ])
READ_ONLY_PRODUCT = set(
product(READ_ONLY_PERMISSION, READ_ONLY_MODELVIEWS))
GAMMA_READ_ONLY_PRODUCT = set(
product(READ_ONLY_PERMISSION, GAMMA_READ_ONLY_MODELVIEWS))
OBJECT_SPEC_PERMISSIONS = set([ OBJECT_SPEC_PERMISSIONS = set([
'database_access', 'database_access',
@ -81,7 +67,7 @@ OBJECT_SPEC_PERMISSIONS = set([
def merge_perm(sm, permission_name, view_menu_name): def merge_perm(sm, permission_name, view_menu_name):
pv = sm.find_permission_view_menu(permission_name, view_menu_name) pv = sm.find_permission_view_menu(permission_name, view_menu_name)
if not pv: if not pv and permission_name and view_menu_name:
sm.add_permission_view_menu(permission_name, view_menu_name) sm.add_permission_view_menu(permission_name, view_menu_name)
@ -107,114 +93,125 @@ def get_or_create_main_db():
return dbobj return dbobj
def sync_role_definitions(): def is_admin_only(pvm):
"""Inits the Superset application with security roles and such""" # not readonly operations on read only model views allowed only for admins
logging.info("Syncing role definition") if (pvm.view_menu.name in READ_ONLY_MODELVIEWS and
pvm.permission.name not in READ_ONLY_PERMISSION):
return True
return (pvm.view_menu.name in ADMIN_ONLY_VIEW_MENUES or
pvm.permission.name in ADMIN_ONLY_PERMISSIONS)
# Creating default roles
alpha = sm.add_role("Alpha")
admin = sm.add_role("Admin")
gamma = sm.add_role("Gamma")
public = sm.add_role("Public")
sql_lab = sm.add_role("sql_lab")
granter = sm.add_role("granter")
get_or_create_main_db() def is_alpha_only(pvm):
if (pvm.view_menu.name in GAMMA_READ_ONLY_MODELVIEWS and
pvm.permission.name not in READ_ONLY_PERMISSION):
return True
return pvm.permission.name in ALPHA_ONLY_PERMISSIONS
def is_admin_pvm(pvm):
return not is_user_defined_permission(pvm)
def is_alpha_pvm(pvm):
return not (is_user_defined_permission(pvm) or is_admin_only(pvm))
def is_gamma_pvm(pvm):
return not (is_user_defined_permission(pvm) or is_admin_only(pvm) or
is_alpha_only(pvm))
def is_sql_lab_pvm(pvm):
return pvm.view_menu.name in {'SQL Lab'} or pvm.permission.name in {
'can_sql_json', 'can_csv', 'can_search_queries'}
def is_granter_pvm(pvm):
return pvm.permission.name in {'can_override_role_permissions',
'can_approve'}
def set_role(role_name, pvms, pvm_check):
logging.info("Syncing {} perms".format(role_name))
role = sm.add_role(role_name)
role_pvms = [p for p in pvms if pvm_check(p)]
role.permissions = role_pvms
def create_custom_permissions():
# Global perms # Global perms
merge_perm(sm, 'all_datasource_access', 'all_datasource_access') merge_perm(sm, 'all_datasource_access', 'all_datasource_access')
merge_perm(sm, 'all_database_access', 'all_database_access') merge_perm(sm, 'all_database_access', 'all_database_access')
perms = db.session.query(ab_models.PermissionView).all()
perms = [p for p in perms if p.permission and p.view_menu]
logging.info("Syncing admin perms") def create_missing_datasource_perms(view_menu_set):
for p in perms: logging.info("Creating missing datasource permissions.")
# admin has all_database_access and all_datasource_access datasources = source_registry.SourceRegistry.get_all_datasources(
if is_user_defined_permission(p): db.session)
sm.del_permission_role(admin, p)
else:
sm.add_permission_role(admin, p)
logging.info("Syncing alpha perms")
for p in perms:
# alpha has all_database_access and all_datasource_access
if is_user_defined_permission(p):
sm.del_permission_role(alpha, p)
elif (
(
p.view_menu.name not in ADMIN_ONLY_VIEW_MENUES and
p.permission.name not in ADMIN_ONLY_PERMISSIONS
) or
(p.permission.name, p.view_menu.name) in READ_ONLY_PRODUCT
):
sm.add_permission_role(alpha, p)
else:
sm.del_permission_role(alpha, p)
logging.info("Syncing gamma perms and public if specified")
PUBLIC_ROLE_LIKE_GAMMA = conf.get('PUBLIC_ROLE_LIKE_GAMMA', False)
for p in perms:
if (
(
p.view_menu.name not in ADMIN_ONLY_VIEW_MENUES and
p.view_menu.name not in GAMMA_READ_ONLY_MODELVIEWS and
p.permission.name not in ADMIN_ONLY_PERMISSIONS and
p.permission.name not in ALPHA_ONLY_PERMISSIONS
) or
(p.permission.name, p.view_menu.name) in
GAMMA_READ_ONLY_PRODUCT
):
sm.add_permission_role(gamma, p)
if PUBLIC_ROLE_LIKE_GAMMA:
sm.add_permission_role(public, p)
else:
sm.del_permission_role(gamma, p)
sm.del_permission_role(public, p)
logging.info("Syncing sql_lab perms")
for p in perms:
if (
p.view_menu.name in {'SQL Lab'} or
p.permission.name in {
'can_sql_json', 'can_csv', 'can_search_queries'}
):
sm.add_permission_role(sql_lab, p)
else:
sm.del_permission_role(sql_lab, p)
logging.info("Syncing granter perms")
for p in perms:
if (
p.permission.name in {
'can_override_role_permissions', 'can_aprove'}
):
sm.add_permission_role(granter, p)
else:
sm.del_permission_role(granter, p)
logging.info("Making sure all data source perms have been created")
session = db.session()
datasources = [
o for o in session.query(models.SqlaTable).all()]
datasources += [
o for o in session.query(models.DruidDatasource).all()]
for datasource in datasources: for datasource in datasources:
perm = datasource.get_perm() if datasource and datasource.perm not in view_menu_set:
merge_perm(sm, 'datasource_access', perm) merge_perm(sm, 'datasource_access', datasource.get_perm())
if datasource.schema: if datasource.schema_perm:
merge_perm(sm, 'schema_access', datasource.schema_perm) merge_perm(sm, 'schema_access', datasource.schema_perm)
if perm != datasource.perm:
datasource.perm = perm
logging.info("Making sure all database perms have been created")
databases = [o for o in session.query(models.Database).all()] def create_missing_database_perms(view_menu_set):
logging.info("Creating missing database permissions.")
databases = db.session.query(models.Database).all()
for database in databases: for database in databases:
perm = database.get_perm() if database and database.perm not in view_menu_set:
if perm != database.perm: merge_perm(sm, 'database_access', database.perm)
database.perm = perm
merge_perm(sm, 'database_access', perm)
session.commit()
logging.info("Making sure all metrics perms exist")
models.init_metrics_perm() def create_missing_metrics_perm(view_menu_set):
"""Create permissions for restricted metrics
:param metrics: a list of metrics to be processed, if not specified,
all metrics are processed
:type metrics: models.SqlMetric or models.DruidMetric
"""
logging.info("Creating missing metrics permissions")
metrics = []
for model in [models.SqlMetric, models.DruidMetric]:
metrics += list(db.session.query(model).all())
for metric in metrics:
if (metric.is_restricted and metric.perm and
metric.perm not in view_menu_set):
merge_perm('metric_access', metric.perm)
def sync_role_definitions():
"""Inits the Superset application with security roles and such"""
logging.info("Syncing role definition")
get_or_create_main_db()
create_custom_permissions()
pvms = db.session.query(ab_models.PermissionView).all()
pvms = [p for p in pvms if p.permission and p.view_menu]
# cleanup
pvms_to_delete = [p for p in pvms if not (p.permission and p.view_menu)]
for pvm_to_delete in pvms_to_delete:
sm.get_session.delete(pvm_to_delete)
# Creating default roles
set_role('Admin', pvms, is_admin_pvm)
set_role('Alpha', pvms, is_alpha_pvm)
set_role('Gamma', pvms, is_gamma_pvm)
set_role('granter', pvms, is_granter_pvm)
set_role('sql_lab', pvms, is_sql_lab_pvm)
if conf.get('PUBLIC_ROLE_LIKE_GAMMA', False):
set_role('Public', pvms, is_gamma_pvm)
view_menu_set = db.session.query(models.SqlaTable).all()
create_missing_datasource_perms(view_menu_set)
create_missing_database_perms(view_menu_set)
create_missing_metrics_perm(view_menu_set)
# commit role and view menu updates
sm.get_session.commit()

View File

@ -333,7 +333,6 @@ def get_datasource_full_name(database_name, datasource_name, schema=None):
def get_schema_perm(database, schema): def get_schema_perm(database, schema):
if schema: if schema:
return "[{}].[{}]".format(database, schema) return "[{}].[{}]".format(database, schema)
return database.perm
def validate_json(obj): def validate_json(obj):

View File

@ -466,10 +466,12 @@ class SqlMetricInlineView(CompactCRUDMixin, SupersetModelView): # noqa
} }
def post_add(self, metric): def post_add(self, metric):
utils.init_metrics_perm(superset, [metric]) if metric.is_restricted:
security.merge_perm(sm, 'metric_access', metric.get_perm())
def post_update(self, metric): def post_update(self, metric):
utils.init_metrics_perm(superset, [metric]) if metric.is_restricted:
security.merge_perm(sm, 'metric_access', metric.get_perm())
appbuilder.add_view_no_menu(SqlMetricInlineView) appbuilder.add_view_no_menu(SqlMetricInlineView)
@ -702,7 +704,7 @@ class TableModelView(SupersetModelView, DeleteMixin): # noqa
def post_add(self, table): def post_add(self, table):
table.fetch_metadata() table.fetch_metadata()
security.merge_perm(sm, 'datasource_access', table.perm) security.merge_perm(sm, 'datasource_access', table.get_perm())
if table.schema: if table.schema:
security.merge_perm(sm, 'schema_access', table.schema_perm) security.merge_perm(sm, 'schema_access', table.schema_perm)
@ -1069,7 +1071,7 @@ class DruidDatasourceModelView(SupersetModelView, DeleteMixin): # noqa
def post_add(self, datasource): def post_add(self, datasource):
datasource.generate_metrics() datasource.generate_metrics()
security.merge_perm(sm, 'datasource_access', datasource.perm) security.merge_perm(sm, 'datasource_access', datasource.get_perm())
if datasource.schema: if datasource.schema:
security.merge_perm(sm, 'schema_access', datasource.schema_perm) security.merge_perm(sm, 'schema_access', datasource.schema_perm)

View File

@ -107,7 +107,6 @@ class RequestAccessTests(SupersetTestCase):
updated_role = sm.find_role('override_me') updated_role = sm.find_role('override_me')
perms = sorted( perms = sorted(
updated_role.permissions, key=lambda p: p.view_menu.name) updated_role.permissions, key=lambda p: p.view_menu.name)
self.assertEquals(3, len(perms))
druid_ds_1 = self.get_druid_ds_by_name('druid_ds_1') druid_ds_1 = self.get_druid_ds_by_name('druid_ds_1')
self.assertEquals(druid_ds_1.perm, perms[0].view_menu.name) self.assertEquals(druid_ds_1.perm, perms[0].view_menu.name)
self.assertEquals('datasource_access', perms[0].permission.name) self.assertEquals('datasource_access', perms[0].permission.name)
@ -121,6 +120,7 @@ class RequestAccessTests(SupersetTestCase):
self.assertEquals(birth_names.perm, perms[2].view_menu.name) self.assertEquals(birth_names.perm, perms[2].view_menu.name)
self.assertEquals( self.assertEquals(
'datasource_access', updated_role.permissions[2].permission.name) 'datasource_access', updated_role.permissions[2].permission.name)
self.assertEquals(3, len(perms))
def test_override_role_permissions_drops_absent_perms(self): def test_override_role_permissions_drops_absent_perms(self):
override_me = sm.find_role('override_me') override_me = sm.find_role('override_me')

View File

@ -40,16 +40,16 @@ class SupersetTestCase(unittest.TestCase):
self.client = app.test_client() self.client = app.test_client()
self.maxDiff = None self.maxDiff = None
gamma_sqllab = sm.add_role("gamma_sqllab") gamma_sqllab_role = sm.add_role("gamma_sqllab")
for perm in sm.find_role('Gamma').permissions: for perm in sm.find_role('Gamma').permissions:
sm.add_permission_role(gamma_sqllab, perm) sm.add_permission_role(gamma_sqllab_role, perm)
db_perm = self.get_main_database(sm.get_session).perm db_perm = self.get_main_database(sm.get_session).perm
security.merge_perm(sm, 'database_access', db_perm) security.merge_perm(sm, 'database_access', db_perm)
db_pvm = sm.find_permission_view_menu( db_pvm = sm.find_permission_view_menu(
view_menu_name=db_perm, permission_name='database_access') view_menu_name=db_perm, permission_name='database_access')
gamma_sqllab.permissions.append(db_pvm) gamma_sqllab_role.permissions.append(db_pvm)
for perm in sm.find_role('sql_lab').permissions: for perm in sm.find_role('sql_lab').permissions:
sm.add_permission_role(gamma_sqllab, perm) sm.add_permission_role(gamma_sqllab_role, perm)
admin = appbuilder.sm.find_user('admin') admin = appbuilder.sm.find_user('admin')
if not admin: if not admin:
@ -65,12 +65,11 @@ class SupersetTestCase(unittest.TestCase):
appbuilder.sm.find_role('Gamma'), appbuilder.sm.find_role('Gamma'),
password='general') password='general')
gamma_sqllab = appbuilder.sm.find_user('gamma_sqllab') gamma_sqllab_user = appbuilder.sm.find_user('gamma_sqllab')
if not gamma_sqllab: if not gamma_sqllab_user:
gamma_sqllab = appbuilder.sm.add_user( appbuilder.sm.add_user(
'gamma_sqllab', 'gamma_sqllab', 'user', 'gamma_sqllab@fab.org', 'gamma_sqllab', 'gamma_sqllab', 'user', 'gamma_sqllab@fab.org',
appbuilder.sm.find_role('gamma_sqllab'), gamma_sqllab_role, password='general')
password='general')
alpha = appbuilder.sm.find_user('alpha') alpha = appbuilder.sm.find_user('alpha')
if not alpha: if not alpha:
@ -266,6 +265,3 @@ class SupersetTestCase(unittest.TestCase):
self.assertIn(('can_save_dash', 'Superset'), gamma_perm_set) self.assertIn(('can_save_dash', 'Superset'), gamma_perm_set)
self.assertIn(('can_slice', 'Superset'), gamma_perm_set) self.assertIn(('can_slice', 'Superset'), gamma_perm_set)

View File

@ -10,7 +10,7 @@ import unittest
from mock import Mock, patch from mock import Mock, patch
from superset import db, sm, utils from superset import db, sm, security
from superset.models import DruidCluster, DruidDatasource from superset.models import DruidCluster, DruidDatasource
from .base_tests import SupersetTestCase from .base_tests import SupersetTestCase
@ -240,21 +240,21 @@ class DruidTests(SupersetTestCase):
db.session) db.session)
no_gamma_ds.cluster = cluster no_gamma_ds.cluster = cluster
db.session.merge(no_gamma_ds) db.session.merge(no_gamma_ds)
sm.add_permission_view_menu('datasource_access', gamma_ds.perm)
sm.add_permission_view_menu('datasource_access', no_gamma_ds.perm)
db.session.commit() db.session.commit()
perm = sm.find_permission_view_menu('datasource_access', gamma_ds.perm) security.merge_perm(sm, 'datasource_access', gamma_ds.perm)
security.merge_perm(sm, 'datasource_access', no_gamma_ds.perm)
perm = sm.find_permission_view_menu(
'datasource_access', gamma_ds.get_perm())
sm.add_permission_role(sm.find_role('Gamma'), perm) sm.add_permission_role(sm.find_role('Gamma'), perm)
db.session.commit() sm.get_session.commit()
self.login(username='gamma') self.login(username='gamma')
url = '/druiddatasourcemodelview/list/' url = '/druiddatasourcemodelview/list/'
resp = self.get_resp(url) resp = self.get_resp(url)
assert 'datasource_for_gamma' in resp self.assertIn('datasource_for_gamma', resp)
assert 'datasource_not_for_gamma' not in resp self.assertNotIn('datasource_not_for_gamma', resp)
if __name__ == '__main__': if __name__ == '__main__':

173
tests/security_tests.py Normal file
View File

@ -0,0 +1,173 @@
from superset import security, sm
from .base_tests import SupersetTestCase
def get_perm_tuples(role_name):
perm_set = set()
for perm in sm.find_role(role_name).permissions:
perm_set.add((perm.permission.name, perm.view_menu.name))
return perm_set
class RolePermissionTests(SupersetTestCase):
"""Testing export import functionality for dashboards"""
def __init__(self, *args, **kwargs):
super(RolePermissionTests, self).__init__(*args, **kwargs)
def assert_can_read(self, view_menu, permissions_set):
self.assertIn(('can_show', view_menu), permissions_set)
self.assertIn(('can_list', view_menu), permissions_set)
def assert_can_write(self, view_menu, permissions_set):
self.assertIn(('can_add', view_menu), permissions_set)
self.assertIn(('can_download', view_menu), permissions_set)
self.assertIn(('can_delete', view_menu), permissions_set)
self.assertIn(('can_edit', view_menu), permissions_set)
def assert_cannot_write(self, view_menu, permissions_set):
self.assertNotIn(('can_add', view_menu), permissions_set)
self.assertNotIn(('can_download', view_menu), permissions_set)
self.assertNotIn(('can_delete', view_menu), permissions_set)
self.assertNotIn(('can_edit', view_menu), permissions_set)
self.assertNotIn(('can_save', view_menu), permissions_set)
def assert_can_all(self, view_menu, permissions_set):
self.assert_can_read(view_menu, permissions_set)
self.assert_can_write(view_menu, permissions_set)
def assert_cannot_gamma(self, perm_set):
self.assert_cannot_write('DruidColumnInlineView', perm_set)
def assert_can_gamma(self, perm_set):
self.assert_can_read('DatabaseAsync', perm_set)
self.assert_can_read('TableModelView', perm_set)
# make sure that user can create slices and dashboards
self.assert_can_all('SliceModelView', perm_set)
self.assert_can_all('DashboardModelView', perm_set)
self.assertIn(('can_add_slices', 'Superset'), perm_set)
self.assertIn(('can_copy_dash', 'Superset'), perm_set)
self.assertIn(('can_activity_per_day', 'Superset'), perm_set)
self.assertIn(('can_created_dashboards', 'Superset'), perm_set)
self.assertIn(('can_created_slices', 'Superset'), perm_set)
self.assertIn(('can_csv', 'Superset'), perm_set)
self.assertIn(('can_dashboard', 'Superset'), perm_set)
self.assertIn(('can_explore', 'Superset'), perm_set)
self.assertIn(('can_explore_json', 'Superset'), perm_set)
self.assertIn(('can_fave_dashboards', 'Superset'), perm_set)
self.assertIn(('can_fave_slices', 'Superset'), perm_set)
self.assertIn(('can_save_dash', 'Superset'), perm_set)
self.assertIn(('can_slice', 'Superset'), perm_set)
self.assertIn(('can_explore', 'Superset'), perm_set)
self.assertIn(('can_explore_json', 'Superset'), perm_set)
self.assertIn(('can_queries', 'Superset'), perm_set)
def assert_can_alpha(self, perm_set):
self.assert_can_all('SqlMetricInlineView', perm_set)
self.assert_can_all('TableColumnInlineView', perm_set)
self.assert_can_all('TableModelView', perm_set)
self.assert_can_all('DruidColumnInlineView', perm_set)
self.assert_can_all('DruidDatasourceModelView', perm_set)
self.assert_can_all('DruidMetricInlineView', perm_set)
self.assertIn(
('all_datasource_access', 'all_datasource_access'), perm_set)
self.assertIn(('muldelete', 'DruidDatasourceModelView'), perm_set)
def assert_cannot_alpha(self, perm_set):
self.assert_cannot_write('AccessRequestsModelView', perm_set)
self.assert_cannot_write('Queries', perm_set)
self.assert_cannot_write('RoleModelView', perm_set)
self.assert_cannot_write('UserDBModelView', perm_set)
def assert_can_admin(self, perm_set):
self.assert_can_all('DatabaseAsync', perm_set)
self.assert_can_all('DatabaseView', perm_set)
self.assert_can_all('DruidClusterModelView', perm_set)
self.assert_can_all('AccessRequestsModelView', perm_set)
self.assert_can_all('RoleModelView', perm_set)
self.assert_can_all('UserDBModelView', perm_set)
self.assertIn(('all_database_access', 'all_database_access'), perm_set)
self.assertIn(('can_override_role_permissions', 'Superset'), perm_set)
self.assertIn(('can_sync_druid_source', 'Superset'), perm_set)
self.assertIn(('can_override_role_permissions', 'Superset'), perm_set)
self.assertIn(('can_approve', 'Superset'), perm_set)
self.assertIn(('can_update_role', 'Superset'), perm_set)
def test_is_admin_only(self):
self.assertFalse(security.is_admin_only(
sm.find_permission_view_menu('can_show', 'TableModelView')))
self.assertFalse(security.is_admin_only(
sm.find_permission_view_menu(
'all_datasource_access', 'all_datasource_access')))
self.assertTrue(security.is_admin_only(
sm.find_permission_view_menu('can_delete', 'DatabaseView')))
self.assertTrue(security.is_admin_only(
sm.find_permission_view_menu(
'can_show', 'AccessRequestsModelView')))
self.assertTrue(security.is_admin_only(
sm.find_permission_view_menu(
'can_edit', 'UserDBModelView')))
self.assertTrue(security.is_admin_only(
sm.find_permission_view_menu(
'can_approve', 'Superset')))
self.assertTrue(security.is_admin_only(
sm.find_permission_view_menu(
'all_database_access', 'all_database_access')))
def test_is_alpha_only(self):
self.assertFalse(security.is_alpha_only(
sm.find_permission_view_menu('can_show', 'TableModelView')))
self.assertTrue(security.is_alpha_only(
sm.find_permission_view_menu('muldelete', 'TableModelView')))
self.assertTrue(security.is_alpha_only(
sm.find_permission_view_menu(
'all_datasource_access', 'all_datasource_access')))
self.assertTrue(security.is_alpha_only(
sm.find_permission_view_menu('can_edit', 'SqlMetricInlineView')))
self.assertTrue(security.is_alpha_only(
sm.find_permission_view_menu(
'can_delete', 'DruidMetricInlineView')))
def test_is_gamma_pvm(self):
self.assertTrue(security.is_gamma_pvm(
sm.find_permission_view_menu('can_show', 'TableModelView')))
def test_gamma_permissions(self):
self.assert_can_gamma(get_perm_tuples('Gamma'))
self.assert_cannot_gamma(get_perm_tuples('Gamma'))
self.assert_cannot_alpha(get_perm_tuples('Alpha'))
def test_alpha_permissions(self):
self.assert_can_gamma(get_perm_tuples('Alpha'))
self.assert_can_alpha(get_perm_tuples('Alpha'))
self.assert_cannot_alpha(get_perm_tuples('Alpha'))
def test_admin_permissions(self):
self.assert_can_gamma(get_perm_tuples('Admin'))
self.assert_can_alpha(get_perm_tuples('Admin'))
self.assert_can_admin(get_perm_tuples('Admin'))
def test_sql_lab_permissions(self):
sql_lab_set = get_perm_tuples('sql_lab')
self.assertIn(('can_sql_json', 'Superset'), sql_lab_set)
self.assertIn(('can_csv', 'Superset'), sql_lab_set)
self.assertIn(('can_search_queries', 'Superset'), sql_lab_set)
self.assert_cannot_gamma(sql_lab_set)
self.assert_cannot_alpha(sql_lab_set)
def test_granter_permissions(self):
granter_set = get_perm_tuples('granter')
self.assertIn(('can_override_role_permissions', 'Superset'), granter_set)
self.assertIn(('can_approve', 'Superset'), granter_set)
self.assert_cannot_gamma(granter_set)
self.assert_cannot_alpha(granter_set)

View File

@ -18,11 +18,8 @@ class SqlLabTests(SupersetTestCase):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(SqlLabTests, self).__init__(*args, **kwargs) super(SqlLabTests, self).__init__(*args, **kwargs)
gamma_sqllab = appbuilder.sm.find_role('gamma_sqllab')
security.merge_perm(sm, 'database_access', self.get_main_database(db.session).perm)
def run_some_queries(self): def run_some_queries(self):
self.logout()
db.session.query(models.Query).delete() db.session.query(models.Query).delete()
db.session.commit() db.session.commit()
self.run_sql( self.run_sql(
@ -87,6 +84,7 @@ class SqlLabTests(SupersetTestCase):
# Not logged in, should error out # Not logged in, should error out
resp = self.client.get('/superset/queries/0') resp = self.client.get('/superset/queries/0')
# Redirects to the login page
self.assertEquals(403, resp.status_code) self.assertEquals(403, resp.status_code)
# Admin sees queries # Admin sees queries
@ -114,6 +112,7 @@ class SqlLabTests(SupersetTestCase):
self.logout() self.logout()
resp = self.client.get('/superset/queries/0') resp = self.client.get('/superset/queries/0')
# Redirects to the login page
self.assertEquals(403, resp.status_code) self.assertEquals(403, resp.status_code)
def test_search_query_on_db_id(self): def test_search_query_on_db_id(self):