mirror of https://github.com/apache/superset.git
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:
parent
733ab8014b
commit
92aa1a6124
|
@ -52,7 +52,6 @@ from sqlalchemy_utils import EncryptedType
|
|||
|
||||
from werkzeug.datastructures import ImmutableMultiDict
|
||||
|
||||
import superset
|
||||
from superset import app, db, db_engine_specs, get_session, utils, sm
|
||||
from superset.source_registry import SourceRegistry
|
||||
from superset.viz import viz_types
|
||||
|
@ -70,24 +69,13 @@ FillterPattern = re.compile(r'''((?:[^,"']|"[^"]*"|'[^']*')+)''')
|
|||
|
||||
|
||||
def set_perm(mapper, connection, target): # noqa
|
||||
target.perm = target.get_perm()
|
||||
|
||||
|
||||
def init_metrics_perm(metrics=None):
|
||||
"""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
|
||||
"""
|
||||
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)
|
||||
if target.perm != target.get_perm():
|
||||
link_table = target.__table__
|
||||
connection.execute(
|
||||
link_table.update()
|
||||
.where(link_table.c.id == target.id)
|
||||
.values(perm=target.get_perm())
|
||||
)
|
||||
|
||||
|
||||
class JavascriptPostAggregator(Postaggregator):
|
||||
|
@ -860,8 +848,8 @@ class Database(Model, AuditMixinNullable):
|
|||
return (
|
||||
"[{obj.database_name}].(id:{obj.id})").format(obj=self)
|
||||
|
||||
sqla.event.listen(Database, 'before_insert', set_perm)
|
||||
sqla.event.listen(Database, 'before_update', set_perm)
|
||||
sqla.event.listen(Database, 'after_insert', set_perm)
|
||||
sqla.event.listen(Database, 'after_update', set_perm)
|
||||
|
||||
|
||||
class SqlaTable(Model, Queryable, AuditMixinNullable, ImportMixin):
|
||||
|
@ -1340,8 +1328,8 @@ class SqlaTable(Model, Queryable, AuditMixinNullable, ImportMixin):
|
|||
|
||||
return datasource.id
|
||||
|
||||
sqla.event.listen(SqlaTable, 'before_insert', set_perm)
|
||||
sqla.event.listen(SqlaTable, 'before_update', set_perm)
|
||||
sqla.event.listen(SqlaTable, 'after_insert', set_perm)
|
||||
sqla.event.listen(SqlaTable, 'after_update', set_perm)
|
||||
|
||||
|
||||
class SqlMetric(Model, AuditMixinNullable, ImportMixin):
|
||||
|
@ -2238,8 +2226,8 @@ class DruidDatasource(Model, AuditMixinNullable, Queryable):
|
|||
filters = cond
|
||||
return filters
|
||||
|
||||
sqla.event.listen(DruidDatasource, 'before_insert', set_perm)
|
||||
sqla.event.listen(DruidDatasource, 'before_update', set_perm)
|
||||
sqla.event.listen(DruidDatasource, 'after_insert', set_perm)
|
||||
sqla.event.listen(DruidDatasource, 'after_update', set_perm)
|
||||
|
||||
|
||||
class Log(Model):
|
||||
|
@ -2466,8 +2454,6 @@ class DruidColumn(Model, AuditMixinNullable):
|
|||
session.add(metric)
|
||||
session.flush()
|
||||
|
||||
init_metrics_perm(new_metrics)
|
||||
|
||||
|
||||
class FavStar(Model):
|
||||
__tablename__ = 'favstar'
|
||||
|
|
|
@ -3,11 +3,10 @@ from __future__ import division
|
|||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from itertools import product
|
||||
import logging
|
||||
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 = {
|
||||
|
@ -17,13 +16,10 @@ READ_ONLY_MODELVIEWS = {
|
|||
}
|
||||
|
||||
GAMMA_READ_ONLY_MODELVIEWS = {
|
||||
'ColumnInlineView',
|
||||
'SqlMetricInlineView',
|
||||
'TableColumnInlineView',
|
||||
'TableModelView',
|
||||
'DatasourceModelView',
|
||||
'DruidColumnInlineView',
|
||||
'MetricInlineView',
|
||||
'DruidDatasourceModelView',
|
||||
'DruidMetricInlineView',
|
||||
} | READ_ONLY_MODELVIEWS
|
||||
|
@ -38,13 +34,11 @@ ADMIN_ONLY_VIEW_MENUES = {
|
|||
'RoleModelView',
|
||||
'Security',
|
||||
'UserDBModelView',
|
||||
} | READ_ONLY_MODELVIEWS
|
||||
}
|
||||
|
||||
ADMIN_ONLY_PERMISSIONS = {
|
||||
'all_database_access',
|
||||
'datasource_access',
|
||||
'schema_access',
|
||||
'database_access',
|
||||
# TODO: move can_sql_json to sql_lab role
|
||||
'can_sql_json',
|
||||
'can_override_role_permissions',
|
||||
'can_sync_druid_source',
|
||||
|
@ -52,24 +46,16 @@ ADMIN_ONLY_PERMISSIONS = {
|
|||
'can_approve',
|
||||
'can_update_role',
|
||||
}
|
||||
|
||||
READ_ONLY_PERMISSION = {
|
||||
'can_show',
|
||||
'can_list',
|
||||
}
|
||||
|
||||
ALPHA_ONLY_PERMISSIONS = set([
|
||||
'datasource_access',
|
||||
'schema_access',
|
||||
'database_access',
|
||||
'muldelete',
|
||||
'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([
|
||||
'database_access',
|
||||
|
@ -81,7 +67,7 @@ OBJECT_SPEC_PERMISSIONS = set([
|
|||
|
||||
def merge_perm(sm, 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)
|
||||
|
||||
|
||||
|
@ -107,114 +93,125 @@ def get_or_create_main_db():
|
|||
return dbobj
|
||||
|
||||
|
||||
def sync_role_definitions():
|
||||
"""Inits the Superset application with security roles and such"""
|
||||
logging.info("Syncing role definition")
|
||||
def is_admin_only(pvm):
|
||||
# not readonly operations on read only model views allowed only for admins
|
||||
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
|
||||
merge_perm(sm, 'all_datasource_access', 'all_datasource_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")
|
||||
for p in perms:
|
||||
# admin has all_database_access and all_datasource_access
|
||||
if is_user_defined_permission(p):
|
||||
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()]
|
||||
def create_missing_datasource_perms(view_menu_set):
|
||||
logging.info("Creating missing datasource permissions.")
|
||||
datasources = source_registry.SourceRegistry.get_all_datasources(
|
||||
db.session)
|
||||
for datasource in datasources:
|
||||
perm = datasource.get_perm()
|
||||
merge_perm(sm, 'datasource_access', perm)
|
||||
if datasource.schema:
|
||||
merge_perm(sm, 'schema_access', datasource.schema_perm)
|
||||
if perm != datasource.perm:
|
||||
datasource.perm = perm
|
||||
if datasource and datasource.perm not in view_menu_set:
|
||||
merge_perm(sm, 'datasource_access', datasource.get_perm())
|
||||
if datasource.schema_perm:
|
||||
merge_perm(sm, 'schema_access', datasource.schema_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:
|
||||
perm = database.get_perm()
|
||||
if perm != database.perm:
|
||||
database.perm = perm
|
||||
merge_perm(sm, 'database_access', perm)
|
||||
session.commit()
|
||||
if database and database.perm not in view_menu_set:
|
||||
merge_perm(sm, 'database_access', database.perm)
|
||||
|
||||
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()
|
||||
|
|
|
@ -333,7 +333,6 @@ def get_datasource_full_name(database_name, datasource_name, schema=None):
|
|||
def get_schema_perm(database, schema):
|
||||
if schema:
|
||||
return "[{}].[{}]".format(database, schema)
|
||||
return database.perm
|
||||
|
||||
|
||||
def validate_json(obj):
|
||||
|
|
|
@ -466,10 +466,12 @@ class SqlMetricInlineView(CompactCRUDMixin, SupersetModelView): # noqa
|
|||
}
|
||||
|
||||
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):
|
||||
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)
|
||||
|
||||
|
@ -702,7 +704,7 @@ class TableModelView(SupersetModelView, DeleteMixin): # noqa
|
|||
|
||||
def post_add(self, table):
|
||||
table.fetch_metadata()
|
||||
security.merge_perm(sm, 'datasource_access', table.perm)
|
||||
security.merge_perm(sm, 'datasource_access', table.get_perm())
|
||||
if table.schema:
|
||||
security.merge_perm(sm, 'schema_access', table.schema_perm)
|
||||
|
||||
|
@ -1069,7 +1071,7 @@ class DruidDatasourceModelView(SupersetModelView, DeleteMixin): # noqa
|
|||
|
||||
def post_add(self, datasource):
|
||||
datasource.generate_metrics()
|
||||
security.merge_perm(sm, 'datasource_access', datasource.perm)
|
||||
security.merge_perm(sm, 'datasource_access', datasource.get_perm())
|
||||
if datasource.schema:
|
||||
security.merge_perm(sm, 'schema_access', datasource.schema_perm)
|
||||
|
||||
|
|
|
@ -107,7 +107,6 @@ class RequestAccessTests(SupersetTestCase):
|
|||
updated_role = sm.find_role('override_me')
|
||||
perms = sorted(
|
||||
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')
|
||||
self.assertEquals(druid_ds_1.perm, perms[0].view_menu.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(
|
||||
'datasource_access', updated_role.permissions[2].permission.name)
|
||||
self.assertEquals(3, len(perms))
|
||||
|
||||
def test_override_role_permissions_drops_absent_perms(self):
|
||||
override_me = sm.find_role('override_me')
|
||||
|
|
|
@ -40,16 +40,16 @@ class SupersetTestCase(unittest.TestCase):
|
|||
self.client = app.test_client()
|
||||
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:
|
||||
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
|
||||
security.merge_perm(sm, 'database_access', db_perm)
|
||||
db_pvm = sm.find_permission_view_menu(
|
||||
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:
|
||||
sm.add_permission_role(gamma_sqllab, perm)
|
||||
sm.add_permission_role(gamma_sqllab_role, perm)
|
||||
|
||||
admin = appbuilder.sm.find_user('admin')
|
||||
if not admin:
|
||||
|
@ -65,12 +65,11 @@ class SupersetTestCase(unittest.TestCase):
|
|||
appbuilder.sm.find_role('Gamma'),
|
||||
password='general')
|
||||
|
||||
gamma_sqllab = appbuilder.sm.find_user('gamma_sqllab')
|
||||
if not gamma_sqllab:
|
||||
gamma_sqllab = appbuilder.sm.add_user(
|
||||
gamma_sqllab_user = appbuilder.sm.find_user('gamma_sqllab')
|
||||
if not gamma_sqllab_user:
|
||||
appbuilder.sm.add_user(
|
||||
'gamma_sqllab', 'gamma_sqllab', 'user', 'gamma_sqllab@fab.org',
|
||||
appbuilder.sm.find_role('gamma_sqllab'),
|
||||
password='general')
|
||||
gamma_sqllab_role, password='general')
|
||||
|
||||
alpha = appbuilder.sm.find_user('alpha')
|
||||
if not alpha:
|
||||
|
@ -266,6 +265,3 @@ class SupersetTestCase(unittest.TestCase):
|
|||
self.assertIn(('can_save_dash', 'Superset'), gamma_perm_set)
|
||||
self.assertIn(('can_slice', 'Superset'), gamma_perm_set)
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import unittest
|
|||
|
||||
from mock import Mock, patch
|
||||
|
||||
from superset import db, sm, utils
|
||||
from superset import db, sm, security
|
||||
from superset.models import DruidCluster, DruidDatasource
|
||||
|
||||
from .base_tests import SupersetTestCase
|
||||
|
@ -240,21 +240,21 @@ class DruidTests(SupersetTestCase):
|
|||
db.session)
|
||||
no_gamma_ds.cluster = cluster
|
||||
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()
|
||||
|
||||
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)
|
||||
db.session.commit()
|
||||
sm.get_session.commit()
|
||||
|
||||
self.login(username='gamma')
|
||||
url = '/druiddatasourcemodelview/list/'
|
||||
resp = self.get_resp(url)
|
||||
assert 'datasource_for_gamma' in resp
|
||||
assert 'datasource_not_for_gamma' not in resp
|
||||
self.assertIn('datasource_for_gamma', resp)
|
||||
self.assertNotIn('datasource_not_for_gamma', resp)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -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)
|
||||
|
|
@ -18,11 +18,8 @@ class SqlLabTests(SupersetTestCase):
|
|||
|
||||
def __init__(self, *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):
|
||||
self.logout()
|
||||
db.session.query(models.Query).delete()
|
||||
db.session.commit()
|
||||
self.run_sql(
|
||||
|
@ -87,6 +84,7 @@ class SqlLabTests(SupersetTestCase):
|
|||
|
||||
# Not logged in, should error out
|
||||
resp = self.client.get('/superset/queries/0')
|
||||
# Redirects to the login page
|
||||
self.assertEquals(403, resp.status_code)
|
||||
|
||||
# Admin sees queries
|
||||
|
@ -114,6 +112,7 @@ class SqlLabTests(SupersetTestCase):
|
|||
|
||||
self.logout()
|
||||
resp = self.client.get('/superset/queries/0')
|
||||
# Redirects to the login page
|
||||
self.assertEquals(403, resp.status_code)
|
||||
|
||||
def test_search_query_on_db_id(self):
|
||||
|
|
Loading…
Reference in New Issue