[SQL Lab] fix gamma metadata access (#2702)

This commit is contained in:
Maxime Beauchemin 2017-05-09 13:36:49 -07:00 committed by GitHub
parent a471afe206
commit 04748b4cda
3 changed files with 58 additions and 28 deletions

View File

@ -74,11 +74,10 @@ class SupersetTemplateException(SupersetException):
def can_access(sm, permission_name, view_name, user):
"""Protecting from has_access failing from missing perms/view"""
return (
sm.is_item_public(permission_name, view_name) or
(not user.is_anonymous() and
sm._has_view_access(user, permission_name, view_name))
)
if user.is_anonymous():
return sm.is_item_public(permission_name, view_name)
else:
return sm._has_view_access(user, permission_name, view_name)
def flasher(msg, severity=None):

View File

@ -15,6 +15,7 @@ from flask_appbuilder.security.sqla import models as ab_models
from superset import appbuilder, conf, db, utils, sm, sql_parse
from superset.connectors.connector_registry import ConnectorRegistry
from superset.connectors.sqla.models import SqlaTable
def get_error_msg():
@ -101,8 +102,7 @@ class BaseSupersetView(BaseView):
return True
schema_perm = utils.get_schema_perm(database, schema)
if schema and utils.can_access(
sm, 'schema_access', schema_perm, g.user):
if schema and self.can_access('schema_access', schema_perm):
return True
datasources = ConnectorRegistry.query_datasources_by_name(
@ -130,32 +130,61 @@ class BaseSupersetView(BaseView):
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
schema_perm = utils.get_schema_perm(database, schema)
if schema and utils.can_access(
sm, 'schema_access', schema_perm, g.user):
return datasource_names
if schema:
schema_perm = utils.get_schema_perm(database, schema)
if self.can_access('schema_access', schema_perm):
return datasource_names
role_ids = set([role.id for role in g.user.roles])
# TODO: cache user_perms or user_datasources
PV = ab_models.PermissionView
pv_role = PV.role # pylint: disable=no-member
user_pvms = (
db.session.query(PV)
.join(ab_models.Permission)
.filter(ab_models.Permission.name == 'datasource_access')
.filter(pv_role.any(ab_models.Role.id.in_(role_ids)))
.all()
)
user_perms = set([pvm.view_menu.name for pvm in user_pvms])
user_perms = self.user_datasource_perms()
user_datasources = ConnectorRegistry.query_datasources_by_permissions(
db.session, database, user_perms)
full_names = set([d.full_name for d in user_datasources])
return [d for d in datasource_names if d in full_names]
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]
class SupersetModelView(ModelView):

View File

@ -3,6 +3,7 @@ from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from collections import defaultdict
from datetime import datetime, timedelta
import json
import logging
@ -1198,8 +1199,10 @@ class Superset(BaseSupersetView):
.filter_by(id=db_id)
.one()
)
schemas = database.all_schema_names()
schemas = self.schemas_accessible_by_user(database, schemas)
return Response(
json.dumps({'schemas': database.all_schema_names()}),
json.dumps({'schemas': schemas}),
mimetype="application/json")
@api
@ -2179,7 +2182,6 @@ class Superset(BaseSupersetView):
.one()
)
roles = {}
from collections import defaultdict
permissions = defaultdict(set)
for role in user.roles:
perms = set()