示例#1
0
    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))
示例#2
0
    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))
示例#3
0
    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))
示例#4
0
    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))
示例#5
0
    def post(self):
        """
        Execute a query (or retrieve recent results).

        :qparam string query: The query text to execute
        :qparam number query_id: The query object to update with the result (optional)
        :qparam number max_age: If query results less than `max_age` seconds old are available,
                                return them, otherwise execute the query; if omitted or -1, returns
                                any cached result, or executes if not available. Set to zero to
                                always execute.
        :qparam number data_source_id: ID of data source to query
        :qparam object parameters: A set of parameter values to apply to the query.
        """
        params = request.get_json(force=True)

        query = params['query']
        max_age = params.get('max_age', -1)
        # max_age might have the value of None, in which case calling int(None) will fail
        if max_age is None:
            max_age = -1
        max_age = int(max_age)
        query_id = params.get('query_id', 'adhoc')
        parameters = params.get('parameters',
                                collect_parameters_from_request(request.args))

        parameterized_query = ParameterizedQuery(query, org=self.current_org)

        data_source_id = params.get('data_source_id')

        if data_source_id:
            data_source = models.DataSource.get_by_id_and_org(
                params.get('data_source_id'), self.current_org)
        else:
            return error_messages['select_data_source']

        if query_id:
            query = models.Query.get_by_id_and_org(params.get('query_id'),
                                                   self.current_org)
        else:
            return error_messages['select_query']

        if not has_access(data_source, self.current_user, not_view_only):
            return error_messages['no_permission']

        if not has_access(query, self.current_user, not_view_only):
            return error_messages['no_permission']

        return run_query(parameterized_query, parameters, data_source,
                         query_id, max_age)
示例#6
0
    def post(self):
        params = request.get_json(force=True)
        data_source = models.DataSource.get_by_id_and_org(params.get('data_source_id'), self.current_org)

        if not has_access(data_source.groups, self.current_user, not_view_only):
            return {'job': {'status': 4, 'error': 'You do not have permission to run queries with this data source.'}}, 403

        self.record_event({
            'action': 'execute_query',
            'timestamp': int(time.time()),
            'object_id': data_source.id,
            'object_type': 'data_source',
            'query': params['query']
        })

        max_age = int(params.get('max_age', -1))

        if max_age == 0:
            query_result = None
        else:
            query_result = models.QueryResult.get_latest(data_source, params['query'], max_age)

        if query_result:
            return {'query_result': query_result.to_dict()}
        else:
            query_id = params.get('query_id', 'adhoc')
            job = QueryTask.add_task(params['query'], data_source,
                                     metadata={"Username": self.current_user.name, "Query ID": query_id})
            return {'job': job.to_dict()}
示例#7
0
    def post(self):
        params = request.get_json(force=True)
        parameter_values = collect_parameters_from_request(request.args)

        query = params['query']
        max_age = int(params.get('max_age', -1))
        query_id = params.get('query_id', 'adhoc')

        data_source = models.DataSource.get_by_id_and_org(
            params.get('data_source_id'), self.current_org)

        if not has_access(data_source.groups, self.current_user,
                          not_view_only):
            return {
                'job': {
                    'status':
                    4,
                    'error':
                    'You do not have permission to run queries with this data source.'
                }
            }, 403

        self.record_event({
            'action': 'execute_query',
            'timestamp': int(time.time()),
            'object_id': data_source.id,
            'object_type': 'data_source',
            'query': query
        })

        return run_query(data_source, parameter_values, query, query_id,
                         max_age)
