From 212f8802ecb67a8d677376a80d6d4164d04a752c Mon Sep 17 00:00:00 2001 From: Beto Dealmeida Date: Wed, 20 Feb 2019 17:41:41 -0800 Subject: [PATCH 1/5] Per database policies for slices --- superset/views/core.py | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/superset/views/core.py b/superset/views/core.py index fa704989d89f..31d8e8851e73 100755 --- a/superset/views/core.py +++ b/superset/views/core.py @@ -27,7 +27,7 @@ from flask import ( abort, flash, g, Markup, redirect, render_template, request, Response, url_for, ) -from flask_appbuilder import expose, SimpleFormView +from flask_appbuilder import expose, Model, SimpleFormView from flask_appbuilder.actions import action from flask_appbuilder.models.sqla.interface import SQLAInterface from flask_appbuilder.security.decorators import has_access, has_access_api @@ -36,7 +36,8 @@ import pandas as pd import simplejson as json import sqlalchemy as sqla -from sqlalchemy import and_, create_engine, MetaData, or_, update +from sqlalchemy import ( + and_, Column, create_engine, ForeignKey, Integer, MetaData, or_, Table, update) from sqlalchemy.engine.url import make_url from sqlalchemy.exc import IntegrityError from werkzeug.routing import BaseConverter @@ -104,9 +105,26 @@ class SliceFilter(SupersetFilter): def apply(self, query, func): # noqa if security_manager.all_datasource_access(): return query - perms = self.get_view_menus('datasource_access') + # TODO(bogdan): add `schema_access` support here - return query.filter(self.model.perm.in_(perms)) + datasource_perms = self.get_view_menus('datasource_access') + database_perms = self.get_view_menus('database_access') + + SQLTable = Table( + 'tables', + Model.metadata, + Column('id', Integer, primary_key=True), + Column('database_id', Integer, ForeignKey('databases.id')), + extend_existing=True) + query = ( + query.outerjoin(SQLTable, self.model.datasource_id == SQLTable.c.id) + .outerjoin(models.Database, models.Database.id == SQLTable.c.database_id) + .filter(or_( + models.Database.perm.in_(database_perms), + self.model.perm.in_(datasource_perms), + )) + ) + return query class DashboardFilter(SupersetFilter): From f74151b63748b90e02e866728e0afd4db4dc2b32 Mon Sep 17 00:00:00 2001 From: Beto Dealmeida Date: Fri, 22 Feb 2019 14:37:39 -0800 Subject: [PATCH 2/5] Show charts and dashboards based on DB perms as well --- superset/views/core.py | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/superset/views/core.py b/superset/views/core.py index 31d8e8851e73..2b139c4d4ac6 100755 --- a/superset/views/core.py +++ b/superset/views/core.py @@ -101,6 +101,14 @@ def is_owner(obj, user): return obj and user in obj.owners +SQLTable = Table( + 'tables', + Model.metadata, + Column('id', Integer, primary_key=True), + Column('database_id', Integer, ForeignKey('databases.id')), + extend_existing=True) + + class SliceFilter(SupersetFilter): def apply(self, query, func): # noqa if security_manager.all_datasource_access(): @@ -108,19 +116,11 @@ def apply(self, query, func): # noqa # TODO(bogdan): add `schema_access` support here datasource_perms = self.get_view_menus('datasource_access') - database_perms = self.get_view_menus('database_access') - - SQLTable = Table( - 'tables', - Model.metadata, - Column('id', Integer, primary_key=True), - Column('database_id', Integer, ForeignKey('databases.id')), - extend_existing=True) query = ( query.outerjoin(SQLTable, self.model.datasource_id == SQLTable.c.id) .outerjoin(models.Database, models.Database.id == SQLTable.c.database_id) .filter(or_( - models.Database.perm.in_(database_perms), + models.Database.perm.in_(datasource_perms), self.model.perm.in_(datasource_perms), )) ) @@ -142,7 +142,12 @@ def apply(self, query, func): # noqa slice_ids_qry = ( db.session .query(Slice.id) - .filter(Slice.perm.in_(datasource_perms)) + .outerjoin(SQLTable, Slice.datasource_id == SQLTable.c.id) + .outerjoin(models.Database, models.Database.id == SQLTable.c.database_id) + .filter(or_( + models.Database.perm.in_(datasource_perms), + Slice.perm.in_(datasource_perms), + )) ) owner_ids_qry = ( db.session @@ -151,12 +156,15 @@ def apply(self, query, func): # noqa .filter(User.id == User.get_user_id()) ) query = query.filter( - or_(Dash.id.in_( - db.session.query(Dash.id) - .distinct() - .join(Dash.slices) - .filter(Slice.id.in_(slice_ids_qry)), - ), Dash.id.in_(owner_ids_qry)), + or_( + Dash.id.in_( + db.session.query(Dash.id) + .distinct() + .join(Dash.slices) + .filter(Slice.id.in_(slice_ids_qry)), + ), + Dash.id.in_(owner_ids_qry), + ), ) return query From 50a0102eb40b142f11297feeb45e73167a86439d Mon Sep 17 00:00:00 2001 From: Beto Dealmeida Date: Fri, 22 Feb 2019 14:41:02 -0800 Subject: [PATCH 3/5] Revert indentation change --- superset/views/core.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/superset/views/core.py b/superset/views/core.py index 2b139c4d4ac6..639cd932c77a 100755 --- a/superset/views/core.py +++ b/superset/views/core.py @@ -156,15 +156,12 @@ def apply(self, query, func): # noqa .filter(User.id == User.get_user_id()) ) query = query.filter( - or_( - Dash.id.in_( - db.session.query(Dash.id) - .distinct() - .join(Dash.slices) - .filter(Slice.id.in_(slice_ids_qry)), - ), - Dash.id.in_(owner_ids_qry), - ), + or_(Dash.id.in_( + db.session.query(Dash.id) + .distinct() + .join(Dash.slices) + .filter(Slice.id.in_(slice_ids_qry)), + ), Dash.id.in_(owner_ids_qry)), ) return query From d8c39396bfb02983973cef991d189f2216515582 Mon Sep 17 00:00:00 2001 From: Beto Dealmeida Date: Mon, 25 Feb 2019 10:33:35 -0800 Subject: [PATCH 4/5] Fix reference --- superset/views/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/superset/views/core.py b/superset/views/core.py index 639cd932c77a..967093347cbf 100755 --- a/superset/views/core.py +++ b/superset/views/core.py @@ -105,7 +105,7 @@ def is_owner(obj, user): 'tables', Model.metadata, Column('id', Integer, primary_key=True), - Column('database_id', Integer, ForeignKey('databases.id')), + Column('database_id', Integer, ForeignKey('dbs.id')), extend_existing=True) From c14fe4440b0a1004d37714f8b82df48def3a1d06 Mon Sep 17 00:00:00 2001 From: Beto Dealmeida Date: Mon, 25 Feb 2019 11:19:36 -0800 Subject: [PATCH 5/5] Fix pylint --- superset/views/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/superset/views/core.py b/superset/views/core.py index 967093347cbf..f12e6515708e 100755 --- a/superset/views/core.py +++ b/superset/views/core.py @@ -103,7 +103,7 @@ def is_owner(obj, user): SQLTable = Table( 'tables', - Model.metadata, + Model.metadata, # pylint: disable=no-member Column('id', Integer, primary_key=True), Column('database_id', Integer, ForeignKey('dbs.id')), extend_existing=True)