fix(advice): clear stale advice on edit, and pin the injection guard
Two things I wanted to be sure of before this merges.
Stale advice
------------
The advice is written for the gravity that was there when it was
generated. If the brewer then edits the reading - to fix a typo, or to
mark it final - the old advice no longer describes it, and the page was
showing advice that contradicted the number next to it.
`upsert_reading` now clears the advice fields, so the stale advice goes
and a fresh one is generated (the form already regenerates on every save).
Only the advice fields are cleared - the brewer's own comment is never
touched.
The injection guard
-------------------
The reading's `_id` is an ObjectId, so the original `_as_id` coercion
(which turns run ids into plain strings, to stop a caller passing a dict
that Mongo would interpret as a query operator) did not apply - it turned
the ObjectId into an empty string and the update silently matched
nothing. `_as_doc_id` accepts only an ObjectId or a string that parses as
one.
Verified against a live injection attempt: `{"$ne": None}`, `{"$gt": ""}`,
a list, an int, None and a non-ObjectId string all return None and match
nothing. There is now a test that pins it, because it is a security
property that would otherwise only be covered by reading the code.
160 tests (up from 158).
This commit is contained in:
@@ -180,7 +180,13 @@ class BeerRepository:
|
||||
"date": _as_date(reading_date),
|
||||
"final_reading": "True" if final_reading else "False",
|
||||
"comment": str(comment),
|
||||
}
|
||||
},
|
||||
# The advice was written for the gravity that was there when
|
||||
# it was generated. If the reading has been edited, that
|
||||
# advice no longer describes it, so it is cleared and a fresh
|
||||
# one is generated. (Advice is only ever cleared here - never
|
||||
# the brewer's comment.)
|
||||
"$unset": {"advice": "", "advice_ok": "", "advice_at": ""},
|
||||
}
|
||||
result = self.readings.update_one(query, update, upsert=True)
|
||||
if result.upserted_id is not None:
|
||||
|
||||
Reference in New Issue
Block a user