示例#8
0
    def post(self):
        """
        Execute a query (or retrieve recent results).

        :qparam string query: The query text to execute
        :qparam number query_id: The query object to update with the result (optional)
        :qparam number max_age: If query results less than `max_age` seconds old are available,
                                return them, otherwise execute the query; if omitted or -1, returns
                                any cached result, or executes if not available. Set to zero to
                                always execute.
        :qparam number data_source_id: ID of data source to query
        """
        params = request.get_json(force=True)
        parameter_values = collect_parameters_from_request(request.args)

        query = params['query']
        max_age = int(params.get('max_age', -1))
        query_id = params.get('query_id', 'adhoc')

        data_source = models.DataSource.get_by_id_and_org(params.get('data_source_id'), self.current_org)

        if not has_access(data_source.groups, self.current_user, not_view_only):
            return {'job': {'status': 4, 'error': 'You do not have permission to run queries with this data source.'}}, 403

        self.record_event({
            'action': 'execute_query',
            'object_id': data_source.id,
            'object_type': 'data_source',
            'query': query
        })
        return run_query(data_source, parameter_values, query, query_id, max_age)
示例#9
0
    def post(self):
        params = request.get_json(force=True)
        data_source = models.DataSource.get_by_id_and_org(params.get('data_source_id'), self.current_org)

        if not has_access(data_source.groups, self.current_user, not_view_only):
            return {'job': {'status': 4, 'error': 'You do not have permission to run queries with this data source.'}}, 403

        self.record_event({
            'action': 'execute_query',
            'timestamp': int(time.time()),
            'object_id': data_source.id,
            'object_type': 'data_source',
            'query': params['query']
        })

        max_age = int(params.get('max_age', -1))

        if max_age == 0:
            query_result = None
        else:
            query_result = models.QueryResult.get_latest(data_source, params['query'], max_age)

        if query_result:
            return {'query_result': query_result.to_dict()}
        else:
            query_id = params.get('query_id', 'adhoc')
            job = QueryTask.add_task(params['query'], data_source,
                                     metadata={"Username": self.current_user.name, "Query ID": query_id})
            return {'job': job.to_dict()}
示例#10
0
    def post(self, data_source_id):
        params = request.get_json(force=True)
        parameter_values = collect_parameters_from_request(request.args)
        query = mustache_render(params['query'], parameter_values)
        data_source = get_object_or_404(
            models.DataSource.get_by_id_and_org,
            data_source_id,
            self.current_org,
        )

        # get the validator method
        validator = self.get_validator(data_source.query_runner)
        if (validator is None
                or not has_access(data_source.groups, self.current_user, not_view_only)):
            return {
                'valid': False,
                'report': 'You do not have permission to run queries with this data source.'
            }, 403

        try:
            valid, report = validator(data_source.query_runner, query)
            return {'valid': valid, 'report': report}, 200
        except apiclient.errors.HttpError as e:
            if e.resp.status == 400:
                error = json_loads(e.content)['error']['message']
            else:
                error = e.content
            return {'valid': False, 'report': error}, 200
        except Exception as e:
            return {'valid': False, 'report': str(e)}, 500
示例#11
0
    def post(self, query_id):
        """
        Execute a saved query.

        :param number query_id: The ID of the query whose results should be fetched.
        :param object parameters: The parameter values to apply to the query.
        :qparam number max_age: If query results less than `max_age` seconds old are available,
                                return them, otherwise execute the query; if omitted or -1, returns
                                any cached result, or executes if not available. Set to zero to
                                always execute.
        """
        params = request.get_json(force=True)
        parameter_values = params.get('parameters')

        max_age = params.get('max_age', -1)
        # max_age might have the value of None, in which case calling int(None) will fail
        if max_age is None:
            max_age = -1
        max_age = int(max_age)

        query = get_object_or_404(models.Query.get_by_id_and_org, query_id, self.current_org)

        allow_executing_with_view_only_permissions = query.parameterized.is_safe

        if has_access(query, self.current_user, allow_executing_with_view_only_permissions):
            return run_query(query.parameterized, parameter_values, query.data_source, query_id, max_age)
        else:
            return {'job': {'status': 4, 'error': 'You do not have permission to run queries with this data source.'}}, 403
