redash/tests/test_permissions.py
Omer Lachish 51d8131db5
Allow Parameters on Public Dashboards (#3659)
* change has_access and require_access signatures to work with the objects that require access, instead of their groups

* use the textless endpoint (/api/queries/:id/results) for pristine
queriest

* Revert "use the textless endpoint (/api/queries/:id/results) for pristine"

This reverts commit cd2cee77385ecf79efd2f1aa21fab0dd43943264.

* go to textless /api/queries/:id/results by default

* change `run_query`'s signature to accept a ParameterizedQuery instead of
constructing it inside

* raise HTTP 400 when receiving invalid parameter values. Fixes #3394

* enqueue jobs for ApiUsers

* rename `id` to `user_id`

* support executing queries using Query api_keys by instantiating an ApiUser that would be able to execute the specific query

* show deprecation messages for ALLOW_PARAMETERS_IN_EMBEDS. Also, move
other message (email not verified) to use the same mechanism

* add link to forum message regarding embed deprecation

* change API to /api/queries/:id/dropdowns/:dropdown_id

* split to 2 different dropdown endpoints and implement the second

* add test cases for /api/queries/:id/dropdowns/:id

* use new /dropdowns endpoint in frontend

* first e2e test for sharing embeds

* Pleasing the CodeClimate overlords

* All glory to CodeClimate

* remove residues from bad rebase

* add query id and data source id to serialized public dashboards

* add global parameters directive to public dashboards page

* allow access to a query by the api_key of the dashboard which includes
it

* rename `object` to `obj`

* simplify permission tests once `has_access` accepts groups

* support global parameters for public dashboards

* change has_access and require_access signatures to work with the objects that require access, instead of their groups

* rename `object` to `obj`

* simplify permission tests once `has_access` accepts groups

* no need to log `is_api_key`

* send parameters to public dashboard page

* allow access to a query by the api_key of the dashboard which includes it

* disable sharing if dashboard is associated with unsafe queries

* remove cypress test added in the wrong place due to a faulty rebase

* add support for clicking buttons in cy.clickThrough

* Cypress test which verifies that dashboards with safe queries can be shared

* Cypress test which verifies that dashboards with unsafe queries can't be shared

* remove duplicate tests

* use this.enabled and negate when needed

* remove stale comment

* add another Cypress test to verify that unauthenticated users have access to public dashboards with parameters

* obviously, I commit 'only' the first time I use it

* search for query access by query id and not api_key

* no need to fetch latest query data as it is loaded by frontend from the textless endpoint

* test that queries associated with dashboards are accessible when supplying the dashboard api_key

* propagate `isDirty` down to `QueryBasedParameterInput`

* go to /api/:id/dropdown while editing a query, since dropdown queries might still not be associated with the parent. see #3711

* show helpful error message if dropdown values cannot be fetched

* use backticks instead of line concatenation

* remove requirement to have direct access to dropdown query in order validate it. parent query association checks are sufficient

* remove isDirty-based implementation and allow dropdown queries through nested ACL even if they aren't associated yet (given that the user has _direct_ access to the dropdown query)

* fix tests to cover all cases for /api/queries/:id/dropdowns/:id

* fix indentation

* require access to the query, not the data source

* resolve dashboard user by query id

* apply new copy to Cypress tests

* if only something would have prevented me from commiting an 'only' call 🤔

* very important handling of whitespace

* respond to parameter's Apply button

* text widgets are safe for sharing

* remove redundant event

* add a safety check that object has dashboard_api_keys before calling it

* supply a parameter value for text parameters to have it show up

* add parameter values for date and datetime

* use the current year and month to avoid pagination

* use Cypress.moment() instead of preinstalled moment()

* explicitly create parameters

* refresh query data if a  querystring parameter is provided

* avoid sending a data_source_id - it's only relevant to unsaved queries, since a saved query's data_source is available in the backend

* remove empty query text workaround

* provide default value to parameter

* add a few more dashboard sharing specs

* lint

* wait for DynamicTable to appear to reveal that actual results are displaying

* override error message for unsafely shared widgets
2019-07-15 15:09:30 +03:00

67 lines
2.7 KiB
Python

from tests import BaseTestCase
from collections import namedtuple
from unittest import TestCase
from redash.permissions import has_access
from redash import models
MockUser = namedtuple('MockUser', ['permissions', 'group_ids'])
view_only = True
class TestHasAccess(BaseTestCase):
def test_allows_admin_regardless_of_groups(self):
user = MockUser(['admin'], [])
self.assertTrue(has_access({}, user, view_only))
self.assertTrue(has_access({}, user, not view_only))
def test_allows_if_user_member_in_group_with_view_access(self):
user = MockUser([], [1])
self.assertTrue(has_access({1: view_only}, user, view_only))
def test_allows_if_user_member_in_group_with_full_access(self):
user = MockUser([], [1])
self.assertTrue(has_access({1: not view_only}, user, not view_only))
def test_allows_if_user_member_in_multiple_groups(self):
user = MockUser([], [1, 2, 3])
self.assertTrue(has_access({1: not view_only, 2: view_only}, user, not view_only))
self.assertFalse(has_access({1: view_only, 2: view_only}, user, not view_only))
self.assertTrue(has_access({1: view_only, 2: view_only}, user, view_only))
self.assertTrue(has_access({1: not view_only, 2: not view_only}, user, view_only))
def test_not_allows_if_not_enough_permission(self):
user = MockUser([], [1])
self.assertFalse(has_access({1: view_only}, user, not view_only))
self.assertFalse(has_access({2: view_only}, user, not view_only))
self.assertFalse(has_access({2: view_only}, user, view_only))
self.assertFalse(has_access({2: not view_only, 1: view_only}, user, not view_only))
def test_allows_access_to_query_by_query_api_key(self):
query = self.factory.create_query()
user = models.ApiUser(query.api_key, None, [])
self.assertTrue(has_access(query, user, view_only))
def test_doesnt_allow_access_to_query_by_different_api_key(self):
query = self.factory.create_query()
other_query = self.factory.create_query()
user = models.ApiUser(other_query.api_key, None, [])
self.assertFalse(has_access(query, user, view_only))
def test_allows_access_to_query_by_dashboard_api_key(self):
dashboard = self.factory.create_dashboard()
visualization = self.factory.create_visualization()
self.factory.create_widget(dashboard=dashboard, visualization=visualization)
query = self.factory.create_query(visualizations=[visualization])
api_key = self.factory.create_api_key(object=dashboard).api_key
user = models.ApiUser(api_key, None, [])
self.assertTrue(has_access(query, user, view_only))