Conversation
There was a problem hiding this comment.
Pull request overview
Adds a “Relaxed Permissions” mode at the Team level to allow users without any assigned Press Roles to bypass role checks, with a dashboard toggle and backend enforcement around who can enable/disable it.
Changes:
- Introduces a new
relaxed_permissionsTeam field (DocType + dashboard fields) and server-side authorization preventing non-owner/non-admin toggles. - Extends
press.guards.role_guardto skip role checks in relaxed mode when the user has zero assigned roles. - Updates the dashboard Roles UI to expose a switch for toggling relaxed permissions.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
press/press/doctype/team/team.py |
Adds relaxed_permissions field exposure and a before_validate guard restricting who can change it. |
press/press/doctype/team/team.json |
Adds the DocType field + field order entry for relaxed_permissions. |
press/guards/role_guard/__init__.py |
Adds relaxed-mode helpers and integrates skip_roles() into existing guard paths. |
press/api/account.py |
Treats relaxed/no-role users as “admin” in the user_permissions() response. |
dashboard/src/components/settings/RoleList.vue |
Adds a UI switch bound to team.setValue.submit for toggling relaxed permissions. |
Comments suppressed due to low confidence (2)
press/guards/role_guard/init.py:242
skip_roles()introduces a DB lookup + join-count query and is now invoked on every guarded call path (api/action/document). This can add multiple queries per request across many endpoints. Consider caching the relaxed-mode flag and the per-(team,user) role-count result onfrappe.local(request-scope) or viafrappe.cache()with a short TTL to avoid repeated queries within the same request/session.
users to bypass role checks if they don't have any roles assigned.
"""
return bool(int(frappe.get_value("Team", get_current_team(), "relaxed_permissions")))
def skip_roles() -> bool:
"""
Check if the current user has no roles assigned in the current team.
"""
if not is_relaxed_mode():
return False
PressRole = frappe.qb.DocType("Press Role")
PressRoleUser = frappe.qb.DocType("Press Role User")
return (
frappe.qb.from_(PressRole)
.inner_join(PressRoleUser)
.on(PressRoleUser.parent == PressRole.name)
.select(Count(PressRole.name).as_("roles_count"))
.where(PressRole.team == get_current_team())
.where(PressRoleUser.user == frappe.session.user)
.run(as_dict=True)
.pop()
.get("roles_count")
== 0
)
press/guards/role_guard/init.py:243
- Relaxed mode is intended to let users with no assigned roles bypass restrictions, but
is_restricted()(used by list queries for Site/Server/Release Group and notifications) does not considerskip_roles(). As a result, users with no roles can still see restricted lists even though decorator checks are bypassed. Updatingis_restricted()to return false whenskip_roles()is true (and/or updating the call sites) would make relaxed mode behavior consistent across reads and writes.
"""
if not is_relaxed_mode():
return False
PressRole = frappe.qb.DocType("Press Role")
PressRoleUser = frappe.qb.DocType("Press Role User")
return (
frappe.qb.from_(PressRole)
.inner_join(PressRoleUser)
.on(PressRoleUser.parent == PressRole.name)
.select(Count(PressRole.name).as_("roles_count"))
.where(PressRole.team == get_current_team())
.where(PressRoleUser.user == frappe.session.user)
.run(as_dict=True)
.pop()
.get("roles_count")
== 0
)
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- `pyotp` - `country_code_for_region`
Codecov Report❌ Patch coverage is
❌ Your patch status has failed because the patch coverage (53.84%) is below the target coverage (75.00%). You can increase the patch coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## develop #5389 +/- ##
===========================================
- Coverage 50.91% 50.90% -0.02%
===========================================
Files 846 846
Lines 69489 69544 +55
Branches 274 274
===========================================
+ Hits 35382 35399 +17
- Misses 34086 34124 +38
Partials 21 21
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
feat(permissions): Relaxed mode (backport #5389)
Uh oh!
There was an error while loading. Please reload this page.