示例#12
0
    def post(self, query_id):
        """
        Execute a saved query.

        :param number query_id: The ID of the query whose results should be fetched.
        :param object parameters: The parameter values to apply to the query.
        :qparam number max_age: If query results less than `max_age` seconds old are available,
                                return them, otherwise execute the query; if omitted or -1, returns
                                any cached result, or executes if not available. Set to zero to
                                always execute.
        """
        params = request.get_json(force=True)
        parameters = params.get('parameters', {})
        max_age = int(params.get('max_age', 0))

        query = get_object_or_404(models.Query.get_by_id_and_org, query_id,
                                  self.current_org)

        if not has_access(query.data_source.groups, self.current_user,
                          not_view_only):
            return {
                'job': {
                    'status':
                    4,
                    'error':
                    'You do not have permission to run queries with this data source.'
                }
            }, 403
        else:
            return run_query(query.data_source, parameters, query.query_text,
                             query_id, max_age)
示例#13
0
    def post(self, query_id):
        """
        Execute a saved query.

        :param number query_id: The ID of the query whose results should be fetched.
        :param object parameters: The parameter values to apply to the query.
        :qparam number max_age: If query results less than `max_age` seconds old are available,
                                return them, otherwise execute the query; if omitted or -1, returns
                                any cached result, or executes if not available. Set to zero to
                                always execute.
        """
        params = request.get_json(force=True, silent=True) or {}
        parameter_values = params.get('parameters', {})

        max_age = params.get('max_age', -1)
        # max_age might have the value of None, in which case calling int(None) will fail
        if max_age is None:
            max_age = -1
        max_age = int(max_age)

        query = get_object_or_404(models.Query.get_by_id_and_org, query_id, self.current_org)

        allow_executing_with_view_only_permissions = query.parameterized.is_safe

        if has_access(query, self.current_user, allow_executing_with_view_only_permissions):
            return run_query(query.parameterized, parameter_values, query.data_source, query_id, max_age)
        else:
            if not query.parameterized.is_safe:
                if current_user.is_api_user():
                    return error_messages['unsafe_when_shared']
                else:
                    return error_messages['unsafe_on_view_only']
            else:
                return error_messages['no_permission']
示例#14
0
    def post(self):
        """
        Execute a query (or retrieve recent results).

        :qparam string query: The query text to execute
        :qparam number query_id: The query object to update with the result (optional)
        :qparam number max_age: If query results less than `max_age` seconds old are available, return them, otherwise execute the query; if omitted, always execute
        :qparam number data_source_id: ID of data source to query
        """
        params = request.get_json(force=True)
        parameter_values = collect_parameters_from_request(request.args)

        query = params['query']
        max_age = int(params.get('max_age', -1))
        query_id = params.get('query_id', 'adhoc')

        data_source = models.DataSource.get_by_id_and_org(params.get('data_source_id'), self.current_org)

        if not has_access(data_source.groups, self.current_user, not_view_only):
            return {'job': {'status': 4, 'error': 'You do not have permission to run queries with this data source.'}}, 403

        self.record_event({
            'action': 'execute_query',
            'timestamp': int(time.time()),
            'object_id': data_source.id,
            'object_type': 'data_source',
            'query': query
        })
        return run_query(data_source, parameter_values, query, query_id, max_age)
示例#15
0
    def post(self):
        """
        Execute a query (or retrieve recent results).

        :qparam string query: The query text to execute
        :qparam number query_id: The query object to update with the result (optional)
        :qparam number max_age: If query results less than `max_age` seconds old are available,
                                return them, otherwise execute the query; if omitted or -1, returns
                                any cached result, or executes if not available. Set to zero to
                                always execute.
        :qparam number data_source_id: ID of data source to query
        :qparam object parameters: A set of parameter values to apply to the query.
        """
        params = request.get_json(force=True)

        query = params['query']
        max_age = params.get('max_age', -1)
        # max_age might have the value of None, in which case calling int(None) will fail
        if max_age is None:
            max_age = -1
        max_age = int(max_age)
        query_id = params.get('query_id', 'adhoc')
        parameters = params.get('parameters',
                                collect_parameters_from_request(request.args))

        parameterized_query = ParameterizedQuery(query)

        data_source_id = params.get('data_source_id')
        if data_source_id:
            data_source = models.DataSource.get_by_id_and_org(
                params.get('data_source_id'), self.current_org)
        else:
            return {
                'job': {
                    'status': 4,
                    'error': 'Please select data source to run this query.'
                }
            }, 401

        if not has_access(data_source, self.current_user, not_view_only):
            return {
                'job': {
                    'status':
                    4,
                    'error':
                    'You do not have permission to run queries with this data source.'
                }
            }, 403

        self.record_event({
            'action': 'execute_query',
            'object_id': data_source.id,
            'object_type': 'data_source',
            'query': query,
            'query_id': query_id,
            'parameters': parameters
        })
        return run_query(parameterized_query, parameters, data_source,
                         query_id, max_age)
