Use new helper for dashboards API

This commit is contained in:
Arik Fraimovich 2016-10-24 21:33:49 +03:00
parent edea6f3a05
commit 8b091129ed
3 changed files with 66 additions and 82 deletions

View File

@ -1,5 +1,3 @@
import logging
from flask import request, url_for
from flask_restful import abort
@ -7,7 +5,7 @@ from funcy import distinct, take
from itertools import chain
from redash import models
from redash.permissions import require_permission, require_admin_or_owner
from redash.permissions import require_permission, require_admin_or_owner, require_object_modify_permission
from redash.handlers.base import BaseResource, get_object_or_404
import redash.permissions
@ -63,25 +61,14 @@ class DashboardResource(BaseResource):
# TODO: either convert all requests to use slugs or ids
dashboard = models.Dashboard.get_by_id_and_org(dashboard_slug, self.current_org)
# check access permissions
if not redash.permissions.is_admin_or_owner(object_owner_id=dashboard.user.id):
if not self.current_user.has_access(
access_type=models.AccessPermission.ACCESS_TYPE_MODIFY,
object_id=dashboard.id,
object_type=models.Dashboard.__name__):
abort(403)
require_object_modify_permission(dashboard, self.current_user)
# Optimistic locking: figure out which user made the last
# change to this dashboard, and bail out if necessary
last_change = models.Change.get_latest(object_id=dashboard.id, object_type=models.Dashboard.__name__)
if last_change and 'version' in dashboard_properties:
if last_change.object_version > dashboard_properties['version']:
abort(409) # HTTP 'Conflict' status code
old_dashboard = {'name': dashboard.name, 'layout': dashboard.layout}
# old_dashboard = {'name': dashboard.name, 'layout': dashboard.layout}
dashboard.layout = dashboard_properties['layout']
dashboard.name = dashboard_properties['name']
new_change = dashboard.tracked_save(changing_user=self.current_user, old_object=old_dashboard)
# new_change = dashboard.tracked_save(changing_user=self.current_user, old_object=old_dashboard)
dashboard.save()
result = dashboard.to_dict(with_widgets=True, user=self.current_user)
return result

View File

@ -1,5 +1,64 @@
import json
from tests import BaseTestCase
from redash.models import ApiKey
from redash.models import ApiKey, Dashboard
class DashboardAPITest(BaseTestCase):
def test_get_dashboard(self):
d1 = self.factory.create_dashboard()
rv = self.make_request('get', '/api/dashboards/{0}'.format(d1.slug))
self.assertEquals(rv.status_code, 200)
expected = d1.to_dict(with_widgets=True)
actual = json.loads(rv.data)
self.assertResponseEqual(expected, actual)
def test_get_dashboard_filters_unauthorized_widgets(self):
dashboard = self.factory.create_dashboard()
restricted_ds = self.factory.create_data_source(group=self.factory.create_group())
query = self.factory.create_query(data_source=restricted_ds)
vis = self.factory.create_visualization(query=query)
restricted_widget = self.factory.create_widget(visualization=vis, dashboard=dashboard)
widget = self.factory.create_widget(dashboard=dashboard)
dashboard.layout = '[[{}, {}]]'.format(widget.id, restricted_widget.id)
dashboard.save()
rv = self.make_request('get', '/api/dashboards/{0}'.format(dashboard.slug))
self.assertEquals(rv.status_code, 200)
self.assertTrue(rv.json['widgets'][0][1]['restricted'])
self.assertNotIn('restricted', rv.json['widgets'][0][0])
def test_get_non_existing_dashboard(self):
rv = self.make_request('get', '/api/dashboards/not_existing')
self.assertEquals(rv.status_code, 404)
def test_create_new_dashboard(self):
dashboard_name = 'Test Dashboard'
rv = self.make_request('post', '/api/dashboards', data={'name': dashboard_name})
self.assertEquals(rv.status_code, 200)
self.assertEquals(rv.json['name'], 'Test Dashboard')
self.assertEquals(rv.json['user_id'], self.factory.user.id)
self.assertEquals(rv.json['layout'], [])
def test_update_dashboard(self):
d = self.factory.create_dashboard()
new_name = 'New Name'
rv = self.make_request('post', '/api/dashboards/{0}'.format(d.id),
data={'name': new_name, 'layout': '[]'})
self.assertEquals(rv.status_code, 200)
self.assertEquals(rv.json['name'], new_name)
def test_delete_dashboard(self):
d = self.factory.create_dashboard()
rv = self.make_request('delete', '/api/dashboards/{0}'.format(d.slug))
self.assertEquals(rv.status_code, 200)
d = Dashboard.get_by_slug_and_org(d.slug, d.org)
self.assertTrue(d.is_archived)
class TestDashboardShareResourcePost(BaseTestCase):

View File

@ -71,68 +71,6 @@ class StatusTest(BaseTestCase):
self.assertEqual(rv.status_code, 302)
class DashboardAPITest(BaseTestCase, AuthenticationTestMixin):
def setUp(self):
self.paths = ['/api/dashboards']
super(DashboardAPITest, self).setUp()
def test_get_dashboard(self):
d1 = self.factory.create_dashboard()
rv = self.make_request('get', '/api/dashboards/{0}'.format(d1.slug))
self.assertEquals(rv.status_code, 200)
expected = d1.to_dict(with_widgets=True)
actual = json.loads(rv.data)
self.assertResponseEqual(expected, actual)
def test_get_dashboard_filters_unauthorized_widgets(self):
dashboard = self.factory.create_dashboard()
restricted_ds = self.factory.create_data_source(group=self.factory.create_group())
query = self.factory.create_query(data_source=restricted_ds)
vis = self.factory.create_visualization(query=query)
restricted_widget = self.factory.create_widget(visualization=vis, dashboard=dashboard)
widget = self.factory.create_widget(dashboard=dashboard)
dashboard.layout = '[[{}, {}]]'.format(widget.id, restricted_widget.id)
dashboard.save()
rv = self.make_request('get', '/api/dashboards/{0}'.format(dashboard.slug))
self.assertEquals(rv.status_code, 200)
self.assertTrue(rv.json['widgets'][0][1]['restricted'])
self.assertNotIn('restricted', rv.json['widgets'][0][0])
def test_get_non_existing_dashboard(self):
rv = self.make_request('get', '/api/dashboards/not_existing')
self.assertEquals(rv.status_code, 404)
def test_create_new_dashboard(self):
dashboard_name = 'Test Dashboard'
rv = self.make_request('post', '/api/dashboards', data={'name': dashboard_name})
self.assertEquals(rv.status_code, 200)
self.assertEquals(rv.json['name'], 'Test Dashboard')
self.assertEquals(rv.json['user_id'], self.factory.user.id)
self.assertEquals(rv.json['layout'], [])
def test_update_dashboard(self):
d = self.factory.create_dashboard()
new_name = 'New Name'
rv = self.make_request('post', '/api/dashboards/{0}'.format(d.id),
data={'name': new_name, 'layout': '[]'})
self.assertEquals(rv.status_code, 200)
self.assertEquals(rv.json['name'], new_name)
def test_delete_dashboard(self):
d = self.factory.create_dashboard()
rv = self.make_request('delete', '/api/dashboards/{0}'.format(d.slug))
self.assertEquals(rv.status_code, 200)
d = models.Dashboard.get_by_slug_and_org(d.slug, d.org)
self.assertTrue(d.is_archived)
class VisualizationResourceTest(BaseTestCase):
def test_create_visualization(self):
query = self.factory.create_query()