summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoas Schilling <coding@schilljs.com>2017-01-23 12:10:06 +0100
committerGitHub <noreply@github.com>2017-01-23 12:10:06 +0100
commit5d486478d3d6d316b1895ea440a05f31488e2f9f (patch)
tree2eef0379b617d8a720d0c9f0b8a4d33a298f4b8e
parent16afaa783b8e7b0e728543556c92dcc93241ae4b (diff)
parent916cc57b0ee827ac9635a6c7b4b2fdbc47e03491 (diff)
downloadnextcloud-server-5d486478d3d6d316b1895ea440a05f31488e2f9f.tar.gz
nextcloud-server-5d486478d3d6d316b1895ea440a05f31488e2f9f.zip
Merge pull request #3141 from nextcloud/subadmin-check-on-removing-user-from-group
Subadmin check on removing user from group
-rw-r--r--apps/provisioning_api/lib/Controller/UsersController.php48
-rw-r--r--apps/provisioning_api/tests/Controller/UsersControllerTest.php214
-rw-r--r--lib/private/SubAdmin.php2
-rw-r--r--settings/ajax/togglegroups.php92
-rw-r--r--settings/js/users/groups.js4
-rw-r--r--settings/js/users/users.js75
6 files changed, 288 insertions, 147 deletions
diff --git a/apps/provisioning_api/lib/Controller/UsersController.php b/apps/provisioning_api/lib/Controller/UsersController.php
index cc1d63d2d34..2e8a2ffe5ed 100644
--- a/apps/provisioning_api/lib/Controller/UsersController.php
+++ b/apps/provisioning_api/lib/Controller/UsersController.php
@@ -33,10 +33,10 @@ use \OC_Helper;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCS\OCSException;
use OCP\AppFramework\OCS\OCSForbiddenException;
-use OCP\AppFramework\OCS\OCSNotFoundException;
use OCP\AppFramework\OCSController;
use OCP\Files\NotFoundException;
use OCP\IConfig;
+use OCP\IGroup;
use OCP\IGroupManager;
use OCP\ILogger;
use OCP\IRequest;
@@ -275,9 +275,9 @@ class UsersController extends OCSController {
break;
case 'quota':
$quota = $value;
- if($quota !== 'none' and $quota !== 'default') {
+ if($quota !== 'none' && $quota !== 'default') {
if (is_numeric($quota)) {
- $quota = floatval($quota);
+ $quota = (float) $quota;
} else {
$quota = \OCP\Util::computerFileSize($quota);
}
@@ -421,6 +421,7 @@ class UsersController extends OCSController {
// Looking up someone else
if($subAdminManager->isUserAccessible($loggedInUser, $targetUser)) {
// Return the group that the method caller is subadmin of for the user in question
+ /** @var IGroup[] $getSubAdminsGroups */
$getSubAdminsGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
foreach ($getSubAdminsGroups as $key => $group) {
$getSubAdminsGroups[$key] = $group->getGID();
@@ -440,6 +441,8 @@ class UsersController extends OCSController {
/**
* @PasswordConfirmationRequired
+ * @NoAdminRequired
+ *
* @param string $userId
* @param string $groupid
* @return DataResponse
@@ -459,6 +462,13 @@ class UsersController extends OCSController {
throw new OCSException('', 103);
}
+ // 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)) {
+ throw new OCSException('', 104);
+ }
+
// Add user to group
$group->addUser($targetUser);
return new DataResponse();
@@ -492,25 +502,33 @@ class UsersController extends OCSController {
// 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)) {
+ if (!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminOfGroup($loggedInUser, $group)) {
throw new OCSException('', 104);
}
+
// Check they aren't removing themselves from 'admin' or their 'subadmin; group
- if($userId === $loggedInUser->getUID()) {
- if($this->groupManager->isAdmin($loggedInUser->getUID())) {
- if($group->getGID() === 'admin') {
+ if ($userId === $loggedInUser->getUID()) {
+ if ($this->groupManager->isAdmin($loggedInUser->getUID())) {
+ if ($group->getGID() === 'admin') {
throw new OCSException('Cannot remove yourself from the admin group', 105);
}
} else {
- // Not an admin, check they are not removing themself from their subadmin group
- $subAdminGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
- foreach ($subAdminGroups as $key => $group) {
- $subAdminGroups[$key] = $group->getGID();
- }
+ // Not an admin, so the user must be a subadmin of this group, but that is not allowed.
+ throw new OCSException('Cannot remove yourself from this group as you are a SubAdmin', 105);
+ }
- if(in_array($group->getGID(), $subAdminGroups, true)) {
- throw new OCSException('Cannot remove yourself from this group as you are a SubAdmin', 105);
- }
+ } else if (!$this->groupManager->isAdmin($loggedInUser->getUID())) {
+ /** @var IGroup[] $subAdminGroups */
+ $subAdminGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
+ $subAdminGroups = array_map(function (IGroup $subAdminGroup) {
+ return $subAdminGroup->getGID();
+ }, $subAdminGroups);
+ $userGroups = $this->groupManager->getUserGroupIds($targetUser);
+ $userSubAdminGroups = array_intersect($subAdminGroups, $userGroups);
+
+ if (count($userSubAdminGroups) <= 1) {
+ // Subadmin must not be able to remove a user from all their subadmin groups.
+ throw new OCSException('Cannot remove user from this group as this is the only remaining group you are a SubAdmin of', 105);
}
}
diff --git a/apps/provisioning_api/tests/Controller/UsersControllerTest.php b/apps/provisioning_api/tests/Controller/UsersControllerTest.php
index e04ee86feae..4d3da5fd33a 100644
--- a/apps/provisioning_api/tests/Controller/UsersControllerTest.php
+++ b/apps/provisioning_api/tests/Controller/UsersControllerTest.php
@@ -30,6 +30,9 @@
namespace OCA\Provisioning_API\Tests\Controller;
use OCA\Provisioning_API\Controller\UsersController;
+use OCP\AppFramework\Http\DataResponse;
+use OCP\IGroup;
+use OCP\IUser;
use OCP\IUserManager;
use OCP\IConfig;
use OCP\IUserSession;
@@ -1598,11 +1601,10 @@ class UsersControllerTest extends OriginalTest {
* @expectedExceptionCode 102
*/
public function testAddToGroupWithTargetGroupNotExisting() {
- $this->groupManager
- ->expects($this->once())
+ $this->groupManager->expects($this->once())
->method('get')
->with('GroupToAddTo')
- ->will($this->returnValue(null));
+ ->willReturn(null);
$this->api->addToGroup('TargetUser', 'GroupToAddTo');
}
@@ -1620,16 +1622,149 @@ class UsersControllerTest extends OriginalTest {
* @expectedExceptionCode 103
*/
public function testAddToGroupWithTargetUserNotExisting() {
- $targetGroup = $this->getMockBuilder('\OCP\IGroup')->disableOriginalConstructor()->getMock();
- $this->groupManager
- ->expects($this->once())
+ $targetGroup = $this->createMock(IGroup::class);
+ $this->groupManager->expects($this->once())
->method('get')
->with('GroupToAddTo')
- ->will($this->returnValue($targetGroup));
+ ->willReturn($targetGroup);
+
+ $this->api->addToGroup('TargetUser', 'GroupToAddTo');
+ }
+
+ /**
+ * @expectedException \OCP\AppFramework\OCS\OCSException
+ * @expectedExceptionCode 104
+ */
+ public function testAddToGroupNoSubadmin() {
+ $targetUser = $this->createMock(IUser::class);
+ $loggedInUser = $this->createMock(IUser::class);
+ $loggedInUser->expects($this->once())
+ ->method('getUID')
+ ->willReturn('subadmin');
+
+ $targetGroup = $this->createMock(IGroup::class);
+ $targetGroup->expects($this->never())
+ ->method('addUser')
+ ->with($targetUser);
+
+ $this->groupManager->expects($this->once())
+ ->method('get')
+ ->with('GroupToAddTo')
+ ->willReturn($targetGroup);
+
+
+ $subAdminManager = $this->createMock(\OC\SubAdmin::class);
+ $subAdminManager->expects($this->once())
+ ->method('isSubAdminOfGroup')
+ ->with($loggedInUser, $targetGroup)
+ ->willReturn(false);
+
+ $this->groupManager->expects($this->once())
+ ->method('getSubAdmin')
+ ->willReturn($subAdminManager);
+ $this->groupManager->expects($this->once())
+ ->method('isAdmin')
+ ->with('subadmin')
+ ->willReturn(false);
+
+ $this->userManager->expects($this->once())
+ ->method('get')
+ ->with('TargetUser')
+ ->willReturn($targetUser);
+
+ $this->userSession->expects($this->once())
+ ->method('getUser')
+ ->willReturn($loggedInUser);
$this->api->addToGroup('TargetUser', 'GroupToAddTo');
}
+ public function testAddToGroupSuccessAsSubadmin() {
+ $targetUser = $this->createMock(IUser::class);
+ $loggedInUser = $this->createMock(IUser::class);
+ $loggedInUser->expects($this->once())
+ ->method('getUID')
+ ->willReturn('subadmin');
+
+ $targetGroup = $this->createMock(IGroup::class);
+ $targetGroup->expects($this->once())
+ ->method('addUser')
+ ->with($targetUser);
+
+ $this->groupManager->expects($this->once())
+ ->method('get')
+ ->with('GroupToAddTo')
+ ->willReturn($targetGroup);
+
+
+ $subAdminManager = $this->createMock(\OC\SubAdmin::class);
+ $subAdminManager->expects($this->once())
+ ->method('isSubAdminOfGroup')
+ ->with($loggedInUser, $targetGroup)
+ ->willReturn(true);
+
+ $this->groupManager->expects($this->once())
+ ->method('getSubAdmin')
+ ->willReturn($subAdminManager);
+ $this->groupManager->expects($this->once())
+ ->method('isAdmin')
+ ->with('subadmin')
+ ->willReturn(false);
+
+ $this->userManager->expects($this->once())
+ ->method('get')
+ ->with('TargetUser')
+ ->willReturn($targetUser);
+
+ $this->userSession->expects($this->once())
+ ->method('getUser')
+ ->willReturn($loggedInUser);
+
+ $this->assertEquals(new DataResponse(), $this->api->addToGroup('TargetUser', 'GroupToAddTo'));
+ }
+
+ public function testAddToGroupSuccessAsAdmin() {
+ $targetUser = $this->createMock(IUser::class);
+ $loggedInUser = $this->createMock(IUser::class);
+ $loggedInUser->expects($this->once())
+ ->method('getUID')
+ ->willReturn('admin');
+
+ $targetGroup = $this->createMock(IGroup::class);
+ $targetGroup->expects($this->once())
+ ->method('addUser')
+ ->with($targetUser);
+
+ $this->groupManager->expects($this->once())
+ ->method('get')
+ ->with('GroupToAddTo')
+ ->willReturn($targetGroup);
+
+
+ $subAdminManager = $this->createMock(\OC\SubAdmin::class);
+ $subAdminManager->expects($this->never())
+ ->method('isSubAdminOfGroup');
+
+ $this->groupManager->expects($this->once())
+ ->method('getSubAdmin')
+ ->willReturn($subAdminManager);
+ $this->groupManager->expects($this->once())
+ ->method('isAdmin')
+ ->with('admin')
+ ->willReturn(true);
+
+ $this->userManager->expects($this->once())
+ ->method('get')
+ ->with('TargetUser')
+ ->willReturn($targetUser);
+
+ $this->userSession->expects($this->once())
+ ->method('getUser')
+ ->willReturn($loggedInUser);
+
+ $this->assertEquals(new DataResponse(), $this->api->addToGroup('TargetUser', 'GroupToAddTo'));
+ }
+
/**
* @expectedException \OCP\AppFramework\OCS\OCSException
* @expectedExceptionCode 101
@@ -1813,22 +1948,79 @@ class UsersControllerTest extends OriginalTest {
->method('isSubAdminofGroup')
->with($loggedInUser, $targetGroup)
->will($this->returnValue(true));
+ $this->groupManager
+ ->expects($this->once())
+ ->method('getSubAdmin')
+ ->will($this->returnValue($subAdminManager));
+ $this->groupManager
+ ->expects($this->any())
+ ->method('isAdmin')
+ ->with('subadmin')
+ ->will($this->returnValue(false));
+
+ $this->api->removeFromGroup('subadmin', 'subadmin');
+ }
+
+ /**
+ * @expectedException \OCP\AppFramework\OCS\OCSException
+ * @expectedExceptionCode 105
+ * @expectedExceptionMessage Cannot remove user from this group as this is the only remaining group you are a SubAdmin of
+ */
+ public function testRemoveFromGroupAsSubAdminFromLastSubAdminGroup() {
+ $loggedInUser = $this->getMockBuilder('\OCP\IUser')->disableOriginalConstructor()->getMock();
+ $loggedInUser
+ ->expects($this->any())
+ ->method('getUID')
+ ->will($this->returnValue('subadmin'));
+ $targetUser = $this->getMockBuilder('\OCP\IUser')->disableOriginalConstructor()->getMock();
+ $targetGroup = $this->getMockBuilder('\OCP\IGroup')->disableOriginalConstructor()->getMock();
+ $targetGroup
+ ->expects($this->any())
+ ->method('getGID')
+ ->will($this->returnValue('subadmin'));
+ $this->userSession
+ ->expects($this->once())
+ ->method('getUser')
+ ->will($this->returnValue($loggedInUser));
+ $this->groupManager
+ ->expects($this->once())
+ ->method('get')
+ ->with('subadmin')
+ ->will($this->returnValue($targetGroup));
+ $this->userManager
+ ->expects($this->once())
+ ->method('get')
+ ->with('AnotherUser')
+ ->will($this->returnValue($targetUser));
+ $subAdminManager = $this->getMockBuilder('OC\SubAdmin')
+ ->disableOriginalConstructor()->getMock();
$subAdminManager
->expects($this->once())
- ->method('getSubAdminsGroups')
- ->with($loggedInUser)
- ->will($this->returnValue([$targetGroup]));
+ ->method('isSubAdminofGroup')
+ ->with($loggedInUser, $targetGroup)
+ ->will($this->returnValue(true));
$this->groupManager
->expects($this->once())
->method('getSubAdmin')
->will($this->returnValue($subAdminManager));
+ $subAdminManager
+ ->expects($this->once())
+ ->method('getSubAdminsGroups')
+ ->with($loggedInUser)
+ ->will($this->returnValue([$targetGroup]));
+
$this->groupManager
->expects($this->any())
->method('isAdmin')
->with('subadmin')
->will($this->returnValue(false));
+ $this->groupManager
+ ->expects($this->once())
+ ->method('getUserGroupIds')
+ ->with($targetUser)
+ ->willReturn(['subadmin', 'other group']);
- $this->api->removeFromGroup('subadmin', 'subadmin');
+ $this->api->removeFromGroup('AnotherUser', 'subadmin');
}
public function testRemoveFromGroupSuccessful() {
diff --git a/lib/private/SubAdmin.php b/lib/private/SubAdmin.php
index 9a2beed09fe..0650c7c6c01 100644
--- a/lib/private/SubAdmin.php
+++ b/lib/private/SubAdmin.php
@@ -188,7 +188,7 @@ class SubAdmin extends PublicEmitter {
* @param IGroup $group
* @return bool
*/
- public function isSubAdminofGroup(IUser $user, IGroup $group) {
+ public function isSubAdminOfGroup(IUser $user, IGroup $group) {
$qb = $this->dbConn->getQueryBuilder();
/*
diff --git a/settings/ajax/togglegroups.php b/settings/ajax/togglegroups.php
deleted file mode 100644
index b9958bef0c9..00000000000
--- a/settings/ajax/togglegroups.php
+++ /dev/null
@@ -1,92 +0,0 @@
-<?php
-/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Bart Visscher <bartv@thisnet.nl>
- * @author Christopher Schäpers <kondou@ts.unde.re>
- * @author Georg Ehrke <georg@owncloud.com>
- * @author Jakob Sack <mail@jakobsack.de>
- * @author Lukas Reschke <lukas@statuscode.ch>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
- */
-OC_JSON::checkSubAdminUser();
-OCP\JSON::callCheck();
-
-$lastConfirm = (int) \OC::$server->getSession()->get('last-password-confirm');
-if ($lastConfirm < (time() - 30 * 60 + 15)) { // allow 15 seconds delay
- $l = \OC::$server->getL10N('core');
- OC_JSON::error(array( 'data' => array( 'message' => $l->t('Password confirmation is required'))));
- exit();
-}
-
-$success = true;
-$username = (string)$_POST['username'];
-$group = (string)$_POST['group'];
-
-if($username === OC_User::getUser() && $group === "admin" && OC_User::isAdminUser($username)) {
- $l = \OC::$server->getL10N('core');
- OC_JSON::error(array( 'data' => array( 'message' => $l->t('Admins can\'t remove themself from the admin group'))));
- exit();
-}
-
-$isUserAccessible = false;
-$isGroupAccessible = false;
-$currentUserObject = \OC::$server->getUserSession()->getUser();
-$targetUserObject = \OC::$server->getUserManager()->get($username);
-$targetGroupObject = \OC::$server->getGroupManager()->get($group);
-if($targetUserObject !== null && $currentUserObject !== null && $targetGroupObject !== null) {
- $isUserAccessible = \OC::$server->getGroupManager()->getSubAdmin()->isUserAccessible($currentUserObject, $targetUserObject);
- $isGroupAccessible = \OC::$server->getGroupManager()->getSubAdmin()->isSubAdminofGroup($currentUserObject, $targetGroupObject);
-}
-
-if(!OC_User::isAdminUser(OC_User::getUser())
- && (!$isUserAccessible
- || !$isGroupAccessible)) {
- $l = \OC::$server->getL10N('core');
- OC_JSON::error(array( 'data' => array( 'message' => $l->t('Authentication error') )));
- exit();
-}
-
-if(!OC_Group::groupExists($group)) {
- OC_Group::createGroup($group);
-}
-
-$l = \OC::$server->getL10N('settings');
-
-$error = $l->t("Unable to add user to group %s", $group);
-$action = "add";
-
-// Toggle group
-if( OC_Group::inGroup( $username, $group )) {
- $action = "remove";
- $error = $l->t("Unable to remove user from group %s", $group);
- $success = OC_Group::removeFromGroup( $username, $group );
- $usersInGroup=OC_Group::usersInGroup($group);
-}
-else{
- $success = OC_Group::addToGroup( $username, $group );
-}
-
-// Return Success story
-if( $success ) {
- OC_JSON::success(array("data" => array( "username" => $username, "action" => $action, "groupname" => $group )));
-}
-else{
- OC_JSON::error(array("data" => array( "message" => $error )));
-}
diff --git a/settings/js/users/groups.js b/settings/js/users/groups.js
index cfe01c17530..aac1609bce7 100644
--- a/settings/js/users/groups.js
+++ b/settings/js/users/groups.js
@@ -225,7 +225,9 @@ GroupList = {
toggleAddGroup: function (event) {
if (GroupList.isAddGroupButtonVisible()) {
- event.stopPropagation();
+ if (event) {
+ event.stopPropagation();
+ }
$('#newgroup-form').show();
$('#newgroup-init').hide();
$('#newgroupname').focus();
diff --git a/settings/js/users/users.js b/settings/js/users/users.js
index a2ccc059f15..3cf7b5e810a 100644
--- a/settings/js/users/users.js
+++ b/settings/js/users/users.js
@@ -420,42 +420,63 @@ var UserList = {
var $element = $(element);
- var checkHandler = null;
+ var addUserToGroup = null,
+ removeUserFromGroup = null;
if(user) { // Only if in a user row, and not the #newusergroups select
- checkHandler = function (group) {
- if (user === OC.currentUser && group === 'admin') {
+ var handleUserGroupMembership = function (group, add) {
+ if (user === OC.getCurrentUser().uid && group === 'admin') {
return false;
}
if (!OC.isUserAdmin() && checked.length === 1 && checked[0] === group) {
return false;
}
- $.post(
- OC.filePath('settings', 'ajax', 'togglegroups.php'),
- {
- username: user,
- group: group
+
+ if (add && OC.isUserAdmin() && UserList.availableGroups.indexOf(group) === -1) {
+ GroupList.createGroup(group);
+ if (UserList.availableGroups.indexOf(group) === -1) {
+ UserList.availableGroups.push(group);
+ }
+ }
+
+ $.ajax({
+ url: OC.linkToOCS('cloud/users/' + user , 2) + 'groups',
+ data: {
+ groupid: group
},
- function (response) {
- if (response.status === 'success') {
- GroupList.update();
- var groupName = response.data.groupname;
- if (UserList.availableGroups.indexOf(groupName) === -1 &&
- response.data.action === 'add'
- ) {
- UserList.availableGroups.push(groupName);
- }
+ type: add ? 'POST' : 'DELETE',
+ beforeSend: function (request) {
+ request.setRequestHeader('Accept', 'application/json');
+ },
+ success: function() {
+ GroupList.update();
+ if (add && UserList.availableGroups.indexOf(group) === -1) {
+ UserList.availableGroups.push(group);
+ }
- if (response.data.action === 'add') {
- GroupList.incGroupCount(groupName);
- } else {
- GroupList.decGroupCount(groupName);
- }
+ if (add) {
+ GroupList.incGroupCount(group);
+ } else {
+ GroupList.decGroupCount(group);
}
- if (response.data.message) {
- OC.Notification.show(response.data.message);
+ },
+ error: function() {
+ if (add) {
+ OC.Notification.show(t('settings', 'Unable to add user to group {group}', {
+ group: group
+ }));
+ } else {
+ OC.Notification.show(t('settings', 'Unable to remove user from group {group}', {
+ group: group
+ }));
}
}
- );
+ });
+ };
+ addUserToGroup = function (group) {
+ return handleUserGroupMembership(group, true);
+ };
+ removeUserFromGroup = function (group) {
+ return handleUserGroupMembership(group, false);
};
}
var addGroup = function (select, group) {
@@ -473,8 +494,8 @@ var UserList = {
createText: label,
selectedFirst: true,
checked: checked,
- oncheck: checkHandler,
- onuncheck: checkHandler,
+ oncheck: addUserToGroup,
+ onuncheck: removeUserFromGroup,
minWidth: 100
});
},