示例#16
0
def serialize_dashboard(obj,
                        with_widgets=False,
                        user=None,
                        with_favorite_state=True):
    layout = json_loads(obj.layout)

    widgets = []

    if with_widgets:
        for w in obj.widgets:
            if w.visualization_id is None:
                widgets.append(serialize_widget(w))
            elif user and has_access(w.visualization.query_rel, user,
                                     view_only):
                widgets.append(serialize_widget(w))
            else:
                widget = project(serialize_widget(w),
                                 ('id', 'width', 'dashboard_id', 'options',
                                  'created_at', 'updated_at'))
                widget['restricted'] = True
                widgets.append(widget)
    else:
        widgets = None

    if obj.user is not None:
        _user = obj.user.to_dict()
    else:
        assets = app.extensions['webpack']['assets'] or {}
        path = 'images/avatar.svg'
        profile_image_url = url_for('static', filename=assets.get(path, path))
        _user = {
            'name': 'user',
            'profile_image_url': profile_image_url,
        }

    d = {
        'id': obj.id,
        'slug': obj.slug,
        'name': obj.name,
        'user_id': obj.user_id,
        # TODO: we should properly load the users
        'user': _user,
        'layout': layout,
        'dashboard_filters_enabled': obj.dashboard_filters_enabled,
        'widgets': widgets,
        'is_archived': obj.is_archived,
        'is_draft': obj.is_draft,
        'tags': obj.tags or [],
        # TODO: bulk load favorites
        'updated_at': obj.updated_at,
        'created_at': obj.created_at,
        'version': obj.version
    }

    if with_favorite_state:
        d['is_favorite'] = models.Favorite.is_favorite(current_user.id, obj)

    return d
示例#17
0
def serialize_dashboard(obj,
                        with_widgets=False,
                        user=None,
                        with_favorite_state=True):
    layout = json_loads(obj.layout)

    widgets = []

    if with_widgets:
        for w in obj.widgets:
            if w.visualization_id is None:
                widgets.append(serialize_widget(w))
            elif user and has_access(w.visualization.query_rel, user,
                                     view_only):
                widgets.append(serialize_widget(w))
            else:
                widget = project(
                    serialize_widget(w),
                    (
                        "id",
                        "width",
                        "dashboard_id",
                        "options",
                        "created_at",
                        "updated_at",
                    ),
                )
                widget["restricted"] = True
                widgets.append(widget)
    else:
        widgets = None

    d = {
        "id": obj.id,
        "slug": obj.name_as_slug,
        "name": obj.name,
        "user_id": obj.user_id,
        "user": {
            "id": obj.user.id,
            "name": obj.user.name,
            "email": obj.user.email,
            "profile_image_url": obj.user.profile_image_url,
        },
        "layout": layout,
        "dashboard_filters_enabled": obj.dashboard_filters_enabled,
        "widgets": widgets,
        "options": obj.options,
        "is_archived": obj.is_archived,
        "is_draft": obj.is_draft,
        "tags": obj.tags or [],
        "updated_at": obj.updated_at,
        "created_at": obj.created_at,
        "version": obj.version,
    }

    return d
示例#18
0
    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))
