Skip to content

feat(settings): admin UI for managing nested groups#59593

Draft
KiaraGrouwstra wants to merge 40 commits into
nextcloud:masterfrom
KiaraGrouwstra:recursive-groups
Draft

feat(settings): admin UI for managing nested groups#59593
KiaraGrouwstra wants to merge 40 commits into
nextcloud:masterfrom
KiaraGrouwstra:recursive-groups

Conversation

@KiaraGrouwstra
Copy link
Copy Markdown

@KiaraGrouwstra KiaraGrouwstra commented Apr 11, 2026

Adds an admin UI for managing nested groups and group-level sub-admin delegation.

Part 5 (final) of a series implementing #36150. Builds on PRs:

What is in this PR

  • GroupNestingModal.vue -- new modal reachable from each row in the groups list via a "Manage nested groups" action. Uses NcSelect pickers backed by the existing searchGroups service to add or remove subgroups and admin groups, excluding self and already-added entries from autocomplete.
  • GroupListItem.vue -- added FamilyTree icon and "Manage nested groups" action button.
  • apps/settings/src/store/users.js -- store actions wrapping the OCS endpoints: fetchSubGroups / addSubGroup / removeSubGroup, fetchGroupSubAdmins / addGroupSubAdmin / removeGroupSubAdmin.
  • Compiled bundle included.

Screenshots

User set-up (dave is member of no groups, so cannot be managed via inherited group sub-admin status):

Screenshot from 2026-04-11 22-16-46

Adding group associations:

Screenshot from 2026-04-11 16-48-09 Screenshot from 2026-04-11 16-52-44 Screenshot from 2026-04-11 21-15-58

Files shared through groups the users are effectively members of:

Screenshot from 2026-04-11 22-07-10

Managing users of groups the user is effectively a sub-admin of:

Screenshot from 2026-04-11 22-26-06

Test plan

  • Manual: "Manage nested groups" action appears in group list, modal opens and shows subgroups/admin groups.
  • Manual: picker autocomplete excludes self and already-added entries.
  • Manual: add/remove subgroups and admin groups via the modal, verify success/error toasts.
  • Manual: bob shared a file with engineering; alice (member of backend, nested under engineering) received it; dave (ungrouped) did not.
  • Manual: designated managers as admin group of engineering; carol gained sub-admin rights over engineering, backend and frontend.

Checklist

AI (if applicable)

  • The content of this PR was partly or fully generated using AI

@miaulalala
Copy link
Copy Markdown
Contributor

Thanks a lot for ypur PR! Can you please split it into separate PRs for each area of concern? It's fine if the PRs branch off a previous PR, but to make it easier to review, smaller change sets are preferred. If you need any help or have any questions, join us at https://cloud.nextcloud.com/call/xs25tz5y - our community dev chat.

@szaimen szaimen removed their request for review April 13, 2026 21:20
dependabot Bot and others added 13 commits April 20, 2026 20:49
Bumps the github-actions group with 8 updates:

