Secure unsecured views and prevent regressions (#6553)

* Secure views and prevent regressions

* Force POST on shortner

* Fix tests
This commit is contained in:
Maxime Beauchemin
2018-12-18 11:57:13 -08:00
committed by GitHub
parent 926f78c21d
commit 3f29a1dd70
5 changed files with 53 additions and 12 deletions

View File

@@ -129,7 +129,8 @@ class ImportExportTests(SupersetTestCase):
id=dash_id).first()
def get_dash_by_slug(self, dash_slug):
return db.session.query(models.Dashboard).filter_by(
sesh = db.session()
return sesh.query(models.Dashboard).filter_by(
slug=dash_slug).first()
def get_datasource(self, datasource_id):
@@ -195,6 +196,7 @@ class ImportExportTests(SupersetTestCase):
json.loads(expected_slc.params), json.loads(actual_slc.params))
def test_export_1_dashboard(self):
self.login('admin')
birth_dash = self.get_dash_by_slug('births')
export_dash_url = (
'/dashboard/export_dashboards_form?id={}&action=go'
@@ -206,6 +208,7 @@ class ImportExportTests(SupersetTestCase):
object_hook=utils.decode_dashboards,
)['dashboards']
birth_dash = self.get_dash_by_slug('births')
self.assert_dash_equals(birth_dash, exported_dashboards[0])
self.assertEquals(
birth_dash.id,
@@ -223,6 +226,7 @@ class ImportExportTests(SupersetTestCase):
self.get_table_by_name('birth_names'), exported_tables[0])
def test_export_2_dashboards(self):
self.login('admin')
birth_dash = self.get_dash_by_slug('births')
world_health_dash = self.get_dash_by_slug('world_health')
export_dash_url = (
@@ -236,12 +240,15 @@ class ImportExportTests(SupersetTestCase):
)['dashboards'],
key=lambda d: d.dashboard_title)
self.assertEquals(2, len(exported_dashboards))
birth_dash = self.get_dash_by_slug('births')
self.assert_dash_equals(birth_dash, exported_dashboards[0])
self.assertEquals(
birth_dash.id,
json.loads(exported_dashboards[0].json_metadata)['remote_id'],
)
world_health_dash = self.get_dash_by_slug('world_health')
self.assert_dash_equals(world_health_dash, exported_dashboards[1])
self.assertEquals(
world_health_dash.id,

View File

@@ -1,4 +1,6 @@
from superset import app, security_manager
import inspect
from superset import app, appbuilder, security_manager
from .base_tests import SupersetTestCase
@@ -12,9 +14,6 @@ def get_perm_tuples(role_name):
class RolePermissionTests(SupersetTestCase):
"""Testing export import functionality for dashboards"""
def __init__(self, *args, **kwargs):
super(RolePermissionTests, self).__init__(*args, **kwargs)
def assert_can_read(self, view_menu, permissions_set):
self.assertIn(('can_show', view_menu), permissions_set)
self.assertIn(('can_list', view_menu), permissions_set)
@@ -216,3 +215,34 @@ class RolePermissionTests(SupersetTestCase):
self.assertIn(('can_fave_slices', 'Superset'), gamma_perm_set)
self.assertIn(('can_save_dash', 'Superset'), gamma_perm_set)
self.assertIn(('can_slice', 'Superset'), gamma_perm_set)
def test_views_are_secured(self):
"""Preventing the addition of unsecured views without has_access decorator"""
# These FAB views are secured in their body as opposed to by decorators
method_whitelist = ('action', 'action_post')
# List of redirect & other benign views
views_whitelist = [
['MyIndexView', 'index'],
['UtilView', 'back'],
['LocaleView', 'index'],
['AuthDBView', 'login'],
['AuthDBView', 'logout'],
['R', 'index'],
['Superset', 'log'],
['Superset', 'theme'],
['Superset', 'welcome'],
]
unsecured_views = []
for view_class in appbuilder.baseviews:
class_name = view_class.__class__.__name__
for name, value in inspect.getmembers(view_class, predicate=inspect.ismethod):
if (
name not in method_whitelist and
[class_name, name] not in views_whitelist and
hasattr(value, '_urls') and
not hasattr(value, '_permission_name')
):
unsecured_views.append((class_name, name))
if unsecured_views:
view_str = '\n'.join([str(v) for v in unsecured_views])
raise Exception(f'Some views are not secured:\n{view_str}')