示例#19
0
文件: __init__.py 项目: zm1228/redash
def serialize_dashboard(obj,
                        with_widgets=False,
                        user=None,
                        with_favorite_state=True):
    layout = json_loads(obj.layout)

    widgets = []

    if with_widgets:
        for w in obj.widgets:
            if w.visualization_id is None:
                widgets.append(serialize_widget(w))
            elif user and has_access(w.visualization.query_rel, user,
                                     view_only):
                widgets.append(serialize_widget(w))
            else:
                widget = project(
                    serialize_widget(w),
                    (
                        "id",
                        "width",
                        "dashboard_id",
                        "options",
                        "created_at",
                        "updated_at",
                    ),
                )
                widget["restricted"] = True
                widgets.append(widget)
    else:
        widgets = None

    d = {
        "id": obj.id,
        "slug": obj.slug,
        "name": obj.name,
        "user_id": obj.user_id,
        # TODO: we should properly load the users
        "user": obj.user.to_dict(),
        "layout": layout,
        "dashboard_filters_enabled": obj.dashboard_filters_enabled,
        "widgets": widgets,
        "is_archived": obj.is_archived,
        "is_draft": obj.is_draft,
        "tags": obj.tags or [],
        # TODO: bulk load favorites
        "updated_at": obj.updated_at,
        "created_at": obj.created_at,
        "version": obj.version,
    }

    if with_favorite_state:
        d["is_favorite"] = models.Favorite.is_favorite(current_user.id, obj)

    return d
示例#20
0
def _load_query(user, query_id):
    query = models.Query.get_by_id(query_id)

    if user.org_id != query.org_id:
        raise PermissionError("Query id {} not found.".format(query.id))

    if not has_access(query.data_source, user, not_view_only):
        raise PermissionError(u"You are not allowed to execute queries on {} data source (used for query id {}).".format(
            query.data_source.name, query.id))

    return query
示例#21
0
def _load_query(user, query_id):
    query = models.Query.get_by_id(query_id)

    if user.org_id != query.org_id:
        raise PermissionError("Query id {} not found.".format(query.id))

    if not has_access(query.data_source, user, not_view_only):
        raise PermissionError(u"You are not allowed to execute queries on {} data source (used for query id {}).".format(
            query.data_source.name, query.id))

    return query
def _load_query(user, query_id):
    query = models.Query.get_by_id(query_id)

    if user.org_id != query.org_id:
        raise PermissionError("Query id {} not found.".format(query.id))

    # TODO: this duplicates some of the logic we already have in the redash.handlers.query_results.
    # We should merge it so it's consistent.
    if not has_access(query.data_source, user, view_only):
        raise PermissionError("You do not have access to query id {}.".format(query.id))

    return query
示例#23
0
def serialize_dashboard(obj,
                        with_widgets=False,
                        user=None,
                        with_favorite_state=True):
    layout = json_loads(obj.layout)

    widgets = []

    if with_widgets:
        for w in obj.widgets:
            if w.visualization_id is None:
                widgets.append(serialize_widget(w))
            elif user and has_access(w.visualization.query_rel, user,
                                     view_only):
                widgets.append(serialize_widget(w))
            else:
                widget = project(serialize_widget(w),
                                 ('id', 'width', 'dashboard_id', 'options',
                                  'created_at', 'updated_at'))
                widget['restricted'] = True
                widgets.append(widget)
    else:
        widgets = None

    d = {
        'id': obj.id,
        'slug': obj.slug,
        'name': obj.name,
        'user_id': current_user.id,
        'created_by': obj.user.to_dict(),
        'user': current_user.to_dict(),
        'layout': layout,
        'dashboard_filters_enabled': obj.dashboard_filters_enabled,
        'widgets': widgets,
        'is_archived': obj.is_archived,
        'is_draft': obj.is_draft,
        'tags': obj.tags or [],
        'updated_at': obj.updated_at,
        'created_at': obj.created_at,
        'version': obj.version,
        'background_image': obj.background_image,
        'description': obj.description,
        'type': obj.type or 'dashboard',
        'folder_id': obj.folder_id
    }

    d['groups'] = [
        g.to_dict(with_permissions_for=True)
        for g in models.DashboardGroup.get_by_dashboard(obj)
    ]

    return d
