Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pause manual erasure requests #4115

Merged
merged 15 commits into from
Sep 26, 2023
Merged

Conversation

galvana
Copy link
Contributor

@galvana galvana commented Sep 18, 2023

Description Of Changes

Updated the privacy request workflow to pause any erasure requests with manual webhook connection configs before completing the request. The privacy request is flagged as requires input and waits for a user to mark which fields have been manually deleted before the request can be completed.

I kept the changes very light, I just made enough changes to pause the request in the UI and give the user a way to track which fields have been deleted. The manual erasure inputs are not used for any request execution. The changes are also not very DRY, often just erasure duplicates of existing manual access functionality. The requirements around this ticket were a bit loose (originally scoped as a defect) so I didn't want to integrate this too closely with the existing manual access workflow.

Code Changes

  • Updated the run_privacy_request function of request_runner_service.py to pause erasure privacy requests if there are any manual webhook connection configs enabled.
  • Updated the privacy request detail page to use different side menus for manual access and erasure
  • Added new endpoints to cache and retrieve manual erasure inputs

Steps to Confirm

  • Create a new system
  • Add a Manual Process integration
  • Click Customize DSR and add some fields
  • Submit an erasure request via the Privacy Center
  • Navigate to the Privacy request tab in the Admin UI and verify that the privacy request is in a Requires Input state, either immediately of after clicking approve (based on your test environment's settings).

Pre-Merge Checklist

  • All CI Pipelines Succeeded
  • Issue Requirements are Met
  • Update CHANGELOG.md
  • For API changes, the Postman collection has been updated

@cypress
Copy link

cypress bot commented Sep 19, 2023

Passing run #4348 ↗︎

0 4 0 0 Flakiness 0
⚠️ You've recorded test results over your free plan limit.
Upgrade your plan to view test results.

Details:

Merge e7299c3 into 5c741f1...
Project: fides Commit: 6d68e41109 ℹ️
Status: Passed Duration: 00:59 💡
Started: Sep 26, 2023 6:44 PM Ended: Sep 26, 2023 6:45 PM

This comment has been generated by cypress-bot as a result of this project's GitHub integration settings.

@galvana galvana changed the title Prod 1005 pause manual erasure requests Pause manual erasure requests Sep 19, 2023
@codecov
Copy link

codecov bot commented Sep 20, 2023

Codecov Report

Attention: 3 lines in your changes are missing coverage. Please review.

Comparison is base (85dc387) 87.50% compared to head (e7299c3) 87.53%.
Report is 4 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4115      +/-   ##
==========================================
+ Coverage   87.50%   87.53%   +0.02%     
==========================================
  Files         326      326              
  Lines       20324    20417      +93     
  Branches     2640     2654      +14     
==========================================
+ Hits        17784    17871      +87     
- Misses       2081     2083       +2     
- Partials      459      463       +4     
Files Coverage Δ
src/fides/api/models/manual_webhook.py 100.00% <100.00%> (ø)
src/fides/api/models/privacy_request.py 96.42% <100.00%> (+0.18%) ⬆️
...c/fides/api/service/connectors/manual_connector.py 92.30% <100.00%> (ø)
.../service/privacy_request/request_runner_service.py 78.42% <100.00%> (+1.25%) ⬆️
src/fides/common/api/v1/urn_registry.py 100.00% <100.00%> (ø)
.../api/api/v1/endpoints/privacy_request_endpoints.py 90.23% <90.32%> (-0.15%) ⬇️

... and 6 files with indirect coverage changes

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@galvana galvana marked this pull request as ready for review September 20, 2023 02:17
Copy link
Contributor

@adamsachs adamsachs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice work @galvana , looks good for a first pass! like you said, def some code consolidation opportunities but that's fine to defer, especially since i think this is still pretty straightforward to follow - though there's one i think it'd be worth addressing for now.

there are a couple other points that i'd just like to make sure we've considered and/or are being communicated to product (and potentially documented in release notes/user guides), especially the one about persisting the "confirmation" signal.

parsed_data.dict(),
)

def get_manual_webhook_input_strict(
def cache_manual_webhook_erasure_input(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i know we're following the example from the access input as a first pass, and i think that's probably fine. but i'd want to make sure we flag this, since i could see it leading to problems if users (or our product team) doesn't realize the implication here.

specifically, there's no sort of persisted record of the confirmation that the records have been deleted from the manual integration. there'd be no way of tracking that admin X confirmed at time Y that person Z's records were deleted from system A (whoops ran out of letters) -- at least, not one that we can rely on since we have to treat the cache as ephemeral. i think it's true that we don't persist directly in our db the manual input data for access requests (though maybe we should?) but it's a bit different there because that input is packaged up as part of the access result package and that package is put into storage and/or sent back to the end user -- so it is persisted somewhere.

this is certainly not listed out as an explicit requirement here, but it feels like a reporting/audit requirement that could potentially have legal implications if/when this gets implemented. not saying we need to solve it here in a first pass, i'd just want this to be flagged before we release!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do not need a persisted record of the confirmation since a successfully completed deletion requires the confirmation we can infer that a confirmation was made. CC @rsilvery

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, that's fine for me in terms of an MVP, but there's some tension with the other piece of this implementation as noted here.

maybe we can ticket for a follow up, just to track it at least?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Placeholder ticket #4164

data: Dict[str, Any] = manual_webhook.erasure_fields_schema.parse_obj(
cached_results
).dict(exclude_unset=True)
if set(data.keys()) != set(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i could be following wrong, but is there a narrow (and perhaps too contrived) edge case where the value has been set to False for a given field (i.e. someone actually checks and unchecks a field) and we essentially judge this as OK, we're ready to proceed, when in reality they still have one or more fields outstanding? maybe that's a desired behavior, i.e. if an admin has explicitly unchecked a box then its up to their discretion to allow the request to proceed...

anyway, sorta just curious whether that's a legitimate possibility and if so whethere you'd thought thru it at all...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is ok, but that's only because it's hard for us to determine when it's acceptable to proceed with a manual erasure. There are cases when certain fields might not exist in the manual data source so we'll still want to proceed even if no fields are checked.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK fair enough, i mean i think there's a bit of tension between that and what we're saying here, i.e. that completed deletion infers a confirmation was made. if we're allowing deletion to proceed without requiring confirmation of all fields, someone who is auditing things really has no way of determining what was deleted on a particular DSR request.

totally acknowledge that this is an edge case and the requirement generally is perhaps beyond MVP scope. i just think that a robust/long term implementation probably includes some sort of persisted tracking of what was confirmed on a particular DSR 👍

dependencies=[Security(verify_oauth_client, scopes=[PRIVACY_REQUEST_UPLOAD_DATA])],
response_model=None,
)
def upload_manual_webhook_erasure_data(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i know you specifically mentioned not DRYing this code up, and that's fine, but this is basically identical to the above endpoint besides cache_manual_webhook_erasure_input instead of cache_manual_webhook_access_input and then one word differences in log messages. IMO it's worth some minimal effort on DRYing this up for readability and so that we can be sure not to have any drift if/when any of this logic needs to be updated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point about DRYing this portion up to clearly show these two endpoints are related. I extracted the shared logic into a function so now we can just do this for each endpoint

    _handle_manual_webhook_input(
        action="access",
        connection_config=connection_config,
        privacy_request_id=privacy_request_id,
        db=db,
        input_data=input_data,
    )

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

awesome, thank you @galvana!

@galvana galvana merged commit 92e0580 into main Sep 26, 2023
42 of 45 checks passed
@galvana galvana deleted the PROD-1005-pause-manual-erasure-requests branch September 26, 2023 20:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants