-
Notifications
You must be signed in to change notification settings - Fork 0
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
fix: RoleCache.has_role should be case-insensitive #35
Conversation
I'll contribute this to Upstream once we have a code review here |
9707186
to
a738c4f
Compare
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.
@shadinaif few minor notes regarding testing. They're important for upstream contribution.
@@ -90,7 +90,7 @@ def has_role(self, role, course_id, org): | |||
return any( | |||
access_role.role in self.get_roles(role) and | |||
access_role.course_id == course_id and | |||
access_role.org == org | |||
access_role.org.lower() == org.lower() |
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.
Clear!
expected_has_role = ( | ||
target[0] == other_target[0] and | ||
(target[1] or '') == (other_target[1] or '') and | ||
target[2].lower() == other_target[2].lower() | ||
) |
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.
Such code is a bit too complicated for testing. Testing cases should have as few branches as possible.
expected_has_role = ( | |
target[0] == other_target[0] and | |
(target[1] or '') == (other_target[1] or '') and | |
target[2].lower() == other_target[2].lower() | |
) |
(CourseStaffRole(IN_KEY), ('staff', IN_KEY, 'edX')), | ||
(CourseStaffRole(IN_KEY), ('staff', IN_KEY, 'EDX')), |
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.
Add expected_has_role
to this list to avoid introducing complicated logic in testing
(CourseStaffRole(IN_KEY), ('staff', IN_KEY, 'edX')), | |
(CourseStaffRole(IN_KEY), ('staff', IN_KEY, 'EDX')), | |
(CourseStaffRole(IN_KEY), ('staff', IN_KEY, 'edX'), True), # Should have role | |
(CourseStaffRole(IN_KEY), ('staff', IN_KEY, 'EDX'), False), # Should have role despite case difference |
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.
sounds reasonable, thank you!
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.
it'll not work exactly like this because the test iterates on all records, but I'll find a way 👍🏼
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.
Done 👍🏼
a738c4f
to
db728cf
Compare
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.
@shadinaif please note that I think the fix in the code is pretty fine, but tests are very hard to understand.
I'm just reviewing with very high quality standards i.e. upstream quality, let me know if you think we should stop and focus on making the fix locally and then worry about upstream contribution.
for _, other_target, other_test_id in self.ROLES: | ||
assert cache.has_role(*other_target) == (test_id == other_test_id) |
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.
@shadinaif I presume I'm very familiar with the issue being presented here, but the test still isn't understanble.
I think the real cause is that the original test_only_in_role
function was cryptic.
In such case I would support creating a new test case e.g. test_only_in_role_case_insensitive
so it doesn't have for-loop or at least it doesn't have to be so generic and becomes hard to understand.
db728cf
to
bdb520d
Compare
I've update the tests @OmarIthawi I believe it's clear now. Thank you! |
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.
super!
hi @OmarIthawi and @shadinaif, just asking, is this a backport? Or is there an equivalent upstream PR? |
unfortunately, it's not equivalent to upstream. When I tried to create a PR, I found that the code there had changed and a cherry-pick was not possible. I'm planning to report/fix upstream by the end of this month. I'll keep updated @andrey-canon , thank you for checking 👍🏼 |
Thanks @shadinaif!! |
Hi @shadinaif thanks for you answer and I was asking because we have a migration file where we track all the custom commits. This file helps us to decide which commits we must include in the next release, so if the commit is not there, there is a chance that we will miss it, so could you please add the commit data into the file? |
Thank you @andrey-canon . I've added it as gray and explained the reason in the sheet. The fix is needed, but this code should be discarded in the upgrade process (this is why I set it as gray). I'll follow up with you after having the fix in upstream |
thanks @shadinaif |
Description
RoleCache
comparesorg
in a case-sensitive manner while the value oforg
is assumed as case-insensitive by the database collation, and by the django admin form. This PR is to fix the issue to makeRoleCache
behave as the rest of the platformSupporting information
Testing instructions
Preperation to test:
test_user
demo
organization:course-v1:Demo+topic1+index1
andcourse-v1:demo+topic2+index2
. We have the first course with organizationDemo
in course-overview instead ofdemo
. This is acceptable in the platformBefore the fix:
test_user
aninstructor
on the entiredemo
organization, the admin will have to grant it course by course. This is becauseCourseAccessRole
will not allow two similar records like[user: test_user, course_id: "", role: instructor, org: demo]
and[user: test_user, course_id: "", role: instructor, org: Demo]
. The key constraint treatsorg
as case-insensitiveAfter the fix:
[user: test_user, course_id: "", role: instructor, org: demo]
,[user: test_user, course_id: "", role: instructor, org: Demo]
, or even[user: test_user, course_id: "", role: instructor, org: DEMO]
will maketest_user
an instructor on all courses as expectedDeadline
Other information