aboutsummaryrefslogtreecommitdiff
path: root/app/handlers/token.py
diff options
context:
space:
mode:
authorMilo Casagrande <milo.casagrande@linaro.org>2014-07-29 18:11:55 +0200
committerMilo Casagrande <milo.casagrande@linaro.org>2014-07-29 18:13:14 +0200
commitcb3168d84f6e597c9a2c7bec016cf749207c5b3d (patch)
treefbfd39744bd229326c7726db98e22c8939b8b705 /app/handlers/token.py
parent77d545d4e4d7e04297ee032ffa2278eaf350aa86 (diff)
TokenHandler: Implement GET and partial POST.
* Implement GET method. * Implement POST only on new token creation. * Add intial test coverage. Change-Id: I775391abbf97bfc09723a23db9c77499906b8248
Diffstat (limited to 'app/handlers/token.py')
-rw-r--r--app/handlers/token.py134
1 files changed, 132 insertions, 2 deletions
diff --git a/app/handlers/token.py b/app/handlers/token.py
index 26365bc..94d505c 100644
--- a/app/handlers/token.py
+++ b/app/handlers/token.py
@@ -15,6 +15,10 @@
"""The RequestHandler for /token URLs."""
+import json
+import tornado
+
+from functools import partial
from tornado.web import (
asynchronous,
)
@@ -22,16 +26,27 @@ from tornado.web import (
from handlers.base import BaseHandler
from handlers.decorators import protected_th
from models import (
+ ADMIN_KEY,
CREATED_KEY,
+ DELETE_KEY,
EMAIL_KEY,
EXPIRED_KEY,
EXPIRES_KEY,
+ GET_KEY,
IP_ADDRESS_KEY,
+ IP_RESTRICTED,
+ POST_KEY,
PROPERTIES_KEY,
+ SUPERUSER_KEY,
TOKEN_KEY,
USERNAME_KEY,
)
-from models.token import TOKEN_COLLECTION
+from models.token import (
+ TOKEN_COLLECTION,
+ Token,
+)
+from utils.db import find_one
+from utils.validator import is_valid_json
class TokenHandler(BaseHandler):
@@ -47,9 +62,15 @@ class TokenHandler(BaseHandler):
def _valid_keys(self, method):
valid_keys = {
'POST': [
+ ADMIN_KEY,
+ DELETE_KEY,
EMAIL_KEY,
EXPIRES_KEY,
+ GET_KEY,
IP_ADDRESS_KEY,
+ IP_RESTRICTED,
+ POST_KEY,
+ SUPERUSER_KEY,
USERNAME_KEY,
],
'GET': [
@@ -69,4 +90,113 @@ class TokenHandler(BaseHandler):
@protected_th("GET")
@asynchronous
def get(self, *args, **kwargs):
- super(TokenHandler, self).get(*args, **kwargs)
+ self.execute_get(*args, **kwargs)
+
+ def _get_one(self, doc_id):
+ # Overridden _get_one: with the token we do not search by _id, but
+ # by token field.
+ return find_one(
+ self.collection, doc_id, field='token',
+ fields=self._get_query_fields()
+ )
+
+ @protected_th("POST")
+ @asynchronous
+ def post(self, *args, **kwargs):
+ self.executor.submit(
+ partial(self._post, *args, **kwargs)
+ ).add_done_callback(
+ lambda future: tornado.ioloop.IOLoop.instance().add_callback(
+ partial(self._create_valid_response, future.result())
+ )
+ )
+
+ def _post(self, *args, **kwargs):
+ valid_request = self._valid_post_request()
+
+ if valid_request == 200:
+ try:
+ json_obj = json.loads(self.request.body.decode('utf8'))
+
+ if is_valid_json(json_obj, self._valid_keys('POST')):
+ if kwargs and kwargs.get('id', None):
+ self.log.info(
+ "New token creation from IP address %s",
+ self.request.remote_ip
+ )
+ return self._update_data(kwargs['id'], json_obj)
+ else:
+ self.log.info(
+ "Token update from IP address %s",
+ self.request.remote_ip
+ )
+ return self._new_data(json_obj)
+ else:
+ self.write_error(
+ status_code=400,
+ message="Provided JSON is not valid"
+ )
+ except ValueError:
+ self.log.error("No JSON data found in the POST request")
+ self.write_error(status_code=420)
+ else:
+ self.write_error(status_code=valid_request)
+
+ def _new_data(self, json_obj):
+ new_token = Token()
+
+ try:
+ new_token.email = json_obj[EMAIL_KEY]
+ new_token.username = json_obj.get(USERNAME_KEY, None)
+ new_token.expires_on = json_obj.get(EXPIRES_KEY, None)
+
+ if json_obj.get(GET_KEY, None):
+ new_token.is_get_token = json_obj.get(GET_KEY)
+
+ if json_obj.get(POST_KEY, None):
+ new_token.is_post_token = json_obj.get(POST_KEY)
+
+ if json_obj.get(DELETE_KEY, None):
+ new_token.is_delete_token = json_obj.get(DELETE_KEY)
+
+ if json_obj.get(SUPERUSER_KEY, None):
+ new_token.is_superuser = json_obj.get(SUPERUSER_KEY)
+
+ if json_obj.get(ADMIN_KEY, None):
+ new_token.is_admin = json_obj.get(ADMIN_KEY)
+
+ new_token.is_ip_restricted = json_obj.get(IP_RESTRICTED, 0)
+ if new_token.is_ip_restricted:
+ if json_obj.get(IP_ADDRESS_KEY, None):
+ new_token.ip_address = json_obj.get(IP_ADDRESS_KEY, None)
+ else:
+ raise Exception(
+ "IP restricted token but no IP addresses given"
+ )
+ except KeyError:
+ self.write_error(
+ status_code=400,
+ message="New tokens require the email address field [email]"
+ )
+ except (TypeError, ValueError):
+ self.write_error(
+ status_code=400,
+ message="Wrong field value or type in the JSON data")
+ except Exception, ex:
+ self.write_error(
+ status_code=400,
+ message=str(ex)
+ )
+ else:
+ return 201
+
+ def _update_data(self, identifier, json_obj):
+ return 202
+
+ @protected_th("DELETE")
+ @asynchronous
+ def delete(self, *args, **kwargs):
+ super(TokenHandler, self).delete(*args, **kwargs)
+
+ def _delete(self, doc_id):
+ pass