示例#24
0
def serialize_dashboard(obj,
                        with_widgets=False,
                        user=None,
                        with_favorite_state=True):
    layout = json_loads(obj.layout)

    widgets = []

    if with_widgets:
        for w in obj.widgets:
            if w.visualization_id is None:
                widgets.append(serialize_widget(w))
            elif user and has_access(w.visualization.query_rel, user,
                                     view_only):
                widgets.append(serialize_widget(w))
            else:
                widget = project(serialize_widget(w),
                                 ('id', 'width', 'dashboard_id', 'options',
                                  'created_at', 'updated_at'))
                widget['restricted'] = True
                widgets.append(widget)
    else:
        widgets = None

    d = {
        'id': obj.id,
        'slug': obj.slug,
        'name': obj.name,
        'user_id': obj.user_id,
        # TODO: we should properly load the users
        'user': obj.user.to_dict(),
        'layout': layout,
        'dashboard_filters_enabled': obj.dashboard_filters_enabled,
        'widgets': widgets,
        'is_archived': obj.is_archived,
        'is_draft': obj.is_draft,
        'tags': obj.tags or [],
        # TODO: bulk load favorites
        'updated_at': obj.updated_at,
        'created_at': obj.created_at,
        'version': obj.version
    }

    if with_favorite_state:
        d['is_favorite'] = models.Favorite.is_favorite(current_user.id, obj)

    return d
示例#25
0
def _load_query(user, q):
    try:
        query = models.Query.get_by_id(q.id)
    except NoResultFound:
        query = None

    location = '(at line {} column {})'.format(q.line, q.column)

    if not query or user.org_id != query.org_id:
        raise PermissionError(u"Query id {} not found. {}".format(
            query_id, location))

    if not has_access(query.data_source.groups, user, not_view_only):
        raise PermissionError(
            u"You are not allowed to execute queries on {} data source (used for query id {}). {}"
            .format(query.data_source.name, query.id, location))

    return query
示例#26
0
def serialize_dashboard(obj, with_widgets=False, user=None, with_favorite_state=True):
    layout = json_loads(obj.layout)

    widgets = []

    if with_widgets:
        for w in obj.widgets:
            if w.visualization_id is None:
                widgets.append(serialize_widget(w))
            elif user and has_access(w.visualization.query_rel, user, view_only):
                widgets.append(serialize_widget(w))
            else:
                widget = project(serialize_widget(w),
                                ('id', 'width', 'dashboard_id', 'options', 'created_at', 'updated_at'))
                widget['restricted'] = True
                widgets.append(widget)
    else:
        widgets = None

    d = {
        'id': obj.id,
        'slug': obj.slug,
        'name': obj.name,
        'user_id': obj.user_id,
        # TODO: we should properly load the users
        'user': obj.user.to_dict(),
        'layout': layout,
        'dashboard_filters_enabled': obj.dashboard_filters_enabled,
        'widgets': widgets,
        'is_archived': obj.is_archived,
        'is_draft': obj.is_draft,
        'tags': obj.tags or [],
        # TODO: bulk load favorites
        'updated_at': obj.updated_at,
        'created_at': obj.created_at,
        'version': obj.version
    }

    if with_favorite_state:
        d['is_favorite'] = models.Favorite.is_favorite(current_user.id, obj)

    return d
示例#27
0
def serialize_dashboard_overview(obj, user=None):
    layout = json_loads(obj.layout)

    visualizations = []

    for w in obj.widgets:
        if w.visualization_id is not None:
            if user and has_access(w.visualization.query_rel, user, view_only):
                visualizations.append(w.visualization_id)

    d = {
        'id': obj.id,
        'slug': obj.slug,
        'name': obj.name,
        'visualizations': visualizations,
        'updated_at': obj.updated_at,
        'created_at': obj.created_at,
        'type': obj.type or 'dashboard'
    }

    return d
