[security] Refactor security code into SupersetSecurityManager (#4565)
* move access permissions methods to security manager * consolidate all security methods into SupersetSecurityManager * update security method calls * update calls from tests * move get_or_create_main_db to utils * raise if supersetsecuritymanager is not extended * rename sm to security_manager
This commit is contained in:
parent
f510956da2
commit
8dd052de4b
|
|
@ -0,0 +1,8 @@
|
|||
# Updating Superset
|
||||
|
||||
This file documents any backwards-incompatible changes in Superset and
|
||||
assists people when migrating to a new version.
|
||||
|
||||
## Superset 0.23.0
|
||||
|
||||
* [4565](https://github.com/apache/incubator-superset/pull/4565)
|
||||
|
|
@ -18,8 +18,9 @@ from flask_migrate import Migrate
|
|||
from flask_wtf.csrf import CSRFProtect
|
||||
from werkzeug.contrib.fixers import ProxyFix
|
||||
|
||||
from superset import config, utils
|
||||
from superset.connectors.connector_registry import ConnectorRegistry
|
||||
from superset import utils, config # noqa
|
||||
from superset.security import SupersetSecurityManager
|
||||
|
||||
APP_DIR = os.path.dirname(__file__)
|
||||
CONFIG_MODULE = os.environ.get('SUPERSET_CONFIG', 'superset.config')
|
||||
|
|
@ -149,16 +150,23 @@ class MyIndexView(IndexView):
|
|||
return redirect('/superset/welcome')
|
||||
|
||||
|
||||
custom_sm = app.config.get('CUSTOM_SECURITY_MANAGER') or SupersetSecurityManager
|
||||
if not issubclass(custom_sm, SupersetSecurityManager):
|
||||
raise Exception(
|
||||
"""Your CUSTOM_SECURITY_MANAGER must now extend SupersetSecurityManager,
|
||||
not FAB's security manager.
|
||||
See [4565] in UPDATING.md""")
|
||||
|
||||
appbuilder = AppBuilder(
|
||||
app,
|
||||
db.session,
|
||||
base_template='superset/base.html',
|
||||
indexview=MyIndexView,
|
||||
security_manager_class=app.config.get('CUSTOM_SECURITY_MANAGER'),
|
||||
security_manager_class=custom_sm,
|
||||
update_perms=utils.get_update_perms_flag(),
|
||||
)
|
||||
|
||||
sm = appbuilder.sm
|
||||
security_manager = appbuilder.sm
|
||||
|
||||
results_backend = app.config.get('RESULTS_BACKEND')
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ from flask_script import Manager
|
|||
from pathlib2 import Path
|
||||
import yaml
|
||||
|
||||
from superset import app, db, dict_import_export_util, security, utils
|
||||
from superset import app, data, db, dict_import_export_util, security_manager, utils
|
||||
|
||||
config = app.config
|
||||
celery_app = utils.get_celery_app(config)
|
||||
|
|
@ -28,7 +28,8 @@ manager.add_command('db', MigrateCommand)
|
|||
@manager.command
|
||||
def init():
|
||||
"""Inits the Superset application"""
|
||||
security.sync_role_definitions()
|
||||
utils.get_or_create_main_db()
|
||||
security_manager.sync_role_definitions()
|
||||
|
||||
|
||||
@manager.option(
|
||||
|
|
@ -108,7 +109,6 @@ def version(verbose):
|
|||
help='Load additional test data')
|
||||
def load_examples(load_test_data):
|
||||
"""Loads a set of Slices and Dashboards and a supporting dataset """
|
||||
from superset import data
|
||||
print('Loading examples into {}'.format(db))
|
||||
|
||||
data.load_css_templates()
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ from sqlalchemy import (
|
|||
)
|
||||
from sqlalchemy.orm import backref, relationship
|
||||
|
||||
from superset import conf, db, import_util, sm, utils
|
||||
from superset import conf, db, import_util, security_manager, utils
|
||||
from superset.connectors.base.models import BaseColumn, BaseDatasource, BaseMetric
|
||||
from superset.exceptions import MetricPermException
|
||||
from superset.models.helpers import (
|
||||
|
|
@ -465,7 +465,7 @@ class DruidDatasource(Model, BaseDatasource):
|
|||
'DruidCluster', backref='datasources', foreign_keys=[cluster_name])
|
||||
user_id = Column(Integer, ForeignKey('ab_user.id'))
|
||||
owner = relationship(
|
||||
sm.user_model,
|
||||
security_manager.user_model,
|
||||
backref=backref('datasources', cascade='all, delete-orphan'),
|
||||
foreign_keys=[user_id])
|
||||
UniqueConstraint('cluster_name', 'datasource_name')
|
||||
|
|
@ -506,7 +506,7 @@ class DruidDatasource(Model, BaseDatasource):
|
|||
@property
|
||||
def schema_perm(self):
|
||||
"""Returns schema permission if present, cluster one otherwise."""
|
||||
return utils.get_schema_perm(self.cluster, self.schema)
|
||||
return security_manager.get_schema_perm(self.cluster, self.schema)
|
||||
|
||||
def get_perm(self):
|
||||
return (
|
||||
|
|
@ -980,7 +980,7 @@ class DruidDatasource(Model, BaseDatasource):
|
|||
m.metric_name for m in self.metrics
|
||||
if m.is_restricted and
|
||||
m.metric_name in aggregations.keys() and
|
||||
not sm.has_access('metric_access', m.perm)
|
||||
not security_manager.has_access('metric_access', m.perm)
|
||||
]
|
||||
if rejected_metrics:
|
||||
raise MetricPermException(
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ from flask_appbuilder.models.sqla.interface import SQLAInterface
|
|||
from flask_babel import gettext as __
|
||||
from flask_babel import lazy_gettext as _
|
||||
|
||||
from superset import appbuilder, db, security, sm, utils
|
||||
from superset import appbuilder, db, security_manager, utils
|
||||
from superset.connectors.base.views import DatasourceModelView
|
||||
from superset.connectors.connector_registry import ConnectorRegistry
|
||||
from superset.utils import has_access
|
||||
|
|
@ -140,11 +140,11 @@ class DruidMetricInlineView(CompactCRUDMixin, SupersetModelView): # noqa
|
|||
|
||||
def post_add(self, metric):
|
||||
if metric.is_restricted:
|
||||
security.merge_perm(sm, 'metric_access', metric.get_perm())
|
||||
security_manager.merge_perm('metric_access', metric.get_perm())
|
||||
|
||||
def post_update(self, metric):
|
||||
if metric.is_restricted:
|
||||
security.merge_perm(sm, 'metric_access', metric.get_perm())
|
||||
security_manager.merge_perm('metric_access', metric.get_perm())
|
||||
|
||||
|
||||
appbuilder.add_view_no_menu(DruidMetricInlineView)
|
||||
|
|
@ -177,7 +177,7 @@ class DruidClusterModelView(SupersetModelView, DeleteMixin, YamlExportMixin): #
|
|||
}
|
||||
|
||||
def pre_add(self, cluster):
|
||||
security.merge_perm(sm, 'database_access', cluster.perm)
|
||||
security_manager.merge_perm('database_access', cluster.perm)
|
||||
|
||||
def pre_update(self, cluster):
|
||||
self.pre_add(cluster)
|
||||
|
|
@ -278,9 +278,9 @@ class DruidDatasourceModelView(DatasourceModelView, DeleteMixin, YamlExportMixin
|
|||
|
||||
def post_add(self, datasource):
|
||||
datasource.refresh_metrics()
|
||||
security.merge_perm(sm, 'datasource_access', datasource.get_perm())
|
||||
security_manager.merge_perm('datasource_access', datasource.get_perm())
|
||||
if datasource.schema:
|
||||
security.merge_perm(sm, 'schema_access', datasource.schema_perm)
|
||||
security_manager.merge_perm('schema_access', datasource.schema_perm)
|
||||
|
||||
def post_update(self, datasource):
|
||||
self.post_add(datasource)
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ from sqlalchemy.sql import column, literal_column, table, text
|
|||
from sqlalchemy.sql.expression import TextAsFrom
|
||||
import sqlparse
|
||||
|
||||
from superset import db, import_util, sm, utils
|
||||
from superset import db, import_util, security_manager, utils
|
||||
from superset.connectors.base.models import BaseColumn, BaseDatasource, BaseMetric
|
||||
from superset.jinja_context import get_template_processor
|
||||
from superset.models.annotations import Annotation
|
||||
|
|
@ -259,7 +259,7 @@ class SqlaTable(Model, BaseDatasource):
|
|||
fetch_values_predicate = Column(String(1000))
|
||||
user_id = Column(Integer, ForeignKey('ab_user.id'))
|
||||
owner = relationship(
|
||||
sm.user_model,
|
||||
security_manager.user_model,
|
||||
backref='tables',
|
||||
foreign_keys=[user_id])
|
||||
database = relationship(
|
||||
|
|
@ -298,7 +298,7 @@ class SqlaTable(Model, BaseDatasource):
|
|||
@property
|
||||
def schema_perm(self):
|
||||
"""Returns schema permission if present, database one otherwise."""
|
||||
return utils.get_schema_perm(self.database, self.schema)
|
||||
return security_manager.get_schema_perm(self.database, self.schema)
|
||||
|
||||
def get_perm(self):
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ from flask_babel import gettext as __
|
|||
from flask_babel import lazy_gettext as _
|
||||
from past.builtins import basestring
|
||||
|
||||
from superset import appbuilder, db, security, sm, utils
|
||||
from superset import appbuilder, db, security_manager, utils
|
||||
from superset.connectors.base.views import DatasourceModelView
|
||||
from superset.utils import has_access
|
||||
from superset.views.base import (
|
||||
|
|
@ -144,11 +144,11 @@ class SqlMetricInlineView(CompactCRUDMixin, SupersetModelView): # noqa
|
|||
|
||||
def post_add(self, metric):
|
||||
if metric.is_restricted:
|
||||
security.merge_perm(sm, 'metric_access', metric.get_perm())
|
||||
security_manager.merge_perm('metric_access', metric.get_perm())
|
||||
|
||||
def post_update(self, metric):
|
||||
if metric.is_restricted:
|
||||
security.merge_perm(sm, 'metric_access', metric.get_perm())
|
||||
security_manager.merge_perm('metric_access', metric.get_perm())
|
||||
|
||||
|
||||
appbuilder.add_view_no_menu(SqlMetricInlineView)
|
||||
|
|
@ -253,9 +253,9 @@ class TableModelView(DatasourceModelView, DeleteMixin, YamlExportMixin): # noqa
|
|||
|
||||
def post_add(self, table, flash_message=True):
|
||||
table.fetch_metadata()
|
||||
security.merge_perm(sm, 'datasource_access', table.get_perm())
|
||||
security_manager.merge_perm('datasource_access', table.get_perm())
|
||||
if table.schema:
|
||||
security.merge_perm(sm, 'schema_access', table.schema_perm)
|
||||
security_manager.merge_perm('schema_access', table.schema_perm)
|
||||
|
||||
if flash_message:
|
||||
flash(_(
|
||||
|
|
|
|||
|
|
@ -16,10 +16,9 @@ from sqlalchemy import BigInteger, Date, DateTime, Float, String, Text
|
|||
import geohash
|
||||
import polyline
|
||||
|
||||
from superset import app, db, utils
|
||||
from superset import app, db, security_manager, utils
|
||||
from superset.connectors.connector_registry import ConnectorRegistry
|
||||
from superset.models import core as models
|
||||
from superset.security import get_or_create_main_db
|
||||
|
||||
# Shortcuts
|
||||
DB = models.Database
|
||||
|
|
@ -71,7 +70,7 @@ def load_energy():
|
|||
if not tbl:
|
||||
tbl = TBL(table_name=tbl_name)
|
||||
tbl.description = "Energy consumption"
|
||||
tbl.database = get_or_create_main_db()
|
||||
tbl.database = utils.get_or_create_main_db()
|
||||
db.session.merge(tbl)
|
||||
db.session.commit()
|
||||
tbl.fetch_metadata()
|
||||
|
|
@ -179,7 +178,7 @@ def load_world_bank_health_n_pop():
|
|||
tbl = TBL(table_name=tbl_name)
|
||||
tbl.description = utils.readfile(os.path.join(DATA_FOLDER, 'countries.md'))
|
||||
tbl.main_dttm_col = 'year'
|
||||
tbl.database = get_or_create_main_db()
|
||||
tbl.database = utils.get_or_create_main_db()
|
||||
tbl.filter_select_enabled = True
|
||||
db.session.merge(tbl)
|
||||
db.session.commit()
|
||||
|
|
@ -583,7 +582,7 @@ def load_birth_names():
|
|||
if not obj:
|
||||
obj = TBL(table_name='birth_names')
|
||||
obj.main_dttm_col = 'ds'
|
||||
obj.database = get_or_create_main_db()
|
||||
obj.database = utils.get_or_create_main_db()
|
||||
obj.filter_select_enabled = True
|
||||
db.session.merge(obj)
|
||||
db.session.commit()
|
||||
|
|
@ -870,7 +869,7 @@ def load_unicode_test_data():
|
|||
if not obj:
|
||||
obj = TBL(table_name='unicode_test')
|
||||
obj.main_dttm_col = 'dttm'
|
||||
obj.database = get_or_create_main_db()
|
||||
obj.database = utils.get_or_create_main_db()
|
||||
db.session.merge(obj)
|
||||
db.session.commit()
|
||||
obj.fetch_metadata()
|
||||
|
|
@ -948,7 +947,7 @@ def load_random_time_series_data():
|
|||
if not obj:
|
||||
obj = TBL(table_name='random_time_series')
|
||||
obj.main_dttm_col = 'ds'
|
||||
obj.database = get_or_create_main_db()
|
||||
obj.database = utils.get_or_create_main_db()
|
||||
db.session.merge(obj)
|
||||
db.session.commit()
|
||||
obj.fetch_metadata()
|
||||
|
|
@ -1011,7 +1010,7 @@ def load_country_map_data():
|
|||
if not obj:
|
||||
obj = TBL(table_name='birth_france_by_region')
|
||||
obj.main_dttm_col = 'dttm'
|
||||
obj.database = get_or_create_main_db()
|
||||
obj.database = utils.get_or_create_main_db()
|
||||
db.session.merge(obj)
|
||||
db.session.commit()
|
||||
obj.fetch_metadata()
|
||||
|
|
@ -1086,7 +1085,7 @@ def load_long_lat_data():
|
|||
if not obj:
|
||||
obj = TBL(table_name='long_lat')
|
||||
obj.main_dttm_col = 'datetime'
|
||||
obj.database = get_or_create_main_db()
|
||||
obj.database = utils.get_or_create_main_db()
|
||||
db.session.merge(obj)
|
||||
db.session.commit()
|
||||
obj.fetch_metadata()
|
||||
|
|
@ -1147,7 +1146,7 @@ def load_multiformat_time_series_data():
|
|||
if not obj:
|
||||
obj = TBL(table_name='multiformat_time_series')
|
||||
obj.main_dttm_col = 'ds'
|
||||
obj.database = get_or_create_main_db()
|
||||
obj.database = utils.get_or_create_main_db()
|
||||
dttm_and_expr_dict = {
|
||||
'ds': [None, None],
|
||||
'ds2': [None, None],
|
||||
|
|
@ -1769,7 +1768,7 @@ def load_flights():
|
|||
if not tbl:
|
||||
tbl = TBL(table_name=tbl_name)
|
||||
tbl.description = "Random set of flights in the US"
|
||||
tbl.database = get_or_create_main_db()
|
||||
tbl.database = utils.get_or_create_main_db()
|
||||
db.session.merge(tbl)
|
||||
db.session.commit()
|
||||
tbl.fetch_metadata()
|
||||
|
|
@ -1800,7 +1799,7 @@ def load_paris_iris_geojson():
|
|||
if not tbl:
|
||||
tbl = TBL(table_name=tbl_name)
|
||||
tbl.description = "Map of Paris"
|
||||
tbl.database = get_or_create_main_db()
|
||||
tbl.database = utils.get_or_create_main_db()
|
||||
db.session.merge(tbl)
|
||||
db.session.commit()
|
||||
tbl.fetch_metadata()
|
||||
|
|
@ -1830,7 +1829,7 @@ def load_sf_population_polygons():
|
|||
if not tbl:
|
||||
tbl = TBL(table_name=tbl_name)
|
||||
tbl.description = "Population density of San Francisco"
|
||||
tbl.database = get_or_create_main_db()
|
||||
tbl.database = utils.get_or_create_main_db()
|
||||
db.session.merge(tbl)
|
||||
db.session.commit()
|
||||
tbl.fetch_metadata()
|
||||
|
|
@ -1860,7 +1859,7 @@ def load_bart_lines():
|
|||
if not tbl:
|
||||
tbl = TBL(table_name=tbl_name)
|
||||
tbl.description = "BART lines"
|
||||
tbl.database = get_or_create_main_db()
|
||||
tbl.database = utils.get_or_create_main_db()
|
||||
db.session.merge(tbl)
|
||||
db.session.commit()
|
||||
tbl.fetch_metadata()
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ from sqlalchemy.sql import text
|
|||
from sqlalchemy.sql.expression import TextAsFrom
|
||||
from sqlalchemy_utils import EncryptedType
|
||||
|
||||
from superset import app, db, db_engine_specs, sm, utils
|
||||
from superset import app, db, db_engine_specs, security_manager, utils
|
||||
from superset.connectors.connector_registry import ConnectorRegistry
|
||||
from superset.models.helpers import AuditMixinNullable, ImportMixin, set_perm
|
||||
from superset.viz import viz_types
|
||||
|
|
@ -104,7 +104,7 @@ class Slice(Model, AuditMixinNullable, ImportMixin):
|
|||
description = Column(Text)
|
||||
cache_timeout = Column(Integer)
|
||||
perm = Column(String(1000))
|
||||
owners = relationship(sm.user_model, secondary=slice_user)
|
||||
owners = relationship(security_manager.user_model, secondary=slice_user)
|
||||
|
||||
export_fields = ('slice_name', 'datasource_type', 'datasource_name',
|
||||
'viz_type', 'params', 'cache_timeout')
|
||||
|
|
@ -322,7 +322,7 @@ class Dashboard(Model, AuditMixinNullable, ImportMixin):
|
|||
slug = Column(String(255), unique=True)
|
||||
slices = relationship(
|
||||
'Slice', secondary=dashboard_slices, backref='dashboards')
|
||||
owners = relationship(sm.user_model, secondary=dashboard_user)
|
||||
owners = relationship(security_manager.user_model, secondary=dashboard_user)
|
||||
|
||||
export_fields = ('dashboard_title', 'position_json', 'json_metadata',
|
||||
'description', 'css', 'slug')
|
||||
|
|
@ -681,7 +681,7 @@ class Database(Model, AuditMixinNullable, ImportMixin):
|
|||
DB_CONNECTION_MUTATOR = config.get('DB_CONNECTION_MUTATOR')
|
||||
if DB_CONNECTION_MUTATOR:
|
||||
url, params = DB_CONNECTION_MUTATOR(
|
||||
url, params, effective_username, sm)
|
||||
url, params, effective_username, security_manager)
|
||||
return create_engine(url, **params)
|
||||
|
||||
def get_reserved_words(self):
|
||||
|
|
@ -862,7 +862,8 @@ class Log(Model):
|
|||
dashboard_id = Column(Integer)
|
||||
slice_id = Column(Integer)
|
||||
json = Column(Text)
|
||||
user = relationship(sm.user_model, backref='logs', foreign_keys=[user_id])
|
||||
user = relationship(
|
||||
security_manager.user_model, backref='logs', foreign_keys=[user_id])
|
||||
dttm = Column(DateTime, default=datetime.utcnow)
|
||||
dt = Column(Date, default=date.today())
|
||||
duration_ms = Column(Integer)
|
||||
|
|
@ -961,7 +962,7 @@ class DatasourceAccessRequest(Model, AuditMixinNullable):
|
|||
def roles_with_datasource(self):
|
||||
action_list = ''
|
||||
perm = self.datasource.perm # pylint: disable=no-member
|
||||
pv = sm.find_permission_view_menu('datasource_access', perm)
|
||||
pv = security_manager.find_permission_view_menu('datasource_access', perm)
|
||||
for r in pv.role:
|
||||
if r.name in self.ROLES_BLACKLIST:
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ from sqlalchemy.ext.declarative import declared_attr
|
|||
from sqlalchemy.orm.exc import MultipleResultsFound
|
||||
import yaml
|
||||
|
||||
from superset import sm
|
||||
from superset import security_manager
|
||||
from superset.utils import QueryStatus
|
||||
|
||||
|
||||
|
|
@ -353,4 +353,4 @@ def set_perm(mapper, connection, target): # noqa
|
|||
)
|
||||
|
||||
# add to view menu if not already exists
|
||||
merge_perm(sm, 'datasource_access', target.get_perm(), connection)
|
||||
merge_perm(security_manager, 'datasource_access', target.get_perm(), connection)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ from sqlalchemy import (
|
|||
)
|
||||
from sqlalchemy.orm import backref, relationship
|
||||
|
||||
from superset import sm
|
||||
from superset import security_manager
|
||||
from superset.models.helpers import AuditMixinNullable
|
||||
from superset.utils import QueryStatus, user_label
|
||||
|
||||
|
|
@ -76,7 +76,7 @@ class Query(Model):
|
|||
'Database',
|
||||
foreign_keys=[database_id],
|
||||
backref=backref('queries', cascade='all, delete-orphan'))
|
||||
user = relationship(sm.user_model, foreign_keys=[user_id])
|
||||
user = relationship(security_manager.user_model, foreign_keys=[user_id])
|
||||
|
||||
__table_args__ = (
|
||||
sqla.Index('ti_user_id_changed_on', user_id, changed_on),
|
||||
|
|
@ -138,7 +138,7 @@ class SavedQuery(Model, AuditMixinNullable):
|
|||
description = Column(Text)
|
||||
sql = Column(Text)
|
||||
user = relationship(
|
||||
sm.user_model,
|
||||
security_manager.user_model,
|
||||
backref=backref('saved_queries', cascade='all, delete-orphan'),
|
||||
foreign_keys=[user_id])
|
||||
database = relationship(
|
||||
|
|
|
|||
|
|
@ -7,12 +7,13 @@ from __future__ import unicode_literals
|
|||
|
||||
import logging
|
||||
|
||||
from flask import g
|
||||
from flask_appbuilder.security.sqla import models as ab_models
|
||||
from flask_appbuilder.security.sqla.manager import SecurityManager
|
||||
from sqlalchemy import or_
|
||||
|
||||
from superset import conf, db, sm
|
||||
from superset import sql_parse
|
||||
from superset.connectors.connector_registry import ConnectorRegistry
|
||||
from superset.models import core as models
|
||||
|
||||
READ_ONLY_MODEL_VIEWS = {
|
||||
'DatabaseAsync',
|
||||
|
|
@ -77,177 +78,282 @@ OBJECT_SPEC_PERMISSIONS = set([
|
|||
])
|
||||
|
||||
|
||||
def merge_perm(sm, permission_name, view_menu_name):
|
||||
# Implementation copied from sm.find_permission_view_menu.
|
||||
# TODO: use sm.find_permission_view_menu once issue
|
||||
# https://github.com/airbnb/superset/issues/1944 is resolved.
|
||||
permission = sm.find_permission(permission_name)
|
||||
view_menu = sm.find_view_menu(view_menu_name)
|
||||
pv = None
|
||||
if permission and view_menu:
|
||||
pv = sm.get_session.query(sm.permissionview_model).filter_by(
|
||||
permission=permission, view_menu=view_menu).first()
|
||||
if not pv and permission_name and view_menu_name:
|
||||
sm.add_permission_view_menu(permission_name, view_menu_name)
|
||||
class SupersetSecurityManager(SecurityManager):
|
||||
|
||||
def get_schema_perm(self, database, schema):
|
||||
if schema:
|
||||
return '[{}].[{}]'.format(database, schema)
|
||||
|
||||
def is_user_defined_permission(perm):
|
||||
return perm.permission.name in OBJECT_SPEC_PERMISSIONS
|
||||
def can_access(self, permission_name, view_name, user=None):
|
||||
"""Protecting from has_access failing from missing perms/view"""
|
||||
if not user:
|
||||
user = g.user
|
||||
if user.is_anonymous():
|
||||
return self.is_item_public(permission_name, view_name)
|
||||
return self._has_view_access(user, permission_name, view_name)
|
||||
|
||||
def all_datasource_access(self, user=None):
|
||||
return self.can_access(
|
||||
'all_datasource_access', 'all_datasource_access', user=user)
|
||||
|
||||
def get_or_create_main_db():
|
||||
logging.info('Creating database reference')
|
||||
dbobj = (
|
||||
db.session.query(models.Database)
|
||||
.filter_by(database_name='main')
|
||||
.first()
|
||||
)
|
||||
if not dbobj:
|
||||
dbobj = models.Database(database_name='main')
|
||||
dbobj.set_sqlalchemy_uri(conf.get('SQLALCHEMY_DATABASE_URI'))
|
||||
dbobj.expose_in_sqllab = True
|
||||
dbobj.allow_run_sync = True
|
||||
db.session.add(dbobj)
|
||||
db.session.commit()
|
||||
return dbobj
|
||||
def database_access(self, database, user=None):
|
||||
return (
|
||||
self.can_access(
|
||||
'all_database_access', 'all_database_access', user=user) or
|
||||
self.can_access('database_access', database.perm, user=user)
|
||||
)
|
||||
|
||||
def schema_access(self, datasource, user=None):
|
||||
return (
|
||||
self.database_access(datasource.database, user=user) or
|
||||
self.all_datasource_access(user=user) or
|
||||
self.can_access('schema_access', datasource.schema_perm, user=user)
|
||||
)
|
||||
|
||||
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_MODEL_VIEWS and
|
||||
pvm.permission.name not in READ_ONLY_PERMISSION):
|
||||
return True
|
||||
return (
|
||||
pvm.view_menu.name in ADMIN_ONLY_VIEW_MENUS or
|
||||
pvm.permission.name in ADMIN_ONLY_PERMISSIONS
|
||||
)
|
||||
def datasource_access(self, datasource, user=None):
|
||||
return (
|
||||
self.schema_access(datasource, user=user) or
|
||||
self.can_access('datasource_access', datasource.perm, user=user)
|
||||
)
|
||||
|
||||
def datasource_access_by_name(
|
||||
self, database, datasource_name, schema=None):
|
||||
from superset import db
|
||||
|
||||
def is_alpha_only(pvm):
|
||||
if (pvm.view_menu.name in GAMMA_READ_ONLY_MODEL_VIEWS and
|
||||
pvm.permission.name not in READ_ONLY_PERMISSION):
|
||||
return True
|
||||
return (
|
||||
pvm.view_menu.name in ALPHA_ONLY_VIEW_MENUS or
|
||||
pvm.permission.name in ALPHA_ONLY_PERMISSIONS
|
||||
)
|
||||
if self.database_access(database) or self.all_datasource_access():
|
||||
return True
|
||||
|
||||
schema_perm = self.get_schema_perm(database, schema)
|
||||
if schema and self.can_access('schema_access', schema_perm):
|
||||
return True
|
||||
|
||||
def is_admin_pvm(pvm):
|
||||
return not is_user_defined_permission(pvm)
|
||||
datasources = ConnectorRegistry.query_datasources_by_name(
|
||||
db.session, database, datasource_name, schema=schema)
|
||||
for datasource in datasources:
|
||||
if self.can_access('datasource_access', datasource.perm):
|
||||
return True
|
||||
return False
|
||||
|
||||
def datasource_access_by_fullname(
|
||||
self, database, full_table_name, schema):
|
||||
table_name_pieces = full_table_name.split('.')
|
||||
if len(table_name_pieces) == 2:
|
||||
table_schema = table_name_pieces[0]
|
||||
table_name = table_name_pieces[1]
|
||||
else:
|
||||
table_schema = schema
|
||||
table_name = table_name_pieces[0]
|
||||
return self.datasource_access_by_name(
|
||||
database, table_name, schema=table_schema)
|
||||
|
||||
def is_alpha_pvm(pvm):
|
||||
return not (is_user_defined_permission(pvm) or is_admin_only(pvm))
|
||||
def rejected_datasources(self, sql, database, schema):
|
||||
superset_query = sql_parse.SupersetQuery(sql)
|
||||
return [
|
||||
t for t in superset_query.tables if not
|
||||
self.datasource_access_by_fullname(database, t, schema)]
|
||||
|
||||
def user_datasource_perms(self):
|
||||
datasource_perms = set()
|
||||
for r in g.user.roles:
|
||||
for perm in r.permissions:
|
||||
if (
|
||||
perm.permission and
|
||||
'datasource_access' == perm.permission.name):
|
||||
datasource_perms.add(perm.view_menu.name)
|
||||
return datasource_perms
|
||||
|
||||
def is_gamma_pvm(pvm):
|
||||
return not (is_user_defined_permission(pvm) or is_admin_only(pvm) or
|
||||
is_alpha_only(pvm))
|
||||
def schemas_accessible_by_user(self, database, schemas):
|
||||
from superset import db
|
||||
from superset.connectors.sqla.models import SqlaTable
|
||||
if self.database_access(database) or self.all_datasource_access():
|
||||
return schemas
|
||||
|
||||
subset = set()
|
||||
for schema in schemas:
|
||||
schema_perm = self.get_schema_perm(database, schema)
|
||||
if self.can_access('schema_access', schema_perm):
|
||||
subset.add(schema)
|
||||
|
||||
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',
|
||||
}
|
||||
perms = self.user_datasource_perms()
|
||||
if perms:
|
||||
tables = (
|
||||
db.session.query(SqlaTable)
|
||||
.filter(
|
||||
SqlaTable.perm.in_(perms),
|
||||
SqlaTable.database_id == database.id,
|
||||
)
|
||||
.all()
|
||||
)
|
||||
for t in tables:
|
||||
if t.schema:
|
||||
subset.add(t.schema)
|
||||
return sorted(list(subset))
|
||||
|
||||
def accessible_by_user(self, database, datasource_names, schema=None):
|
||||
from superset import db
|
||||
if self.database_access(database) or self.all_datasource_access():
|
||||
return datasource_names
|
||||
|
||||
def is_granter_pvm(pvm):
|
||||
return pvm.permission.name in {
|
||||
'can_override_role_permissions', 'can_approve',
|
||||
}
|
||||
if schema:
|
||||
schema_perm = self.get_schema_perm(database, schema)
|
||||
if self.can_access('schema_access', schema_perm):
|
||||
return datasource_names
|
||||
|
||||
user_perms = self.user_datasource_perms()
|
||||
user_datasources = ConnectorRegistry.query_datasources_by_permissions(
|
||||
db.session, database, user_perms)
|
||||
if schema:
|
||||
names = {
|
||||
d.table_name
|
||||
for d in user_datasources if d.schema == schema}
|
||||
return [d for d in datasource_names if d in names]
|
||||
else:
|
||||
full_names = {d.full_name for d in user_datasources}
|
||||
return [d for d in datasource_names if d in full_names]
|
||||
|
||||
def set_role(role_name, pvm_check):
|
||||
logging.info('Syncing {} perms'.format(role_name))
|
||||
sesh = sm.get_session()
|
||||
pvms = sesh.query(ab_models.PermissionView).all()
|
||||
pvms = [p for p in pvms if p.permission and p.view_menu]
|
||||
role = sm.add_role(role_name)
|
||||
role_pvms = [p for p in pvms if pvm_check(p)]
|
||||
role.permissions = role_pvms
|
||||
sesh.merge(role)
|
||||
sesh.commit()
|
||||
def merge_perm(self, permission_name, view_menu_name):
|
||||
# Implementation copied from sm.find_permission_view_menu.
|
||||
# TODO: use sm.find_permission_view_menu once issue
|
||||
# https://github.com/airbnb/superset/issues/1944 is resolved.
|
||||
permission = self.find_permission(permission_name)
|
||||
view_menu = self.find_view_menu(view_menu_name)
|
||||
pv = None
|
||||
if permission and view_menu:
|
||||
pv = self.get_session.query(self.permissionview_model).filter_by(
|
||||
permission=permission, view_menu=view_menu).first()
|
||||
if not pv and permission_name and view_menu_name:
|
||||
self.add_permission_view_menu(permission_name, view_menu_name)
|
||||
|
||||
def is_user_defined_permission(self, perm):
|
||||
return perm.permission.name in OBJECT_SPEC_PERMISSIONS
|
||||
|
||||
def create_custom_permissions():
|
||||
# Global perms
|
||||
merge_perm(sm, 'all_datasource_access', 'all_datasource_access')
|
||||
merge_perm(sm, 'all_database_access', 'all_database_access')
|
||||
def create_custom_permissions(self):
|
||||
# Global perms
|
||||
self.merge_perm('all_datasource_access', 'all_datasource_access')
|
||||
self.merge_perm('all_database_access', 'all_database_access')
|
||||
|
||||
def create_missing_perms(self):
|
||||
"""Creates missing perms for datasources, schemas and metrics"""
|
||||
from superset import db
|
||||
from superset.models import core as models
|
||||
|
||||
def create_missing_perms():
|
||||
"""Creates missing perms for datasources, schemas and metrics"""
|
||||
logging.info(
|
||||
'Fetching a set of all perms to lookup which ones are missing')
|
||||
all_pvs = set()
|
||||
for pv in self.get_session.query(self.permissionview_model).all():
|
||||
if pv.permission and pv.view_menu:
|
||||
all_pvs.add((pv.permission.name, pv.view_menu.name))
|
||||
|
||||
logging.info(
|
||||
'Fetching a set of all perms to lookup which ones are missing')
|
||||
all_pvs = set()
|
||||
for pv in sm.get_session.query(sm.permissionview_model).all():
|
||||
if pv.permission and pv.view_menu:
|
||||
all_pvs.add((pv.permission.name, pv.view_menu.name))
|
||||
def merge_pv(view_menu, perm):
|
||||
"""Create permission view menu only if it doesn't exist"""
|
||||
if view_menu and perm and (view_menu, perm) not in all_pvs:
|
||||
self.merge_perm(view_menu, perm)
|
||||
|
||||
def merge_pv(view_menu, perm):
|
||||
"""Create permission view menu only if it doesn't exist"""
|
||||
if view_menu and perm and (view_menu, perm) not in all_pvs:
|
||||
merge_perm(sm, view_menu, perm)
|
||||
logging.info('Creating missing datasource permissions.')
|
||||
datasources = ConnectorRegistry.get_all_datasources(db.session)
|
||||
for datasource in datasources:
|
||||
merge_pv('datasource_access', datasource.get_perm())
|
||||
merge_pv('schema_access', datasource.schema_perm)
|
||||
|
||||
logging.info('Creating missing datasource permissions.')
|
||||
datasources = ConnectorRegistry.get_all_datasources(db.session)
|
||||
for datasource in datasources:
|
||||
merge_pv('datasource_access', datasource.get_perm())
|
||||
merge_pv('schema_access', datasource.schema_perm)
|
||||
logging.info('Creating missing database permissions.')
|
||||
databases = db.session.query(models.Database).all()
|
||||
for database in databases:
|
||||
merge_pv('database_access', database.perm)
|
||||
|
||||
logging.info('Creating missing database permissions.')
|
||||
databases = db.session.query(models.Database).all()
|
||||
for database in databases:
|
||||
merge_pv('database_access', database.perm)
|
||||
logging.info('Creating missing metrics permissions')
|
||||
metrics = []
|
||||
for datasource_class in ConnectorRegistry.sources.values():
|
||||
metrics += list(db.session.query(datasource_class.metric_class).all())
|
||||
|
||||
logging.info('Creating missing metrics permissions')
|
||||
metrics = []
|
||||
for datasource_class in ConnectorRegistry.sources.values():
|
||||
metrics += list(db.session.query(datasource_class.metric_class).all())
|
||||
for metric in metrics:
|
||||
if metric.is_restricted:
|
||||
merge_pv('metric_access', metric.perm)
|
||||
|
||||
for metric in metrics:
|
||||
if metric.is_restricted:
|
||||
merge_pv('metric_access', metric.perm)
|
||||
def clean_perms(self):
|
||||
"""FAB leaves faulty permissions that need to be cleaned up"""
|
||||
logging.info('Cleaning faulty perms')
|
||||
sesh = self.get_session
|
||||
pvms = (
|
||||
sesh.query(ab_models.PermissionView)
|
||||
.filter(or_(
|
||||
ab_models.PermissionView.permission == None, # NOQA
|
||||
ab_models.PermissionView.view_menu == None, # NOQA
|
||||
))
|
||||
)
|
||||
deleted_count = pvms.delete()
|
||||
sesh.commit()
|
||||
if deleted_count:
|
||||
logging.info('Deleted {} faulty permissions'.format(deleted_count))
|
||||
|
||||
def sync_role_definitions(self):
|
||||
"""Inits the Superset application with security roles and such"""
|
||||
from superset import conf
|
||||
logging.info('Syncing role definition')
|
||||
|
||||
def clean_perms():
|
||||
"""FAB leaves faulty permissions that need to be cleaned up"""
|
||||
logging.info('Cleaning faulty perms')
|
||||
sesh = sm.get_session()
|
||||
pvms = (
|
||||
sesh.query(ab_models.PermissionView)
|
||||
.filter(or_(
|
||||
ab_models.PermissionView.permission == None, # NOQA
|
||||
ab_models.PermissionView.view_menu == None, # NOQA
|
||||
))
|
||||
)
|
||||
deleted_count = pvms.delete()
|
||||
sesh.commit()
|
||||
if deleted_count:
|
||||
logging.info('Deleted {} faulty permissions'.format(deleted_count))
|
||||
self.create_custom_permissions()
|
||||
|
||||
# Creating default roles
|
||||
self.set_role('Admin', self.is_admin_pvm)
|
||||
self.set_role('Alpha', self.is_alpha_pvm)
|
||||
self.set_role('Gamma', self.is_gamma_pvm)
|
||||
self.set_role('granter', self.is_granter_pvm)
|
||||
self.set_role('sql_lab', self.is_sql_lab_pvm)
|
||||
|
||||
def sync_role_definitions():
|
||||
"""Inits the Superset application with security roles and such"""
|
||||
logging.info('Syncing role definition')
|
||||
if conf.get('PUBLIC_ROLE_LIKE_GAMMA', False):
|
||||
self.set_role('Public', self.is_gamma_pvm)
|
||||
|
||||
get_or_create_main_db()
|
||||
create_custom_permissions()
|
||||
self.create_missing_perms()
|
||||
|
||||
# Creating default roles
|
||||
set_role('Admin', is_admin_pvm)
|
||||
set_role('Alpha', is_alpha_pvm)
|
||||
set_role('Gamma', is_gamma_pvm)
|
||||
set_role('granter', is_granter_pvm)
|
||||
set_role('sql_lab', is_sql_lab_pvm)
|
||||
# commit role and view menu updates
|
||||
self.get_session.commit()
|
||||
self.clean_perms()
|
||||
|
||||
if conf.get('PUBLIC_ROLE_LIKE_GAMMA', False):
|
||||
set_role('Public', is_gamma_pvm)
|
||||
def set_role(self, role_name, pvm_check):
|
||||
logging.info('Syncing {} perms'.format(role_name))
|
||||
sesh = self.get_session
|
||||
pvms = sesh.query(ab_models.PermissionView).all()
|
||||
pvms = [p for p in pvms if p.permission and p.view_menu]
|
||||
role = self.add_role(role_name)
|
||||
role_pvms = [p for p in pvms if pvm_check(p)]
|
||||
role.permissions = role_pvms
|
||||
sesh.merge(role)
|
||||
sesh.commit()
|
||||
|
||||
create_missing_perms()
|
||||
def is_admin_only(self, pvm):
|
||||
# not readonly operations on read only model views allowed only for admins
|
||||
if (pvm.view_menu.name in READ_ONLY_MODEL_VIEWS and
|
||||
pvm.permission.name not in READ_ONLY_PERMISSION):
|
||||
return True
|
||||
return (
|
||||
pvm.view_menu.name in ADMIN_ONLY_VIEW_MENUS or
|
||||
pvm.permission.name in ADMIN_ONLY_PERMISSIONS
|
||||
)
|
||||
|
||||
# commit role and view menu updates
|
||||
sm.get_session.commit()
|
||||
clean_perms()
|
||||
def is_alpha_only(self, pvm):
|
||||
if (pvm.view_menu.name in GAMMA_READ_ONLY_MODEL_VIEWS and
|
||||
pvm.permission.name not in READ_ONLY_PERMISSION):
|
||||
return True
|
||||
return (
|
||||
pvm.view_menu.name in ALPHA_ONLY_VIEW_MENUS or
|
||||
pvm.permission.name in ALPHA_ONLY_PERMISSIONS
|
||||
)
|
||||
|
||||
def is_admin_pvm(self, pvm):
|
||||
return not self.is_user_defined_permission(pvm)
|
||||
|
||||
def is_alpha_pvm(self, pvm):
|
||||
return not (self.is_user_defined_permission(pvm) or self.is_admin_only(pvm))
|
||||
|
||||
def is_gamma_pvm(self, pvm):
|
||||
return not (self.is_user_defined_permission(pvm) or self.is_admin_only(pvm) or
|
||||
self.is_alpha_only(pvm))
|
||||
|
||||
def is_sql_lab_pvm(self, 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(self, pvm):
|
||||
return pvm.permission.name in {
|
||||
'can_override_role_permissions', 'can_approve',
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import sqlalchemy
|
|||
from sqlalchemy.orm import sessionmaker
|
||||
from sqlalchemy.pool import NullPool
|
||||
|
||||
from superset import app, dataframe, db, results_backend, sm, utils
|
||||
from superset import app, dataframe, db, results_backend, security_manager, utils
|
||||
from superset.db_engine_specs import LimitMethod
|
||||
from superset.jinja_context import get_template_processor
|
||||
from superset.models.sql_lab import Query
|
||||
|
|
@ -196,7 +196,8 @@ def execute_sql(
|
|||
# Hook to allow environment-specific mutation (usually comments) to the SQL
|
||||
SQL_QUERY_MUTATOR = config.get('SQL_QUERY_MUTATOR')
|
||||
if SQL_QUERY_MUTATOR:
|
||||
executed_sql = SQL_QUERY_MUTATOR(executed_sql, user_name, sm, database)
|
||||
executed_sql = SQL_QUERY_MUTATOR(
|
||||
executed_sql, user_name, security_manager, database)
|
||||
|
||||
query.executed_sql = executed_sql
|
||||
query.status = QueryStatus.RUNNING
|
||||
|
|
|
|||
|
|
@ -55,13 +55,6 @@ EPOCH = datetime(1970, 1, 1)
|
|||
DTTM_ALIAS = '__timestamp'
|
||||
|
||||
|
||||
def can_access(sm, permission_name, view_name, user):
|
||||
"""Protecting from has_access failing from missing perms/view"""
|
||||
if user.is_anonymous():
|
||||
return sm.is_item_public(permission_name, view_name)
|
||||
return sm._has_view_access(user, permission_name, view_name)
|
||||
|
||||
|
||||
def flasher(msg, severity=None):
|
||||
"""Flask's flash if available, logging call if not"""
|
||||
try:
|
||||
|
|
@ -477,11 +470,6 @@ def get_datasource_full_name(database_name, datasource_name, schema=None):
|
|||
return '[{}].[{}].[{}]'.format(database_name, schema, datasource_name)
|
||||
|
||||
|
||||
def get_schema_perm(database, schema):
|
||||
if schema:
|
||||
return '[{}].[{}]'.format(database, schema)
|
||||
|
||||
|
||||
def validate_json(obj):
|
||||
if obj:
|
||||
try:
|
||||
|
|
@ -834,3 +822,23 @@ def user_label(user):
|
|||
return user.first_name + ' ' + user.last_name
|
||||
else:
|
||||
return user.username
|
||||
|
||||
|
||||
def get_or_create_main_db():
|
||||
from superset import conf, db
|
||||
from superset.models import core as models
|
||||
|
||||
logging.info('Creating database reference')
|
||||
dbobj = (
|
||||
db.session.query(models.Database)
|
||||
.filter_by(database_name='main')
|
||||
.first()
|
||||
)
|
||||
if not dbobj:
|
||||
dbobj = models.Database(database_name='main')
|
||||
dbobj.set_sqlalchemy_uri(conf.get('SQLALCHEMY_DATABASE_URI'))
|
||||
dbobj.expose_in_sqllab = True
|
||||
dbobj.allow_run_sync = True
|
||||
db.session.add(dbobj)
|
||||
db.session.commit()
|
||||
return dbobj
|
||||
|
|
|
|||
|
|
@ -20,9 +20,7 @@ from flask_babel import gettext as __
|
|||
from flask_babel import lazy_gettext as _
|
||||
import yaml
|
||||
|
||||
from superset import appbuilder, conf, db, sm, sql_parse, utils
|
||||
from superset.connectors.connector_registry import ConnectorRegistry
|
||||
from superset.connectors.sqla.models import SqlaTable
|
||||
from superset import conf, security_manager, utils
|
||||
from superset.translations.utils import get_language_pack
|
||||
|
||||
FRONTEND_CONF_KEYS = (
|
||||
|
|
@ -83,131 +81,11 @@ def get_datasource_exist_error_mgs(full_name):
|
|||
def get_user_roles():
|
||||
if g.user.is_anonymous():
|
||||
public_role = conf.get('AUTH_ROLE_PUBLIC')
|
||||
return [appbuilder.sm.find_role(public_role)] if public_role else []
|
||||
return [security_manager.find_role(public_role)] if public_role else []
|
||||
return g.user.roles
|
||||
|
||||
|
||||
class BaseSupersetView(BaseView):
|
||||
def can_access(self, permission_name, view_name, user=None):
|
||||
if not user:
|
||||
user = g.user
|
||||
return utils.can_access(
|
||||
appbuilder.sm, permission_name, view_name, user)
|
||||
|
||||
def all_datasource_access(self, user=None):
|
||||
return self.can_access(
|
||||
'all_datasource_access', 'all_datasource_access', user=user)
|
||||
|
||||
def database_access(self, database, user=None):
|
||||
return (
|
||||
self.can_access(
|
||||
'all_database_access', 'all_database_access', user=user) or
|
||||
self.can_access('database_access', database.perm, user=user)
|
||||
)
|
||||
|
||||
def schema_access(self, datasource, user=None):
|
||||
return (
|
||||
self.database_access(datasource.database, user=user) or
|
||||
self.all_datasource_access(user=user) or
|
||||
self.can_access('schema_access', datasource.schema_perm, user=user)
|
||||
)
|
||||
|
||||
def datasource_access(self, datasource, user=None):
|
||||
return (
|
||||
self.schema_access(datasource, user=user) or
|
||||
self.can_access('datasource_access', datasource.perm, user=user)
|
||||
)
|
||||
|
||||
def datasource_access_by_name(
|
||||
self, database, datasource_name, schema=None):
|
||||
if self.database_access(database) or self.all_datasource_access():
|
||||
return True
|
||||
|
||||
schema_perm = utils.get_schema_perm(database, schema)
|
||||
if schema and self.can_access('schema_access', schema_perm):
|
||||
return True
|
||||
|
||||
datasources = ConnectorRegistry.query_datasources_by_name(
|
||||
db.session, database, datasource_name, schema=schema)
|
||||
for datasource in datasources:
|
||||
if self.can_access('datasource_access', datasource.perm):
|
||||
return True
|
||||
return False
|
||||
|
||||
def datasource_access_by_fullname(
|
||||
self, database, full_table_name, schema):
|
||||
table_name_pieces = full_table_name.split('.')
|
||||
if len(table_name_pieces) == 2:
|
||||
table_schema = table_name_pieces[0]
|
||||
table_name = table_name_pieces[1]
|
||||
else:
|
||||
table_schema = schema
|
||||
table_name = table_name_pieces[0]
|
||||
return self.datasource_access_by_name(
|
||||
database, table_name, schema=table_schema)
|
||||
|
||||
def rejected_datasources(self, sql, database, schema):
|
||||
superset_query = sql_parse.SupersetQuery(sql)
|
||||
return [
|
||||
t for t in superset_query.tables if not
|
||||
self.datasource_access_by_fullname(database, t, schema)]
|
||||
|
||||
def user_datasource_perms(self):
|
||||
datasource_perms = set()
|
||||
for r in g.user.roles:
|
||||
for perm in r.permissions:
|
||||
if (
|
||||
perm.permission and
|
||||
'datasource_access' == perm.permission.name):
|
||||
datasource_perms.add(perm.view_menu.name)
|
||||
return datasource_perms
|
||||
|
||||
def schemas_accessible_by_user(self, database, schemas):
|
||||
if self.database_access(database) or self.all_datasource_access():
|
||||
return schemas
|
||||
|
||||
subset = set()
|
||||
for schema in schemas:
|
||||
schema_perm = utils.get_schema_perm(database, schema)
|
||||
if self.can_access('schema_access', schema_perm):
|
||||
subset.add(schema)
|
||||
|
||||
perms = self.user_datasource_perms()
|
||||
if perms:
|
||||
tables = (
|
||||
db.session.query(SqlaTable)
|
||||
.filter(
|
||||
SqlaTable.perm.in_(perms),
|
||||
SqlaTable.database_id == database.id,
|
||||
)
|
||||
.all()
|
||||
)
|
||||
for t in tables:
|
||||
if t.schema:
|
||||
subset.add(t.schema)
|
||||
return sorted(list(subset))
|
||||
|
||||
def accessible_by_user(self, database, datasource_names, schema=None):
|
||||
if self.database_access(database) or self.all_datasource_access():
|
||||
return datasource_names
|
||||
|
||||
if schema:
|
||||
schema_perm = utils.get_schema_perm(database, schema)
|
||||
if self.can_access('schema_access', schema_perm):
|
||||
return datasource_names
|
||||
|
||||
user_perms = self.user_datasource_perms()
|
||||
user_datasources = ConnectorRegistry.query_datasources_by_permissions(
|
||||
db.session, database, user_perms)
|
||||
if schema:
|
||||
names = {
|
||||
d.table_name
|
||||
for d in user_datasources if d.schema == schema}
|
||||
return [d for d in datasource_names if d in names]
|
||||
else:
|
||||
full_names = {d.full_name for d in user_datasources}
|
||||
return [d for d in datasource_names if d in full_names]
|
||||
|
||||
def common_bootsrap_payload(self):
|
||||
"""Common data always sent to the client"""
|
||||
messages = get_flashed_messages(with_categories=True)
|
||||
|
|
@ -274,31 +152,32 @@ class DeleteMixin(object):
|
|||
except Exception as e:
|
||||
flash(str(e), 'danger')
|
||||
else:
|
||||
view_menu = sm.find_view_menu(item.get_perm())
|
||||
pvs = sm.get_session.query(sm.permissionview_model).filter_by(
|
||||
view_menu = security_manager.find_view_menu(item.get_perm())
|
||||
pvs = security_manager.get_session.query(
|
||||
security_manager.permissionview_model).filter_by(
|
||||
view_menu=view_menu).all()
|
||||
|
||||
schema_view_menu = None
|
||||
if hasattr(item, 'schema_perm'):
|
||||
schema_view_menu = sm.find_view_menu(item.schema_perm)
|
||||
schema_view_menu = security_manager.find_view_menu(item.schema_perm)
|
||||
|
||||
pvs.extend(sm.get_session.query(
|
||||
sm.permissionview_model).filter_by(
|
||||
pvs.extend(security_manager.get_session.query(
|
||||
security_manager.permissionview_model).filter_by(
|
||||
view_menu=schema_view_menu).all())
|
||||
|
||||
if self.datamodel.delete(item):
|
||||
self.post_delete(item)
|
||||
|
||||
for pv in pvs:
|
||||
sm.get_session.delete(pv)
|
||||
security_manager.get_session.delete(pv)
|
||||
|
||||
if view_menu:
|
||||
sm.get_session.delete(view_menu)
|
||||
security_manager.get_session.delete(view_menu)
|
||||
|
||||
if schema_view_menu:
|
||||
sm.get_session.delete(schema_view_menu)
|
||||
security_manager.get_session.delete(schema_view_menu)
|
||||
|
||||
sm.get_session.commit()
|
||||
security_manager.get_session.commit()
|
||||
|
||||
flash(*self.datamodel.message)
|
||||
self.update_redirect()
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ from werkzeug.routing import BaseConverter
|
|||
from werkzeug.utils import secure_filename
|
||||
|
||||
from superset import (
|
||||
app, appbuilder, cache, db, results_backend, security, sm, sql_lab, utils,
|
||||
app, appbuilder, cache, db, results_backend, security_manager, sql_lab, utils,
|
||||
viz,
|
||||
)
|
||||
from superset.connectors.connector_registry import ConnectorRegistry
|
||||
|
|
@ -57,7 +57,6 @@ from .utils import bootstrap_user_data
|
|||
config = app.config
|
||||
stats_logger = config.get('STATS_LOGGER')
|
||||
log_this = models.Log.log_this
|
||||
can_access = utils.can_access
|
||||
DAR = models.DatasourceAccessRequest
|
||||
|
||||
|
||||
|
|
@ -284,10 +283,10 @@ class DatabaseView(SupersetModelView, DeleteMixin, YamlExportMixin): # noqa
|
|||
|
||||
def pre_add(self, db):
|
||||
db.set_sqlalchemy_uri(db.sqlalchemy_uri)
|
||||
security.merge_perm(sm, 'database_access', db.perm)
|
||||
security_manager.merge_perm('database_access', db.perm)
|
||||
for schema in db.all_schema_names():
|
||||
security.merge_perm(
|
||||
sm, 'schema_access', utils.get_schema_perm(db, schema))
|
||||
security_manager.merge_perm(
|
||||
'schema_access', security_manager.get_schema_perm(db, schema))
|
||||
|
||||
def pre_update(self, db):
|
||||
self.pre_add(db)
|
||||
|
|
@ -809,13 +808,13 @@ class Superset(BaseSupersetView):
|
|||
existing_datasources = ConnectorRegistry.get_all_datasources(db.session)
|
||||
datasources = [
|
||||
d for d in existing_datasources if d.full_name in db_ds_names]
|
||||
role = sm.find_role(role_name)
|
||||
role = security_manager.find_role(role_name)
|
||||
# remove all permissions
|
||||
role.permissions = []
|
||||
# grant permissions to the list of datasources
|
||||
granted_perms = []
|
||||
for datasource in datasources:
|
||||
view_menu_perm = sm.find_permission_view_menu(
|
||||
view_menu_perm = security_manager.find_permission_view_menu(
|
||||
view_menu_name=datasource.perm,
|
||||
permission_name='datasource_access')
|
||||
# prevent creating empty permissions
|
||||
|
|
@ -854,7 +853,7 @@ class Superset(BaseSupersetView):
|
|||
|
||||
has_access = all(
|
||||
(
|
||||
datasource and self.datasource_access(datasource)
|
||||
datasource and security_manager.datasource_access(datasource)
|
||||
for datasource in datasources
|
||||
))
|
||||
if has_access:
|
||||
|
|
@ -884,9 +883,9 @@ class Superset(BaseSupersetView):
|
|||
for r in session.query(DAR).all():
|
||||
datasource = ConnectorRegistry.get_datasource(
|
||||
r.datasource_type, r.datasource_id, session)
|
||||
user = sm.get_user_by_id(r.created_by_fk)
|
||||
user = security_manager.get_user_by_id(r.created_by_fk)
|
||||
if not datasource or \
|
||||
self.datasource_access(datasource, user):
|
||||
security_manager.datasource_access(datasource, user):
|
||||
# datasource does not exist anymore
|
||||
session.delete(r)
|
||||
session.commit()
|
||||
|
|
@ -904,7 +903,7 @@ class Superset(BaseSupersetView):
|
|||
flash(DATASOURCE_MISSING_ERR, 'alert')
|
||||
return json_error_response(DATASOURCE_MISSING_ERR)
|
||||
|
||||
requested_by = sm.find_user(username=created_by_username)
|
||||
requested_by = security_manager.find_user(username=created_by_username)
|
||||
if not requested_by:
|
||||
flash(USER_MISSING_ERR, 'alert')
|
||||
return json_error_response(USER_MISSING_ERR)
|
||||
|
|
@ -923,10 +922,10 @@ class Superset(BaseSupersetView):
|
|||
return json_error_response(ACCESS_REQUEST_MISSING_ERR)
|
||||
|
||||
# check if you can approve
|
||||
if self.all_datasource_access() or g.user.id == datasource.owner_id:
|
||||
if security_manager.all_datasource_access() or g.user.id == datasource.owner_id:
|
||||
# can by done by admin only
|
||||
if role_to_grant:
|
||||
role = sm.find_role(role_to_grant)
|
||||
role = security_manager.find_role(role_to_grant)
|
||||
requested_by.roles.append(role)
|
||||
msg = __(
|
||||
'%(user)s was granted the role %(role)s that gives access '
|
||||
|
|
@ -940,10 +939,10 @@ class Superset(BaseSupersetView):
|
|||
flash(msg, 'info')
|
||||
|
||||
if role_to_extend:
|
||||
perm_view = sm.find_permission_view_menu(
|
||||
perm_view = security_manager.find_permission_view_menu(
|
||||
'email/datasource_access', datasource.perm)
|
||||
role = sm.find_role(role_to_extend)
|
||||
sm.add_permission_role(role, perm_view)
|
||||
role = security_manager.find_role(role_to_extend)
|
||||
security_manager.add_permission_role(role, perm_view)
|
||||
msg = __('Role %(r)s was extended to provide the access to '
|
||||
'the datasource %(ds)s', r=role_to_extend,
|
||||
ds=datasource.full_name)
|
||||
|
|
@ -1085,7 +1084,7 @@ class Superset(BaseSupersetView):
|
|||
utils.error_msg_from_exception(e),
|
||||
stacktrace=traceback.format_exc())
|
||||
|
||||
if not self.datasource_access(viz_obj.datasource):
|
||||
if not security_manager.datasource_access(viz_obj.datasource, g.user):
|
||||
return json_error_response(DATASOURCE_ACCESS_ERR, status=404)
|
||||
|
||||
if csv:
|
||||
|
|
@ -1245,7 +1244,7 @@ class Superset(BaseSupersetView):
|
|||
flash(DATASOURCE_MISSING_ERR, 'danger')
|
||||
return redirect(error_redirect)
|
||||
|
||||
if not self.datasource_access(datasource):
|
||||
if not security_manager.datasource_access(datasource):
|
||||
flash(
|
||||
__(get_datasource_access_error_msg(datasource.name)),
|
||||
'danger')
|
||||
|
|
@ -1260,9 +1259,10 @@ class Superset(BaseSupersetView):
|
|||
return redirect(datasource.default_endpoint)
|
||||
|
||||
# slc perms
|
||||
slice_add_perm = self.can_access('can_add', 'SliceModelView')
|
||||
slice_add_perm = security_manager.can_access('can_add', 'SliceModelView')
|
||||
slice_overwrite_perm = is_owner(slc, g.user)
|
||||
slice_download_perm = self.can_access('can_download', 'SliceModelView')
|
||||
slice_download_perm = security_manager.can_access(
|
||||
'can_download', 'SliceModelView')
|
||||
|
||||
form_data['datasource'] = str(datasource_id) + '__' + datasource_type
|
||||
|
||||
|
|
@ -1342,7 +1342,7 @@ class Superset(BaseSupersetView):
|
|||
datasource_type, datasource_id, db.session)
|
||||
if not datasource:
|
||||
return json_error_response(DATASOURCE_MISSING_ERR)
|
||||
if not self.datasource_access(datasource):
|
||||
if not security_manager.datasource_access(datasource):
|
||||
return json_error_response(DATASOURCE_ACCESS_ERR)
|
||||
|
||||
payload = json.dumps(
|
||||
|
|
@ -1402,7 +1402,7 @@ class Superset(BaseSupersetView):
|
|||
'info')
|
||||
elif request.args.get('add_to_dash') == 'new':
|
||||
# check create dashboard permissions
|
||||
dash_add_perm = self.can_access('can_add', 'DashboardModelView')
|
||||
dash_add_perm = security_manager.can_access('can_add', 'DashboardModelView')
|
||||
if not dash_add_perm:
|
||||
return json_error_response(
|
||||
_('You don\'t have the rights to ') + _('create a ') + _('dashboard'),
|
||||
|
|
@ -1501,7 +1501,7 @@ class Superset(BaseSupersetView):
|
|||
.one()
|
||||
)
|
||||
schemas = database.all_schema_names()
|
||||
schemas = self.schemas_accessible_by_user(database, schemas)
|
||||
schemas = security_manager.schemas_accessible_by_user(database, schemas)
|
||||
return Response(
|
||||
json.dumps({'schemas': schemas}),
|
||||
mimetype='application/json')
|
||||
|
|
@ -1515,9 +1515,9 @@ class Superset(BaseSupersetView):
|
|||
schema = utils.js_string_to_python(schema)
|
||||
substr = utils.js_string_to_python(substr)
|
||||
database = db.session.query(models.Database).filter_by(id=db_id).one()
|
||||
table_names = self.accessible_by_user(
|
||||
table_names = security_manager.accessible_by_user(
|
||||
database, database.all_table_names(schema), schema)
|
||||
view_names = self.accessible_by_user(
|
||||
view_names = security_manager.accessible_by_user(
|
||||
database, database.all_view_names(schema), schema)
|
||||
|
||||
if substr:
|
||||
|
|
@ -1761,7 +1761,7 @@ class Superset(BaseSupersetView):
|
|||
@expose('/fave_dashboards_by_username/<username>/', methods=['GET'])
|
||||
def fave_dashboards_by_username(self, username):
|
||||
"""This lets us use a user's username to pull favourite dashboards"""
|
||||
user = sm.find_user(username=username)
|
||||
user = security_manager.find_user(username=username)
|
||||
return self.fave_dashboards(user.get_id())
|
||||
|
||||
@api
|
||||
|
|
@ -2041,7 +2041,7 @@ class Superset(BaseSupersetView):
|
|||
|
||||
if config.get('ENABLE_ACCESS_REQUEST'):
|
||||
for datasource in datasources:
|
||||
if datasource and not self.datasource_access(datasource):
|
||||
if datasource and not security_manager.datasource_access(datasource):
|
||||
flash(
|
||||
__(get_datasource_access_error_msg(datasource.name)),
|
||||
'danger')
|
||||
|
|
@ -2057,7 +2057,7 @@ class Superset(BaseSupersetView):
|
|||
|
||||
dash_edit_perm = check_ownership(dash, raise_if_false=False)
|
||||
dash_save_perm = \
|
||||
dash_edit_perm and self.can_access('can_save_dash', 'Superset')
|
||||
dash_edit_perm and security_manager.can_access('can_save_dash', 'Superset')
|
||||
|
||||
standalone_mode = request.args.get('standalone') == 'true'
|
||||
|
||||
|
|
@ -2108,7 +2108,7 @@ class Superset(BaseSupersetView):
|
|||
metrics_spec: list of metrics (dictionary). Metric consists of
|
||||
2 attributes: type and name. Type can be count,
|
||||
etc. `count` type is stored internally as longSum
|
||||
other fields will be ignored.
|
||||
other fields will be ignored.
|
||||
|
||||
Example: {
|
||||
'name': 'test_click',
|
||||
|
|
@ -2121,7 +2121,7 @@ class Superset(BaseSupersetView):
|
|||
user_name = payload['user']
|
||||
cluster_name = payload['cluster']
|
||||
|
||||
user = sm.find_user(username=user_name)
|
||||
user = security_manager.find_user(username=user_name)
|
||||
DruidDatasource = ConnectorRegistry.sources['druid']
|
||||
DruidCluster = DruidDatasource.cluster_class
|
||||
if not user:
|
||||
|
|
@ -2324,7 +2324,7 @@ class Superset(BaseSupersetView):
|
|||
)
|
||||
|
||||
query = db.session.query(Query).filter_by(results_key=key).one()
|
||||
rejected_tables = self.rejected_datasources(
|
||||
rejected_tables = security_manager.rejected_datasources(
|
||||
query.sql, query.database, query.schema)
|
||||
if rejected_tables:
|
||||
return json_error_response(get_datasource_access_error_msg(
|
||||
|
|
@ -2373,7 +2373,7 @@ class Superset(BaseSupersetView):
|
|||
json_error_response(
|
||||
'Database with id {} is missing.'.format(database_id))
|
||||
|
||||
rejected_tables = self.rejected_datasources(sql, mydb, schema)
|
||||
rejected_tables = security_manager.rejected_datasources(sql, mydb, schema)
|
||||
if rejected_tables:
|
||||
return json_error_response(get_datasource_access_error_msg(
|
||||
'{}'.format(rejected_tables)))
|
||||
|
|
@ -2470,7 +2470,7 @@ class Superset(BaseSupersetView):
|
|||
.one()
|
||||
)
|
||||
|
||||
rejected_tables = self.rejected_datasources(
|
||||
rejected_tables = security_manager.rejected_datasources(
|
||||
query.sql, query.database, query.schema)
|
||||
if rejected_tables:
|
||||
flash(get_datasource_access_error_msg('{}'.format(rejected_tables)))
|
||||
|
|
@ -2514,7 +2514,7 @@ class Superset(BaseSupersetView):
|
|||
return json_error_response(DATASOURCE_MISSING_ERR)
|
||||
|
||||
# Check permission for datasource
|
||||
if not self.datasource_access(datasource):
|
||||
if not security_manager.datasource_access(datasource):
|
||||
return json_error_response(DATASOURCE_ACCESS_ERR)
|
||||
return json_success(json.dumps(datasource.data))
|
||||
|
||||
|
|
@ -2662,7 +2662,7 @@ class Superset(BaseSupersetView):
|
|||
get the database query string for this slice
|
||||
"""
|
||||
viz_obj = self.get_viz(slice_id)
|
||||
if not self.datasource_access(viz_obj.datasource):
|
||||
if not security_manager.datasource_access(viz_obj.datasource):
|
||||
return json_error_response(DATASOURCE_ACCESS_ERR, status=401)
|
||||
return self.get_query_string_response(viz_obj)
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import unittest
|
|||
|
||||
import mock
|
||||
|
||||
from superset import app, db, security, sm
|
||||
from superset import app, db, security_manager
|
||||
from superset.connectors.connector_registry import ConnectorRegistry
|
||||
from superset.connectors.druid.models import DruidDatasource
|
||||
from superset.connectors.sqla.models import SqlaTable
|
||||
|
|
@ -70,13 +70,14 @@ def create_access_request(session, ds_type, ds_name, role_name, user_name):
|
|||
else:
|
||||
ds = session.query(ds_class).filter(
|
||||
ds_class.datasource_name == ds_name).first()
|
||||
ds_perm_view = sm.find_permission_view_menu(
|
||||
ds_perm_view = security_manager.find_permission_view_menu(
|
||||
'datasource_access', ds.perm)
|
||||
sm.add_permission_role(sm.find_role(role_name), ds_perm_view)
|
||||
security_manager.add_permission_role(
|
||||
security_manager.find_role(role_name), ds_perm_view)
|
||||
access_request = models.DatasourceAccessRequest(
|
||||
datasource_id=ds.id,
|
||||
datasource_type=ds_type,
|
||||
created_by_fk=sm.find_user(username=user_name).id,
|
||||
created_by_fk=security_manager.find_user(username=user_name).id,
|
||||
)
|
||||
session.add(access_request)
|
||||
session.commit()
|
||||
|
|
@ -89,21 +90,21 @@ class RequestAccessTests(SupersetTestCase):
|
|||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
sm.add_role('override_me')
|
||||
sm.add_role(TEST_ROLE_1)
|
||||
sm.add_role(TEST_ROLE_2)
|
||||
sm.add_role(DB_ACCESS_ROLE)
|
||||
sm.add_role(SCHEMA_ACCESS_ROLE)
|
||||
security_manager.add_role('override_me')
|
||||
security_manager.add_role(TEST_ROLE_1)
|
||||
security_manager.add_role(TEST_ROLE_2)
|
||||
security_manager.add_role(DB_ACCESS_ROLE)
|
||||
security_manager.add_role(SCHEMA_ACCESS_ROLE)
|
||||
db.session.commit()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
override_me = sm.find_role('override_me')
|
||||
override_me = security_manager.find_role('override_me')
|
||||
db.session.delete(override_me)
|
||||
db.session.delete(sm.find_role(TEST_ROLE_1))
|
||||
db.session.delete(sm.find_role(TEST_ROLE_2))
|
||||
db.session.delete(sm.find_role(DB_ACCESS_ROLE))
|
||||
db.session.delete(sm.find_role(SCHEMA_ACCESS_ROLE))
|
||||
db.session.delete(security_manager.find_role(TEST_ROLE_1))
|
||||
db.session.delete(security_manager.find_role(TEST_ROLE_2))
|
||||
db.session.delete(security_manager.find_role(DB_ACCESS_ROLE))
|
||||
db.session.delete(security_manager.find_role(SCHEMA_ACCESS_ROLE))
|
||||
db.session.commit()
|
||||
|
||||
def setUp(self):
|
||||
|
|
@ -111,7 +112,7 @@ class RequestAccessTests(SupersetTestCase):
|
|||
|
||||
def tearDown(self):
|
||||
self.logout()
|
||||
override_me = sm.find_role('override_me')
|
||||
override_me = security_manager.find_role('override_me')
|
||||
override_me.permissions = []
|
||||
db.session.commit()
|
||||
db.session.close()
|
||||
|
|
@ -133,7 +134,7 @@ class RequestAccessTests(SupersetTestCase):
|
|||
content_type='application/json')
|
||||
self.assertEquals(201, response.status_code)
|
||||
|
||||
updated_override_me = sm.find_role('override_me')
|
||||
updated_override_me = security_manager.find_role('override_me')
|
||||
self.assertEquals(1, len(updated_override_me.permissions))
|
||||
birth_names = self.get_table_by_name('birth_names')
|
||||
self.assertEquals(
|
||||
|
|
@ -150,7 +151,7 @@ class RequestAccessTests(SupersetTestCase):
|
|||
content_type='application/json')
|
||||
self.assertEquals(201, response.status_code)
|
||||
|
||||
updated_role = sm.find_role('override_me')
|
||||
updated_role = security_manager.find_role('override_me')
|
||||
perms = sorted(
|
||||
updated_role.permissions, key=lambda p: p.view_menu.name)
|
||||
druid_ds_1 = self.get_druid_ds_by_name('druid_ds_1')
|
||||
|
|
@ -169,9 +170,9 @@ class RequestAccessTests(SupersetTestCase):
|
|||
self.assertEquals(3, len(perms))
|
||||
|
||||
def test_override_role_permissions_drops_absent_perms(self):
|
||||
override_me = sm.find_role('override_me')
|
||||
override_me = security_manager.find_role('override_me')
|
||||
override_me.permissions.append(
|
||||
sm.find_permission_view_menu(
|
||||
security_manager.find_permission_view_menu(
|
||||
view_menu_name=self.get_table_by_name('long_lat').perm,
|
||||
permission_name='datasource_access'),
|
||||
)
|
||||
|
|
@ -182,7 +183,7 @@ class RequestAccessTests(SupersetTestCase):
|
|||
data=json.dumps(ROLE_TABLES_PERM_DATA),
|
||||
content_type='application/json')
|
||||
self.assertEquals(201, response.status_code)
|
||||
updated_override_me = sm.find_role('override_me')
|
||||
updated_override_me = security_manager.find_role('override_me')
|
||||
self.assertEquals(1, len(updated_override_me.permissions))
|
||||
birth_names = self.get_table_by_name('birth_names')
|
||||
self.assertEquals(
|
||||
|
|
@ -218,8 +219,8 @@ class RequestAccessTests(SupersetTestCase):
|
|||
access_requests = self.get_access_requests('gamma', 'table', ds_1_id)
|
||||
self.assertFalse(access_requests)
|
||||
|
||||
gamma_user = sm.find_user(username='gamma')
|
||||
gamma_user.roles.remove(sm.find_role('test_role1'))
|
||||
gamma_user = security_manager.find_user(username='gamma')
|
||||
gamma_user.roles.remove(security_manager.find_role('test_role1'))
|
||||
|
||||
def test_clean_requests_after_alpha_grant(self):
|
||||
session = db.session
|
||||
|
|
@ -234,8 +235,8 @@ class RequestAccessTests(SupersetTestCase):
|
|||
session, 'table', 'birth_names', TEST_ROLE_2, 'gamma2')
|
||||
ds_1_id = access_request1.datasource_id
|
||||
# gamma becomes alpha
|
||||
alpha_role = sm.find_role('Alpha')
|
||||
gamma_user = sm.find_user(username='gamma')
|
||||
alpha_role = security_manager.find_role('Alpha')
|
||||
gamma_user = security_manager.find_user(username='gamma')
|
||||
gamma_user.roles.append(alpha_role)
|
||||
session.commit()
|
||||
access_requests = self.get_access_requests('gamma', 'table', ds_1_id)
|
||||
|
|
@ -245,8 +246,8 @@ class RequestAccessTests(SupersetTestCase):
|
|||
access_requests = self.get_access_requests('gamma', 'table', ds_1_id)
|
||||
self.assertFalse(access_requests)
|
||||
|
||||
gamma_user = sm.find_user(username='gamma')
|
||||
gamma_user.roles.remove(sm.find_role('Alpha'))
|
||||
gamma_user = security_manager.find_user(username='gamma')
|
||||
gamma_user.roles.remove(security_manager.find_role('Alpha'))
|
||||
session.commit()
|
||||
|
||||
def test_clean_requests_after_db_grant(self):
|
||||
|
|
@ -256,7 +257,7 @@ class RequestAccessTests(SupersetTestCase):
|
|||
# Gamma gets database access, gamma2 access request granted
|
||||
# Check if request by gamma has been deleted
|
||||
|
||||
gamma_user = sm.find_user(username='gamma')
|
||||
gamma_user = security_manager.find_user(username='gamma')
|
||||
access_request1 = create_access_request(
|
||||
session, 'table', 'long_lat', TEST_ROLE_1, 'gamma')
|
||||
create_access_request(
|
||||
|
|
@ -265,13 +266,12 @@ class RequestAccessTests(SupersetTestCase):
|
|||
# gamma gets granted database access
|
||||
database = session.query(models.Database).first()
|
||||
|
||||
security.merge_perm(
|
||||
sm, 'database_access', database.perm)
|
||||
ds_perm_view = sm.find_permission_view_menu(
|
||||
security_manager.merge_perm('database_access', database.perm)
|
||||
ds_perm_view = security_manager.find_permission_view_menu(
|
||||
'database_access', database.perm)
|
||||
sm.add_permission_role(
|
||||
sm.find_role(DB_ACCESS_ROLE), ds_perm_view)
|
||||
gamma_user.roles.append(sm.find_role(DB_ACCESS_ROLE))
|
||||
security_manager.add_permission_role(
|
||||
security_manager.find_role(DB_ACCESS_ROLE), ds_perm_view)
|
||||
gamma_user.roles.append(security_manager.find_role(DB_ACCESS_ROLE))
|
||||
session.commit()
|
||||
access_requests = self.get_access_requests('gamma', 'table', ds_1_id)
|
||||
self.assertTrue(access_requests)
|
||||
|
|
@ -281,8 +281,8 @@ class RequestAccessTests(SupersetTestCase):
|
|||
access_requests = self.get_access_requests('gamma', 'table', ds_1_id)
|
||||
|
||||
self.assertFalse(access_requests)
|
||||
gamma_user = sm.find_user(username='gamma')
|
||||
gamma_user.roles.remove(sm.find_role(DB_ACCESS_ROLE))
|
||||
gamma_user = security_manager.find_user(username='gamma')
|
||||
gamma_user.roles.remove(security_manager.find_role(DB_ACCESS_ROLE))
|
||||
session.commit()
|
||||
|
||||
def test_clean_requests_after_schema_grant(self):
|
||||
|
|
@ -292,7 +292,7 @@ class RequestAccessTests(SupersetTestCase):
|
|||
# Gamma gets schema access, gamma2 access request granted
|
||||
# Check if request by gamma has been deleted
|
||||
|
||||
gamma_user = sm.find_user(username='gamma')
|
||||
gamma_user = security_manager.find_user(username='gamma')
|
||||
access_request1 = create_access_request(
|
||||
session, 'table', 'wb_health_population', TEST_ROLE_1, 'gamma')
|
||||
create_access_request(
|
||||
|
|
@ -302,21 +302,20 @@ class RequestAccessTests(SupersetTestCase):
|
|||
table_name='wb_health_population').first()
|
||||
|
||||
ds.schema = 'temp_schema'
|
||||
security.merge_perm(
|
||||
sm, 'schema_access', ds.schema_perm)
|
||||
schema_perm_view = sm.find_permission_view_menu(
|
||||
security_manager.merge_perm('schema_access', ds.schema_perm)
|
||||
schema_perm_view = security_manager.find_permission_view_menu(
|
||||
'schema_access', ds.schema_perm)
|
||||
sm.add_permission_role(
|
||||
sm.find_role(SCHEMA_ACCESS_ROLE), schema_perm_view)
|
||||
gamma_user.roles.append(sm.find_role(SCHEMA_ACCESS_ROLE))
|
||||
security_manager.add_permission_role(
|
||||
security_manager.find_role(SCHEMA_ACCESS_ROLE), schema_perm_view)
|
||||
gamma_user.roles.append(security_manager.find_role(SCHEMA_ACCESS_ROLE))
|
||||
session.commit()
|
||||
# gamma2 request gets fulfilled
|
||||
self.client.get(EXTEND_ROLE_REQUEST.format(
|
||||
'table', ds_1_id, 'gamma2', TEST_ROLE_2))
|
||||
access_requests = self.get_access_requests('gamma', 'table', ds_1_id)
|
||||
self.assertFalse(access_requests)
|
||||
gamma_user = sm.find_user(username='gamma')
|
||||
gamma_user.roles.remove(sm.find_role(SCHEMA_ACCESS_ROLE))
|
||||
gamma_user = security_manager.find_user(username='gamma')
|
||||
gamma_user.roles.remove(security_manager.find_role(SCHEMA_ACCESS_ROLE))
|
||||
|
||||
ds = session.query(SqlaTable).filter_by(
|
||||
table_name='wb_health_population').first()
|
||||
|
|
@ -329,7 +328,7 @@ class RequestAccessTests(SupersetTestCase):
|
|||
if app.config.get('ENABLE_ACCESS_REQUEST'):
|
||||
session = db.session
|
||||
TEST_ROLE_NAME = 'table_role'
|
||||
sm.add_role(TEST_ROLE_NAME)
|
||||
security_manager.add_role(TEST_ROLE_NAME)
|
||||
|
||||
# Case 1. Grant new role to the user.
|
||||
|
||||
|
|
@ -341,8 +340,8 @@ class RequestAccessTests(SupersetTestCase):
|
|||
# Test email content.
|
||||
self.assertTrue(mock_send_mime.called)
|
||||
call_args = mock_send_mime.call_args[0]
|
||||
self.assertEqual([sm.find_user(username='gamma').email,
|
||||
sm.find_user(username='admin').email],
|
||||
self.assertEqual([security_manager.find_user(username='gamma').email,
|
||||
security_manager.find_user(username='admin').email],
|
||||
call_args[1])
|
||||
self.assertEqual(
|
||||
'[Superset] Access to the datasource {} was granted'.format(
|
||||
|
|
@ -354,7 +353,7 @@ class RequestAccessTests(SupersetTestCase):
|
|||
# request was removed
|
||||
self.assertFalse(access_requests)
|
||||
# user was granted table_role
|
||||
user_roles = [r.name for r in sm.find_user('gamma').roles]
|
||||
user_roles = [r.name for r in security_manager.find_user('gamma').roles]
|
||||
self.assertIn(TEST_ROLE_NAME, user_roles)
|
||||
|
||||
# Case 2. Extend the role to have access to the table
|
||||
|
|
@ -371,8 +370,8 @@ class RequestAccessTests(SupersetTestCase):
|
|||
# Test email content.
|
||||
self.assertTrue(mock_send_mime.called)
|
||||
call_args = mock_send_mime.call_args[0]
|
||||
self.assertEqual([sm.find_user(username='gamma').email,
|
||||
sm.find_user(username='admin').email],
|
||||
self.assertEqual([security_manager.find_user(username='gamma').email,
|
||||
security_manager.find_user(username='admin').email],
|
||||
call_args[1])
|
||||
self.assertEqual(
|
||||
'[Superset] Access to the datasource {} was granted'.format(
|
||||
|
|
@ -383,21 +382,21 @@ class RequestAccessTests(SupersetTestCase):
|
|||
# request was removed
|
||||
self.assertFalse(access_requests)
|
||||
# table_role was extended to grant access to the long_lat table/
|
||||
perm_view = sm.find_permission_view_menu(
|
||||
perm_view = security_manager.find_permission_view_menu(
|
||||
'datasource_access', long_lat_perm)
|
||||
TEST_ROLE = sm.find_role(TEST_ROLE_NAME)
|
||||
TEST_ROLE = security_manager.find_role(TEST_ROLE_NAME)
|
||||
self.assertIn(perm_view, TEST_ROLE.permissions)
|
||||
|
||||
# Case 3. Grant new role to the user to access the druid datasource.
|
||||
|
||||
sm.add_role('druid_role')
|
||||
security_manager.add_role('druid_role')
|
||||
access_request3 = create_access_request(
|
||||
session, 'druid', 'druid_ds_1', 'druid_role', 'gamma')
|
||||
self.get_resp(GRANT_ROLE_REQUEST.format(
|
||||
'druid', access_request3.datasource_id, 'gamma', 'druid_role'))
|
||||
|
||||
# user was granted table_role
|
||||
user_roles = [r.name for r in sm.find_user('gamma').roles]
|
||||
user_roles = [r.name for r in security_manager.find_user('gamma').roles]
|
||||
self.assertIn('druid_role', user_roles)
|
||||
|
||||
# Case 4. Extend the role to have access to the druid datasource
|
||||
|
|
@ -409,17 +408,17 @@ class RequestAccessTests(SupersetTestCase):
|
|||
self.client.get(EXTEND_ROLE_REQUEST.format(
|
||||
'druid', access_request4.datasource_id, 'gamma', 'druid_role'))
|
||||
# druid_role was extended to grant access to the druid_access_ds_2
|
||||
druid_role = sm.find_role('druid_role')
|
||||
perm_view = sm.find_permission_view_menu(
|
||||
druid_role = security_manager.find_role('druid_role')
|
||||
perm_view = security_manager.find_permission_view_menu(
|
||||
'datasource_access', druid_ds_2_perm)
|
||||
self.assertIn(perm_view, druid_role.permissions)
|
||||
|
||||
# cleanup
|
||||
gamma_user = sm.find_user(username='gamma')
|
||||
gamma_user.roles.remove(sm.find_role('druid_role'))
|
||||
gamma_user.roles.remove(sm.find_role(TEST_ROLE_NAME))
|
||||
session.delete(sm.find_role('druid_role'))
|
||||
session.delete(sm.find_role(TEST_ROLE_NAME))
|
||||
gamma_user = security_manager.find_user(username='gamma')
|
||||
gamma_user.roles.remove(security_manager.find_role('druid_role'))
|
||||
gamma_user.roles.remove(security_manager.find_role(TEST_ROLE_NAME))
|
||||
session.delete(security_manager.find_role('druid_role'))
|
||||
session.delete(security_manager.find_role(TEST_ROLE_NAME))
|
||||
session.commit()
|
||||
|
||||
def test_request_access(self):
|
||||
|
|
@ -427,9 +426,9 @@ class RequestAccessTests(SupersetTestCase):
|
|||
session = db.session
|
||||
self.logout()
|
||||
self.login(username='gamma')
|
||||
gamma_user = sm.find_user(username='gamma')
|
||||
sm.add_role('dummy_role')
|
||||
gamma_user.roles.append(sm.find_role('dummy_role'))
|
||||
gamma_user = security_manager.find_user(username='gamma')
|
||||
security_manager.add_role('dummy_role')
|
||||
gamma_user.roles.append(security_manager.find_role('dummy_role'))
|
||||
session.commit()
|
||||
|
||||
ACCESS_REQUEST = (
|
||||
|
|
@ -461,14 +460,16 @@ class RequestAccessTests(SupersetTestCase):
|
|||
table_3_id = table3.id
|
||||
table3_perm = table3.perm
|
||||
|
||||
sm.add_role('energy_usage_role')
|
||||
alpha_role = sm.find_role('Alpha')
|
||||
sm.add_permission_role(
|
||||
security_manager.add_role('energy_usage_role')
|
||||
alpha_role = security_manager.find_role('Alpha')
|
||||
security_manager.add_permission_role(
|
||||
alpha_role,
|
||||
sm.find_permission_view_menu('datasource_access', table3_perm))
|
||||
sm.add_permission_role(
|
||||
sm.find_role('energy_usage_role'),
|
||||
sm.find_permission_view_menu('datasource_access', table3_perm))
|
||||
security_manager.find_permission_view_menu(
|
||||
'datasource_access', table3_perm))
|
||||
security_manager.add_permission_role(
|
||||
security_manager.find_role('energy_usage_role'),
|
||||
security_manager.find_permission_view_menu(
|
||||
'datasource_access', table3_perm))
|
||||
session.commit()
|
||||
|
||||
self.get_resp(
|
||||
|
|
@ -500,14 +501,16 @@ class RequestAccessTests(SupersetTestCase):
|
|||
druid_ds_5_id = druid_ds_5.id
|
||||
druid_ds_5_perm = druid_ds_5.perm
|
||||
|
||||
druid_ds_2_role = sm.add_role('druid_ds_2_role')
|
||||
admin_role = sm.find_role('Admin')
|
||||
sm.add_permission_role(
|
||||
druid_ds_2_role = security_manager.add_role('druid_ds_2_role')
|
||||
admin_role = security_manager.find_role('Admin')
|
||||
security_manager.add_permission_role(
|
||||
admin_role,
|
||||
sm.find_permission_view_menu('datasource_access', druid_ds_5_perm))
|
||||
sm.add_permission_role(
|
||||
security_manager.find_permission_view_menu(
|
||||
'datasource_access', druid_ds_5_perm))
|
||||
security_manager.add_permission_role(
|
||||
druid_ds_2_role,
|
||||
sm.find_permission_view_menu('datasource_access', druid_ds_5_perm))
|
||||
security_manager.find_permission_view_menu(
|
||||
'datasource_access', druid_ds_5_perm))
|
||||
session.commit()
|
||||
|
||||
self.get_resp(ACCESS_REQUEST.format('druid', druid_ds_5_id, 'go'))
|
||||
|
|
@ -520,8 +523,8 @@ class RequestAccessTests(SupersetTestCase):
|
|||
'<ul><li>{}</li></ul>'.format(approve_link_5))
|
||||
|
||||
# cleanup
|
||||
gamma_user = sm.find_user(username='gamma')
|
||||
gamma_user.roles.remove(sm.find_role('dummy_role'))
|
||||
gamma_user = security_manager.find_user(username='gamma')
|
||||
gamma_user.roles.remove(security_manager.find_role('dummy_role'))
|
||||
session.commit()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -12,11 +12,10 @@ import unittest
|
|||
|
||||
from flask_appbuilder.security.sqla import models as ab_models
|
||||
|
||||
from superset import app, appbuilder, cli, db, security, sm
|
||||
from superset import app, cli, db, security_manager, utils
|
||||
from superset.connectors.druid.models import DruidCluster, DruidDatasource
|
||||
from superset.connectors.sqla.models import SqlaTable
|
||||
from superset.models import core as models
|
||||
from superset.security import sync_role_definitions
|
||||
|
||||
os.environ['SUPERSET_CONFIG'] = 'tests.superset_test_config'
|
||||
|
||||
|
|
@ -36,59 +35,60 @@ class SupersetTestCase(unittest.TestCase):
|
|||
logging.info('Loading examples')
|
||||
cli.load_examples(load_test_data=True)
|
||||
logging.info('Done loading examples')
|
||||
sync_role_definitions()
|
||||
security_manager.sync_role_definitions()
|
||||
os.environ['examples_loaded'] = '1'
|
||||
else:
|
||||
sync_role_definitions()
|
||||
security_manager.sync_role_definitions()
|
||||
super(SupersetTestCase, self).__init__(*args, **kwargs)
|
||||
self.client = app.test_client()
|
||||
self.maxDiff = None
|
||||
|
||||
gamma_sqllab_role = sm.add_role('gamma_sqllab')
|
||||
for perm in sm.find_role('Gamma').permissions:
|
||||
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(
|
||||
gamma_sqllab_role = security_manager.add_role('gamma_sqllab')
|
||||
for perm in security_manager.find_role('Gamma').permissions:
|
||||
security_manager.add_permission_role(gamma_sqllab_role, perm)
|
||||
utils.get_or_create_main_db()
|
||||
db_perm = self.get_main_database(security_manager.get_session).perm
|
||||
security_manager.merge_perm('database_access', db_perm)
|
||||
db_pvm = security_manager.find_permission_view_menu(
|
||||
view_menu_name=db_perm, permission_name='database_access')
|
||||
gamma_sqllab_role.permissions.append(db_pvm)
|
||||
for perm in sm.find_role('sql_lab').permissions:
|
||||
sm.add_permission_role(gamma_sqllab_role, perm)
|
||||
for perm in security_manager.find_role('sql_lab').permissions:
|
||||
security_manager.add_permission_role(gamma_sqllab_role, perm)
|
||||
|
||||
admin = appbuilder.sm.find_user('admin')
|
||||
admin = security_manager.find_user('admin')
|
||||
if not admin:
|
||||
appbuilder.sm.add_user(
|
||||
security_manager.add_user(
|
||||
'admin', 'admin', ' user', 'admin@fab.org',
|
||||
appbuilder.sm.find_role('Admin'),
|
||||
security_manager.find_role('Admin'),
|
||||
password='general')
|
||||
|
||||
gamma = appbuilder.sm.find_user('gamma')
|
||||
gamma = security_manager.find_user('gamma')
|
||||
if not gamma:
|
||||
appbuilder.sm.add_user(
|
||||
security_manager.add_user(
|
||||
'gamma', 'gamma', 'user', 'gamma@fab.org',
|
||||
appbuilder.sm.find_role('Gamma'),
|
||||
security_manager.find_role('Gamma'),
|
||||
password='general')
|
||||
|
||||
gamma2 = appbuilder.sm.find_user('gamma2')
|
||||
gamma2 = security_manager.find_user('gamma2')
|
||||
if not gamma2:
|
||||
appbuilder.sm.add_user(
|
||||
security_manager.add_user(
|
||||
'gamma2', 'gamma2', 'user', 'gamma2@fab.org',
|
||||
appbuilder.sm.find_role('Gamma'),
|
||||
security_manager.find_role('Gamma'),
|
||||
password='general')
|
||||
|
||||
gamma_sqllab_user = appbuilder.sm.find_user('gamma_sqllab')
|
||||
gamma_sqllab_user = security_manager.find_user('gamma_sqllab')
|
||||
if not gamma_sqllab_user:
|
||||
appbuilder.sm.add_user(
|
||||
security_manager.add_user(
|
||||
'gamma_sqllab', 'gamma_sqllab', 'user', 'gamma_sqllab@fab.org',
|
||||
gamma_sqllab_role, password='general')
|
||||
|
||||
alpha = appbuilder.sm.find_user('alpha')
|
||||
alpha = security_manager.find_user('alpha')
|
||||
if not alpha:
|
||||
appbuilder.sm.add_user(
|
||||
security_manager.add_user(
|
||||
'alpha', 'alpha', 'user', 'alpha@fab.org',
|
||||
appbuilder.sm.find_role('Alpha'),
|
||||
security_manager.find_role('Alpha'),
|
||||
password='general')
|
||||
sm.get_session.commit()
|
||||
security_manager.get_session.commit()
|
||||
# create druid cluster and druid datasources
|
||||
session = db.session
|
||||
cluster = (
|
||||
|
|
@ -177,7 +177,7 @@ class SupersetTestCase(unittest.TestCase):
|
|||
return (
|
||||
db.session.query(DAR)
|
||||
.filter(
|
||||
DAR.created_by == sm.find_user(username=username),
|
||||
DAR.created_by == security_manager.find_user(username=username),
|
||||
DAR.datasource_type == ds_type,
|
||||
DAR.datasource_id == ds_id,
|
||||
)
|
||||
|
|
@ -188,20 +188,20 @@ class SupersetTestCase(unittest.TestCase):
|
|||
self.client.get('/logout/', follow_redirects=True)
|
||||
|
||||
def grant_public_access_to_table(self, table):
|
||||
public_role = appbuilder.sm.find_role('Public')
|
||||
public_role = security_manager.find_role('Public')
|
||||
perms = db.session.query(ab_models.PermissionView).all()
|
||||
for perm in perms:
|
||||
if (perm.permission.name == 'datasource_access' and
|
||||
perm.view_menu and table.perm in perm.view_menu.name):
|
||||
appbuilder.sm.add_permission_role(public_role, perm)
|
||||
security_manager.add_permission_role(public_role, perm)
|
||||
|
||||
def revoke_public_access_to_table(self, table):
|
||||
public_role = appbuilder.sm.find_role('Public')
|
||||
public_role = security_manager.find_role('Public')
|
||||
perms = db.session.query(ab_models.PermissionView).all()
|
||||
for perm in perms:
|
||||
if (perm.permission.name == 'datasource_access' and
|
||||
perm.view_menu and table.perm in perm.view_menu.name):
|
||||
appbuilder.sm.del_permission_role(public_role, perm)
|
||||
security_manager.del_permission_role(public_role, perm)
|
||||
|
||||
def run_sql(self, sql, client_id, user_name=None, raise_on_error=False):
|
||||
if user_name:
|
||||
|
|
@ -241,7 +241,7 @@ class SupersetTestCase(unittest.TestCase):
|
|||
assert_can_write(view_menu)
|
||||
|
||||
gamma_perm_set = set()
|
||||
for perm in sm.find_role('Gamma').permissions:
|
||||
for perm in security_manager.find_role('Gamma').permissions:
|
||||
gamma_perm_set.add((perm.permission.name, perm.view_menu.name))
|
||||
|
||||
# check read only perms
|
||||
|
|
|
|||
|
|
@ -14,10 +14,9 @@ import unittest
|
|||
import pandas as pd
|
||||
from past.builtins import basestring
|
||||
|
||||
from superset import app, appbuilder, cli, dataframe, db
|
||||
from superset import app, cli, dataframe, db, security_manager
|
||||
from superset.models.helpers import QueryStatus
|
||||
from superset.models.sql_lab import Query
|
||||
from superset.security import sync_role_definitions
|
||||
from superset.sql_parse import SupersetQuery
|
||||
from .base_tests import SupersetTestCase
|
||||
|
||||
|
|
@ -98,17 +97,17 @@ class CeleryTestCase(SupersetTestCase):
|
|||
except OSError as e:
|
||||
app.logger.warn(str(e))
|
||||
|
||||
sync_role_definitions()
|
||||
security_manager.sync_role_definitions()
|
||||
|
||||
worker_command = BASE_DIR + '/bin/superset worker'
|
||||
subprocess.Popen(
|
||||
worker_command, shell=True, stdout=subprocess.PIPE)
|
||||
|
||||
admin = appbuilder.sm.find_user('admin')
|
||||
admin = security_manager.find_user('admin')
|
||||
if not admin:
|
||||
appbuilder.sm.add_user(
|
||||
security_manager.add_user(
|
||||
'admin', 'admin', ' user', 'admin@fab.org',
|
||||
appbuilder.sm.find_role('Admin'),
|
||||
security_manager.find_role('Admin'),
|
||||
password='general')
|
||||
cli.load_examples(load_test_data=True)
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import psycopg2
|
|||
from six import text_type
|
||||
import sqlalchemy as sqla
|
||||
|
||||
from superset import appbuilder, dataframe, db, jinja_context, sm, sql_lab, utils
|
||||
from superset import dataframe, db, jinja_context, security_manager, sql_lab, utils
|
||||
from superset.connectors.sqla.models import SqlaTable
|
||||
from superset.models import core as models
|
||||
from superset.models.sql_lab import Query
|
||||
|
|
@ -136,7 +136,7 @@ class CoreTests(SupersetTestCase):
|
|||
|
||||
def test_admin_only_permissions(self):
|
||||
def assert_admin_permission_in(role_name, assert_func):
|
||||
role = sm.find_role(role_name)
|
||||
role = security_manager.find_role(role_name)
|
||||
permissions = [p.permission.name for p in role.permissions]
|
||||
assert_func('can_sync_druid_source', permissions)
|
||||
assert_func('can_approve', permissions)
|
||||
|
|
@ -147,7 +147,7 @@ class CoreTests(SupersetTestCase):
|
|||
|
||||
def test_admin_only_menu_views(self):
|
||||
def assert_admin_view_menus_in(role_name, assert_func):
|
||||
role = sm.find_role(role_name)
|
||||
role = security_manager.find_role(role_name)
|
||||
view_menus = [p.view_menu.name for p in role.permissions]
|
||||
assert_func('ResetPasswordView', view_menus)
|
||||
assert_func('RoleModelView', view_menus)
|
||||
|
|
@ -267,7 +267,7 @@ class CoreTests(SupersetTestCase):
|
|||
|
||||
def test_get_user_slices(self):
|
||||
self.login(username='admin')
|
||||
userid = appbuilder.sm.find_user('admin').id
|
||||
userid = security_manager.find_user('admin').id
|
||||
url = '/sliceaddview/api/read?_flt_0_created_by={}'.format(userid)
|
||||
resp = self.client.get(url)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
|
|
@ -275,11 +275,11 @@ class CoreTests(SupersetTestCase):
|
|||
def test_slices_V2(self):
|
||||
# Add explore-v2-beta role to admin user
|
||||
# Test all slice urls as user with with explore-v2-beta role
|
||||
sm.add_role('explore-v2-beta')
|
||||
security_manager.add_role('explore-v2-beta')
|
||||
|
||||
appbuilder.sm.add_user(
|
||||
security_manager.add_user(
|
||||
'explore_beta', 'explore_beta', ' user', 'explore_beta@airbnb.com',
|
||||
appbuilder.sm.find_role('explore-v2-beta'),
|
||||
security_manager.find_role('explore-v2-beta'),
|
||||
password='general')
|
||||
self.login(username='explore_beta', password='general')
|
||||
|
||||
|
|
@ -651,8 +651,8 @@ class CoreTests(SupersetTestCase):
|
|||
|
||||
dash = db.session.query(models.Dashboard).filter_by(
|
||||
slug='births').first()
|
||||
dash.owners = [appbuilder.sm.find_user('admin')]
|
||||
dash.created_by = appbuilder.sm.find_user('admin')
|
||||
dash.owners = [security_manager.find_user('admin')]
|
||||
dash.created_by = security_manager.find_user('admin')
|
||||
db.session.merge(dash)
|
||||
db.session.commit()
|
||||
|
||||
|
|
@ -674,7 +674,7 @@ class CoreTests(SupersetTestCase):
|
|||
self.assertRaises(
|
||||
Exception, self.test_save_dash, 'alpha')
|
||||
|
||||
alpha = appbuilder.sm.find_user('alpha')
|
||||
alpha = security_manager.find_user('alpha')
|
||||
|
||||
dash = (
|
||||
db.session
|
||||
|
|
@ -775,7 +775,7 @@ class CoreTests(SupersetTestCase):
|
|||
resp = self.get_json_resp(url)
|
||||
self.assertEqual(resp['count'], 1)
|
||||
|
||||
userid = appbuilder.sm.find_user('admin').id
|
||||
userid = security_manager.find_user('admin').id
|
||||
resp = self.get_resp('/superset/profile/admin/')
|
||||
self.assertIn('"app"', resp)
|
||||
data = self.get_json_resp('/superset/recent_activity/{}/'.format(userid))
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import unittest
|
|||
|
||||
from mock import Mock, patch
|
||||
|
||||
from superset import db, security, sm
|
||||
from superset import db, security_manager
|
||||
from superset.connectors.druid.models import (
|
||||
DruidCluster, DruidColumn, DruidDatasource, DruidMetric,
|
||||
)
|
||||
|
|
@ -278,13 +278,13 @@ class DruidTests(SupersetTestCase):
|
|||
db.session.merge(no_gamma_ds)
|
||||
db.session.commit()
|
||||
|
||||
security.merge_perm(sm, 'datasource_access', gamma_ds.perm)
|
||||
security.merge_perm(sm, 'datasource_access', no_gamma_ds.perm)
|
||||
security_manager.merge_perm('datasource_access', gamma_ds.perm)
|
||||
security_manager.merge_perm('datasource_access', no_gamma_ds.perm)
|
||||
|
||||
perm = sm.find_permission_view_menu(
|
||||
perm = security_manager.find_permission_view_menu(
|
||||
'datasource_access', gamma_ds.get_perm())
|
||||
sm.add_permission_role(sm.find_role('Gamma'), perm)
|
||||
sm.get_session.commit()
|
||||
security_manager.add_permission_role(security_manager.find_role('Gamma'), perm)
|
||||
security_manager.get_session.commit()
|
||||
|
||||
self.login(username='gamma')
|
||||
url = '/druiddatasourcemodelview/list/'
|
||||
|
|
@ -331,10 +331,11 @@ class DruidTests(SupersetTestCase):
|
|||
db.session.commit()
|
||||
|
||||
view_menu_name = cluster.datasources[0].get_perm()
|
||||
view_menu = sm.find_view_menu(view_menu_name)
|
||||
permission = sm.find_permission('datasource_access')
|
||||
view_menu = security_manager.find_view_menu(view_menu_name)
|
||||
permission = security_manager.find_permission('datasource_access')
|
||||
|
||||
pv = sm.get_session.query(sm.permissionview_model).filter_by(
|
||||
pv = security_manager.get_session.query(
|
||||
security_manager.permissionview_model).filter_by(
|
||||
permission=permission, view_menu=view_menu).first()
|
||||
assert pv is not None
|
||||
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@ from __future__ import division
|
|||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from superset import app, security, sm
|
||||
from superset import app, security_manager
|
||||
from .base_tests import SupersetTestCase
|
||||
|
||||
|
||||
def get_perm_tuples(role_name):
|
||||
perm_set = set()
|
||||
for perm in sm.find_role(role_name).permissions:
|
||||
for perm in security_manager.find_role(role_name).permissions:
|
||||
perm_set.add((perm.permission.name, perm.view_menu.name))
|
||||
return perm_set
|
||||
|
||||
|
|
@ -103,46 +103,47 @@ class RolePermissionTests(SupersetTestCase):
|
|||
self.assertIn(('can_approve', '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(
|
||||
self.assertFalse(security_manager.is_admin_only(
|
||||
security_manager.find_permission_view_menu('can_show', 'TableModelView')))
|
||||
self.assertFalse(security_manager.is_admin_only(
|
||||
security_manager.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_manager.is_admin_only(
|
||||
security_manager.find_permission_view_menu('can_delete', 'DatabaseView')))
|
||||
if app.config.get('ENABLE_ACCESS_REQUEST'):
|
||||
self.assertTrue(security.is_admin_only(
|
||||
sm.find_permission_view_menu(
|
||||
self.assertTrue(security_manager.is_admin_only(
|
||||
security_manager.find_permission_view_menu(
|
||||
'can_show', 'AccessRequestsModelView')))
|
||||
self.assertTrue(security.is_admin_only(
|
||||
sm.find_permission_view_menu(
|
||||
self.assertTrue(security_manager.is_admin_only(
|
||||
security_manager.find_permission_view_menu(
|
||||
'can_edit', 'UserDBModelView')))
|
||||
self.assertTrue(security.is_admin_only(
|
||||
sm.find_permission_view_menu(
|
||||
self.assertTrue(security_manager.is_admin_only(
|
||||
security_manager.find_permission_view_menu(
|
||||
'can_approve', 'Superset')))
|
||||
self.assertTrue(security.is_admin_only(
|
||||
sm.find_permission_view_menu(
|
||||
self.assertTrue(security_manager.is_admin_only(
|
||||
security_manager.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.assertFalse(security_manager.is_alpha_only(
|
||||
security_manager.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(
|
||||
self.assertTrue(security_manager.is_alpha_only(
|
||||
security_manager.find_permission_view_menu('muldelete', 'TableModelView')))
|
||||
self.assertTrue(security_manager.is_alpha_only(
|
||||
security_manager.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(
|
||||
self.assertTrue(security_manager.is_alpha_only(
|
||||
security_manager.find_permission_view_menu(
|
||||
'can_edit', 'SqlMetricInlineView')))
|
||||
self.assertTrue(security_manager.is_alpha_only(
|
||||
security_manager.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')))
|
||||
self.assertTrue(security_manager.is_gamma_pvm(
|
||||
security_manager.find_permission_view_menu('can_show', 'TableModelView')))
|
||||
|
||||
def test_gamma_permissions(self):
|
||||
self.assert_can_gamma(get_perm_tuples('Gamma'))
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import unittest
|
|||
|
||||
from flask_appbuilder.security.sqla import models as ab_models
|
||||
|
||||
from superset import appbuilder, db, sm, utils
|
||||
from superset import db, security_manager, utils
|
||||
from superset.models.sql_lab import Query
|
||||
from superset.sql_lab import convert_results_to_df
|
||||
from .base_tests import SupersetTestCase
|
||||
|
|
@ -56,7 +56,7 @@ class SqlLabTests(SupersetTestCase):
|
|||
|
||||
def test_sql_json_has_access(self):
|
||||
main_db = self.get_main_database(db.session)
|
||||
sm.add_permission_view_menu('database_access', main_db.perm)
|
||||
security_manager.add_permission_view_menu('database_access', main_db.perm)
|
||||
db.session.commit()
|
||||
main_db_permission_view = (
|
||||
db.session.query(ab_models.PermissionView)
|
||||
|
|
@ -66,17 +66,17 @@ class SqlLabTests(SupersetTestCase):
|
|||
.filter(ab_models.Permission.name == 'database_access')
|
||||
.first()
|
||||
)
|
||||
astronaut = sm.add_role('Astronaut')
|
||||
sm.add_permission_role(astronaut, main_db_permission_view)
|
||||
astronaut = security_manager.add_role('Astronaut')
|
||||
security_manager.add_permission_role(astronaut, main_db_permission_view)
|
||||
# Astronaut role is Gamma + sqllab + main db permissions
|
||||
for perm in sm.find_role('Gamma').permissions:
|
||||
sm.add_permission_role(astronaut, perm)
|
||||
for perm in sm.find_role('sql_lab').permissions:
|
||||
sm.add_permission_role(astronaut, perm)
|
||||
for perm in security_manager.find_role('Gamma').permissions:
|
||||
security_manager.add_permission_role(astronaut, perm)
|
||||
for perm in security_manager.find_role('sql_lab').permissions:
|
||||
security_manager.add_permission_role(astronaut, perm)
|
||||
|
||||
gagarin = appbuilder.sm.find_user('gagarin')
|
||||
gagarin = security_manager.find_user('gagarin')
|
||||
if not gagarin:
|
||||
appbuilder.sm.add_user(
|
||||
security_manager.add_user(
|
||||
'gagarin', 'Iurii', 'Gagarin', 'gagarin@cosmos.ussr',
|
||||
astronaut,
|
||||
password='general')
|
||||
|
|
@ -139,14 +139,14 @@ class SqlLabTests(SupersetTestCase):
|
|||
self.login('admin')
|
||||
|
||||
# Test search queries on user Id
|
||||
user_id = appbuilder.sm.find_user('admin').id
|
||||
user_id = security_manager.find_user('admin').id
|
||||
data = self.get_json_resp(
|
||||
'/superset/search_queries?user_id={}'.format(user_id))
|
||||
self.assertEquals(2, len(data))
|
||||
user_ids = {k['userId'] for k in data}
|
||||
self.assertEquals(set([user_id]), user_ids)
|
||||
|
||||
user_id = appbuilder.sm.find_user('gamma_sqllab').id
|
||||
user_id = security_manager.find_user('gamma_sqllab').id
|
||||
resp = self.get_resp(
|
||||
'/superset/search_queries?user_id={}'.format(user_id))
|
||||
data = json.loads(resp)
|
||||
|
|
|
|||
Loading…
Reference in New Issue