about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFrederick Muriuki Muriithi2023-08-30 12:42:28 +0300
committerFrederick Muriuki Muriithi2023-10-10 11:12:49 +0300
commit3e06396c8966250540e72f7fa909b78dd10a5534 (patch)
tree4de835b81170fe67e98ee1712b18b409a7da1a6e
parent567e6f00efbf700adf82d6118be445b66b5e212d (diff)
downloadgenenetwork3-3e06396c8966250540e72f7fa909b78dd10a5534.tar.gz
Implement some queuing logic for diffs
Queue the diffs into files - this might change somewhat once we verify whether
case-attribute editing needs an approval step.
-rw-r--r--gn3/case_attributes.py61
1 files changed, 42 insertions, 19 deletions
diff --git a/gn3/case_attributes.py b/gn3/case_attributes.py
index 3e22764..04df030 100644
--- a/gn3/case_attributes.py
+++ b/gn3/case_attributes.py
@@ -3,7 +3,9 @@ import os
 import csv
 import json
 import tempfile
+from pathlib import Path
 from functools import reduce
+from datetime import datetime
 
 from MySQLdb.cursors import DictCursor
 from flask import jsonify, request, Response, Blueprint, current_app
@@ -19,6 +21,8 @@ from gn3.auth.authorisation.errors import AuthorisationError
 
 caseattr = Blueprint("case-attribute", __name__)
 
+CATTR_DIFFS_DIR = "case-attribute-diffs"
+
 class NoDiffError(ValueError):
     """Raised if there is no difference between the old and new data."""
     def __init__(self):
@@ -171,7 +175,7 @@ def __compute_diff__(fieldnames: tuple[str, ...], original_data: tuple[dict, ...
         return json.loads(diff_results["output"])
     return {}
 
-def __queue_diff__(conn: Connection, user: User, diff) -> str:
+def __queue_diff__(conn: Connection, diff_data, diff_data_dir: Path) -> Path:
     """
     Queue diff for future processing.
 
@@ -179,9 +183,20 @@ def __queue_diff__(conn: Connection, user: User, diff) -> str:
         On success, this will return the filename where the diff was saved.
         On failure, it will raise a MySQL error.
     """
+    diff = diff_data["diff"]
     if bool(diff["Additions"]) or bool(diff["Modifications"]) or bool(diff["Deletions"]):
         # TODO: Check user has "edit case attribute privileges"
-        raise NotImplementedError
+        diff_data_dir.mkdir(parents=True, exist_ok=True)
+
+        created = datetime.now()
+        filepath = Path(
+            diff_data_dir,
+            f"{diff_data['inbredset_id']}:::{diff_data['user_id']}:::"
+            f"{created.isoformat()}.json")
+        with open(filepath, "w", encoding="utf8") as diff_file:
+            # We want this to fail if the metadata items below are not provided.
+            diff_file.write(json.dumps({**diff_data, "created": created.isoformat()}))
+        return filepath
     raise NoDiffError
 
 def __apply_diff__(conn: Connection, user: User, diff_filename) -> None:
@@ -226,24 +241,24 @@ def edit_case_attributes(inbredset_id: int) -> Response:
           database_connection(current_app.config["SQL_URI"]) as conn):
         # TODO: Check user has "edit case attribute privileges"
         user = the_token.user
+        fieldnames = (["Strain"] + sorted(
+            attr["Name"] for attr in
+            __case_attribute_labels_by_inbred_set__(conn, inbredset_id)))
         try:
-            fieldnames = (["Strain"] + sorted(
-                attr["Name"] for attr in
-                __case_attribute_labels_by_inbred_set__(conn, inbredset_id)))
-            diff_filename = __queue_diff__(conn, user, __compute_diff__(
-                fieldnames,
-                __process_orig_data__(
-                    fieldnames,
-                    __case_attribute_values_by_inbred_set__(conn, inbredset_id),
-                    __inbredset_strains__(conn, inbredset_id)),
-                __process_edit_data__(fieldnames, request.json["edit-data"])))
-
-            __apply_diff__(conn, user, diff_filename)
-            return jsonify({
-                "diff-status": "applied",
-                "message": ("The changes to the case-attributes have been "
-                            "applied successfully.")
-            })
+            diff_filename = __queue_diff__(
+                conn, {
+                    "inbredset_id": inbredset_id,
+                    "user_id": str(user.user_id),
+                    "fieldnames": fieldnames,
+                    "diff": __compute_diff__(
+                        fieldnames,
+                        __process_orig_data__(
+                            fieldnames,
+                            __case_attribute_values_by_inbred_set__(conn, inbredset_id),
+                            __inbredset_strains__(conn, inbredset_id)),
+                        __process_edit_data__(fieldnames, request.json["edit-data"]))
+                },
+                Path(current_app.config.get("TMPDIR"), CATTR_DIFFS_DIR))
         except NoDiffError as _nde:
             msg = "There were no changes to make from submitted data."
             response = jsonify({
@@ -252,6 +267,14 @@ def edit_case_attributes(inbredset_id: int) -> Response:
             })
             response.status_code = 400
             return response
+
+        try:
+            __apply_diff__(conn, user, diff_filename)
+            return jsonify({
+                "diff-status": "applied",
+                "message": ("The changes to the case-attributes have been "
+                            "applied successfully.")
+            })
         except AuthorisationError as _auth_err:
             return jsonify({
                 "diff-status": "queued",