From 4c8a93380f9b1baff46614bf6208ba53ac1a7a27 Mon Sep 17 00:00:00 2001 From: hyh123a Date: Wed, 25 Aug 2021 15:13:34 +0800 Subject: [PATCH] add the log function and test in equipments --- myems-api/core/equipment.py | 41 +++++++++++ myems-api/log.py | 140 ++++++++++++++++++++++++++++++++++++ 2 files changed, 181 insertions(+) create mode 100644 myems-api/log.py diff --git a/myems-api/core/equipment.py b/myems-api/core/equipment.py index ee9f59aa..ec62daac 100644 --- a/myems-api/core/equipment.py +++ b/myems-api/core/equipment.py @@ -3,19 +3,23 @@ import simplejson as json import mysql.connector import config import uuid +from log import decorator_record_action_log class EquipmentCollection: @staticmethod + @decorator_record_action_log def __init__(): """Initializes EquipmentCollection""" pass @staticmethod + @decorator_record_action_log def on_options(req, resp): resp.status = falcon.HTTP_200 @staticmethod + @decorator_record_action_log def on_get(req, resp): cnx = mysql.connector.connect(**config.myems_system_db) cursor = cnx.cursor(dictionary=True) @@ -58,6 +62,7 @@ class EquipmentCollection: resp.body = json.dumps(result) @staticmethod + @decorator_record_action_log def on_post(req, resp): """Handles POST requests""" try: @@ -145,15 +150,18 @@ class EquipmentCollection: class EquipmentItem: @staticmethod + @decorator_record_action_log def __init__(): """Initializes EquipmentItem""" pass @staticmethod + @decorator_record_action_log def on_options(req, resp, id_): resp.status = falcon.HTTP_200 @staticmethod + @decorator_record_action_log def on_get(req, resp, id_): if not id_.isdigit() or int(id_) <= 0: raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', @@ -200,6 +208,7 @@ class EquipmentItem: resp.body = json.dumps(meta_result) @staticmethod + @decorator_record_action_log def on_delete(req, resp, id_): if not id_.isdigit() or int(id_) <= 0: raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', @@ -286,6 +295,7 @@ class EquipmentItem: resp.status = falcon.HTTP_204 @staticmethod + @decorator_record_action_log def on_put(req, resp, id_): """Handles PUT requests""" if not id_.isdigit() or int(id_) <= 0: @@ -382,6 +392,7 @@ class EquipmentItem: # Clone an Equipment @staticmethod + @decorator_record_action_log def on_post(req, resp, id_): """Handles PUT requests""" if not id_.isdigit() or int(id_) <= 0: @@ -527,15 +538,18 @@ class EquipmentItem: class EquipmentParameterCollection: @staticmethod + @decorator_record_action_log def __init__(): """Initializes EquipmentParameterCollection""" pass @staticmethod + @decorator_record_action_log def on_options(req, resp, id_): resp.status = falcon.HTTP_200 @staticmethod + @decorator_record_action_log def on_get(req, resp, id_): if not id_.isdigit() or int(id_) <= 0: raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', @@ -658,6 +672,7 @@ class EquipmentParameterCollection: resp.body = json.dumps(result) @staticmethod + @decorator_record_action_log def on_post(req, resp, id_): """Handles POST requests""" if not id_.isdigit() or int(id_) <= 0: @@ -841,15 +856,18 @@ class EquipmentParameterCollection: class EquipmentParameterItem: @staticmethod + @decorator_record_action_log def __init__(): """Initializes EquipmentParameterItem""" pass @staticmethod + @decorator_record_action_log def on_options(req, resp, id_, pid): resp.status = falcon.HTTP_200 @staticmethod + @decorator_record_action_log def on_get(req, resp, id_, pid): if not id_.isdigit() or int(id_) <= 0: raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', @@ -966,6 +984,7 @@ class EquipmentParameterItem: resp.body = json.dumps(meta_result) @staticmethod + @decorator_record_action_log def on_delete(req, resp, id_, pid): if not id_.isdigit() or int(id_) <= 0: raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', @@ -1012,6 +1031,7 @@ class EquipmentParameterItem: resp.status = falcon.HTTP_204 @staticmethod + @decorator_record_action_log def on_put(req, resp, id_, pid): """Handles POST requests""" if not id_.isdigit() or int(id_) <= 0: @@ -1213,15 +1233,18 @@ class EquipmentParameterItem: class EquipmentMeterCollection: @staticmethod + @decorator_record_action_log def __init__(): """Initializes EquipmentMeterCollection""" pass @staticmethod + @decorator_record_action_log def on_options(req, resp, id_): resp.status = falcon.HTTP_200 @staticmethod + @decorator_record_action_log def on_get(req, resp, id_): if not id_.isdigit() or int(id_) <= 0: raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', @@ -1270,6 +1293,7 @@ class EquipmentMeterCollection: resp.body = json.dumps(result) @staticmethod + @decorator_record_action_log def on_post(req, resp, id_): """Handles POST requests""" try: @@ -1341,15 +1365,18 @@ class EquipmentMeterCollection: class EquipmentMeterItem: @staticmethod + @decorator_record_action_log def __init__(): """Initializes EquipmentMeterItem""" pass @staticmethod + @decorator_record_action_log def on_options(req, resp, id_, mid): resp.status = falcon.HTTP_200 @staticmethod + @decorator_record_action_log def on_delete(req, resp, id_, mid): if not id_.isdigit() or int(id_) <= 0: raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', @@ -1400,15 +1427,18 @@ class EquipmentMeterItem: class EquipmentOfflineMeterCollection: @staticmethod + @decorator_record_action_log def __init__(): """Initializes EquipmentOfflineMeterCollection""" pass @staticmethod + @decorator_record_action_log def on_options(req, resp, id_): resp.status = falcon.HTTP_200 @staticmethod + @decorator_record_action_log def on_get(req, resp, id_): if not id_.isdigit() or int(id_) <= 0: raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', @@ -1457,6 +1487,7 @@ class EquipmentOfflineMeterCollection: resp.body = json.dumps(result) @staticmethod + @decorator_record_action_log def on_post(req, resp, id_): """Handles POST requests""" try: @@ -1528,15 +1559,18 @@ class EquipmentOfflineMeterCollection: class EquipmentOfflineMeterItem: @staticmethod + @decorator_record_action_log def __init__(): """Initializes EquipmentOfflineMeterItem""" pass @staticmethod + @decorator_record_action_log def on_options(req, resp, id_, mid): resp.status = falcon.HTTP_200 @staticmethod + @decorator_record_action_log def on_delete(req, resp, id_, mid): if not id_.isdigit() or int(id_) <= 0: raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', @@ -1588,15 +1622,18 @@ class EquipmentOfflineMeterItem: class EquipmentVirtualMeterCollection: @staticmethod + @decorator_record_action_log def __init__(): """Initializes EquipmentVirtualMeterCollection""" pass @staticmethod + @decorator_record_action_log def on_options(req, resp, id_): resp.status = falcon.HTTP_200 @staticmethod + @decorator_record_action_log def on_get(req, resp, id_): if not id_.isdigit() or int(id_) <= 0: raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', @@ -1645,6 +1682,7 @@ class EquipmentVirtualMeterCollection: resp.body = json.dumps(result) @staticmethod + @decorator_record_action_log def on_post(req, resp, id_): """Handles POST requests""" try: @@ -1716,15 +1754,18 @@ class EquipmentVirtualMeterCollection: class EquipmentVirtualMeterItem: @staticmethod + @decorator_record_action_log def __init__(): """Initializes EquipmentVirtualMeterItem""" pass @staticmethod + @decorator_record_action_log def on_options(req, resp, id_, mid): resp.status = falcon.HTTP_200 @staticmethod + @decorator_record_action_log def on_delete(req, resp, id_, mid): if not id_.isdigit() or int(id_) <= 0: raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', diff --git a/myems-api/log.py b/myems-api/log.py new file mode 100644 index 00000000..383db162 --- /dev/null +++ b/myems-api/log.py @@ -0,0 +1,140 @@ +import os +from functools import wraps +import config +import mysql.connector +from datetime import datetime, timezone +import uuid +from gunicorn.http.body import Body + + +def write_log(user_uuid, action, _class, record_id, record_text): + """ + :param user_uuid: user_uuid + :param action: create, update, delete and others: login, logout, reset password, change password + :param _class: class_name + :param record_id: int + :param record_text: str + """ + now = datetime.now() + cnx = None + cursor = None + try: + cnx = mysql.connector.connect(**config.myems_user_db) + cursor = cnx.cursor() + cursor.execute(" SELECT display_name " + " FROM tbl_users " + " WHERE uuid = %s ", + (user_uuid,)) + row = cursor.fetchone() + user = dict() + if row is not None and len(row) > 0: + user["name"] = row[0] + else: + user["name"] = "visitor" + + cnx = mysql.connector.connect(**config.myems_user_db) + cursor = cnx.cursor() + add_row = (" INSERT INTO tbl_action_logs " + " (user_name, date_time, action, class, record_id, record_text) " + " VALUES (%s, %s, %s, %s, %s , %s) ") + cursor.execute(add_row, (user['name'], + now, + action, + _class, + record_id if record_id else None, + record_text if record_text else None, + )) + cnx.commit() + except Exception as e: + print(str(e)) + if cnx: + cnx.disconnect() + if cursor: + cursor.close() + finally: + if cnx: + cnx.disconnect() + if cursor: + cursor.close() + + +def decorator_record_action_log(func): + @wraps(func) + def log_fun(*args, **kwargs): + type_dict = { + "on_post": "create", + "on_put": "update", + "on_delete": "delete", + } + + func_names = func.__qualname__ + class_name = func_names.split(".")[0] + fun_name = func_names.split(".")[1] + if fun_name not in type_dict.keys(): + return func(*args, **kwargs) + + if len(args) > 1: + req, resp = args + cookies = req.cookies + if cookies is not None and 'user_uuid' in cookies.keys(): + user_uuid = cookies['user_uuid'] + else: + user_uuid = None + else: + return func(*args, **kwargs) + + action = type_dict.get(fun_name) + + if class_name == "UserLogin": + action = "login" + elif class_name == "UserLogout": + action = "logout" + elif class_name == "ResetPassword": + action = "reset password" + elif class_name == "ChangePassword": + action = "change password" + else: + pass + + if fun_name == "on_post": + file_name = str(uuid.uuid4()) + with open(file_name, "wb") as fw: + reads = req.stream.read() + fw.write(reads) + raw_json = reads.decode('utf-8') + + with open(file_name, "rb") as fr: + req.stream = Body(fr) + write_log(user_uuid=user_uuid, action=action, _class=class_name, + record_id=None, record_text=raw_json) + func(*args, **kwargs) + os.remove(file_name) + return + + elif fun_name == "on_put": + id_ = kwargs.get('id_') + file_name = str(uuid.uuid4()) + with open(file_name, "wb") as fw: + reads = req.stream.read() + fw.write(reads) + raw_json = reads.decode('utf-8') + + with open(file_name, "rb") as fr: + req.stream = Body(fr) + write_log(user_uuid=user_uuid, action=action, _class=class_name, + record_id=id_, record_text=raw_json) + func(*args, **kwargs) + os.remove(file_name) + return + + elif fun_name == "on_delete": + id_ = kwargs.get('id_') + write_log(user_uuid=user_uuid, action=action, _class=class_name, + record_id=id_, record_text=None) + func(*args, **kwargs) + return + else: + func(*args, **kwargs) + return + + return log_fun