Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(projectHistoryLog): record submission modifications (#5404)
### 📣 Summary Log updates to submissions, both content and validation status. ### 💭 Notes #### SubmissionUpdate The `SubmissionUpdate` class is just a dataclass meant to make it clear what information we need to create a PH log for submission modification/creation/deletion. It's meant mostly to help future developers since we're not using the usual `initial_data`/`updated_data` pattern where we just take configured fields off of a model. #### ProjectHistoryLog.__init__ This PR includes a small refactor on ProjectHistoryLog to set the `app_name`, `model_name`, and `log_type` in the `__init__` method like we do with `create`. This saves us some repeated code when we are creating logs in bulk. #### Attaching the asset to the request We always need the `asset_uid` when logging any views that include the `AssetNestedObjectViewsetMixin` mixin, so I updated `AuditLoggedViewSet` to always attach the asset (available via the mixin) to the request. We may be able to use this to simplify other code later if we wish. #### Where we add data to the request We can't use the usual method of having the views inherit from `AuditLoggedViewSet` and configuring `logged_fields` on the relevant model because the viewsets that update Instances rarely act directly on the Instance objects via get_object or the serializers. Instead they usually have custom code that works through the deployment object on the asset. We could pass the request from the viewset through the layers of other methods until we get to the part where we are actually updating instances, but this would require a lot of changes in existing view code and we're trying to keep the audit log code relatively self-contained. Changes to logging code should ideally not require changes in view code. Instead, I decided to use a receiver on the Instance model `post_save` signal. This also should allow the code to be more backend-agnostic since we did not update anything directly in the OpenRosaDeploymentBackend model, where most of the actual updating takes place. Theoretically, any backend would have to eventually update the Instance model with the new `xml` and `status` fields, regardless of how else it went about performing the updates. This is an assumption we have to make since we don't have any other "real" backend implementations, but it seems a safe one. The exception to this is when updating multiple validations statuses, because that is done with a bulk update, which doesn't send the `post_save` signal. In that bit of code, we have to manually attach the updated instances to the request. It's not considered great practice to get the request as part of model code but the alternative once again requires a significant refactor to pass the request through multiple layers. ### 👀 Preview steps Feature/no-change template: 1. Regression test: follow the test plan at #5387 to make sure that logging for duplicate submissions still works since that changed. 1. ℹ️ have at least 2 accounts and a project. Make sure both accounts have permission to add submissions to the project. For this preview, assume user1 owns the project. 2. Add a submission as the owner 3. Log in as user2 and add a submission. You may want to do this in a separate private tab, otherwise sometimes the enketo login stays cached and the submissions end up attached to the first user. 4. Login as user1 again and enable submissions without username or email 5. Add one more submission. It should come in as anonymous (ie no _submitted_by) 6. Go to the My Project > Data. 7. Change the validation status of a user1's submission to 'On Hold' using the dropdown in the table. 8. Go to `/api/v2/assets/<asset_uid>/history` 9. 🟢 There should be a new project history log with `action="modify-submission"` and the usual metadata, plus ``` "submission": { "status": "On Hold", "submitted_by": "user1" } ``` 10. Go back to the table and select all 3 submissions. 11. Select 'Change status' and update the status to 'Approved' for all of them 12. 🟢 Reload the endpoint. There should be 3 new logs with `action="modify-submission"` and the usual metadata, plus ``` "submission": { "status": "Approved", "submitted_by": "user1/user2/AnonymousUser" } ``` Note: there should be one log each for the different users since they each have one submission 13. Go back to the table and click the pencil by user2's submission. Edit an answer to a question. 14. 🟢 Reload the endpoint. There should be a new log with `action="modify-submission"` and the usual metadata, plus ``` "submission": { "submitted_by": "user2" } ``` Note there is no validation status since that did not change. 15. Go back to the table and select all submissions. 16. Hit `Edit` and edit the answer to a question 17. 🟢 Reload the endpoint. There should be a 3 new logs with `action="modify-submission"` and the usual metadata, plus ``` "submission": { "submitted_by": "user1/user2/AnonymousUser" } ```
- Loading branch information