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

Add DELETE endpoint for UserChangemakerPermission #1349

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

slifty
Copy link
Member

@slifty slifty commented Dec 2, 2024

This PR adds the ability to DELETE various permissions.

Related to #1351

Copy link

codecov bot commented Dec 2, 2024

Codecov Report

Attention: Patch coverage is 93.47826% with 3 lines in your changes missing coverage. Please review.

Project coverage is 87.45%. Comparing base (dea02f8) to head (203b00c).
Report is 12 commits behind head on main.

Files with missing lines Patch % Lines
src/handlers/userChangemakerPermissionsHandlers.ts 91.66% 2 Missing ⚠️
...emakerPermissions/loadUserChangemakerPermission.ts 90.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1349      +/-   ##
==========================================
+ Coverage   87.34%   87.45%   +0.11%     
==========================================
  Files         185      187       +2     
  Lines        2387     2432      +45     
  Branches      314      330      +16     
==========================================
+ Hits         2085     2127      +42     
+ Misses        302      279      -23     
- Partials        0       26      +26     

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

Our `Writable` objects did not support optional parameters, and instead
converted them into required parameters where `undefined` was a valid
type.  This may sound similar, but in practice TypeScript will require
the parameter to be defined (with an explicit `undefined` value) as
opposed to simply resolving to undefined by not existing.

This change to the Writable type means that any optional parameter is
properly mapped to an optional parameter in the resulting type.

You may notice that the mapped type now has `| undefined` as a valid
type, but this is OK since technically any optional parameter DOES allow
`undefined` to be a type.
@slifty slifty force-pushed the 1250-delete-permission-endpoints branch from 7410159 to faf490e Compare December 2, 2024 20:10
We are going to support deletion of permissions in an upcoming commit,
and to do this we are going to store an expiration date instead of
actually deleting records.

Issue #1351 Support removal of user permissions
@slifty slifty force-pushed the 1250-delete-permission-endpoints branch from faf490e to a249860 Compare December 2, 2024 20:18
.expect(404);
});

it('returns 404 if the permission had previously been deleted', async () => {
Copy link
Member Author

@slifty slifty Dec 2, 2024

Choose a reason for hiding this comment

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

I wanted to highlight this for consideration. The internet disagrees on this -- should it be 404 the second time, or 204. What does idempotent mean in this context?

It's 404 if it never existed of course.

We do happen to have a record of if something has been deleted because we aren't removing rows, so in theory we could do either one.

If 204, should it update the not_after to the most recent call, or should not_after not be touched if the permission had already expired?

Copy link
Member Author

Choose a reason for hiding this comment

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

@bickelj I wanted to highlight the above comment, since you started to explore some of the questions in it below. Specifically this question of: If 204, should it update the not_after to the most recent call, or should not_after not be touched if the permission had already expired?

Copy link
Member Author

Choose a reason for hiding this comment

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

@jasonaowen @bickelj I do think the above question is something we should answer, even without an audit log.

If someone deletes a permission that has already been deleted we should essentially ignore the second request, correct? Should it return 404, or 204?

@slifty slifty force-pushed the 1250-delete-permission-endpoints branch from a249860 to f9594a6 Compare December 2, 2024 20:36
This endpoint makes it possible for a user with appropriate permissions
to remove a changemaker permission for a given user.

Issue #1250 Support associations between users and organizational entities
@slifty slifty force-pushed the 1250-delete-permission-endpoints branch from f9594a6 to 203b00c Compare December 2, 2024 20:44
Copy link
Contributor

@bickelj bickelj left a comment

Choose a reason for hiding this comment

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

I was able to lint, build, test:ci, migrate, and start this locally. I got the expected responses when attempting to create permissions for non-existent entities. I was able to add a permission as expected and then delete it as expected. For example, an added and then deleted permission:

pdc=> select * from user_changemaker_permissions ;
        user_keycloak_user_id         | permission | changemaker_id |              created_by              |          created_at           |           not_after           
--------------------------------------+------------+----------------+--------------------------------------+-------------------------------+-------------------------------
 8f6e6dd9-d4af-45db-af50-712f7e962cd7 | edit       |              5 | 8f6e6dd9-d4af-45db-af50-712f7e962cd7 | 2024-12-03 11:20:21.078377-06 | 2024-12-03 11:21:15.407213-06
(1 row)

However, after re-deleting that same permission, the not_after was updated in the same row, like this:

pdc=> select * from user_changemaker_permissions ;
        user_keycloak_user_id         | permission | changemaker_id |              created_by              |          created_at           |           not_after           
--------------------------------------+------------+----------------+--------------------------------------+-------------------------------+-------------------------------
 8f6e6dd9-d4af-45db-af50-712f7e962cd7 | edit       |              5 | 8f6e6dd9-d4af-45db-af50-712f7e962cd7 | 2024-12-03 11:20:21.078377-06 | 2024-12-03 11:27:24.499753-06
(1 row)

And then after re-adding the same permission, the not_after was cleared:

pdc=> select * from user_changemaker_permissions ;
        user_keycloak_user_id         | permission | changemaker_id |              created_by              |          created_at           | not_after 
--------------------------------------+------------+----------------+--------------------------------------+-------------------------------+-----------
 8f6e6dd9-d4af-45db-af50-712f7e962cd7 | edit       |              5 | 8f6e6dd9-d4af-45db-af50-712f7e962cd7 | 2024-12-03 11:20:21.078377-06 | 
(1 row)

I think the case of a repeated delete should compare now() to the existing not_after and if now() is later, do not update the not_after because that would be redundant and erase the actual expiration of the permission.

I'm less sure of what I expect for the last case (adding a previously deleted permission) but in the spirit of retaining what actually happened, as complex as it is, I think I want new non-overlapping-in-time rows.

@bickelj
Copy link
Contributor

bickelj commented Dec 3, 2024

Perhaps it is too much to try to track the entire permissions history directly in the permissions table. Instead, we can allow simple insert and delete and enable postgres mod logs. We can look at the database logs if a question arises as to the history of permissions changes. Or if we wish to keep a history in-band in the database itself, we could use a history table off to the side: an audit log table.

@slifty
Copy link
Member Author

slifty commented Dec 3, 2024

Perhaps it is too much to try to track the entire permissions history directly in the permissions table.

I agree that if the goal is simply supporting an audit that the above solution would make a simple design much more complex and prone to having errors in future queries.

I think it makes more sense to have an audit log system (which we had an issue fore: #135) than to turn the permissions tables into audit logs themselves. Whether / when an audit log system becomes an engineering priority I think should be driven by use case + client + @kfogel, if that makes sense.

@bickelj
Copy link
Contributor

bickelj commented Dec 3, 2024

Given what was discussed in the meeting, I think keep the not_after column until we have a better substitute because it's something rather than nothing.

@slifty
Copy link
Member Author

slifty commented Dec 3, 2024

@bickelj I just created #1355 to capture the audit log discussion.

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