diff options
author | Milo Casagrande <milo.casagrande@linaro.org> | 2014-07-29 18:11:55 +0200 |
---|---|---|
committer | Milo Casagrande <milo.casagrande@linaro.org> | 2014-07-29 18:13:14 +0200 |
commit | cb3168d84f6e597c9a2c7bec016cf749207c5b3d (patch) | |
tree | fbfd39744bd229326c7726db98e22c8939b8b705 /app/handlers/token.py | |
parent | 77d545d4e4d7e04297ee032ffa2278eaf350aa86 (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.py | 134 |
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 |