-
-
Notifications
You must be signed in to change notification settings - Fork 182
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
perf(permissions)!: reduce queries in bulk permission assignment api TASK-828 #5087
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly style comments and a thought about testing
kpi/mixins/object_permission.py
Outdated
@@ -442,118 +442,158 @@ def get_all_implied_perms(cls, for_instance=None): | |||
|
|||
@transaction.atomic | |||
@kc_transaction_atomic | |||
def assign_perm(self, user_obj, perm, deny=False, defer_recalc=False, | |||
def assign_perms(self, user_obj, perm, deny=False, defer_recalc=False, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if we are renaming assign_perm
to assign_perms
, we may need to rename perm
param to perms
.
Let's use string annotations too. i.e.:
assign_perms(self, user_obj: 'User', perms: Union[str, list[str]], deny: bool = False, etc...)
kpi/mixins/object_permission.py
Outdated
remove_applicable_kc_permissions( | ||
self, user_obj, contradictory_codenames | ||
) | ||
# Create the new permission and add to the list of permissions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do not create new permission yet. It is just added to the list.
kpi/mixins/object_permission.py
Outdated
) | ||
|
||
if new_permissions: | ||
ObjectPermission.objects.bulk_create(new_permissions) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should use ignore_conflicts=True
in case race conditions and two concurrent requests try to add same permissions at the same time.
kpi/mixins/object_permission.py
Outdated
if len(new_permissions) == 1: | ||
new_permissions = new_permissions[0] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this condition needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was needed because a lot of code calling assign_perm()
was expecting a single string in return. So I wanted to make sure that if we just assigned one permission, it would return one string as expected. But now, since we are keeping the original assign_perm()
function and that will still be used when assigning a single permission, it is no longer needed.
kpi/mixins/object_permission.py
Outdated
for p in perm: | ||
self._update_partial_permissions( | ||
user_obj, p, partial_perms=partial_perms | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This may call clean_up_table()
(within _update_partial_permissions
) several times in a row.
It would be great to avoid that if the list of permissions contains conflicting permissions.
kpi/mixins/object_permission.py
Outdated
post_assign_perm.send( | ||
sender=self.__class__, | ||
instance=self, | ||
user=user_obj, | ||
codename=codename, | ||
codename=', '.join(perm), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
post_assign_asset_perm
expects the (the receiver method in kpi/signals.py) codename to be a string.
You need to adapt the code to be sure it works. I think a test is missing there. We need to be sure that the signal is called and the enketo server URL is updated when anonymous is granted add_submissions
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we have a test that checks expected permission assignments are there when we use assign_perms()
with many multiple permissions at a time.
I would like to be sure that assigning permissions with collections for example we still work the way we expect.
By the way, I would keepassign_perm()
(singular) and it would call your new assign_perms
behind the scene. We would avoid changing assign_perm
everywhere.
We can use typing annotation to know which type each method is expecting.
65bca19
to
adeda44
Compare
…ctor post_assign_asset_perm to take in lists of perms, add more tests
d8cfa8f
to
872ee18
Compare
We're very excited about this PR because what we want to do (use APIs to create shared questions in the library and then automatically grant users access based on their country) is blocked by the inability of Kobo to grant the permissions before our API gateway kills the request. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately, there is something wrong with the PR. @RuthShryock
When assigning a permission to user on a collection, it does not propagate to children of the collection.
But if I use the shell, it does work. My first theory could be some methods cached with @cache_request
which does not return an accurate state of the DB. I did not test it, but that the first explanation I have why it does work in shell but not through the API.
Hello @jdimeo sorry to hear that, if you are admin of your server, you may achieve what you want with |
Hi @noliveleger, I'm in John's org. We are definitely willing to use a workaround if there is one. I have tested creating a Appreciate any help or even somewhere to look documenting Project Views or other potentially helpful functionalities. |
Checklist
Description
Refactored
assign_perm()
andremove_perm()
to support bulk assignment and removal of permissions instead of processing them individuallyNotes
Some background
This was the original task: #3869 added more queries to the endpoint. We should review and either reduce the number of queries or prove why this is necessary. Of course we should also inspect average load times - the goal is to make it faster, not just reduce queries.
After some clarification, the issue is that we call
assign_perm()
andremove_perm()
for each permission assignment, one by one. This is costly and we want to reduce the number of queries and speed-up the endpoint so we should rewriteassign_perm()
andremove_perm()
to support bulk assignment.Testing
Test cases have been added but if you would like to test manually:
asset_permission_assignment.py
such astest_partial_permission_grants_implied_view_asset
self.assertNumQueries