summaryrefslogtreecommitdiff
path: root/jimbrella
diff options
context:
space:
mode:
authorFrederick Yin <fkfd@fkfd.me>2021-10-31 17:03:19 +0800
committerFrederick Yin <fkfd@fkfd.me>2021-10-31 17:13:01 +0800
commit7644830f34f3bd81d3b21b2d05710fbc91f20eb6 (patch)
treed20b89bacc2cec650e00d3f1e9ba68d8d699356b /jimbrella
parent59c899e372a6d5e0309c585de43df015f775ebe7 (diff)
Implement ADMIN_MODIFY_DB logs
When an admin requests /admin/umbrella/edit and the request succeeds, an ADMIN_MODIFY_DB log is kept. `Database.update` will keep track of the updated columns.
Diffstat (limited to 'jimbrella')
-rw-r--r--jimbrella/admin.py16
-rw-r--r--jimbrella/admin_log.py10
-rw-r--r--jimbrella/database.py19
3 files changed, 39 insertions, 6 deletions
diff --git a/jimbrella/admin.py b/jimbrella/admin.py
index 9a9f6c8..eaf0e54 100644
--- a/jimbrella/admin.py
+++ b/jimbrella/admin.py
@@ -72,9 +72,8 @@ def umbrellas_edit():
]:
data[key] = request.form.get(key)
- error = None
try:
- db.update(data)
+ diff = db.update(data)
except UmbrellaValueError as e:
# invalid field is in `e.message`.
return redirect(
@@ -85,6 +84,19 @@ def umbrellas_edit():
except UmbrellaNotFoundError:
pass # impossible on web console
+ for column, value_pair in diff.items():
+ past, new = value_pair
+ admin_log.log(
+ "ADMIN_MODIFY_DB",
+ {
+ "admin_name": session["username"],
+ "serial": data["serial"],
+ "column": column,
+ "past_value": past,
+ "new_value": new,
+ },
+ )
+
return redirect(url_for("admin.umbrellas"))
diff --git a/jimbrella/admin_log.py b/jimbrella/admin_log.py
index 8b5bb09..622abec 100644
--- a/jimbrella/admin_log.py
+++ b/jimbrella/admin_log.py
@@ -106,7 +106,15 @@ class AdminLog:
"{name} missed the due for umbrella #{key}. " + tenant_info
)
elif event == "ADMIN_MODIFY_DB":
- description = "{admin_name} changed {column} of umbrella #{serial} from {past_value} to {new_value}."
+ if not entry["past_value"]:
+ description = "{admin_name} set {column} of umbrella #{serial} to {new_value}."
+ elif not entry["new_value"]:
+ description = "{admin_name} cleared {column} of umbrella #{serial} (was {past_value})."
+ else:
+ description = (
+ "{admin_name} changed {column} of umbrella #{serial} "
+ "from {past_value} to {new_value}."
+ )
friendly_logs.append(
{
diff --git a/jimbrella/database.py b/jimbrella/database.py
index a8d480b..9b6e51f 100644
--- a/jimbrella/database.py
+++ b/jimbrella/database.py
@@ -91,7 +91,7 @@ class Database(CsvTable):
umbrellas[idx]["lent_time_ago_str"] = human_timedelta(lent_time_ago)
return umbrellas
- def update(self, umb) -> list:
+ def update(self, umb) -> dict:
"""An interface to `_update()` with added convenience and safeguards.
Convenience: Not all fields in an umbrella dict need to be present in `umb`. If an
@@ -117,7 +117,8 @@ class Database(CsvTable):
fields mentioned above are made blank, and these fields supplied in `umb`
are ignored.
- Returns updated database (same as `_update()`).
+ Returns a dict, where the keys are all modified columns of the updated row, and the value
+ of each is a 2-tuple (<past value>, <new value>).
"""
# `serial` must be specified.
if "serial" not in umb:
@@ -169,7 +170,19 @@ class Database(CsvTable):
if not umb["lent_at"]:
raise UmbrellaValueError("lent_at")
- return self._update(umb)
+ # commit update
+ self._update(umb)
+
+ # find updated columns
+ # essentially "diff umb_in_db umb"
+ diff = {}
+ for key, new in umb.items():
+ past = umb_in_db[key]
+ if any([new, past]) and new != past:
+ # new and past are not both null values, and they are unequal
+ diff[key] = (past, new)
+
+ return diff
@staticmethod
def group_by_status(umbrellas) -> dict: