[Kimchi-devel] [PATCH] [Wok 5/6] Log failed user requests

Lucio Correia luciojhc at linux.vnet.ibm.com
Wed Jun 8 19:27:14 UTC 2016


Signed-off-by: Lucio Correia <luciojhc at linux.vnet.ibm.com>
---
 src/wok/control/base.py | 158 ++++++++++++++++++++++++++++++------------------
 1 file changed, 98 insertions(+), 60 deletions(-)

diff --git a/src/wok/control/base.py b/src/wok/control/base.py
index 9b34c55..f1cce11 100644
--- a/src/wok/control/base.py
+++ b/src/wok/control/base.py
@@ -119,6 +119,10 @@ class Resource(object):
     def _generate_action_handler_base(self, action_name, render_fn,
                                       destructive=False, action_args=None):
         def wrapper(*args, **kwargs):
+            # status must be always set in order to request be logged.
+            # use 500 as fallback for "exception not handled" cases.
+            status = 500
+
             method = 'POST'
             validate_method((method), self.role_key, self.admin_methods)
             try:
@@ -138,7 +142,36 @@ class Resource(object):
 
                 action_fn = getattr(self.model, model_fn(self, action_name))
                 action_result = action_fn(*model_args)
+                status = 200
 
+                if destructive is False or \
+                    ('persistent' in self.info.keys() and
+                     self.info['persistent'] is True):
+                    result = render_fn(self, action_result)
+                    status = cherrypy.response.status
+                    return result
+            except MissingParameter, e:
+                status = 400
+                raise cherrypy.HTTPError(status, e.message)
+            except InvalidParameter, e:
+                status = 400
+                raise cherrypy.HTTPError(status, e.message)
+            except InvalidOperation, e:
+                status = 400
+                raise cherrypy.HTTPError(status, e.message)
+            except UnauthorizedError, e:
+                status = 403
+                raise cherrypy.HTTPError(status, e.message)
+            except NotFoundError, e:
+                status = 404
+                raise cherrypy.HTTPError(status, e.message)
+            except OperationFailed, e:
+                status = 500
+                raise cherrypy.HTTPError(status, e.message)
+            except WokException, e:
+                status = 500
+                raise cherrypy.HTTPError(status, e.message)
+            finally:
                 # log request
                 code = self.getRequestMessage(method, action_name)
                 reqParams = utf8_dict(self.log_args, request)
@@ -147,29 +180,11 @@ class Resource(object):
                     msg,
                     app=get_plugin_from_request(),
                     req=method,
+                    status=status,
                     user=cherrypy.session.get(USER_NAME, 'N/A'),
                     ip=cherrypy.request.remote.ip
                 ).log()
 
-                if destructive is False or \
-                    ('persistent' in self.info.keys() and
-                     self.info['persistent'] is True):
-                    return render_fn(self, action_result)
-            except MissingParameter, e:
-                raise cherrypy.HTTPError(400, e.message)
-            except InvalidParameter, e:
-                raise cherrypy.HTTPError(400, e.message)
-            except InvalidOperation, e:
-                raise cherrypy.HTTPError(400, e.message)
-            except UnauthorizedError, e:
-                raise cherrypy.HTTPError(403, e.message)
-            except NotFoundError, e:
-                raise cherrypy.HTTPError(404, e.message)
-            except OperationFailed, e:
-                raise cherrypy.HTTPError(500, e.message)
-            except WokException, e:
-                raise cherrypy.HTTPError(500, e.message)
-
         wrapper.__name__ = action_name
         wrapper.exposed = True
         return wrapper
@@ -190,13 +205,13 @@ class Resource(object):
             e = InvalidOperation('WOKAPI0002E', {'resource':
                                                  get_class_name(self)})
             raise cherrypy.HTTPError(405, e.message)
-        except OperationFailed, e:
-            raise cherrypy.HTTPError(500, e.message)
-        except InvalidOperation, e:
-            raise cherrypy.HTTPError(400, e.message)
 
     @cherrypy.expose
     def index(self, *args, **kargs):
+        # status must be always set in order to request be logged.
+        # use 500 as fallback for "exception not handled" cases.
+        status = 500
+
         method = validate_method(('GET', 'DELETE', 'PUT'),
                                  self.role_key, self.admin_methods)
 
@@ -208,30 +223,42 @@ class Resource(object):
             result = {'GET': self.get,
                       'DELETE': self.delete,
                       'PUT': self.update}[method](*args, **kargs)
+
+            status = cherrypy.response.status
         except InvalidOperation, e:
-            raise cherrypy.HTTPError(400, e.message)
+            status = 400
+            raise cherrypy.HTTPError(status, e.message)
         except InvalidParameter, e:
