aboutsummaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorLouis Chemineau <louis@chmn.me>2024-07-11 12:09:39 +0200
committerLouis Chemineau <louis@chmn.me>2024-07-22 17:17:35 +0200
commitdff881544920f426b984f91b7bc8dece1f351342 (patch)
tree9ebce4597dad2cd0fe817257f76348f28805c2ba /apps
parent1af827fdb39dd182743853e17cf5493a8b4637d2 (diff)
downloadnextcloud-server-dff881544920f426b984f91b7bc8dece1f351342.tar.gz
nextcloud-server-dff881544920f426b984f91b7bc8dece1f351342.zip
feat(users): Add support for admin delegation for users and groups management
Signed-off-by: Louis Chemineau <louis@chmn.me>
Diffstat (limited to 'apps')
-rw-r--r--apps/provisioning_api/lib/Controller/AUserData.php4
-rw-r--r--apps/provisioning_api/lib/Controller/GroupsController.php15
-rw-r--r--apps/provisioning_api/lib/Controller/UsersController.php77
-rw-r--r--apps/settings/appinfo/info.xml1
-rw-r--r--apps/settings/composer/composer/autoload_classmap.php1
-rw-r--r--apps/settings/composer/composer/autoload_static.php1
-rw-r--r--apps/settings/lib/Controller/UsersController.php10
-rw-r--r--apps/settings/lib/Settings/Admin/Users.php61
8 files changed, 143 insertions, 27 deletions
diff --git a/apps/provisioning_api/lib/Controller/AUserData.php b/apps/provisioning_api/lib/Controller/AUserData.php
index d7db48dc33f..1b8e759bcce 100644
--- a/apps/provisioning_api/lib/Controller/AUserData.php
+++ b/apps/provisioning_api/lib/Controller/AUserData.php
@@ -98,7 +98,9 @@ abstract class AUserData extends OCSController {
}
$isAdmin = $this->groupManager->isAdmin($currentLoggedInUser->getUID());
+ $isDelegatedAdmin = $this->groupManager->isDelegatedAdmin($currentLoggedInUser->getUID());
if ($isAdmin
+ || $isDelegatedAdmin
|| $this->groupManager->getSubAdmin()->isUserAccessible($currentLoggedInUser, $targetUserObject)) {
$data['enabled'] = $this->config->getUserValue($targetUserObject->getUID(), 'core', 'enabled', 'true') === 'true';
} else {
@@ -116,7 +118,7 @@ abstract class AUserData extends OCSController {
$gids[] = $group->getGID();
}
- if ($isAdmin) {
+ if ($isAdmin || $isDelegatedAdmin) {
try {
# might be thrown by LDAP due to handling of users disappears
# from the external source (reasons unknown to us)
diff --git a/apps/provisioning_api/lib/Controller/GroupsController.php b/apps/provisioning_api/lib/Controller/GroupsController.php
index 9320fe13aaa..97480058fd1 100644
--- a/apps/provisioning_api/lib/Controller/GroupsController.php
+++ b/apps/provisioning_api/lib/Controller/GroupsController.php
@@ -9,8 +9,10 @@ declare(strict_types=1);
namespace OCA\Provisioning_API\Controller;
use OCA\Provisioning_API\ResponseDefinitions;
+use OCA\Settings\Settings\Admin\Users;
use OCP\Accounts\IAccountManager;
use OCP\AppFramework\Http;
+use OCP\AppFramework\Http\Attribute\AuthorizedAdminSetting;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCS\OCSException;
use OCP\AppFramework\OCS\OCSForbiddenException;
@@ -154,8 +156,9 @@ class GroupsController extends AUserData {
}
// Check subadmin has access to this group
- if ($this->groupManager->isAdmin($user->getUID())
- || $isSubadminOfGroup) {
+ $isAdmin = $this->groupManager->isAdmin($user->getUID());
+ $isDelegatedAdmin = $this->groupManager->isDelegatedAdmin($user->getUID());
+ if ($isAdmin || $isDelegatedAdmin || $isSubadminOfGroup) {
$users = $this->groupManager->get($groupId)->getUsers();
$users = array_map(function ($user) {
/** @var IUser $user */
@@ -197,7 +200,9 @@ class GroupsController extends AUserData {
}
// Check subadmin has access to this group
- if ($this->groupManager->isAdmin($currentUser->getUID()) || $isSubadminOfGroup) {
+ $isAdmin = $this->groupManager->isAdmin($currentUser->getUID());
+ $isDelegatedAdmin = $this->groupManager->isDelegatedAdmin($currentUser->getUID());
+ if ($isAdmin || $isDelegatedAdmin || $isSubadminOfGroup) {
$users = $group->searchUsers($search, $limit, $offset);
// Extract required number
@@ -237,6 +242,7 @@ class GroupsController extends AUserData {
*
* 200: Group created successfully
*/
+ #[AuthorizedAdminSetting(settings:Users::class)]
public function addGroup(string $groupid, string $displayname = ''): DataResponse {
// Validate name
if (empty($groupid)) {
@@ -270,6 +276,7 @@ class GroupsController extends AUserData {
*
* 200: Group updated successfully
*/
+ #[AuthorizedAdminSetting(settings:Users::class)]
public function updateGroup(string $groupId, string $key, string $value): DataResponse {
$groupId = urldecode($groupId);
@@ -299,6 +306,7 @@ class GroupsController extends AUserData {
*
* 200: Group deleted successfully
*/
+ #[AuthorizedAdminSetting(settings:Users::class)]
public function deleteGroup(string $groupId): DataResponse {
$groupId = urldecode($groupId);
@@ -322,6 +330,7 @@ class GroupsController extends AUserData {
*
* 200: Sub admins returned
*/
+ #[AuthorizedAdminSetting(settings:Users::class)]
public function getSubAdminsOfGroup(string $groupId): DataResponse {
// Check group exists
$targetGroup = $this->groupManager->get($groupId);
diff --git a/apps/provisioning_api/lib/Controller/UsersController.php b/apps/provisioning_api/lib/Controller/UsersController.php
index 1cdc1392596..a6bb2330390 100644
--- a/apps/provisioning_api/lib/Controller/UsersController.php
+++ b/apps/provisioning_api/lib/Controller/UsersController.php
@@ -16,10 +16,12 @@ use OC\KnownUser\KnownUserService;
use OC\User\Backend;
use OCA\Provisioning_API\ResponseDefinitions;
use OCA\Settings\Mailer\NewUserMailHelper;
+use OCA\Settings\Settings\Admin\Users;
use OCP\Accounts\IAccountManager;
use OCP\Accounts\IAccountProperty;
use OCP\Accounts\PropertyDoesNotExistException;
use OCP\AppFramework\Http;
+use OCP\AppFramework\Http\Attribute\AuthorizedAdminSetting;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCS\OCSException;
use OCP\AppFramework\OCS\OCSForbiddenException;
@@ -101,7 +103,9 @@ class UsersController extends AUserData {
// Admin? Or SubAdmin?
$uid = $user->getUID();
$subAdminManager = $this->groupManager->getSubAdmin();
- if ($this->groupManager->isAdmin($uid)) {
+ $isAdmin = $this->groupManager->isAdmin($uid);
+ $isDelegatedAdmin = $this->groupManager->isDelegatedAdmin($uid);
+ if ($isAdmin || $isDelegatedAdmin) {
$users = $this->userManager->search($search, $limit, $offset);
} elseif ($subAdminManager->isSubAdmin($user)) {
$subAdminOfGroups = $subAdminManager->getSubAdminsGroups($user);
@@ -142,7 +146,9 @@ class UsersController extends AUserData {
// Admin? Or SubAdmin?
$uid = $currentUser->getUID();
$subAdminManager = $this->groupManager->getSubAdmin();
- if ($this->groupManager->isAdmin($uid)) {
+ $isAdmin = $this->groupManager->isAdmin($uid);
+ $isDelegatedAdmin = $this->groupManager->isDelegatedAdmin($uid);
+ if ($isAdmin || $isDelegatedAdmin) {
$users = $this->userManager->search($search, $limit, $offset);
$users = array_keys($users);
} elseif ($subAdminManager->isSubAdmin($currentUser)) {
@@ -213,7 +219,9 @@ class UsersController extends AUserData {
// Admin? Or SubAdmin?
$uid = $currentUser->getUID();
$subAdminManager = $this->groupManager->getSubAdmin();
- if ($this->groupManager->isAdmin($uid)) {
+ $isAdmin = $this->groupManager->isAdmin($uid);
+ $isDelegatedAdmin = $this->groupManager->isDelegatedAdmin($uid);
+ if ($isAdmin || $isDelegatedAdmin) {
$users = $this->userManager->getDisabledUsers($limit, $offset, $search);
$users = array_map(fn (IUser $user): string => $user->getUID(), $users);
} elseif ($subAdminManager->isSubAdmin($currentUser)) {
@@ -275,6 +283,7 @@ class UsersController extends AUserData {
*
* 200: Users details returned based on last logged in information
*/
+ #[AuthorizedAdminSetting(settings:Users::class)]
public function getLastLoggedInUsers(string $search = '',
?int $limit = null,
int $offset = 0,
@@ -447,6 +456,7 @@ class UsersController extends AUserData {
): DataResponse {
$user = $this->userSession->getUser();
$isAdmin = $this->groupManager->isAdmin($user->getUID());
+ $isDelegatedAdmin = $this->groupManager->isDelegatedAdmin($user->getUID());
$subAdminManager = $this->groupManager->getSubAdmin();
if (empty($userid) && $this->config->getAppValue('core', 'newUser.generateUserID', 'no') === 'yes') {
@@ -463,12 +473,12 @@ class UsersController extends AUserData {
if (!$this->groupManager->groupExists($group)) {
throw new OCSException($this->l10n->t('Group %1$s does not exist', [$group]), 104);
}
- if (!$isAdmin && !$subAdminManager->isSubAdminOfGroup($user, $this->groupManager->get($group))) {
+ if (!$isAdmin && !($isDelegatedAdmin && $group !== 'admin') && !$subAdminManager->isSubAdminOfGroup($user, $this->groupManager->get($group))) {
throw new OCSException($this->l10n->t('Insufficient privileges for group %1$s', [$group]), 105);
}
}
} else {
- if (!$isAdmin) {
+ if (!$isAdmin && !$isDelegatedAdmin) {
throw new OCSException($this->l10n->t('No group specified (required for sub-admins)'), 106);
}
}
@@ -486,7 +496,7 @@ class UsersController extends AUserData {
throw new OCSException($this->l10n->t('Cannot create sub-admins for admin group'), 103);
}
// Check if has permission to promote subadmins
- if (!$subAdminManager->isSubAdminOfGroup($user, $group) && !$isAdmin) {
+ if (!$subAdminManager->isSubAdminOfGroup($user, $group) && !$isAdmin && !$isDelegatedAdmin) {
throw new OCSForbiddenException($this->l10n->t('No permissions to promote sub-admins'));
}
$subadminGroups[] = $group;
@@ -718,8 +728,10 @@ class UsersController extends AUserData {
}
$subAdminManager = $this->groupManager->getSubAdmin();
+ $isAdmin = $this->groupManager->isAdmin($currentLoggedInUser->getUID());
+ $isDelegatedAdmin = $this->groupManager->isDelegatedAdmin($currentLoggedInUser->getUID());
if (
- !$this->groupManager->isAdmin($currentLoggedInUser->getUID())
+ !($isAdmin || $isDelegatedAdmin)
&& !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)
) {
throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
@@ -788,6 +800,7 @@ class UsersController extends AUserData {
}
$subAdminManager = $this->groupManager->getSubAdmin();
+ $isDelegatedAdmin = $this->groupManager->isDelegatedAdmin($currentLoggedInUser->getUID());
$isAdminOrSubadmin = $this->groupManager->isAdmin($currentLoggedInUser->getUID())
|| $subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser);
@@ -798,7 +811,7 @@ class UsersController extends AUserData {
$permittedFields[] = IAccountManager::COLLECTION_EMAIL . self::SCOPE_SUFFIX;
} else {
// Check if admin / subadmin
- if ($isAdminOrSubadmin) {
+ if ($isAdminOrSubadmin || $isDelegatedAdmin && !$this->groupManager->isInGroup($targetUser->getUID(), 'admin')) {
// They have permissions over the user
$permittedFields[] = IAccountManager::COLLECTION_EMAIL;
} else {
@@ -903,14 +916,16 @@ class UsersController extends AUserData {
$permittedFields[] = self::USER_FIELD_NOTIFICATION_EMAIL;
if (
$this->config->getSystemValue('force_language', false) === false ||
- $this->groupManager->isAdmin($currentLoggedInUser->getUID())
+ $this->groupManager->isAdmin($currentLoggedInUser->getUID()) ||
+ $this->groupManager->isDelegatedAdmin($currentLoggedInUser->getUID())
) {
$permittedFields[] = self::USER_FIELD_LANGUAGE;
}
if (
$this->config->getSystemValue('force_locale', false) === false ||
- $this->groupManager->isAdmin($currentLoggedInUser->getUID())
+ $this->groupManager->isAdmin($currentLoggedInUser->getUID()) ||
+ $this->groupManager->isDelegatedAdmin($currentLoggedInUser->getUID())
) {
$permittedFields[] = self::USER_FIELD_LOCALE;
}
@@ -941,7 +956,9 @@ class UsersController extends AUserData {
$permittedFields[] = IAccountManager::PROPERTY_AVATAR . self::SCOPE_SUFFIX;
// If admin they can edit their own quota and manager
- if ($this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
+ $isAdmin = $this->groupManager->isAdmin($currentLoggedInUser->getUID());
+ $isDelegatedAdmin = $this->groupManager->isDelegatedAdmin($currentLoggedInUser->getUID());
+ if ($isAdmin || $isDelegatedAdmin) {
$permittedFields[] = self::USER_FIELD_QUOTA;
$permittedFields[] = self::USER_FIELD_MANAGER;
}
@@ -949,7 +966,8 @@ class UsersController extends AUserData {
// Check if admin / subadmin
$subAdminManager = $this->groupManager->getSubAdmin();
if (
- $this->groupManager->isAdmin($currentLoggedInUser->getUID())
+ $this->groupManager->isAdmin($currentLoggedInUser->getUID()) ||
+ $this->groupManager->isDelegatedAdmin($currentLoggedInUser->getUID()) && !$this->groupManager->isInGroup($targetUser->getUID(), 'admin')
|| $subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)
) {
// They have permissions over the user
@@ -1204,7 +1222,9 @@ class UsersController extends AUserData {
// If not permitted
$subAdminManager = $this->groupManager->getSubAdmin();
- if (!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
+ $isAdmin = $this->groupManager->isAdmin($currentLoggedInUser->getUID());
+ $isDelegatedAdmin = $this->groupManager->isDelegatedAdmin($currentLoggedInUser->getUID());
+ if (!$isAdmin && !($isDelegatedAdmin && !$this->groupManager->isInGroup($targetUser->getUID(), 'admin')) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
}
@@ -1240,7 +1260,9 @@ class UsersController extends AUserData {
// If not permitted
$subAdminManager = $this->groupManager->getSubAdmin();
- if (!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
+ $isAdmin = $this->groupManager->isAdmin($currentLoggedInUser->getUID());
+ $isDelegatedAdmin = $this->groupManager->isDelegatedAdmin($currentLoggedInUser->getUID());
+ if (!$isAdmin && !($isDelegatedAdmin && !$this->groupManager->isInGroup($targetUser->getUID(), 'admin')) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
}
@@ -1300,7 +1322,9 @@ class UsersController extends AUserData {
// If not permitted
$subAdminManager = $this->groupManager->getSubAdmin();
- if (!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
+ $isAdmin = $this->groupManager->isAdmin($currentLoggedInUser->getUID());
+ $isDelegatedAdmin = $this->groupManager->isDelegatedAdmin($currentLoggedInUser->getUID());
+ if (!$isAdmin && !($isDelegatedAdmin && !$this->groupManager->isInGroup($targetUser->getUID(), 'admin')) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
}
@@ -1329,7 +1353,9 @@ class UsersController extends AUserData {
throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
}
- if ($targetUser->getUID() === $loggedInUser->getUID() || $this->groupManager->isAdmin($loggedInUser->getUID())) {
+ $isAdmin = $this->groupManager->isAdmin($loggedInUser->getUID());
+ $isDelegatedAdmin = $this->groupManager->isDelegatedAdmin($loggedInUser->getUID());
+ if ($targetUser->getUID() === $loggedInUser->getUID() || $isAdmin || $isDelegatedAdmin) {
// Self lookup or admin lookup
return new DataResponse([
'groups' => $this->groupManager->getUserGroupIds($targetUser)
@@ -1388,7 +1414,9 @@ class UsersController extends AUserData {
// If they're not an admin, check they are a subadmin of the group in question
$loggedInUser = $this->userSession->getUser();
$subAdminManager = $this->groupManager->getSubAdmin();
- if (!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) {
+ $isAdmin = $this->groupManager->isAdmin($loggedInUser->getUID());
+ $isDelegatedAdmin = $this->groupManager->isDelegatedAdmin($loggedInUser->getUID());
+ if (!$isAdmin && !($isDelegatedAdmin && $groupid !== 'admin') && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) {
throw new OCSException('', 104);
}
@@ -1429,13 +1457,15 @@ class UsersController extends AUserData {
// If they're not an admin, check they are a subadmin of the group in question
$subAdminManager = $this->groupManager->getSubAdmin();
- if (!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) {
+ $isAdmin = $this->groupManager->isAdmin($loggedInUser->getUID());
+ $isDelegatedAdmin = $this->groupManager->isDelegatedAdmin($loggedInUser->getUID());
+ if (!$isAdmin && !($isDelegatedAdmin && $groupid !== 'admin') && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) {
throw new OCSException('', 104);
}
// Check they aren't removing themselves from 'admin' or their 'subadmin; group
if ($targetUser->getUID() === $loggedInUser->getUID()) {
- if ($this->groupManager->isAdmin($loggedInUser->getUID())) {
+ if ($isAdmin || $isDelegatedAdmin) {
if ($group->getGID() === 'admin') {
throw new OCSException($this->l10n->t('Cannot remove yourself from the admin group'), 105);
}
@@ -1443,7 +1473,7 @@ class UsersController extends AUserData {
// Not an admin, so the user must be a subadmin of this group, but that is not allowed.
throw new OCSException($this->l10n->t('Cannot remove yourself from this group as you are a sub-admin'), 105);
}
- } elseif (!$this->groupManager->isAdmin($loggedInUser->getUID())) {
+ } elseif (!($isAdmin || $isDelegatedAdmin)) {
/** @var IGroup[] $subAdminGroups */
$subAdminGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
$subAdminGroups = array_map(function (IGroup $subAdminGroup) {
@@ -1475,6 +1505,7 @@ class UsersController extends AUserData {
*
* 200: User added as group subadmin successfully
*/
+ #[AuthorizedAdminSetting(settings:Users::class)]
public function addSubAdmin(string $userId, string $groupid): DataResponse {
$group = $this->groupManager->get($groupid);
$user = $this->userManager->get($userId);
@@ -1515,6 +1546,7 @@ class UsersController extends AUserData {
*
* 200: User removed as group subadmin successfully
*/
+ #[AuthorizedAdminSetting(settings:Users::class)]
public function removeSubAdmin(string $userId, string $groupid): DataResponse {
$group = $this->groupManager->get($groupid);
$user = $this->userManager->get($userId);
@@ -1547,6 +1579,7 @@ class UsersController extends AUserData {
*
* 200: User subadmin groups returned
*/
+ #[AuthorizedAdminSetting(settings:Users::class)]
public function getUserSubAdminGroups(string $userId): DataResponse {
$groups = $this->getUserSubAdminGroupsData($userId);
return new DataResponse($groups);
@@ -1574,9 +1607,11 @@ class UsersController extends AUserData {
// Check if admin / subadmin
$subAdminManager = $this->groupManager->getSubAdmin();
+ $isAdmin = $this->groupManager->isAdmin($currentLoggedInUser->getUID());
+ $isDelegatedAdmin = $this->groupManager->isDelegatedAdmin($currentLoggedInUser->getUID());
if (
!$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)
- && !$this->groupManager->isAdmin($currentLoggedInUser->getUID())
+ && !($isAdmin || $isDelegatedAdmin)
) {
// No rights
throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
diff --git a/apps/settings/appinfo/info.xml b/apps/settings/appinfo/info.xml
index a87e459aaf7..2674b97b57d 100644
--- a/apps/settings/appinfo/info.xml
+++ b/apps/settings/appinfo/info.xml
@@ -34,6 +34,7 @@
<admin>OCA\Settings\Settings\Admin\Sharing</admin>
<admin>OCA\Settings\Settings\Admin\Security</admin>
<admin>OCA\Settings\Settings\Admin\Delegation</admin>
+ <admin>OCA\Settings\Settings\Admin\Users</admin>
<admin-section>OCA\Settings\Sections\Admin\Additional</admin-section>
<admin-section>OCA\Settings\Sections\Admin\Delegation</admin-section>
<admin-section>OCA\Settings\Sections\Admin\Groupware</admin-section>
diff --git a/apps/settings/composer/composer/autoload_classmap.php b/apps/settings/composer/composer/autoload_classmap.php
index 27c1496008e..41f70c3a8e6 100644
--- a/apps/settings/composer/composer/autoload_classmap.php
+++ b/apps/settings/composer/composer/autoload_classmap.php
@@ -71,6 +71,7 @@ return array(
'OCA\\Settings\\Settings\\Admin\\Security' => $baseDir . '/../lib/Settings/Admin/Security.php',
'OCA\\Settings\\Settings\\Admin\\Server' => $baseDir . '/../lib/Settings/Admin/Server.php',
'OCA\\Settings\\Settings\\Admin\\Sharing' => $baseDir . '/../lib/Settings/Admin/Sharing.php',
+ 'OCA\\Settings\\Settings\\Admin\\Users' => $baseDir . '/../lib/Settings/Admin/Users.php',
'OCA\\Settings\\Settings\\Personal\\Additional' => $baseDir . '/../lib/Settings/Personal/Additional.php',
'OCA\\Settings\\Settings\\Personal\\PersonalInfo' => $baseDir . '/../lib/Settings/Personal/PersonalInfo.php',
'OCA\\Settings\\Settings\\Personal\\Security\\Authtokens' => $baseDir . '/../lib/Settings/Personal/Security/Authtokens.php',
diff --git a/apps/settings/composer/composer/autoload_static.php b/apps/settings/composer/composer/autoload_static.php
index 14e4c362887..4fa905b55bb 100644
--- a/apps/settings/composer/composer/autoload_static.php
+++ b/apps/settings/composer/composer/autoload_static.php
@@ -86,6 +86,7 @@ class ComposerStaticInitSettings
'OCA\\Settings\\Settings\\Admin\\Security' => __DIR__ . '/..' . '/../lib/Settings/Admin/Security.php',
'OCA\\Settings\\Settings\\Admin\\Server' => __DIR__ . '/..' . '/../lib/Settings/Admin/Server.php',
'OCA\\Settings\\Settings\\Admin\\Sharing' => __DIR__ . '/..' . '/../lib/Settings/Admin/Sharing.php',
+ 'OCA\\Settings\\Settings\\Admin\\Users' => __DIR__ . '/..' . '/../lib/Settings/Admin/Users.php',
'OCA\\Settings\\Settings\\Personal\\Additional' => __DIR__ . '/..' . '/../lib/Settings/Personal/Additional.php',
'OCA\\Settings\\Settings\\Personal\\PersonalInfo' => __DIR__ . '/..' . '/../lib/Settings/Personal/PersonalInfo.php',
'OCA\\Settings\\Settings\\Personal\\Security\\Authtokens' => __DIR__ . '/..' . '/../lib/Settings/Personal/Security/Authtokens.php',
diff --git a/apps/settings/lib/Controller/UsersController.php b/apps/settings/lib/Controller/UsersController.php
index 999f883bad8..1e934cdf43c 100644
--- a/apps/settings/lib/Controller/UsersController.php
+++ b/apps/settings/lib/Controller/UsersController.php
@@ -19,12 +19,14 @@ use OC\Security\IdentityProof\Manager;
use OC\User\Manager as UserManager;
use OCA\Settings\BackgroundJobs\VerifyUserData;
use OCA\Settings\Events\BeforeTemplateRenderedEvent;
+use OCA\Settings\Settings\Admin\Users;
use OCA\User_LDAP\User_Proxy;
use OCP\Accounts\IAccount;
use OCP\Accounts\IAccountManager;
use OCP\Accounts\PropertyDoesNotExistException;
use OCP\App\IAppManager;
use OCP\AppFramework\Controller;
+use OCP\AppFramework\Http\Attribute\AuthorizedAdminSetting;
use OCP\AppFramework\Http\Attribute\OpenAPI;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Http\JSONResponse;
@@ -93,6 +95,7 @@ class UsersController extends Controller {
$user = $this->userSession->getUser();
$uid = $user->getUID();
$isAdmin = $this->groupManager->isAdmin($uid);
+ $isDelegatedAdmin = $this->groupManager->isDelegatedAdmin($uid);
\OC::$server->getNavigationManager()->setActiveEntry('core_users');
@@ -118,6 +121,7 @@ class UsersController extends Controller {
$groupsInfo = new \OC\Group\MetaData(
$uid,
$isAdmin,
+ $isDelegatedAdmin,
$this->groupManager,
$this->userSession
);
@@ -135,7 +139,7 @@ class UsersController extends Controller {
$userCount = 0;
if (!$isLDAPUsed) {
- if ($isAdmin) {
+ if ($isAdmin || $isDelegatedAdmin) {
$disabledUsers = $this->userManager->countDisabledUsers();
$userCount = array_reduce($this->userManager->countUsers(), function ($v, $w) {
return $v + (int)$w;
@@ -200,7 +204,8 @@ class UsersController extends Controller {
// groups
$serverData['groups'] = array_merge_recursive($adminGroup, [$recentUsersGroup, $disabledUsersGroup], $groups);
// Various data
- $serverData['isAdmin'] = $isAdmin;
+ $serverData['isAdmin'] = $isAdmin || $isDelegatedAdmin;
+ $serverData['isDelegatedAdmin'] = $isDelegatedAdmin;
$serverData['sortGroups'] = $forceSortGroupByName
? \OC\Group\MetaData::SORT_GROUPNAME
: (int)$this->config->getAppValue('core', 'group.sortBy', (string)\OC\Group\MetaData::SORT_USERCOUNT);
@@ -232,6 +237,7 @@ class UsersController extends Controller {
*
* @return JSONResponse
*/
+ #[AuthorizedAdminSetting(settings:Users::class)]
public function setPreference(string $key, string $value): JSONResponse {
$allowed = ['newUser.sendEmail', 'group.sortBy'];
if (!in_array($key, $allowed, true)) {
diff --git a/apps/settings/lib/Settings/Admin/Users.php b/apps/settings/lib/Settings/Admin/Users.php
new file mode 100644
index 00000000000..3af018e0cf1
--- /dev/null
+++ b/apps/settings/lib/Settings/Admin/Users.php
@@ -0,0 +1,61 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+namespace OCA\Settings\Settings\Admin;
+
+use OCP\AppFramework\Http\TemplateResponse;
+use OCP\IL10N;
+use OCP\Settings\IDelegatedSettings;
+
+/**
+ * Empty settings class, used only for admin delegation.
+ */
+class Users implements IDelegatedSettings {
+
+ public function __construct(
+ protected string $appName,
+ private IL10N $l10n,
+ ) {
+ }
+
+ /**
+ * Empty template response
+ */
+ public function getForm(): TemplateResponse {
+
+ return new /** @template-extends TemplateResponse<\OCP\AppFramework\Http::STATUS_OK, array{}> */ class($this->appName, '') extends TemplateResponse {
+ public function render(): string {
+ return '';
+ }
+ };
+ }
+
+ public function getSection(): ?string {
+ return 'admindelegation';
+ }
+
+ /**
+ * @return int whether the form should be rather on the top or bottom of
+ * the admin section. The forms are arranged in ascending order of the
+ * priority values. It is required to return a value between 0 and 100.
+ *
+ * E.g.: 70
+ */
+ public function getPriority(): int {
+ return 0;
+ }
+
+ public function getName(): string {
+ return $this->l10n->t('Users');
+ }
+
+ public function getAuthorizedAppConfig(): array {
+ return [];
+ }
+}