-
Notifications
You must be signed in to change notification settings - Fork 52
Fix management UI and API access permissions for #1425 #1431
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
base: 2.3.3
Are you sure you want to change the base?
Conversation
Signed-off-by: David Wallace <[email protected]>
Signed-off-by: David Wallace <[email protected]>
Signed-off-by: David Wallace <[email protected]>
Signed-off-by: David Wallace <[email protected]>
Signed-off-by: David Wallace <[email protected]>
Signed-off-by: David Wallace <[email protected]>
Signed-off-by: David Wallace <[email protected]>
Signed-off-by: David Wallace <[email protected]>
Signed-off-by: David Wallace <[email protected]>
Signed-off-by: David Wallace <[email protected]>
Signed-off-by: David Wallace <[email protected]>
Signed-off-by: David Wallace <[email protected]>
Signed-off-by: David Wallace <[email protected]>
|
||
|
||
# Add rules | ||
rules.add_rule('management.can_view_management', |
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 will break the backwards compatibility on the base_navigation
template, should I keep the the add_rule
in there just to not break the possible deployed custom templates?
Otherwise instance admins would need to update the theme for that. Think that it is better to use add_perm
than add_rule
..
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 agree, but can we have both and remove one in RDMO 3?
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.
Actually, I think add_rule
fits better since this is just a predicate "exposed" to the user instance in views etc. I think we should use add_rule
for all things can_...
and add_perm
for model/object permissions. management.can_view_management
has no input model or instance. Same for management.can_upload_files
and management.can_import_elements
.
ChatGPT explained it nicely:
🔹 rules.add_rule(name, function)
- What it does: Registers a predicate function under a name.
- A predicate is just a Python function that takes
(user, obj)
and returnsTrue
orFalse
. - Predicates are reusable building blocks.
- Example:
import rules
# Define a predicate
@rules.predicate
def is_staff(user):
return user.is_staff
# Register it under a name
rules.add_rule('is_staff', is_staff)
Now you can reference "is_staff"
as a condition in permissions or combine it with others.
🔹 rules.add_perm(name, rule)
- What it does: Registers a permission under a name and attaches it to one or more rules (predicates).
- A permission is basically a "named check" that can be used in your app (e.g. in
user.has_perm()
or decorators). - Example:
# Define a permission based on our predicate
rules.add_perm('app.view_secret', is_staff)
Now, anywhere in Django, you can do:
user.has_perm('app.view_secret')
and it will use the is_staff
predicate internally.
✅ Summary
add_rule
→ defines a predicate (logic building block).add_perm
→ defines a permission that Django can check, usually built from rules/predicates.
Think of it like this:
- Rule = ingredient
- Permission = finished dish 🍲
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.
ok now I see that its actually used as a permission in ManagementView
so I guess has_perm
is the better idea. Maybe we should remove the can_
from the perms then:
management.view_management
, management.upload_files
, management.import_elements
maybe even management.upload_elements
?
Then the naming is consistent and management
and elements
are kind of "fake" models, if you know what I mean.
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.
Same for projects.can_view_all_projects
to projects.view_projects
.
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.
ok, Ive renamed the permissions like that. The has_perm
is better for when it will be used on a user object anyway..
rdmo/core/permissions.py
Outdated
return super().has_permission(request, view) | ||
|
||
|
||
class HasRulesPermission(BasePermission): |
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 is for the Upload and Import viewsets
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.
Nice! I checked the drf and rules code, because I was wondering if there is something like this already. This just introduces the permission_required
class attribute in the same way as the regular django views, right? I would rename the class to HasPermission
, since also all the other Permissions somehow depend on rules.
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.
ok, HasPermission
it is..
rdmo/management/viewsets.py
Outdated
|
||
permission_classes = (IsAuthenticated, ) | ||
permission_classes = [HasRulesPermission] | ||
permission_required = 'management.can_view_management' |
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.
is the meta used anywhere outside of the management as well??
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.
No, I don't thin so.
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.
Meta should stay IsAuthenticated
since it is just the static information about fields and help texts etc.
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.
Very nice, thanks! I have the usual naming requests and the lengthy discussion with myself (and ChatGPT) which I want to share with you 😃
|
||
|
||
# Add rules | ||
rules.add_rule('management.can_view_management', |
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 agree, but can we have both and remove one in RDMO 3?
|
||
|
||
# Add rules | ||
rules.add_rule('management.can_view_management', |
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.
Actually, I think add_rule
fits better since this is just a predicate "exposed" to the user instance in views etc. I think we should use add_rule
for all things can_...
and add_perm
for model/object permissions. management.can_view_management
has no input model or instance. Same for management.can_upload_files
and management.can_import_elements
.
ChatGPT explained it nicely:
🔹 rules.add_rule(name, function)
- What it does: Registers a predicate function under a name.
- A predicate is just a Python function that takes
(user, obj)
and returnsTrue
orFalse
. - Predicates are reusable building blocks.
- Example:
import rules
# Define a predicate
@rules.predicate
def is_staff(user):
return user.is_staff
# Register it under a name
rules.add_rule('is_staff', is_staff)
Now you can reference "is_staff"
as a condition in permissions or combine it with others.
🔹 rules.add_perm(name, rule)
- What it does: Registers a permission under a name and attaches it to one or more rules (predicates).
- A permission is basically a "named check" that can be used in your app (e.g. in
user.has_perm()
or decorators). - Example:
# Define a permission based on our predicate
rules.add_perm('app.view_secret', is_staff)
Now, anywhere in Django, you can do:
user.has_perm('app.view_secret')
and it will use the is_staff
predicate internally.
✅ Summary
add_rule
→ defines a predicate (logic building block).add_perm
→ defines a permission that Django can check, usually built from rules/predicates.
Think of it like this:
- Rule = ingredient
- Permission = finished dish 🍲
rdmo/management/viewsets.py
Outdated
|
||
permission_classes = (IsAuthenticated, ) | ||
permission_classes = [HasRulesPermission] | ||
permission_required = 'management.can_view_management' |
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.
No, I don't thin so.
rdmo/management/viewsets.py
Outdated
|
||
permission_classes = (IsAuthenticated, ) | ||
permission_classes = [HasRulesPermission] | ||
permission_required = 'management.can_view_management' |
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.
Meta should stay IsAuthenticated
since it is just the static information about fields and help texts etc.
|
||
|
||
# Add rules | ||
rules.add_rule('management.can_view_management', |
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.
ok now I see that its actually used as a permission in ManagementView
so I guess has_perm
is the better idea. Maybe we should remove the can_
from the perms then:
management.view_management
, management.upload_files
, management.import_elements
maybe even management.upload_elements
?
Then the naming is consistent and management
and elements
are kind of "fake" models, if you know what I mean.
|
||
|
||
# Add rules | ||
rules.add_rule('management.can_view_management', |
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.
Same for projects.can_view_all_projects
to projects.view_projects
.
rdmo/core/permissions.py
Outdated
return False | ||
|
||
# prefer a view-level override when present | ||
perm = getattr(view, 'permission_required', None) |
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.
The None
is not needed and I would turn it around, check the perm if perm
and raise the error at the bottom.
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 now simply return:
# the viewset needs to set permission_required
return request.user.has_perm(view.permission_required)
I think it should only be used like that anyway and break when we would forget to set a permission_required
on the viewset.
rdmo/core/permissions.py
Outdated
return super().has_permission(request, view) | ||
|
||
|
||
class HasRulesPermission(BasePermission): |
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.
Nice! I checked the drf and rules code, because I was wondering if there is something like this already. This just introduces the permission_required
class attribute in the same way as the regular django views, right? I would rename the class to HasPermission
, since also all the other Permissions somehow depend on rules.
Signed-off-by: David Wallace <[email protected]>
Signed-off-by: David Wallace <[email protected]>
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.
Great work! I think we are done here.
{% back_to_project_link %} | ||
|
||
{% test_rule 'management.can_view_management' request.user request.site as can_view_management %} | ||
{% comment %}the test_rule will be removed in RDMO 3.0{% endcomment %} |
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 here we can just use {% has_perm 'management.view_management' request.user as can_view_management %}
only test_rule
should still exist for the legacy templates.
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.
ah yes, that would work without breaking it! 😅
Description
Related issue: #1425