-            raise cherrypy.HTTPError(400, e.message)
+            status = 400
+            raise cherrypy.HTTPError(status, e.message)
         except UnauthorizedError, e:
-            raise cherrypy.HTTPError(403, e.message)
+            status = 403
+            raise cherrypy.HTTPError(status, e.message)
         except NotFoundError, e:
-            raise cherrypy.HTTPError(404, e.message)
+            status = 404
+            raise cherrypy.HTTPError(status, e.message)
         except OperationFailed, e:
-            raise cherrypy.HTTPError(500, e.message)
+            status = 500
+            raise cherrypy.HTTPError(status, e.message)
         except WokException, e:
-            raise cherrypy.HTTPError(500, e.message)
-
-        # log request
-        if method not in LOG_DISABLED_METHODS:
-            code = self.getRequestMessage(method)
-            msg = WokMessage(code, self.log_args).get_text(prepend_code=False)
-            RequestRecord(
-                msg,
-                app=get_plugin_from_request(),
-                req=method,
-                user=cherrypy.session.get(USER_NAME, 'N/A'),
-                ip=cherrypy.request.remote.ip
-            ).log()
+            status = 500
+            raise cherrypy.HTTPError(status, e.message)
+        except cherrypy.HTTPError, e:
+            status = e.status
+            raise
+        finally:
+            # log request
+            if method not in LOG_DISABLED_METHODS:
+                code = self.getRequestMessage(method)
+                msg = WokMessage(code, self.log_args)
+                RequestRecord(
+                    msg.get_text(prepend_code=False),
+                    app=get_plugin_from_request(),
+                    req=method,
+                    status=status,
+                    user=cherrypy.session.get(USER_NAME, 'N/A'),
+                    ip=cherrypy.request.remote.ip
+                ).log()
 
         return result
 
@@ -311,10 +338,6 @@ class AsyncResource(Resource):
             e = InvalidOperation('WOKAPI0002E', {'resource':
                                                  get_class_name(self)})
             raise cherrypy.HTTPError(405, e.message)
-        except OperationFailed, e:
-            raise cherrypy.HTTPError(500, e.message)
-        except InvalidOperation, e:
-            raise cherrypy.HTTPError(400, e.message)
 
         cherrypy.response.status = 202
         return wok.template.render("Task", task)
@@ -437,6 +460,10 @@ class Collection(object):
 
     @cherrypy.expose
     def index(self, *args, **kwargs):
+        # status must be always set in order to request be logged.
+        # use 500 as fallback for "exception not handled" cases.
+        status = 500
+
         params = {}
         method = validate_method(('GET', 'POST'),
                                  self.role_key, self.admin_methods)
@@ -449,7 +476,31 @@ class Collection(object):
             elif method == 'POST':
                 params = parse_request()
                 result = self.create(params, *args)
-
+                status = cherrypy.response.status
+                return result
+        except InvalidOperation, e:
+            status = 400
+            raise cherrypy.HTTPError(status, e.message)
+        except InvalidParameter, e:
+            status = 400
+            raise cherrypy.HTTPError(status, e.message)
+        except MissingParameter, e:
+            status = 400
+            raise cherrypy.HTTPError(status, e.message)
+        except NotFoundError, e:
+            status = 404
+            raise cherrypy.HTTPError(status, e.message)
+        except OperationFailed, e:
+            status = 500
+            raise cherrypy.HTTPError(status, e.message)
+        except WokException, e:
+            status = 500
+            raise cherrypy.HTTPError(status, e.message)
+        except cherrypy.HTTPError, e:
+            status = e.status
+            raise
+        finally:
+            if method not in LOG_DISABLED_METHODS:
                 # log request
                 code = self.getRequestMessage(method)
                 reqParams = utf8_dict(self.log_args, params)
@@ -458,24 +509,11 @@ class Collection(object):
                     msg,
                     app=get_plugin_from_request(),
                     req=method,
+                    status=status,
                     user=cherrypy.session.get(USER_NAME, 'N/A'),
                     ip=cherrypy.request.remote.ip
                 ).log()
 
-                return result
-        except InvalidOperation, e:
-            raise cherrypy.HTTPError(400, e.message)
-        except InvalidParameter, e:
-            raise cherrypy.HTTPError(400, e.message)
-        except MissingParameter, e:
-            raise cherrypy.HTTPError(400, e.message)
-        except NotFoundError, e:
-            raise cherrypy.HTTPError(404, e.message)
-        except OperationFailed, e:
-            raise cherrypy.HTTPError(500, e.message)
-        except WokException, e:
-            raise cherrypy.HTTPError(500, e.message)
-
 
 class AsyncCollection(Collection):
     """
-- 
1.9.1




More information about the Kimchi-devel mailing list