Verify user has access to visualization before creating widget

This commit is contained in:
Arik Fraimovich 2016-03-10 11:42:04 +02:00
parent fad8f2b7be
commit b183651e04
4 changed files with 103 additions and 75 deletions

View File

@ -100,7 +100,6 @@ class QueryResultAPI(BaseResource):
should_cache = query_result_id is not None
if query_result_id is None and query_id is not None:
query = get_object_or_404(models.Query.get_by_id_and_org, query_id, self.current_org)
# TODO: check access?
if query:
query_result_id = query._data['latest_query_data']

View File

@ -4,7 +4,7 @@ from flask import request
from redash import models
from redash.wsgi import api
from redash.permissions import require_permission, require_admin_or_owner
from redash.permissions import require_permission, require_admin_or_owner, require_access, view_only
from redash.handlers.base import BaseResource
@ -18,8 +18,16 @@ class WidgetListAPI(BaseResource):
widget_properties['options'] = json.dumps(widget_properties['options'])
widget_properties.pop('id', None)
widget_properties['dashboard'] = dashboard
# TODO: verify access to the visualization
widget_properties['visualization'] = widget_properties.pop('visualization_id')
visualization_id = widget_properties.pop('visualization_id')
if visualization_id:
visualization = models.Visualization.get_by_id_and_org(visualization_id, self.current_org)
require_access(visualization.query.groups, self.current_user, view_only)
else:
visualization = None
widget_properties['visualization'] = visualization
widget = models.Widget.create(**widget_properties)
layout = json.loads(widget.dashboard.layout)

View File

@ -0,0 +1,92 @@
from tests import BaseTestCase
from redash import models
class WidgetAPITest(BaseTestCase):
def create_widget(self, dashboard, visualization, width=1):
data = {
'visualization_id': visualization.id,
'dashboard_id': dashboard.id,
'options': {},
'width': width
}
rv = self.make_request('post', '/api/widgets', data=data)
return rv
def test_create_widget(self):
dashboard = self.factory.create_dashboard()
vis = self.factory.create_visualization()
rv = self.create_widget(dashboard, vis)
self.assertEquals(rv.status_code, 200)
dashboard = models.Dashboard.get(models.Dashboard.id == dashboard.id)
self.assertEquals(unicode(rv.json['layout']), dashboard.layout)
self.assertEquals(dashboard.widgets, 1)
self.assertEquals(rv.json['layout'], [[rv.json['widget']['id']]])
self.assertEquals(rv.json['new_row'], True)
rv2 = self.create_widget(dashboard, vis)
self.assertEquals(dashboard.widgets, 2)
self.assertEquals(rv2.json['layout'],
[[rv.json['widget']['id'], rv2.json['widget']['id']]])
self.assertEquals(rv2.json['new_row'], False)
rv3 = self.create_widget(dashboard, vis)
self.assertEquals(rv3.json['new_row'], True)
rv4 = self.create_widget(dashboard, vis, width=2)
self.assertEquals(rv4.json['layout'],
[[rv.json['widget']['id'], rv2.json['widget']['id']],
[rv3.json['widget']['id']],
[rv4.json['widget']['id']]])
self.assertEquals(rv4.json['new_row'], True)
def test_wont_create_widget_for_visualization_you_dont_have_access_to(self):
dashboard = self.factory.create_dashboard()
vis = self.factory.create_visualization()
ds = self.factory.create_data_source(group=self.factory.create_group())
vis.query.data_source = ds
vis.query.save()
data = {
'visualization_id': vis.id,
'dashboard_id': dashboard.id,
'options': {},
'width': 1
}
rv = self.make_request('post', '/api/widgets', data=data)
self.assertEqual(rv.status_code, 403)
def test_create_text_widget(self):
dashboard = self.factory.create_dashboard()
data = {
'visualization_id': None,
'text': 'Sample text.',
'dashboard_id': dashboard.id,
'options': {},
'width': 2
}
rv = self.make_request('post', '/api/widgets', data=data)
self.assertEquals(rv.status_code, 200)
self.assertEquals(rv.json['widget']['text'], 'Sample text.')
def test_delete_widget(self):
widget = self.factory.create_widget()
rv = self.make_request('delete', '/api/widgets/{0}'.format(widget.id))
self.assertEquals(rv.status_code, 200)
dashboard = models.Dashboard.get_by_slug_and_org(widget.dashboard.slug, widget.dashboard.org)
self.assertEquals(dashboard.widgets.count(), 0)
self.assertEquals(dashboard.layout, '[]')
# TODO: test how it updates the layout

View File

@ -133,77 +133,6 @@ class DashboardAPITest(BaseTestCase, AuthenticationTestMixin):
self.assertTrue(d.is_archived)
class WidgetAPITest(BaseTestCase):
def create_widget(self, dashboard, visualization, width=1):
data = {
'visualization_id': visualization.id,
'dashboard_id': dashboard.id,
'options': {},
'width': width
}
rv = self.make_request('post', '/api/widgets', data=data)
return rv
def test_create_widget(self):
dashboard = self.factory.create_dashboard()
vis = self.factory.create_visualization()
rv = self.create_widget(dashboard, vis)
self.assertEquals(rv.status_code, 200)
dashboard = models.Dashboard.get(models.Dashboard.id == dashboard.id)
self.assertEquals(unicode(rv.json['layout']), dashboard.layout)
self.assertEquals(dashboard.widgets, 1)
self.assertEquals(rv.json['layout'], [[rv.json['widget']['id']]])
self.assertEquals(rv.json['new_row'], True)
rv2 = self.create_widget(dashboard, vis)
self.assertEquals(dashboard.widgets, 2)
self.assertEquals(rv2.json['layout'],
[[rv.json['widget']['id'], rv2.json['widget']['id']]])
self.assertEquals(rv2.json['new_row'], False)
rv3 = self.create_widget(dashboard, vis)
self.assertEquals(rv3.json['new_row'], True)
rv4 = self.create_widget(dashboard, vis, width=2)
self.assertEquals(rv4.json['layout'],
[[rv.json['widget']['id'], rv2.json['widget']['id']],
[rv3.json['widget']['id']],
[rv4.json['widget']['id']]])
self.assertEquals(rv4.json['new_row'], True)
def test_create_text_widget(self):
dashboard = self.factory.create_dashboard()
data = {
'visualization_id': None,
'text': 'Sample text.',
'dashboard_id': dashboard.id,
'options': {},
'width': 2
}
rv = self.make_request('post', '/api/widgets', data=data)
self.assertEquals(rv.status_code, 200)
self.assertEquals(rv.json['widget']['text'], 'Sample text.')
def test_delete_widget(self):
widget = self.factory.create_widget()
rv = self.make_request('delete', '/api/widgets/{0}'.format(widget.id))
self.assertEquals(rv.status_code, 200)
dashboard = models.Dashboard.get_by_slug_and_org(widget.dashboard.slug, widget.dashboard.org)
self.assertEquals(dashboard.widgets.count(), 0)
self.assertEquals(dashboard.layout, '[]')
# TODO: test how it updates the layout
class VisualizationResourceTest(BaseTestCase):
def test_create_visualization(self):
query = self.factory.create_query()