| Package | From | To |
| --- | --- | --- |
| [dorny/paths-filter](https://github.com/dorny/paths-filter) | `3.0.2` | `4.0.1` |
| [actions/github-script](https://github.com/actions/github-script) | `8.0.0` | `9.0.0` |
| [github/codeql-action](https://github.com/github/codeql-action) | `4.35.1` | `4.35.2` |
| [actions/setup-node](https://github.com/actions/setup-node) | `6.3.0` | `6.4.0` |
| [andstor/file-existence-action](https://github.com/andstor/file-existence-action) | `3.0.0` | `3.1.0` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.0` | `7.0.1` |
| [LizardByte/actions](https://github.com/lizardbyte/actions) | `2026.328.161128` | `2026.417.35446` |
| [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) | `8.1.0` | `8.1.1` |


Updates `dorny/paths-filter` from 3.0.2 to 4.0.1
- [Release notes](https://github.com/dorny/paths-filter/releases)
- [Changelog](https://github.com/dorny/paths-filter/blob/master/CHANGELOG.md)
- [Commits](dorny/paths-filter@v3.0.2...fbd0ab8)

Updates `actions/github-script` from 8.0.0 to 9.0.0
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](actions/github-script@ed59741...3a2844b)

Updates `github/codeql-action` from 4.35.1 to 4.35.2
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](github/codeql-action@c10b806...95e58e9)

Updates `actions/setup-node` from 6.3.0 to 6.4.0
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](actions/setup-node@53b8394...48b55a0)

Updates `andstor/file-existence-action` from 3.0.0 to 3.1.0
- [Release notes](https://github.com/andstor/file-existence-action/releases)
- [Commits](andstor/file-existence-action@076e007...558493d)

Updates `actions/upload-artifact` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@bbbca2d...043fb46)

Updates `LizardByte/actions` from 2026.328.161128 to 2026.417.35446
- [Release notes](https://github.com/lizardbyte/actions/releases)
- [Commits](LizardByte/actions@0affa4f...4125866)

Updates `peter-evans/create-pull-request` from 8.1.0 to 8.1.1
- [Release notes](https://github.com/peter-evans/create-pull-request/releases)
- [Commits](peter-evans/create-pull-request@c0f553f...5f6978f)

---
updated-dependencies:
- dependency-name: dorny/paths-filter
  dependency-version: 4.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: actions/github-script
  dependency-version: 9.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: github/codeql-action
  dependency-version: 4.35.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: actions/setup-node
  dependency-version: 6.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: andstor/file-existence-action
  dependency-version: 3.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: LizardByte/actions
  dependency-version: 2026.417.35446
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: peter-evans/create-pull-request
  dependency-version: 8.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion) from 2.0.2 to 2.0.3.
- [Release notes](https://github.com/juliangruber/brace-expansion/releases)
- [Commits](juliangruber/brace-expansion@v2.0.2...v2.0.3)

---
updated-dependencies:
- dependency-name: brace-expansion
  dependency-version: 2.0.3
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
…ctions

Register axios password confirmation interceptors in the apps
management, admin delegation, admin security, and OAuth2 settings
bundles, and pass PwdConfirmationMode.Strict on requests to endpoints
protected with #[PasswordConfirmationRequired(strict: true)], so that
the user password is verified via Basic auth on the request itself
rather than relying on the session timestamp.

Signed-off-by: Peter Ringelmann <peter.ringelmann@nextcloud.com>
Signed-off-by: nextcloud-command <nextcloud-command@users.noreply.github.com>
…-token-handling

fix: Reduce the mixups between apptokens and session ids
Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
Signed-off-by: Hamza <hamzamahjoubi221@gmail.com>
…ctions/github-actions-d76c8db3f9

chore(deps): Bump the github-actions group with 8 updates
…yarn/build/frontend-legacy/brace-expansion-2.0.3

chore(deps): Bump brace-expansion from 2.0.2 to 2.0.3 in /build/frontend-legacy
nickvergessen and others added 11 commits April 22, 2026 06:53
…er-update-code-signing-crl

[master] fix(security): Update code signing revocation list
Signed-off-by: Kent Delante <kent@delante.me>

Amazon's hosted S3 service allows repeating delimiters in keys
(e.g. 'path/to//file.txt' or 'path/to///file.txt') and we get
repeating directories in the filecache as a result (based on the
previous examples we get 'path/to/to/file.txt' or
'path/to/to/to/file.txt'). This ignores it and its contents for S3 external storage.
…limiter

fix(s3): ignore prefixes with repeating delimiters
…fined-array-key-sharing-request

Avoid undefined array key sharing request
…ds are not

Signed-off-by: David Dreschner <david.dreschner@nextcloud.com>
Signed-off-by: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
…rvice

fix(ImipService): Refactor `IMipService` to improve performance
@KiaraGrouwstra KiaraGrouwstra force-pushed the recursive-groups branch 2 times, most recently from bc10ef0 to bce1358 Compare April 22, 2026 17:28
@KiaraGrouwstra KiaraGrouwstra marked this pull request as draft April 22, 2026 17:50
Add a group_group edge table maintained by OC\Group\Database, an
internal INestedGroupBackend capability interface, and BFS-based
transitive closure in OC\Group\Manager with per-request memoization
and batched backend queries.

Public API gains getUserEffectiveGroupIds, addSubGroup/removeSubGroup,
getDirectChildGroupIds/getDirectParentGroupIds, and
getGroupEffectiveDescendantIds/getGroupEffectiveAncestorIds.
Cycles are rejected inside a serialized transaction.
SubGroupAdded/SubGroupRemovedEvent are dispatched along with per-user
UserAdded/UserRemovedEvent (bounded by MAX_SYNTHESIZED_USER_EVENTS) so
listeners such as apps/encryption stay consistent when nesting shifts
the effective recipient set of a group share.

See lib/private/Group/NESTED_GROUPS.md for caveats (encryption
re-keying cap, LDAP enumeration cost, delete-middle-group semantics).

Refs nextcloud#36150.

Signed-off-by: Kiara Grouwstra <cinereal@riseup.net>
A group can now be designated as sub-admin of another group via a
new group_group_admin(admin_gid, gid) table: every effective member
of admin_gid is treated as a sub-admin of gid and, by ancestry, of
all of its subgroups. Direct sub-admins of a parent group inherit
admin rights over every descendant.

isSubAdminOfGroup resolves the target's ancestor set via
getGroupEffectiveAncestorIds and checks both group_admin and
group_group_admin against that set, so rights propagate without
reimplementing Manager's BFS.

Adds createGroupSubAdmin / deleteGroupSubAdmin /
getGroupSubAdminsOfGroup on OCP\Group\ISubAdmin.

Refs nextcloud#36150.

Signed-off-by: Kiara Grouwstra <cinereal@riseup.net>
Migrate Share20, AppManager, SystemTagManager, AuthorizedGroupMapper,
ShareDisableChecker, and MandatoryTwoFactor to resolve group
membership via getUserEffectiveGroupIds so nested-group edges flow
through to share ACLs, app restrictions, tag visibility, settings
delegation, and 2FA enforcement.

MandatoryTwoFactor deliberately keeps the *excluded* groups list on
direct membership: expanding it transitively would let an admin
silently exempt an arbitrary population from 2FA by nesting groups
under an excluded one, a one-way security weakening. Enforced groups
are expanded (strictly more secure).

Refs nextcloud#36150.

Signed-off-by: Kiara Grouwstra <cinereal@riseup.net>
…-admins

Additive routes under cloud/groups/{groupId}:

- GET/POST/DELETE subgroups
- GET/POST/DELETE subadmins/groups

All require the Users admin delegation. Cycle and
unsupported-backend cases are surfaced as typed HTTP errors.

OpenAPI spec regenerated.

Signed-off-by: Kiara Grouwstra <cinereal@riseup.net>
Add a GroupNestingModal reachable from each row in the groups list
via a new "Manage nested groups" action. The modal uses NcSelect
pickers backed by the existing searchGroups service to add or remove
subgroups and admin groups, excluding self and already-added entries
from autocomplete.

Store actions fetchSubGroups / addSubGroup / removeSubGroup and
fetchGroupSubAdmins / addGroupSubAdmin / removeGroupSubAdmin wrap
the new OCS endpoints.

Signed-off-by: Kiara Grouwstra <cinereal@riseup.net>
@KiaraGrouwstra KiaraGrouwstra changed the title recursive groups: allow groups to be member or admin of other groups feat(settings): admin UI for managing nested groups Apr 22, 2026
@KiaraGrouwstra
Copy link
Copy Markdown
Author

@miaulalala:

Can you please split it into separate PRs for each area of concern? It's fine if the PRs branch off a previous PR, but to make it easier to review, smaller change sets are preferred.

Thanks! I've split it up now, for now marking the PRs adding on unmerged ones as draft.

@github-actions
Copy link
Copy Markdown
Contributor

Hello there,
Thank you so much for taking the time and effort to create a pull request to our Nextcloud project.

We hope that the review process is going smooth and is helpful for you. We want to ensure your pull request is reviewed to your satisfaction. If you have a moment, our community management team would very much appreciate your feedback on your experience with this PR review process.

Your feedback is valuable to us as we continuously strive to improve our community developer experience. Please take a moment to complete our short survey by clicking on the following link: https://cloud.nextcloud.com/apps/forms/s/i9Ago4EQRZ7TWxjfmeEpPkf6

Thank you for contributing to Nextcloud and we hope to hear from you soon!

(If you believe you should not receive this message, you can add yourself to the blocklist.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.