Role with restricted permissions overrides broader role access at content level #5324

Closed
opened 2026-02-05 09:57:47 +03:00 by OVERLORD · 6 comments
Owner

Originally created by @rozdun on GitHub (Jun 23, 2025).

Describe the Bug

If a user has two roles - e.g. Team X (no permissions) and Leader (full access - view, create, etc), and content (e.g. a book) overrides Team X by giving it View permission and nothing else, the user is blocked from editing, even though their Leader role has global update/delete rights.

Steps to Reproduce

  1. Create Team X with no permissions.
  2. Create Leader with all book permissions (view, update, delete, own and all).
  3. Assign both Team X and Leader to a user.
  4. Create a book.
  5. In the book’s permissions, add Team X assign "View" permission to it, and set "Everyone else" set to Inherit defaults.

Expected Behaviour

  • Users with Team X role have access to the book but cannot update or delete it. (this works ✔️)
  • Users with both Team X and Leader roles can update and delete because having the Team X role should not restrict Leader's permissions. (this is not the case )

Screenshots or Additional Context

I want to be able to create a role for every team, which I explicitly grant View access to a specific shelf or book, and I want to have a single Leader role that has global Update and Delete permissions, which combined with the first role will let them both view content and edit that specific shelf/book. Currently this is not possible without explicitly adding both roles to every shelf/book.

Browser Details

Irrelevant

Exact BookStack Version

v24.12.1

Originally created by @rozdun on GitHub (Jun 23, 2025). ### Describe the Bug If a user has two roles - e.g. **Team X** (no permissions) and **Leader** (full access - view, create, etc), and content (e.g. a book) overrides **Team X** by giving it View permission and nothing else, the user is **blocked from editing**, even though their **Leader** role has global update/delete rights. ### Steps to Reproduce 1. Create **Team X** with no permissions. 2. Create **Leader** with all book permissions (view, update, delete, own and all). 3. Assign both **Team X** and **Leader** to a user. 4. Create a book. 5. In the book’s permissions, add **Team X** assign "View" permission to it, and set "Everyone else" set to **Inherit defaults**. ### Expected Behaviour - Users with **Team X** role have access to the book but cannot update or delete it. (this works ✔️) - Users with both **Team X** and **Leader** roles can update and delete because having the **Team X** role should not restrict **Leader**'s permissions. (this is not the case ❌) ### Screenshots or Additional Context I want to be able to create a role for every team, which I explicitly grant View access to a specific shelf or book, and I want to have a single **Leader** role that has global Update and Delete permissions, which combined with the first role will let them both view content and edit that specific shelf/book. Currently this is not possible without explicitly adding both roles to every shelf/book. ### Browser Details Irrelevant ### Exact BookStack Version v24.12.1
OVERLORD added the 🐕 Support label 2026-02-05 09:57:47 +03:00
Author
Owner

@ssddanbrown commented on GitHub (Jun 23, 2025):

Hi @rozdun,
That's the expected behaviour, since by setting those specific permissions for the "Team X" roles without edit enabled, that's specifically deny that ability to that role, which will override any role level permissions.

Currently this is not possible without explicitly adding both roles to every shelf/book.

If it is to every book, then you might be better off to avoid adding leaders to the team roles since it sounds like they have different permission requirements in your scenario, but that's all specific to the scenario/context.
Otherwise, yeah, you'll need to also specifically grant the permissions back to the leaders role.

@ssddanbrown commented on GitHub (Jun 23, 2025): Hi @rozdun, That's the expected behaviour, since by setting those specific permissions for the "Team X" roles without `edit` enabled, that's specifically deny that ability to that role, which will override any role level permissions. > Currently this is not possible without explicitly adding both roles to every shelf/book. If it is to every book, then you might be better off to avoid adding leaders to the team roles since it sounds like they have different permission requirements in your scenario, but that's all specific to the scenario/context. Otherwise, yeah, you'll need to also specifically grant the permissions back to the leaders role.
Author
Owner

@rozdun commented on GitHub (Jun 23, 2025):

Hi @ssddanbrown, thanks for a quick response.

That's the expected behaviour, since by setting those specific permissions for the "Team X" roles without edit enabled, that's specifically deny that ability to that role, which will override any role level permissions.