示例#28
0
    def post(self):
        """
        Execute a query (or retrieve recent results).

        :qparam string query: The query text to execute
        :qparam number query_id: The query object to update with the result (optional)
        :qparam number max_age: If query results less than `max_age` seconds old are available,
                                return them, otherwise execute the query; if omitted or -1, returns
                                any cached result, or executes if not available. Set to zero to
                                always execute.
        :qparam number data_source_id: ID of data source to query
        :qparam object parameters: A set of parameter values to apply to the query.
        """
        params = request.get_json(force=True)

        query = params['query']
        max_age = params.get('max_age', -1)
        # max_age might have the value of None, in which case calling int(None) will fail
        if max_age is None:
            max_age = -1
        max_age = int(max_age)
        query_id = params.get('query_id', 'adhoc')
        parameters = params.get('parameters', collect_parameters_from_request(request.args))

        parameterized_query = ParameterizedQuery(query)

        data_source = models.DataSource.get_by_id_and_org(params.get('data_source_id'), self.current_org)

        if not has_access(data_source, self.current_user, not_view_only):
            return {'job': {'status': 4, 'error': 'You do not have permission to run queries with this data source.'}}, 403

        self.record_event({
            'action': 'execute_query',
            'object_id': data_source.id,
            'object_type': 'data_source',
            'query': query,
            'query_id': query_id,
            'parameters': parameters
        })
        return run_query(parameterized_query, parameters, data_source, query_id, max_age)
示例#29
0
    def post(self):
        params = request.get_json(force=True)
        parameter_values = collect_parameters_from_request(request.args)

        query = params['query']
        max_age = int(params.get('max_age', -1))
        query_id = params.get('query_id', 'adhoc')

        data_source = models.DataSource.get_by_id_and_org(params.get('data_source_id'), self.current_org)

        if not has_access(data_source.groups, self.current_user, not_view_only):
            return {'job': {'status': 4, 'error': 'You do not have permission to run queries with this data source.'}}, 403

        self.record_event({
            'action': 'execute_query',
            'timestamp': int(time.time()),
            'object_id': data_source.id,
            'object_type': 'data_source',
            'query': query
        })

        return run_query(data_source, parameter_values, query, query_id, max_age)
示例#30
0
    def post(self, query_id):
        """
        Execute a saved query.

        :param number query_id: The ID of the query whose results should be fetched.
        :param object parameters: The parameter values to apply to the query.
        :qparam number max_age: If query results less than `max_age` seconds old are available,
                                return them, otherwise execute the query; if omitted or -1, returns
                                any cached result, or executes if not available. Set to zero to
                                always execute.
        """
        params = request.get_json(force=True)
        parameters = params.get('parameters', {})
        max_age = params.get('max_age', -1)
        # max_age might have the value of None, in which case calling int(None) will fail
        if max_age is None:
            max_age = -1
        max_age = int(max_age)

        query = get_object_or_404(models.Query.get_by_id_and_org, query_id,
                                  self.current_org)

        allow_executing_with_view_only_permissions = query.parameterized.is_safe

        if has_access(query.data_source.groups, self.current_user,
                      allow_executing_with_view_only_permissions):
            return run_query(query.parameterized, parameters,
                             query.data_source, query_id, max_age)
        else:
            return {
                'job': {
                    'status':
                    4,
                    'error':
                    'You do not have permission to run queries with this data source.'
                }
            }, 403
