Skip to content

feat(provisioning_api): OCS endpoints for nested groups and group sub-admins#59862

Draft
KiaraGrouwstra wants to merge 39 commits intonextcloud:masterfrom
KiaraGrouwstra:recursive-groups-4
Draft

feat(provisioning_api): OCS endpoints for nested groups and group sub-admins#59862
KiaraGrouwstra wants to merge 39 commits intonextcloud:masterfrom
KiaraGrouwstra:recursive-groups-4

Conversation

@KiaraGrouwstra
Copy link
Copy Markdown

@KiaraGrouwstra KiaraGrouwstra commented Apr 22, 2026

Adds OCS REST endpoints for managing nested groups and group-level sub-admin delegation.

Part 4 of a series implementing #36150. Builds on PRs:

OCS endpoints

Additive routes under cloud/groups/{groupId}:

Method Path Body
GET /subgroups
POST /subgroups {subGroupId}
DELETE /subgroups/{subGroupId}
GET /subadmins/groups
POST /subadmins/groups {adminGroupId}
DELETE /subadmins/groups/{adminGroupId}

All require the Users admin delegation. CycleDetectedException and NestedGroupsNotSupportedException are surfaced as typed OCS errors. OpenAPI spec regenerated.

Test plan

  • OpenAPI spec validates.
  • Manual: endpoints respond correctly for add/remove/list operations and return appropriate errors for cycles and missing groups.

Checklist

AI (if applicable)

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

dependabot Bot and others added 30 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
Signed-off-by: Côme Chilliet <come.chilliet@nextcloud.com>
AI-assisted: OpenCode (gpt-5.4)

Signed-off-by: Daniel Kesselberg <mail@danielkesselberg.de>
…sword-required

fix: Add missing PasswordConfirmationRequired attributes
…t user

Signed-off-by: Robin Appelman <robin@icewind.nl>
Signed-off-by: Robin Appelman <robin@icewind.nl>
Signed-off-by: Robin Appelman <robin@icewind.nl>
Signed-off-by: Robin Appelman <robin@icewind.nl>
…user

fix(encryption): limit oprhaned keys scan to one user
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
Signed-off-by: GitHub <noreply@github.com>
…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>
susnux and others added 9 commits April 22, 2026 15:06
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
…rvice

fix(ImipService): Refactor `IMipService` to improve performance
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.