Well to be slightly pedantic here, I add a view permission and the system does not give me the ability to pull the other permissions from the role level, leaving me with having to disable them. I have very limited options as a user there.

If it is to every book, then you might be better off to avoid adding leaders to the team roles since it sounds like they have different permission requirements in your scenario, but that's all specific to the scenario/context.

But how can I have, say, 20 different books, each with users who can either only view or view and edit, without creating 40 roles (20 for Team X, 20 for Team X Leader) and adding both roles for each shelf explicitly? To me, 20 "view access" roles + 1 "global edit" role feels like a natural option here, and the interface suggests it should work this way:

"Everyone Else
Set permissions for all roles not specifically overridden."

To me, this says "set permissions based on roles added explicitly above, THEN add permissions based on any other roles you might have".
Whereas the current design is "set permissions based on roles added explicitly above, then ignore any permissions you may have from other roles", which is incredibly unintuitive.

A global role granting full access should not be negated by a restricted role unless the restriction is explicitly set for that role on the same content.

@rozdun commented on GitHub (Jun 23, 2025): Hi @ssddanbrown, thanks for a quick response. > That's the expected behaviour, since by setting those specific permissions for the "Team X" roles without edit enabled, that's specifically deny that ability to that role, which will override any role level permissions. Well to be slightly pedantic here, I add a view permission and the system does not give me the ability to pull the other permissions from the role level, leaving me with having to disable them. I have very limited options as a user there. > If it is to every book, then you might be better off to avoid adding leaders to the team roles since it sounds like they have different permission requirements in your scenario, but that's all specific to the scenario/context. But how can I have, say, 20 different books, each with users who can either **only view** or **view and edit**, without creating 40 roles (20 for Team X, 20 for Team X Leader) and adding both roles for each shelf explicitly? To me, 20 "view access" roles + 1 "global edit" role feels like a natural option here, and the interface suggests it _should_ work this way: > _"Everyone Else Set permissions for all roles not specifically overridden."_ To me, this says "set permissions based on roles added explicitly above, THEN add permissions based on any other roles you might have". Whereas the current design is "set permissions based on roles added explicitly above, then **ignore** any permissions you may have from other roles", which is incredibly unintuitive. A global role granting full access should not be negated by a restricted role unless the restriction is explicitly set for that role on the same content.
Author
Owner

@rozdun commented on GitHub (Jun 23, 2025):

Correction on one point:

But how can I have, say, 20 different books, each with users who can either only view or view and edit, without creating 40 roles (20 for Team X, 20 for Team X Leader) and adding both roles for each shelf explicitly? To me, 20 "view access" roles + 1 "global edit" role feels like a natural option here, and the interface suggests it should work this way:

What’s actually possible is assigning 20 "view access" roles plus 1 "global edit" role, but both roles must be explicitly added to each book’s permissions.

For example:
– Team X → View only
– Leader → Edit and delete (relies on Team X for view)

The edit role doesn't inherit unless it's also added, which defeats the purpose of a global role.

@rozdun commented on GitHub (Jun 23, 2025): Correction on one point: > But how can I have, say, 20 different books, each with users who can either **only view** or **view and edit**, without creating 40 roles (20 for Team X, 20 for Team X Leader) and adding both roles for each shelf explicitly? To me, 20 "view access" roles + 1 "global edit" role feels like a natural option here, and the interface suggests it _should_ work this way: What’s actually possible is assigning 20 "view access" roles plus 1 "global edit" role, but both roles must be explicitly added to each book’s permissions. For example: – Team X → View only – Leader → Edit and delete (relies on Team X for view) The edit role doesn't inherit unless it's also added, which defeats the purpose of a global role.
Author
Owner

@ssddanbrown commented on GitHub (Jun 23, 2025):

Whereas the current design is "set permissions based on roles added explicitly above, then ignore any permissions you may have from other roles", which is incredibly unintuitive.

They are not ignored (unless inheritance is disabled via everyone else), it's just that the lack of edit permission set for their role is more specific/focused so overrides their globally set permissions.

A global role granting full access should not be negated by a restricted role unless the restriction is explicitly set for that role on the same content.

