felicity-lims/felicity/apps/audit/models.py

93 lines
3 KiB
Python
Raw Normal View History

2021-09-06 02:05:20 +08:00
import json
import logging
2023-04-10 20:23:31 +08:00
from core.uid_gen import FelicitySAID
from database.base_class import DBModel
from sqlalchemy import Column, Integer, String, UnicodeText
2021-05-06 21:48:09 +08:00
2021-09-06 02:05:20 +08:00
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
2021-05-06 21:48:09 +08:00
class AuditLog(DBModel):
"""Model an audit log of user actions"""
2023-03-19 23:21:32 +08:00
user_id = Column(FelicitySAID, doc="The ID of the user who made the change")
target_type = Column(
String(100), nullable=False, doc="The table name of the altered object"
)
2023-03-19 23:21:32 +08:00
target_id = Column(FelicitySAID, doc="The ID of the altered object")
2021-05-06 21:48:09 +08:00
action = Column(Integer, doc="Create (1), update (2), or delete (3)")
state_before = Column(
UnicodeText,
doc="Stores a JSON string representation of a dict containing the altered "
"column names and original values",
)
state_after = Column(
UnicodeText,
doc="Stores a JSON string representation of a dict containing the altered "
"column names and new values",
)
2021-05-06 21:48:09 +08:00
def __init__(self, target_type, target_id, action, state_before, state_after):
2021-09-06 02:05:20 +08:00
self.state_after = state_after
2021-05-06 21:48:09 +08:00
self.target_type = target_type
self.target_id = target_id
self.action = action
self.state_before = state_before
2021-09-06 02:05:20 +08:00
if isinstance(state_after, str):
state_after = json.loads(state_after)
try:
updated_by_uid = state_after["updated_by_uid"]
2021-10-01 15:37:34 +08:00
except (KeyError, TypeError):
2021-09-06 02:05:20 +08:00
updated_by_uid = None
2021-10-01 15:37:34 +08:00
self.user_id = updated_by_uid if updated_by_uid else None
2021-05-06 21:48:09 +08:00
def __repr__(self):
return "<AuditLog %r: %r -> %r>" % (self.user_id, self.target_type, self.action)
2021-05-06 21:48:09 +08:00
def save(self, connection):
2021-09-06 02:05:20 +08:00
state_after = self.state_after
if isinstance(state_after, str):
state_after = json.loads(state_after)
state_before = self.state_before
if isinstance(state_before, str):
state_before = json.loads(state_before)
2021-10-01 15:37:34 +08:00
if state_after:
to_delete = []
for key in state_after.keys():
if state_after[key] == state_before[key]:
to_delete.append(key)
2021-09-06 02:05:20 +08:00
2021-10-01 15:37:34 +08:00
for _key in to_delete:
del state_after[_key]
del state_before[_key]
2021-09-06 02:05:20 +08:00
2021-10-01 15:37:34 +08:00
if len(state_after.keys()) == 1:
if list(state_after.keys())[0] == "updated_at":
2021-10-01 15:37:34 +08:00
return
2021-10-01 15:37:34 +08:00
state_after = json.dumps(state_after) if state_after else json.dumps({})
state_before = json.dumps(state_before) if state_before else json.dumps({})
2021-09-06 02:05:20 +08:00
2021-05-06 21:48:09 +08:00
connection.execute(
self.__table__.insert(),
2021-10-07 15:17:20 +08:00
[
{
"user_id": self.user_id,
"target_type": self.target_type,
"target_id": self.target_id,
"action": self.action,
"state_before": state_before,
"state_after": state_after,
2021-10-07 15:17:20 +08:00
}
],
2021-12-13 00:20:48 +08:00
)