home · contact · privacy
Improve POST /day input validation.
authorChristian Heller <c.heller@plomlompom.de>
Fri, 21 Jun 2024 15:37:33 +0000 (17:37 +0200)
committerChristian Heller <c.heller@plomlompom.de>
Fri, 21 Jun 2024 15:37:33 +0000 (17:37 +0200)
plomtask/http.py

index 28812dffc4bd53e44dbb6aef640ebadd881df8d4..27066036b2c300e23f41f7d348e5090905c9f2f8 100644 (file)
@@ -137,6 +137,20 @@ class InputsParser:
             msg = f'cannot int a form field value for key {key} in: {all_str}'
             raise BadFormatException(msg) from e
 
+    def get_all_floats_or_nones(self, key: str) -> list[float | None]:
+        """Retrieve list of float value at key, None if empty strings."""
+        ret: list[float | None] = []
+        for val in self.get_all_str(key):
+            if '' == val:
+                ret += [None]
+            else:
+                try:
+                    ret += [float(val)]
+                except ValueError as e:
+                    msg = f'cannot float form field value for key {key}: {val}'
+                    raise BadFormatException(msg) from e
+        return ret
+
 
 class TaskHandler(BaseHTTPRequestHandler):
     """Handles single HTTP request."""
@@ -552,13 +566,14 @@ class TaskHandler(BaseHTTPRequestHandler):
         make_type = self._form_data.get_str('make_type')
         old_todos = self._form_data.get_all_int('todo_id')
         new_todos = self._form_data.get_all_int('new_todo')
-        is_done = [t_id in self._form_data.get_all_int('done')
-                   for t_id in old_todos]
         comments = self._form_data.get_all_str('comment')
-        efforts = [float(effort) if effort else None
-                   for effort in self._form_data.get_all_str('effort')]
-        if old_todos and 3*[len(old_todos)] != [len(is_done), len(comments),
-                                                len(efforts)]:
+        efforts = self._form_data.get_all_floats_or_nones('effort')
+        done_todos = self._form_data.get_all_int('done')
+        for _ in [id_ for id_ in done_todos if id_ not in old_todos]:
+            raise BadFormatException('"done" field refers to unknown Todo')
+        is_done = [t_id in done_todos for t_id in old_todos]
+        if not (len(old_todos) == len(is_done) == len(comments)
+                == len(efforts)):
             msg = 'not equal number each of number of todo_id, comments, ' +\
                     'and efforts inputs'
             raise BadFormatException(msg)