Repository: getredash/redash

Issue:
AttributeError: 'ApiUser' object has no attribute 'email'
### Issue Summary

API POST calls to /api/queries/###/refresh throw this error on 1.0.3+b2850

### Steps to Reproduce

1. Make a POST call to /api/queries/###/refresh
2. See error in api_error.log and 500 result

Full error with trace:

```
Exception on /api/queries/###/refresh [POST]
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1639, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1625, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/usr/local/lib/python2.7/dist-packages/flask_restful/__init__.py", line 477, in wrapper
    resp = resource(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/flask_login/utils.py", line 228, in decorated_view
    return func(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/flask/views.py", line 84, in view
    return self.dispatch_request(*args, **kwargs)
  File "/opt/redash/redash.1.0.3.b2850/redash/handlers/base.py", line 28, in dispatch_request
    return super(BaseResource, self).dispatch_request(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/flask_restful/__init__.py", line 587, in dispatch_request
    resp = meth(*args, **kwargs)
  File "/opt/redash/redash.1.0.3.b2850/redash/handlers/queries.py", line 266, in post
    return run_query(query.data_source, parameter_values, query.query_text, query.id)
  File "/opt/redash/redash.1.0.3.b2850/redash/handlers/query_results.py", line 45, in run_query
    job = enqueue_query(query_text, data_source, current_user.id, metadata={"Username": current_user.email, "Query ID": query_id})
  File "/usr/local/lib/python2.7/dist-packages/werkzeug/local.py", line 343, in __getattr__
    return getattr(self._get_current_object(), name)
AttributeError: 'ApiUser' object has no attribute 'email'
```

Same request worked in some previous version of Redash. Looking at the current code on master, it seems to still make the same reference to `current_user.email` so assuming this bug still exists, but haven't confirmed that yet.

### Technical details:

* Redash Version: 1.0.3+b2850
* Browser/OS: N/A
* How did you install Redash: N/A



Discussion:
Just to be clear, ### in those URL paths is an actual query ID number.
I assume you call this API call with a query API key?
Yes, the request is called with an api_key param.
This is the reason for the error. We should probably check the API key here and only allow a user API key, because otherwise it's a security concern (in the case of queries with parameters).

Resolving patch:
diff --git a/redash/handlers/queries.py b/redash/handlers/queries.py
--- a/redash/handlers/queries.py
+++ b/redash/handlers/queries.py
@@ -266,6 +266,12 @@ def post(self, query_id):
 
         Responds with query task details.
         """
+        # TODO: this should actually check for permissions, but because currently you can only
+        # get here either with a user API key or a query one, we can just check whether it's
+        # an api key (meaning this is a query API key, which only grants read access).
+        if self.current_user.is_api_user():
+            abort(403, message="Please use a user API key.")
+
         query = get_object_or_404(models.Query.get_by_id_and_org, query_id, self.current_org)
         require_access(query.groups, self.current_user, not_view_only)
 


Test patch:
diff --git a/tests/handlers/test_queries.py b/tests/handlers/test_queries.py
--- a/tests/handlers/test_queries.py
+++ b/tests/handlers/test_queries.py
@@ -158,6 +158,13 @@ def test_refresh_query_you_dont_have_access_to(self):
         user = self.factory.create_user(group_ids=[group.id])
         response = self.make_request('post', self.path, user=user)
         self.assertEqual(403, response.status_code)
+    
+    def test_refresh_forbiden_with_query_api_key(self):
+        response = self.make_request('post', '{}?api_key={}'.format(self.path, self.query.api_key), user=False)
+        self.assertEqual(403, response.status_code)
+
+        response = self.make_request('post', '{}?api_key={}'.format(self.path, self.factory.user.api_key), user=False)
+        self.assertEqual(200, response.status_code)
 
 
 class TestQueryForkResourcePost(BaseTestCase):