mirror of
https://github.com/valitydev/redash.git
synced 2024-11-07 01:25:16 +00:00
Verify user has access to visualization before creating widget
This commit is contained in:
parent
fad8f2b7be
commit
b183651e04
@ -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']
|
||||
|
||||
|
@ -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)
|
||||
|
92
tests/handlers/test_widgets.py
Normal file
92
tests/handlers/test_widgets.py
Normal 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
|
||||
|
||||
|
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user