def outdated_queries(): manager_status = redis_connection.hgetall('redash:status') query_ids = json_loads(manager_status.get('query_ids', '[]')) if query_ids: outdated_queries = ( models.Query.query.outerjoin(models.QueryResult) .filter(models.Query.id.in_(query_ids)) .order_by(models.Query.created_at.desc()) ) else: outdated_queries = [] record_event(current_org, current_user._get_current_object(), { 'action': 'list', 'object_type': 'outdated_queries', }) updated_at = None if manager_status and manager_status['last_refresh_at']: updated_at = manager_status['last_refresh_at'] response = { 'queries': QuerySerializer(outdated_queries, with_stats=True, with_last_modified_by=False).serialize(), 'updated_at': updated_at, } return json_response(response)
def post(self): """ Create a new query. :<json number data_source_id: The ID of the data source this query will run on :<json string query: Query text :<json string name: :<json string description: :<json string schedule: Schedule interval, in seconds, for repeated execution of this query :<json object options: Query options .. _query-response-label: :>json number id: Query ID :>json number latest_query_data_id: ID for latest output data from this query :>json string name: :>json string description: :>json string query: Query text :>json string query_hash: Hash of query text :>json string schedule: Schedule interval, in seconds, for repeated execution of this query :>json string api_key: Key for public access to this query's results. :>json boolean is_archived: Whether this query is displayed in indexes and search results or not. :>json boolean is_draft: Whether this query is a draft or not :>json string updated_at: Time of last modification, in ISO format :>json string created_at: Time of creation, in ISO format :>json number data_source_id: ID of the data source this query will run on :>json object options: Query options :>json number version: Revision version (for update conflict avoidance) :>json number user_id: ID of query creator :>json number last_modified_by_id: ID of user who last modified this query :>json string retrieved_at: Time when query results were last retrieved, in ISO format (may be null) :>json number runtime: Runtime of last query execution, in seconds (may be null) """ query_def = request.get_json(force=True) data_source = models.DataSource.get_by_id_and_org( query_def.pop('data_source_id'), self.current_org) require_access(data_source.groups, self.current_user, not_view_only) for field in [ 'id', 'created_at', 'api_key', 'visualizations', 'latest_query_data', 'last_modified_by' ]: query_def.pop(field, None) query_def['query_text'] = query_def.pop('query') query_def['user'] = self.current_user query_def['data_source'] = data_source query_def['org'] = self.current_org query_def['is_draft'] = True query = models.Query.create(**query_def) models.db.session.add(query) models.db.session.commit() self.record_event({ 'action': 'create', 'object_id': query.id, 'object_type': 'query' }) return QuerySerializer(query).serialize()
def outdated_queries(): manager_status = redis_connection.hgetall("redash:status") query_ids = json_loads(manager_status.get("query_ids", "[]")) if query_ids: outdated_queries = (models.Query.query.outerjoin( models.QueryResult).filter( models.Query.id.in_(query_ids)).order_by( models.Query.created_at.desc())) else: outdated_queries = [] record_event( current_org, current_user._get_current_object(), { "action": "list", "object_type": "outdated_queries", }, ) response = { "queries": QuerySerializer(outdated_queries, with_stats=True, with_last_modified_by=False).serialize(), "updated_at": manager_status["last_refresh_at"], } return json_response(response)
def post(self, query_id): """ Modify a query. :param query_id: ID of query to update :<json number data_source_id: The ID of the data source this query will run on :<json string query: Query text :<json string name: :<json string description: :<json string schedule: Schedule interval, in seconds, for repeated execution of this query :<json object options: Query options Responds with the updated :ref:`query <query-response-label>` object. """ query = get_object_or_404(models.Query.get_by_id_and_org, query_id, self.current_org) query_def = request.get_json(force=True) require_object_modify_permission(query, self.current_user) require_access_to_dropdown_queries(self.current_user, query_def) for field in [ "id", "created_at", "api_key", "visualizations", "latest_query_data", "user", "last_modified_by", "org", ]: query_def.pop(field, None) if "query" in query_def: query_def["query_text"] = query_def.pop("query") if "tags" in query_def: query_def["tags"] = [tag for tag in query_def["tags"] if tag] if "data_source_id" in query_def: data_source = models.DataSource.get_by_id_and_org( query_def["data_source_id"], self.current_org) require_access(data_source, self.current_user, not_view_only) query_def["last_modified_by"] = self.current_user query_def["changed_by"] = self.current_user # SQLAlchemy handles the case where a concurrent transaction beats us # to the update. But we still have to make sure that we're not starting # out behind. if "version" in query_def and query_def["version"] != query.version: abort(409) try: self.update_model(query, query_def) models.db.session.commit() except StaleDataError: abort(409) return QuerySerializer(query, with_visualizations=True).serialize()
def get(self, query_id): """ Retrieve a query. :param query_id: ID of query to fetch Responds with the :ref:`query <query-response-label>` contents. """ data = json_loads(query_id) if type(data).__name__ != "list": q = get_object_or_404(models.Query.get_by_id_and_org, query_id, self.current_org) require_access(q, self.current_user, view_only) result = QuerySerializer(q, with_visualizations=True).serialize() result["can_edit"] = can_modify(q, self.current_user) self.record_event({ "action": "view", "object_id": query_id, "object_type": "query" }) return result else: results = [] for query_id in data: q = get_object_or_404(models.Query.get_by_id_and_org, query_id, self.current_org) require_access(q, self.current_user, view_only) result = QuerySerializer(q, with_visualizations=True).serialize() result["can_edit"] = can_modify(q, self.current_user) self.record_event({ "action": "view", "object_id": query_id, "object_type": "query" }) results.append(result) return results
def get(self): """ Retrieve up to 10 queries recently modified by the user. Responds with a list of :ref:`query <query-response-label>` objects. """ results = models.Query.by_user(self.current_user).order_by(models.Query.updated_at.desc()).limit(10) return QuerySerializer(results, with_last_modified_by=False, with_user=False).serialize()
def post(self, query_id): """ Modify a query. :param query_id: ID of query to update :<json number data_source_id: The ID of the data source this query will run on :<json string query: Query text :<json string name: :<json string description: :<json string schedule: Schedule interval, in seconds, for repeated execution of this query :<json object options: Query options Responds with the updated :ref:`query <query-response-label>` object. """ query = get_object_or_404(models.Query.get_by_id_and_org, query_id, self.current_org) if not is_admin_or_owner(query.user_id): if models.QueryGroup.get_by_query_groups( query, query.query_groups).first() is None: abort(404) query_def = request.get_json(force=True) #require_object_modify_permission(query, self.current_user) require_access_to_dropdown_queries(self.current_user, query_def) for field in [ 'id', 'created_at', 'api_key', 'visualizations', 'latest_query_data', 'user', 'last_modified_by', 'org' ]: query_def.pop(field, None) if 'query' in query_def: query_def['query_text'] = query_def.pop('query') query_def['last_modified_by'] = self.current_user query_def['changed_by'] = self.current_user # SQLAlchemy handles the case where a concurrent transaction beats us # to the update. But we still have to make sure that we're not starting # out behind. if 'version' in query_def and query_def['version'] != query.version: abort(409) try: self.update_model(query, query_def) models.db.session.commit() except StaleDataError: abort(409) return QuerySerializer(query, with_visualizations=True).serialize()
def post(self, query_id): query = get_object_or_404(models.Query.get_by_id_and_org, query_id, self.current_org) require_admin_or_owner(query.user_id) query.regenerate_api_key() models.db.session.commit() self.record_event({ 'action': 'regnerate_api_key', 'object_id': query_id, 'object_type': 'query', }) result = QuerySerializer(query).serialize() return result
def get(self, query_id): """ Retrieve a query. :param query_id: ID of query to fetch Responds with the :ref:`query <query-response-label>` contents. """ q = get_object_or_404(models.Query.get_by_id_and_org, query_id, self.current_org) require_access(q.groups, self.current_user, view_only) result = QuerySerializer(q, with_visualizations=True).serialize() result['can_edit'] = can_modify(q, self.current_user) return result
def get(self, query_id): """ Retrieve a query. :param query_id: ID of query to fetch Responds with the :ref:`query <query-response-label>` contents. """ q = get_object_or_404(models.Query.get_by_id_and_org, query_id, self.current_org) search_term = request.args.get('q') if search_term: results = models.Query.search_by_user(search_term, self.current_user) else: results = models.Query.by_user(self.current_user) results = filter_by_tags(results, models.Query.tags) ordered_results = order_results(results, fallback=not bool(search_term)) page = request.args.get('page', 1, type=int) page_size = request.args.get('page_size', 25, type=int) response = paginate( ordered_results, page, page_size, QuerySerializer, with_stats=True, with_last_modified_by=False, ) ids = [] for r in response['results']: ids.append(r['id']) if q.id not in ids: require_access(q, self.current_user, view_only) result = QuerySerializer(q, with_visualizations=True).serialize() result['can_edit'] = can_modify(q, self.current_user) self.record_event({ 'action': 'view', 'object_id': query_id, 'object_type': 'query', }) return result
def post(self, query_id): """ Creates a new query, copying the query text from an existing one. :param query_id: ID of query to fork Responds with created :ref:`query <query-response-label>` object. """ query = get_object_or_404(models.Query.get_by_id_and_org, query_id, self.current_org) require_access(query.data_source.groups, self.current_user, not_view_only) forked_query = query.fork(self.current_user) models.db.session.commit() return QuerySerializer(forked_query, with_visualizations=True).serialize()
def outdated_queries(): manager_status = redis_connection.hgetall('redash:status') query_ids = json.loads(manager_status.get('query_ids', '[]')) if query_ids: outdated_queries = (models.Query.query.outerjoin( models.QueryResult).filter( models.Query.id.in_(query_ids)).order_by( models.Query.created_at.desc())) else: outdated_queries = [] response = { 'queries': QuerySerializer(outdated_queries, with_stats=True, with_last_modified_by=False).serialize(), 'updated_at': manager_status['last_refresh_at'], } return json_response(response)
def get(self): """ Search query text, names, and descriptions. :qparam string q: Search term Responds with a list of :ref:`query <query-response-label>` objects. """ term = request.args.get('q', '') if not term: return [] include_drafts = request.args.get('include_drafts') is not None queries = models.Query.search(term, self.current_user.group_ids, include_drafts=include_drafts, limit=None) queries = filter_by_tags(queries, models.Query.tags) return QuerySerializer(queries, with_last_modified_by=False).serialize()
def get(self, query_id): """ Retrieve a query. :param query_id: ID of query to fetch Responds with the :ref:`query <query-response-label>` contents. """ query = get_object_or_404(models.Query.get_by_id_and_org, query_id, self.current_org) if not is_admin_or_owner(query.user_id): if models.QueryGroup.get_by_query_groups( query, query.query_groups).first() is None: abort(404) api_key_hash = {} for vis in query.visualizations: api_key = models.ApiKey.get_by_object(vis) if api_key: api_key_hash[vis.id] = api_key.api_key result = QuerySerializer(query, with_visualizations=True).serialize() for vis_result in result['visualizations']: if vis_result['id'] in api_key_hash: vis_result['api_key'] = api_key_hash[vis_result['id']] # result['can_edit'] = can_modify(q, self.current_user) self.record_event({ 'action': 'view', 'object_id': query_id, 'object_type': 'query', }) return result
def post(self): """ Create a new query. :<json number data_source_id: The ID of the data source this query will run on :<json string query: Query text :<json string name: :<json string description: :<json string schedule: Schedule interval, in seconds, for repeated execution of this query :<json object options: Query options .. _query-response-label: :>json number id: Query ID :>json number latest_query_data_id: ID for latest output data from this query :>json string name: :>json string description: :>json string query: Query text :>json string query_hash: Hash of query text :>json string schedule: Schedule interval, in seconds, for repeated execution of this query :>json string api_key: Key for public access to this query's results. :>json boolean is_archived: Whether this query is displayed in indexes and search results or not. :>json boolean is_draft: Whether this query is a draft or not :>json string updated_at: Time of last modification, in ISO format :>json string created_at: Time of creation, in ISO format :>json number data_source_id: ID of the data source this query will run on :>json object options: Query options :>json number version: Revision version (for update conflict avoidance) :>json number user_id: ID of query creator :>json number last_modified_by_id: ID of user who last modified this query :>json string retrieved_at: Time when query results were last retrieved, in ISO format (may be null) :>json number runtime: Runtime of last query execution, in seconds (may be null) """ query_def = request.get_json(force=True) LOG.info('** receive queries create param: %s' % query_def) group = query_def.pop('group') group_ref = models.Group.query\ .filter(models.Group.name == group)\ .first() query_obj = None query_id = query_def.pop('query_id', None) if query_id: query_obj = get_object_or_404(models.Query.get_by_id_and_org, query_id, self.current_org) data_source = models.DataSource.get_by_id_and_org( query_def.pop("data_source_id"), self.current_org) require_access(data_source, self.current_user, not_view_only) require_access_to_dropdown_queries(self.current_user, query_def) for field in [ "id", "created_at", "api_key", "visualizations", "latest_query_data", "last_modified_by", ]: query_def.pop(field, None) if query_obj: for field in ["user", "org"]: query_def.pop(field, None) if "query" in query_def: query_def["query_text"] = query_def.pop("query") if "tags" in query_def: query_def["tags"] = [tag for tag in query_def["tags"] if tag] query_def["last_modified_by"] = self.current_user query_def["changed_by"] = self.current_user if "version" in query_def and query_def[ "version"] != query_obj.version: abort(409) try: self.update_model(query_obj, query_def) query_obj.group_id = group_ref.id models.db.session.commit() except StaleDataError: abort(409) query = query_obj else: query_def["query_text"] = query_def.pop("query") query_def["user"] = self.current_user query_def["data_source"] = data_source query_def["org"] = self.current_org query_def["is_draft"] = True query_def["group_id"] = group_ref.id LOG.info('** handle queries query ref data: %s' % query_def) query = models.Query.create(**query_def) models.db.session.add(query) models.db.session.commit() self.record_event({ "action": "create", "object_id": query.id, "object_type": "query" }) return QuerySerializer(query, with_visualizations=True).serialize()