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

Sync up Database and PreApprovalWebhook/PreApprovalWebhookReply Models #4838

Merged
merged 3 commits into from
Apr 29, 2024

Conversation

pattisdr
Copy link
Contributor

@pattisdr pattisdr commented Apr 27, 2024

Closes #PROD-2004

Description Of Changes

Autogenerating migrations reveals there are discrepancies between what is defined on the new PreApprovalWebhook and PreApprovalWebhookReply models and the tables in the fides application db. Let's get these in sync. Updating FK's, indices, etc. is trickier once we've started collecting data.

cd src/fides/api/alembic
alembic revision -m "pre_approval_webhook_cleanup" --autogenerate

Code Changes

  • Add missing preapprovalwebhook.key index in database to match model
  • Create unique constraint on preapprovalwebhook.name in database to match model
  • Index the preapprovalwebhookreply.privacy_request_id to match the model
  • Start indexing preapprovalwebhookreply.webhook_id on both the model and in the database
  • Fix/Add FK's on preapprovalwebhookreply privacy_request_id and webhook_id with on delete set null

Add further handling if resources get deleted:

  • Cascade Delete PreApprovalWebhook if the ConnectionConfig is deleted and adjust FK accordingly in migration
  • Set Webhook Id to Null on PreApprovalWebhook Reply if the Webhook itself is deleted to match what happens if Privacy Request is deleted. Alter same column to make it nullable if it does get deleted.
  • Update API endpoint that records if privacy request is eligible to be approved automatically to ignore webhook replies if the webhook is deleted

Steps to Confirm

  • Verify tables look as expected:
fides=# \d preapprovalwebhook;
                        Table "public.preapprovalwebhook"
        Column        |           Type           | Collation | Nullable | Default 
----------------------+--------------------------+-----------+----------+---------
 id                   | character varying(255)   |           | not null | 
 created_at           | timestamp with time zone |           |          | now()
 updated_at           | timestamp with time zone |           |          | now()
 name                 | character varying        |           | not null | 
 key                  | character varying        |           | not null | 
 connection_config_id | character varying        |           | not null | 
Indexes:
    "preapprovalwebhook_pkey" PRIMARY KEY, btree (id)
    "ix_preapprovalwebhook_id" btree (id)
    "ix_preapprovalwebhook_key" UNIQUE, btree (key)
    "preapprovalwebhook_name_key" UNIQUE CONSTRAINT, btree (name)
Foreign-key constraints:
    "preapprovalwebhook_connection_config_id_fkey" FOREIGN KEY (connection_config_id) REFERENCES connectionconfig(id) ON DELETE CASCADE
Referenced by:
    TABLE "preapprovalwebhookreply" CONSTRAINT "preapprovalwebhookreply_webhook_id_fkey" FOREIGN KEY (webhook_id) REFERENCES preapprovalwebhook(id) ON DELETE SET NULL
fides=# \d preapprovalwebhookreply;
                     Table "public.preapprovalwebhookreply"
       Column       |           Type           | Collation | Nullable | Default 
--------------------+--------------------------+-----------+----------+---------
 id                 | character varying(255)   |           | not null | 
 webhook_id         | character varying(255)   |           |          | 
 created_at         | timestamp with time zone |           |          | now()
 updated_at         | timestamp with time zone |           |          | now()
 privacy_request_id | character varying        |           |          | 
 is_eligible        | boolean                  |           | not null | 
Indexes:
    "preapprovalwebhookreply_pkey" PRIMARY KEY, btree (id)
    "ix_preapprovalwebhookreply_id" btree (id)
    "ix_preapprovalwebhookreply_privacy_request_id" btree (privacy_request_id)
    "ix_preapprovalwebhookreply_webhook_id" btree (webhook_id)
    "webhook_id_privacy_request_id" UNIQUE CONSTRAINT, btree (webhook_id, privacy_request_id)
Foreign-key constraints:
    "preapprovalwebhookreply_privacy_request_id_fkey" FOREIGN KEY (privacy_request_id) REFERENCES privacyrequest(id) ON DELETE SET NULL
    "preapprovalwebhookreply_webhook_id_fkey" FOREIGN KEY (webhook_id) REFERENCES preapprovalwebhook(id) ON DELETE SET NULL

Pre-Merge Checklist

…alWebhookReply models:

- Add missing preapprovalwebhook.key index in database to match model
- Create unique constraint on preapprovalwebhook.name in database to match model
- Index the preapprovalwebhookreply.privacy_request_id.privacy_request_id to match the model
- Fix/Add FK's on preapprovalwebhookreply privacy_request_id and webhook_id

Add further handling if resources get deleted:
- Cascade Delete PreApprovalWebhook if the ConnectionConfig is deleted
- Set Webhook Id to Null on PreApprovalWebhook Reply if the Webhook itself is deleted to match what happens if Privacy Request is deleted. Make that nullable too.
Copy link