This all comes down to expectations, which depend on your desired approach to permissions & context.
If we changed to your desired logic, then I'll have other folks complaining that they're not able to specifically deny permissions for a role due to them inheriting grants from other role-level defaults.

We could add tri-state permissions (Enable/Deny/Default, where default would allow inheritance from wider permission levels) but I'm hesitant to add much extra complexity to an already complex system.

@ssddanbrown commented on GitHub (Jun 23, 2025): > Whereas the current design is "set permissions based on roles added explicitly above, then ignore any permissions you may have from other roles", which is incredibly unintuitive. They are not ignored (unless inheritance is disabled via everyone else), it's just that the lack of edit permission set for their role is more specific/focused so overrides their globally set permissions. > A global role granting full access should not be negated by a restricted role unless the restriction is explicitly set for that role on the same content. This all comes down to expectations, which depend on your desired approach to permissions & context. If we changed to your desired logic, then I'll have other folks complaining that they're not able to specifically deny permissions for a role due to them inheriting grants from other role-level defaults. We could add tri-state permissions (Enable/Deny/Default, where default would allow inheritance from wider permission levels) but I'm hesitant to add much extra complexity to an already complex system.
Author
Owner

@rozdun commented on GitHub (Jun 23, 2025):

They are not ignored (unless inheritance is disabled via everyone else), it's just that the lack of edit permission set for their role is more specific/focused so overrides their globally set permissions.

From a user perspective, they are ignored. A single scoped role with limited permissions cancels all broader grants, rendering global roles ineffective unless redundantly re-applied at every content node. This breaks the premise of inheritance and defeats the purpose of centralized role design.

This all comes down to expectations, which depend on your desired approach to permissions & context.
If we changed to your desired logic, then I'll have other folks complaining that they're not able to specifically deny permissions for a role due to them inheriting grants from other role-level defaults.

I'd hazard a guess that most real-world scenarios prioritize granting access to regular users over restricting access to superusers, hence why what I described feels to me like the proper default, and it aligns with standard additive RBAC expectations.

Nevertheless, Enable/Deny/Default would indeed solve both cases and it is very much worth adding.
BookStack already has more granular options than many other solutions, and either people need it (like my group) or they don't, in which case BookStack would already be too complex for them anyway. A power user (which an administrator should be) will instantly understand how this works because it's not a new concept (e.g. Discord).

Image

@rozdun commented on GitHub (Jun 23, 2025): > They are not ignored (unless inheritance is disabled via everyone else), it's just that the lack of edit permission set for their role is more specific/focused so overrides their globally set permissions. From a user perspective, they _are_ ignored. A single scoped role with limited permissions cancels all broader grants, rendering global roles ineffective unless redundantly re-applied at every content node. This breaks the premise of inheritance and defeats the purpose of centralized role design. > This all comes down to expectations, which depend on your desired approach to permissions & context. If we changed to your desired logic, then I'll have other folks complaining that they're not able to specifically deny permissions for a role due to them inheriting grants from other role-level defaults. I'd hazard a guess that most real-world scenarios prioritize granting access to regular users over restricting access to superusers, hence why what I described feels to me like the proper default, and it aligns with standard additive RBAC expectations. Nevertheless, **Enable/Deny/Default would indeed solve both cases and it is very much worth adding**. BookStack already has more granular options than many other solutions, and either people need it (like my group) or they don't, in which case BookStack would _already_ be too complex for them anyway. A power user (which an administrator should be) will instantly understand how this works because it's not a new concept (e.g. Discord). ![Image](https://github.com/user-attachments/assets/c38630d5-c67a-416c-9bfa-ffeff2491a38)
Author
Owner

@ssddanbrown commented on GitHub (Jun 23, 2025):

Okay. I'll go ahead and close this off since I wouldn't look to change the default functionality/logic as originally requested but feel free to open a feature request for the tri-state content-level permission control, so it can gather support for potential future consideration.

@ssddanbrown commented on GitHub (Jun 23, 2025): Okay. I'll go ahead and close this off since I wouldn't look to change the default functionality/logic as originally requested but feel free to open a feature request for the tri-state content-level permission control, so it can gather support for potential future consideration.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/BookStack#5324