From 509fd0620d8f00fe69049494b8461e8f2ea15954 Mon Sep 17 00:00:00 2001 From: rr- Date: Mon, 28 Mar 2016 22:53:56 +0200 Subject: [PATCH] back/middleware: change context to dotdict --- szurubooru/api/users.py | 26 ++++++++++++------------ szurubooru/app.py | 18 ++++++++++------ szurubooru/middleware/authenticator.py | 4 ++-- szurubooru/middleware/db_session.py | 8 ++++++-- szurubooru/middleware/json_translator.py | 5 ++--- szurubooru/model/base.py | 2 +- szurubooru/model/user.py | 2 ++ szurubooru/util.py | 8 ++++++++ 8 files changed, 46 insertions(+), 27 deletions(-) create mode 100644 szurubooru/util.py diff --git a/szurubooru/api/users.py b/szurubooru/api/users.py index b313c63..a684e6e 100644 --- a/szurubooru/api/users.py +++ b/szurubooru/api/users.py @@ -24,19 +24,19 @@ class UserListApi(object): def on_get(self, request, response): ''' Retrieves a list of users. ''' - self._auth_service.verify_privilege(request.context['user'], 'users:list') - request.context['result'] = {'message': 'Searching for users'} + self._auth_service.verify_privilege(request.context.user, 'users:list') + request.context.result = {'message': 'Searching for users'} def on_post(self, request, response): ''' Creates a new user. ''' - self._auth_service.verify_privilege(request.context['user'], 'users:create') + self._auth_service.verify_privilege(request.context.user, 'users:create') name_regex = self._config['service']['user_name_regex'] password_regex = self._config['service']['password_regex'] try: - name = request.context['doc']['name'] - password = request.context['doc']['password'] - email = request.context['doc']['email'].strip() + name = request.context.request['name'] + password = request.context.request['password'] + email = request.context.request['email'].strip() if not email: email = None except KeyError as ex: @@ -53,13 +53,13 @@ class UserListApi(object): 'Malformed data', 'Password must validate %r expression' % password_regex) - session = request.context['session'] + session = request.context.session try: user = self._user_service.create_user(session, name, password, email) session.commit() except: raise IntegrityError('User %r already exists.' % name) - request.context['result'] = {'user': _serialize_user(user)} + request.context.result = {'user': _serialize_user(user)} class UserDetailApi(object): ''' API for individual users. ''' @@ -70,12 +70,12 @@ class UserDetailApi(object): def on_get(self, request, response, user_name): ''' Retrieves an user. ''' - self._auth_service.verify_privilege(request.context['user'], 'users:view') - session = request.context['session'] + self._auth_service.verify_privilege(request.context.user, 'users:view') + session = request.context.session user = self._user_service.get_by_name(session, user_name) - request.context['result'] = _serialize_user(user) + request.context.result = _serialize_user(user) def on_put(self, request, response, user_name): ''' Updates an existing user. ''' - self._auth_service.verify_privilege(request.context['user'], 'users:edit') - request.context['result'] = {'message': 'Updating user ' + user_name} + self._auth_service.verify_privilege(request.context.user, 'users:edit') + request.context.result = {'message': 'Updating user ' + user_name} diff --git a/szurubooru/app.py b/szurubooru/app.py index 75b0a2a..5868aca 100644 --- a/szurubooru/app.py +++ b/szurubooru/app.py @@ -8,6 +8,10 @@ import szurubooru.api import szurubooru.config import szurubooru.middleware import szurubooru.services +import szurubooru.util + +class _CustomRequest(falcon.Request): + context_type = szurubooru.util.dotdict def _on_auth_error(ex, req, resp, params): raise falcon.HTTPForbidden('Authentication error', str(ex)) @@ -40,12 +44,14 @@ def create_app(): user_list = szurubooru.api.UserListApi(config, auth_service, user_service) user = szurubooru.api.UserDetailApi(config, auth_service, user_service) - app = falcon.API(middleware=[ - szurubooru.middleware.RequireJson(), - szurubooru.middleware.JsonTranslator(), - szurubooru.middleware.DbSession(session_maker), - szurubooru.middleware.Authenticator(auth_service, user_service), - ]) + app = falcon.API( + request_type=_CustomRequest, + middleware=[ + szurubooru.middleware.RequireJson(), + szurubooru.middleware.JsonTranslator(), + szurubooru.middleware.DbSession(session_maker), + szurubooru.middleware.Authenticator(auth_service, user_service), + ]) app.add_error_handler(szurubooru.services.AuthError, _on_auth_error) app.add_error_handler(szurubooru.services.IntegrityError, _on_integrity_error) diff --git a/szurubooru/middleware/authenticator.py b/szurubooru/middleware/authenticator.py index 99a1fe9..df96cdb 100644 --- a/szurubooru/middleware/authenticator.py +++ b/szurubooru/middleware/authenticator.py @@ -17,7 +17,7 @@ class Authenticator(object): def process_request(self, request, response): ''' Executed before passing the request to the API. ''' - request.context['user'] = self._get_user(request) + request.context.user = self._get_user(request) def _get_user(self, request): if not request.auth: @@ -34,7 +34,7 @@ class Authenticator(object): username, password = base64.decodebytes( user_and_password.encode('ascii')).decode('utf8').split(':') - session = request.context['session'] + session = request.context.session return self._authenticate(session, username, password) except ValueError as err: msg = 'Basic authentication header value not properly formed. ' \ diff --git a/szurubooru/middleware/db_session.py b/szurubooru/middleware/db_session.py index 3b69059..dff317e 100644 --- a/szurubooru/middleware/db_session.py +++ b/szurubooru/middleware/db_session.py @@ -8,7 +8,11 @@ class DbSession(object): def process_request(self, request, response): ''' Executed before passing the request to the API. ''' - request.context['session'] = self._session_factory() + request.context.session = self._session_factory() def process_response(self, request, response, resource): - request.context['session'].close() + ''' + Executed before passing the response to falcon. + Any commits to database need to happen explicitly in the API layer. + ''' + request.context.session.close() diff --git a/szurubooru/middleware/json_translator.py b/szurubooru/middleware/json_translator.py index 502fac0..f04e6c8 100644 --- a/szurubooru/middleware/json_translator.py +++ b/szurubooru/middleware/json_translator.py @@ -29,7 +29,7 @@ class JsonTranslator(object): 'A valid JSON document is required.') try: - request.context['doc'] = json.loads(body.decode('utf-8')) + request.context.request = json.loads(body.decode('utf-8')) except (ValueError, UnicodeDecodeError): raise falcon.HTTPError( falcon.HTTP_401, @@ -41,5 +41,4 @@ class JsonTranslator(object): ''' Executed before passing the response to falcon. ''' if 'result' not in request.context: return - response.body = json.dumps( - request.context['result'], default=json_serial) + response.body = json.dumps(request.context.result, default=json_serial) diff --git a/szurubooru/model/base.py b/szurubooru/model/base.py index 35050d9..d622ddf 100644 --- a/szurubooru/model/base.py +++ b/szurubooru/model/base.py @@ -1,4 +1,4 @@ ''' Base model for every database resource. ''' from sqlalchemy.ext.declarative import declarative_base -Base = declarative_base() # pylint: disable=C0103 +Base = declarative_base() # pylint: disable=invalid-name diff --git a/szurubooru/model/user.py b/szurubooru/model/user.py index 31186e9..f611a52 100644 --- a/szurubooru/model/user.py +++ b/szurubooru/model/user.py @@ -1,3 +1,5 @@ +# pylint: disable=too-many-instance-attributes,too-few-public-methods + ''' Exports User. ''' import sqlalchemy as sa diff --git a/szurubooru/util.py b/szurubooru/util.py new file mode 100644 index 0000000..929957d --- /dev/null +++ b/szurubooru/util.py @@ -0,0 +1,8 @@ +''' Exports dotdict. ''' + +class dotdict(dict): # pylint: disable=invalid-name + '''dot.notation access to dictionary attributes''' + def __getattr__(self, attr): + return self.get(attr) + __setattr__ = dict.__setitem__ + __delattr__ = dict.__delitem__