示例#31
0
    def post(self):
        """
        Execute a query (or retrieve recent results).

        :qparam string query: The query text to execute
        :qparam number query_id: The query object to update with the result (optional)
        :qparam number max_age: If query results less than `max_age` seconds old are available, return them, otherwise execute the query; if omitted, always execute
        :qparam number data_source_id: ID of data source to query
        """
        params = request.get_json(force=True)
        parameter_values = collect_parameters_from_request(request.args)

        query = params['query']
        max_age = int(params.get('max_age', -1))
        query_id = params.get('query_id', 'adhoc')

        data_source = models.DataSource.get_by_id_and_org(
            params.get('data_source_id'), self.current_org)

        if not has_access(data_source.groups, self.current_user,
                          not_view_only):
            return {
                'job': {
                    'status':
                    4,
                    'error':
                    'You do not have permission to run queries with this data source.'
                }
            }, 403

        if settings.REMOTE_RESOURCE_RESTRICTION_ENABLED and remote_resource_restriction(
                parameter_values, self.current_user, request):
            return {
                'job': {
                    'status':
                    4,
                    'error':
                    'You have a remote resource restriction on the provided parameters.'
                }
            }, 403

        self.record_event({
            'action': 'execute_query',
            'timestamp': int(time.time()),
            'object_id': data_source.id,
            'object_type': 'data_source',
            'query': query
        })

        try:
            return run_query(data_source, parameter_values, query, query_id,
                             max_age)
        except jwt.ExpiredSignatureError:
            return {
                'job': {
                    'status':
                    4,
                    'error':
                    'Your authentication credentials have expired, please re-login.',
                    'provider':
                    settings.REMOTE_JWT_EXPIRED_ENDPOINT +
                    urllib.quote_plus(request.referrer or settings.ROOT_UI_URL)
                }
            }, 401
示例#32
0
    def test_allows_if_user_member_in_group_with_view_access(self):
        user = MockUser([], [1], False)

        self.assertTrue(has_access({1: view_only}, user, view_only))
示例#33
0
    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))
示例#34
0
    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))
示例#35
0
    def test_allows_embed_with_view_access(self):
        user = MockUser([], [], True)

        self.assertTrue(has_access({}, user, view_only))
示例#36
0
def serialize_dashboard(obj,
                        with_widgets=False,
                        user=None,
                        with_favorite_state=True):
    layout = json_loads(obj.layout)

    widgets = []

    if with_widgets:
        for w in obj.widgets:
            if w.visualization_id is None:
                widgets.append(serialize_widget(w))
            elif user and has_access(w.visualization.query_rel, user,
                                     view_only):
                widgets.append(serialize_widget(w))
                # NOTE(jinlong): 判断当前分享的dashboard的组是否在当前访问用户所在的组里.
                user_groups = user.group_ids
                dash_group = obj.group_id
                if dash_group not in user_groups:
                    widget = project(
                        serialize_widget(w),
                        (
                            "id",
                            "width",
                            "dashboard_id",
                            "options",
                            "created_at",
                            "updated_at",
                        ),
                    )
                    widget["restricted"] = True
                    widget["err_infos"] = "没有dashboard所在组权限, 无法查看!"
                    widgets.append(widget)
                else:
                    widgets.append(serialize_widget(w))

            else:
                widget = project(
                    serialize_widget(w),
                    (
                        "id",
                        "width",
                        "dashboard_id",
                        "options",
                        "created_at",
                        "updated_at",
                    ),
                )
                widget["restricted"] = True
                widgets.append(widget)
    else:
        widgets = None

    d = {
        "id": obj.id,
        "slug": obj.slug,
        "name": obj.name,
        "user_id": obj.user_id,
        # TODO: we should properly load the users
        "user": obj.user.to_dict(),
        "layout": layout,
        "dashboard_filters_enabled": obj.dashboard_filters_enabled,
        "widgets": widgets,
        "is_archived": obj.is_archived,
        "is_draft": obj.is_draft,
        "tags": obj.tags or [],
        # TODO: bulk load favorites
        "updated_at": obj.updated_at,
        "created_at": obj.created_at,
        "version": obj.version,
        "group_name": "",
        "creator": obj.user.to_dict().get("name"),
    }

    # NOTE(jinlong): dashboard展示列表时添加group_name和crator
    group_id = obj.group_id
    if group_id:
        group_obj = models.Group.query.get(group_id)
        d['group_name'] = group_obj.name

    if with_favorite_state:
        d["is_favorite"] = models.Favorite.is_favorite(current_user.id, obj)

    return d
示例#37
0
    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))
示例#38
0
    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))
示例#39
0
    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))
示例#40
0
    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))