vercel bot commented Apr 27, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

1 Ignored Deployment
Name Status Preview Comments Updated (UTC)
fides-plus-nightly ⬜️ Ignored (Inspect) Visit Preview Apr 27, 2024 1:08am

Copy link

cypress bot commented Apr 27, 2024

Passing run #7495 ↗︎

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 3e6db52 into bcebc35...
Project: fides Commit: 2e4fa9743b ℹ️
Status: Passed Duration: 00:34 💡
Started: Apr 27, 2024 1:20 AM Ended: Apr 27, 2024 1:20 AM

Review all test suite changes for PR #4838 ↗︎

Comment on lines -1346 to +1357
# Check if all replies are true
replies_for_privacy_request = PreApprovalWebhookReply.filter(
db=db,
conditions=(PreApprovalWebhookReply.privacy_request_id == privacy_request_id),
).all()

# Check if all replies are true. Reply ignored if its webhook has since been deleted.
replies_for_privacy_request = (
db.query(PreApprovalWebhookReply)
.filter(
PreApprovalWebhookReply.privacy_request_id == privacy_request_id,
PreApprovalWebhookReply.webhook_id.isnot(None),
)
.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.

It seems easy to remove a preapproval webhook with the PUT endpoint that removes webhooks that aren't in the request. So if this does happen, replies for a deleted webhook are ignored.

Copy link
Contributor

Choose a reason for hiding this comment

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

Agree, and this additional check to ignore deleted webhooks is a good one 💯

src/fides/api/models/pre_approval_webhook.py Show resolved Hide resolved
Comment on lines 41 to 44
webhook_id = Column(
String, ForeignKey(PreApprovalWebhook.id_field_path), nullable=False
String,
ForeignKey(PreApprovalWebhook.id_field_path, ondelete="SET NULL"), index=True
)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

New: adding an index on this column (similar to the one on priavcy_request_id because it is commonly queried. Further, I'm setting this field to null in the event the webhook itself is deleted.

Copy link
Contributor

Choose a reason for hiding this comment

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

thanks, this makes sense. For future reference, are there any disadvantages to setting an index on a column at all?

Copy link
Contributor Author

@pattisdr pattisdr Apr 29, 2024

Choose a reason for hiding this comment

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

yes good question, the main disadvantage is that it slows down writes, you definitely don't want to/need to index everything. This seemed like one of the fields that would be queried frequently and this will be a large table.

src/fides/api/models/pre_approval_webhook.py Show resolved Hide resolved
Copy link

codecov bot commented Apr 27, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 86.87%. Comparing base (bcebc35) to head (3e6db52).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #4838   +/-   ##
=======================================
  Coverage   86.87%   86.87%           
=======================================
  Files         345      345           
  Lines       20855    20856    +1     
  Branches     2727     2727           
=======================================
+ Hits        18118    18119    +1     
  Misses       2262     2262           
  Partials      475      475           

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

Copy link
Contributor

@eastandwestwind eastandwestwind left a comment

Choose a reason for hiding this comment

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

Dawn, your assumptions about the foreign key delete behavior make sense to me. Thanks for adding tests and additionally updating the eligible endpoint to account for previously deleted webhooks.

I really appreciate you tackling this one! 🌟

Comment on lines -1346 to +1357
# Check if all replies are true
replies_for_privacy_request = PreApprovalWebhookReply.filter(
db=db,
conditions=(PreApprovalWebhookReply.privacy_request_id == privacy_request_id),
).all()

# Check if all replies are true. Reply ignored if its webhook has since been deleted.
replies_for_privacy_request = (
db.query(PreApprovalWebhookReply)
.filter(
PreApprovalWebhookReply.privacy_request_id == privacy_request_id,
PreApprovalWebhookReply.webhook_id.isnot(None),
)
.all()
)

Copy link
Contributor

Choose a reason for hiding this comment

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

Agree, and this additional check to ignore deleted webhooks is a good one 💯

Comment on lines 41 to 44
webhook_id = Column(
String, ForeignKey(PreApprovalWebhook.id_field_path), nullable=False
String,
ForeignKey(PreApprovalWebhook.id_field_path, ondelete="SET NULL"), index=True
)
Copy link
Contributor

Choose a reason for hiding this comment

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

thanks, this makes sense. For future reference, are there any disadvantages to setting an index on a column at all?

src/fides/api/models/pre_approval_webhook.py Show resolved Hide resolved
tests/ops/models/test_pre_approval_webhook.py Show resolved Hide resolved
@pattisdr pattisdr merged commit 5b4983d into main Apr 29, 2024
41 of 42 checks passed
@pattisdr pattisdr deleted the PROD-2004-preapproval-webhook-cleanup branch April 29, 2024 14:14
@cypress cypress bot mentioned this pull request Apr 29, 2024
31 tasks
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.

2 participants