diff --git a/apps/provisioning_api/appinfo/routes.php b/apps/provisioning_api/appinfo/routes.php
index 2a4b50dc27ce8512192ea325593ea1a4b57e51b6..dcf18e0e53b7ecd893c040ec8964199cafce39d7 100644
--- a/apps/provisioning_api/appinfo/routes.php
+++ b/apps/provisioning_api/appinfo/routes.php
@@ -1,6 +1,7 @@
 <?php
 /**
  * @author Joas Schilling <nickvergessen@owncloud.com>
+ * @author Lukas Reschke <lukas@owncloud.com>
  * @author michag86 <micha_g@arcor.de>
  * @author Morris Jobke <hey@morrisjobke.de>
  * @author Roeland Jago Douma <rullzer@owncloud.com>
@@ -32,7 +33,8 @@ $users = new \OCA\Provisioning_API\Users(
 	\OC::$server->getUserManager(),
 	\OC::$server->getConfig(),
 	\OC::$server->getGroupManager(),
-	\OC::$server->getUserSession()
+	\OC::$server->getUserSession(),
+	\OC::$server->getLogger()
 );
 API::register('get', '/cloud/users', [$users, 'getUsers'], 'provisioning_api', API::SUBADMIN_AUTH);
 API::register('post', '/cloud/users', [$users, 'addUser'], 'provisioning_api', API::ADMIN_AUTH);
diff --git a/apps/provisioning_api/lib/groups.php b/apps/provisioning_api/lib/groups.php
index 5b613562324c55ca47db68e012c7deeccceb37dc..c28db35972f722d0247a35843b900129cf32c9e1 100644
--- a/apps/provisioning_api/lib/groups.php
+++ b/apps/provisioning_api/lib/groups.php
@@ -26,7 +26,6 @@
 namespace OCA\Provisioning_API;
 
 use \OC_OCS_Result;
-use \OC_SubAdmin;
 use OCP\IGroup;
 use OCP\IUser;
 
@@ -85,9 +84,16 @@ class Groups{
 		if(!$this->groupManager->groupExists($parameters['groupid'])) {
 			return new OC_OCS_Result(null, \OCP\API::RESPOND_NOT_FOUND, 'The requested group could not be found');
 		}
+
+		$isSubadminOfGroup = false;
+		$targetGroupObject =$this->groupManager->get($parameters['groupid']);
+		if($targetGroupObject !== null) {
+			$isSubadminOfGroup =$this->groupManager->getSubAdmin()->isSubAdminofGroup($user, $targetGroupObject);
+		}
+
 		// Check subadmin has access to this group
 		if($this->groupManager->isAdmin($user->getUID())
-		   || in_array($parameters['groupid'], \OC_SubAdmin::getSubAdminsGroups($user->getUID()))){
+		   || $isSubadminOfGroup) {
 			$users = $this->groupManager->get($parameters['groupid'])->getUsers();
 			$users =  array_map(function($user) {
 				/** @var IUser $user */
@@ -144,11 +150,21 @@ class Groups{
 	public function getSubAdminsOfGroup($parameters) {
 		$group = $parameters['groupid'];
 		// Check group exists
-		if(!$this->groupManager->groupExists($group)) {
+		$targetGroup = $this->groupManager->get($group);
+		if($targetGroup === null) {
 			return new OC_OCS_Result(null, 101, 'Group does not exist');
 		}
+
+		$subadmins = $this->groupManager->getSubAdmin()->getGroupsSubAdmins($targetGroup);
+		// New class returns IUser[] so convert back
+		$uids = [];
+		foreach ($subadmins as $user) {
+			$uids[] = $user->getUID();
+		}
+		$subadmins = $uids;
+
 		// Go
-		if(!$subadmins = OC_Subadmin::getGroupsSubAdmins($group)) {
+		if(!$subadmins) {
 			return new OC_OCS_Result(null, 102, 'Unknown error occured');
 		} else {
 			return new OC_OCS_Result($subadmins);
diff --git a/apps/provisioning_api/lib/users.php b/apps/provisioning_api/lib/users.php
index 527b107ad502b01cb6941c9b567e1b0cc0bd0ffe..a9fafb48912704bd9df72ec8562d55f1e0daff91 100644
--- a/apps/provisioning_api/lib/users.php
+++ b/apps/provisioning_api/lib/users.php
@@ -28,39 +28,40 @@
 namespace OCA\Provisioning_API;
 
 use \OC_OCS_Result;
-use \OC_SubAdmin;
 use \OC_Helper;
-use \OC_Group;
 use OCP\Files\NotFoundException;
+use OCP\ILogger;
 
 class Users {
 
 	/** @var \OCP\IUserManager */
 	private $userManager;
-
 	/** @var \OCP\IConfig */
 	private $config;
-
 	/** @var \OCP\IGroupManager */
 	private $groupManager;
-
 	/** @var \OCP\IUserSession */
 	private $userSession;
+	/** @var ILogger */
+	private $logger;
 
 	/**
 	 * @param \OCP\IUserManager $userManager
 	 * @param \OCP\IConfig $config
 	 * @param \OCP\IGroupManager $groupManager
 	 * @param \OCP\IUserSession $userSession
+	 * @param ILogger $logger
 	 */
 	public function __construct(\OCP\IUserManager $userManager,
 								\OCP\IConfig $config,
 								\OCP\IGroupManager $groupManager,
-								\OCP\IUserSession $userSession) {
+								\OCP\IUserSession $userSession,
+								ILogger $logger) {
 		$this->userManager = $userManager;
 		$this->config = $config;
 		$this->groupManager = $groupManager;
 		$this->userSession = $userSession;
+		$this->logger = $logger;
 	}
 
 	/**
@@ -80,10 +81,15 @@ class Users {
 		}
 
 		// Admin? Or SubAdmin?
-		if($this->groupManager->isAdmin($user->getUID())){
+		$uid = $user->getUID();
+		$subAdminManager = $this->groupManager->getSubAdmin();
+		if($this->groupManager->isAdmin($uid)){
 			$users = $this->userManager->search($search, $limit, $offset);
-		} else if (\OC_SubAdmin::isSubAdmin($user->getUID())) {
-			$subAdminOfGroups = \OC_SubAdmin::getSubAdminsGroups($user->getUID());
+		} else if ($subAdminManager->isSubAdmin($user)) {
+			$subAdminOfGroups = $subAdminManager->getSubAdminsGroups($user);
+			foreach ($subAdminOfGroups as $key => $group) {
+				$subAdminOfGroups[$key] = $group->getGID();
+			}
 
 			if($offset === null) {
 				$offset = 0; 
@@ -112,15 +118,15 @@ class Users {
 		$userId = isset($_POST['userid']) ? $_POST['userid'] : null;
 		$password = isset($_POST['password']) ? $_POST['password'] : null;
 		if($this->userManager->userExists($userId)) {
-			\OCP\Util::writeLog('ocs_api', 'Failed addUser attempt: User already exists.', \OCP\Util::ERROR);
+			$this->logger->error('Failed addUser attempt: User already exists.', ['app' => 'ocs_api']);
 			return new OC_OCS_Result(null, 102, 'User already exists');
 		} else {
 			try {
 				$this->userManager->createUser($userId, $password);
-				\OCP\Util::writeLog('ocs_api', 'Successful addUser call with userid: '.$_POST['userid'], \OCP\Util::INFO);
+				$this->logger->info('Successful addUser call with userid: '.$_POST['userid'], ['app' => 'ocs_api']);
 				return new OC_OCS_Result(null, 100);
 			} catch (\Exception $e) {
-				\OCP\Util::writeLog('ocs_api', 'Failed addUser attempt with exception: '.$e->getMessage(), \OCP\Util::ERROR);
+				$this->logger->error('Failed addUser attempt with exception: '.$e->getMessage(), ['app' => 'ocs_api']);
 				return new OC_OCS_Result(null, 101, 'Bad request');
 			}
 		}
@@ -132,35 +138,38 @@ class Users {
 	 * @param array $parameters
 	 * @return OC_OCS_Result
 	 */
-	public function getUser($parameters){
+	public function getUser($parameters) {
 		$userId = $parameters['userid'];
 
 		// Check if user is logged in
-		$user = $this->userSession->getUser();
-		if ($user === null) {
+		$currentLoggedInUser = $this->userSession->getUser();
+		if ($currentLoggedInUser === null) {
 			return new OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED);
 		}
 
 		$data = [];
 
+		// Check if the target user exists
+		$targetUserObject = $this->userManager->get($userId);
+		if($targetUserObject === null) {
+			return new OC_OCS_Result(null, \OCP\API::RESPOND_NOT_FOUND, 'The requested user could not be found');
+		}
+
 		// Admin? Or SubAdmin?
-		if($this->groupManager->isAdmin($user->getUID()) || OC_SubAdmin::isUserAccessible($user->getUID(), $userId)) {
-			// Check they exist
-			if(!$this->userManager->userExists($userId)) {
-				return new OC_OCS_Result(null, \OCP\API::RESPOND_NOT_FOUND, 'The requested user could not be found');
-			}
+		if($this->groupManager->isAdmin($currentLoggedInUser->getUID())
+			|| $this->groupManager->getSubAdmin()->isUserAccessible($currentLoggedInUser, $targetUserObject)) {
 			$data['enabled'] = $this->config->getUserValue($userId, 'core', 'enabled', 'true');
 		} else {
 			// Check they are looking up themselves
-			if($user->getUID() !== $userId) {
+			if($currentLoggedInUser->getUID() !== $userId) {
 				return new OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED);
 			}
 		}
 
 		// Find the data
-		$data['quota'] = self::fillStorageInfo($userId);
+		$data['quota'] = $this->fillStorageInfo($userId);
 		$data['email'] = $this->config->getUserValue($userId, 'settings', 'email');
-		$data['displayname'] = $this->userManager->get($userId)->getDisplayName();
+		$data['displayname'] = $targetUserObject->getDisplayName();
 
 		return new OC_OCS_Result($data);
 	}
@@ -172,27 +181,34 @@ class Users {
 	 * @return OC_OCS_Result
 	 */
 	public function editUser($parameters) {
-		$userId = $parameters['userid'];
+		/** @var string $targetUserId */
+		$targetUserId = $parameters['userid'];
 
 		// Check if user is logged in
-		$user = $this->userSession->getUser();
-		if ($user === null) {
+		$currentLoggedInUser = $this->userSession->getUser();
+		if ($currentLoggedInUser === null) {
 			return new OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED);
 		}
 
-		if($userId === $user->getUID()) {
+		$targetUser = $this->userManager->get($targetUserId);
+		if($targetUser === null) {
+			return new OC_OCS_Result(null, 997);
+		}
+
+		if($targetUserId === $currentLoggedInUser->getUID()) {
 			// Editing self (display, email)
 			$permittedFields[] = 'display';
 			$permittedFields[] = 'email';
 			$permittedFields[] = 'password';
 			// If admin they can edit their own quota
-			if($this->groupManager->isAdmin($user->getUID())) {
+			if($this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
 				$permittedFields[] = 'quota';
 			}
 		} else {
 			// Check if admin / subadmin
-			if(OC_SubAdmin::isUserAccessible($user->getUID(), $userId)
-			|| $this->groupManager->isAdmin($user->getUID())) {
+			$subAdminManager = $this->groupManager->getSubAdmin();
+			if($subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)
+			|| $this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
 				// They have permissions over the user
 				$permittedFields[] = 'display';
 				$permittedFields[] = 'quota';
@@ -208,9 +224,9 @@ class Users {
 			return new OC_OCS_Result(null, 997);
 		}
 		// Process the edit
-		switch($parameters['_put']['key']){
+		switch($parameters['_put']['key']) {
 			case 'display':
-				$this->userManager->get($userId)->setDisplayName($parameters['_put']['value']);
+				$targetUser->setDisplayName($parameters['_put']['value']);
 				break;
 			case 'quota':
 				$quota = $parameters['_put']['value'];
@@ -225,20 +241,20 @@ class Users {
 					}
 					if($quota === 0) {
 						$quota = 'default';
-					}else if($quota === -1){
+					}else if($quota === -1) {
 						$quota = 'none';
 					} else {
 						$quota = \OCP\Util::humanFileSize($quota);
 					}
 				}
-				$this->config->setUserValue($userId, 'files', 'quota', $quota);
+				$this->config->setUserValue($targetUserId, 'files', 'quota', $quota);
 				break;
 			case 'password':
-				$this->userManager->get($userId)->setPassword($parameters['_put']['value']);
+				$targetUser->setPassword($parameters['_put']['value']);
 				break;
 			case 'email':
 				if(filter_var($parameters['_put']['value'], FILTER_VALIDATE_EMAIL)) {
-					$this->config->setUserValue($userId, 'settings', 'email', $parameters['_put']['value']);
+					$this->config->setUserValue($targetUserId, 'settings', 'email', $parameters['_put']['value']);
 				} else {
 					return new OC_OCS_Result(null, 102);
 				}
@@ -256,21 +272,25 @@ class Users {
 	 */
 	public function deleteUser($parameters) {
 		// Check if user is logged in
-		$user = $this->userSession->getUser();
-		if ($user === null) {
+		$currentLoggedInUser = $this->userSession->getUser();
+		if ($currentLoggedInUser === null) {
 			return new OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED);
 		}
 
-		if(!$this->userManager->userExists($parameters['userid']) 
-		|| $parameters['userid'] === $user->getUID()) {
+		$targetUser = $this->userManager->get($parameters['userid']);
+
+		if($targetUser === null || $targetUser->getUID() === $currentLoggedInUser->getUID()) {
 			return new OC_OCS_Result(null, 101);
 		}
+
 		// If not permitted
-		if(!$this->groupManager->isAdmin($user->getUID()) && !OC_SubAdmin::isUserAccessible($user->getUID(), $parameters['userid'])) {
+		$subAdminManager = $this->groupManager->getSubAdmin();
+		if(!$this->groupManager->isAdmin($currentLoggedInUser->getUID()) && !$subAdminManager->isUserAccessible($currentLoggedInUser, $targetUser)) {
 			return new OC_OCS_Result(null, 997);
 		}
+
 		// Go ahead with the delete
-		if($this->userManager->get($parameters['userid'])->delete()) {
+		if($targetUser->delete()) {
 			return new OC_OCS_Result(null, 100);
 		} else {
 			return new OC_OCS_Result(null, 101);
@@ -283,27 +303,34 @@ class Users {
 	 */
 	public function getUsersGroups($parameters) {
 		// Check if user is logged in
-		$user = $this->userSession->getUser();
-		if ($user === null) {
+		$loggedInUser = $this->userSession->getUser();
+		if ($loggedInUser === null) {
 			return new OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED);
 		}
 
-		if($parameters['userid'] === $user->getUID() || $this->groupManager->isAdmin($user->getUID())) {
+		$targetUser = $this->userManager->get($parameters['userid']);
+		if($targetUser === null) {
+			return new OC_OCS_Result(null, \OCP\API::RESPOND_NOT_FOUND);
+		}
+
+		if($targetUser->getUID() === $loggedInUser->getUID() || $this->groupManager->isAdmin($loggedInUser->getUID())) {
 			// Self lookup or admin lookup
 			return new OC_OCS_Result([
-				'groups' => $this->groupManager->getUserGroupIds(
-					$this->userManager->get($parameters['userid'])
-				)
+				'groups' => $this->groupManager->getUserGroupIds($targetUser)
 			]);
 		} else {
+			$subAdminManager = $this->groupManager->getSubAdmin();
+
 			// Looking up someone else
-			if(OC_SubAdmin::isUserAccessible($user->getUID(), $parameters['userid'])) {
+			if($subAdminManager->isUserAccessible($loggedInUser, $targetUser)) {
 				// Return the group that the method caller is subadmin of for the user in question
+				$getSubAdminsGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
+				foreach ($getSubAdminsGroups as $key => $group) {
+					$getSubAdminsGroups[$key] = $group->getGID();
+				}
 				$groups = array_intersect(
-					OC_SubAdmin::getSubAdminsGroups($user->getUID()),
-					$this->groupManager->getUserGroupIds(
-						$this->userManager->get($parameters['userid'])
-					)
+					$getSubAdminsGroups,
+					$this->groupManager->getUserGroupIds($targetUser)
 				);
 				return new OC_OCS_Result(array('groups' => $groups));
 			} else {
@@ -325,27 +352,28 @@ class Users {
 			return new OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED);
 		}
 
-		$group = !empty($_POST['groupid']) ? $_POST['groupid'] : null;
-		if(is_null($group)){
-			return new OC_OCS_Result(null, 101);
-		}
 		// Check they're an admin
-		if(!$this->groupManager->isInGroup($user->getUID(), 'admin')){
+		if(!$this->groupManager->isAdmin($user->getUID())) {
 			// This user doesn't have rights to add a user to this group
 			return new OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED);
 		}
-		// Check if the group exists
-		if(!$this->groupManager->groupExists($group)){
+
+		$groupId = !empty($_POST['groupid']) ? $_POST['groupid'] : null;
+		if($groupId === null) {
+			return new OC_OCS_Result(null, 101);
+		}
+
+		$group = $this->groupManager->get($groupId);
+		$targetUser = $this->userManager->get($parameters['userid']);
+		if($group === null) {
 			return new OC_OCS_Result(null, 102);
 		}
-		// Check if the user exists
-		if(!$this->userManager->userExists($parameters['userid'])){
+		if($targetUser === null) {
 			return new OC_OCS_Result(null, 103);
 		}
+
 		// Add user to group
-		$this->groupManager->get($group)->addUser(
-			$this->userManager->get($parameters['userid'])
-		);
+		$group->addUser($targetUser);
 		return new OC_OCS_Result(null, 100);
 	}
 
@@ -355,44 +383,47 @@ class Users {
 	 */
 	public function removeFromGroup($parameters) {
 		// Check if user is logged in
-		$user = $this->userSession->getUser();
-		if ($user === null) {
+		$loggedInUser = $this->userSession->getUser();
+		if ($loggedInUser === null) {
 			return new OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED);
 		}
 
-		$group = !empty($parameters['_delete']['groupid']) ? $parameters['_delete']['groupid'] : null;
-		if(is_null($group)){
+		$group = $this->groupManager->get(!empty($parameters['_delete']['groupid']) ? $parameters['_delete']['groupid'] : null);
+		if($group === null) {
 			return new OC_OCS_Result(null, 101);
 		}
+
+		$targetUser = $this->userManager->get($parameters['userid']);
+		if($targetUser === null) {
+			return new OC_OCS_Result(null, 103);
+		}
+
 		// If they're not an admin, check they are a subadmin of the group in question
-		if(!$this->groupManager->isInGroup($user->getUID(), 'admin') && !OC_SubAdmin::isSubAdminofGroup($user->getUID(), $group)){
+		$subAdminManager = $this->groupManager->getSubAdmin();
+		if(!$this->groupManager->isAdmin($loggedInUser->getUID()) && !$subAdminManager->isSubAdminofGroup($loggedInUser, $group)) {
 			return new OC_OCS_Result(null, 104);
 		}
 		// Check they aren't removing themselves from 'admin' or their 'subadmin; group
-		if($parameters['userid'] === $user->getUID()){
-			if($this->groupManager->isInGroup($user->getUID(), 'admin')){
-				if($group === 'admin'){
+		if($parameters['userid'] === $loggedInUser->getUID()) {
+			if($this->groupManager->isAdmin($loggedInUser->getUID())) {
+				if($group->getGID() === 'admin') {
 					return new OC_OCS_Result(null, 105, 'Cannot remove yourself from the admin group');
 				}
 			} else {
 				// Not an admin, check they are not removing themself from their subadmin group
-				if(in_array($group, OC_SubAdmin::getSubAdminsGroups($user->getUID()))){
+				$subAdminGroups = $subAdminManager->getSubAdminsGroups($loggedInUser);
+				foreach ($subAdminGroups as $key => $group) {
+					$subAdminGroups[$key] = $group->getGID();
+				}
+
+				if(in_array($group->getGID(), $subAdminGroups, true)) {
 					return new OC_OCS_Result(null, 105, 'Cannot remove yourself from this group as you are a SubAdmin');
 				}
 			}
 		}
-		// Check if the group exists
-		if(!$this->groupManager->groupExists($group)){
-			return new OC_OCS_Result(null, 102);
-		}
-		// Check if the user exists
-		if(!$this->userManager->userExists($parameters['userid'])){
-			return new OC_OCS_Result(null, 103);
-		}
+
 		// Remove user from group
-		$this->groupManager->get($group)->removeUser(
-			$this->userManager->get($parameters['userid'])
-		);
+		$group->removeUser($targetUser);
 		return new OC_OCS_Result(null, 100);
 	}
 
@@ -403,31 +434,34 @@ class Users {
 	 * @return OC_OCS_Result
 	 */
 	public function addSubAdmin($parameters) {
-		$group = $_POST['groupid'];
-		$user = $parameters['userid'];	
+		$group = $this->groupManager->get($_POST['groupid']);
+		$user = $this->userManager->get($parameters['userid']);
+
 		// Check if the user exists
-		if(!$this->userManager->userExists($user)) {
+		if($user === null) {
 			return new OC_OCS_Result(null, 101, 'User does not exist');
 		}
 		// Check if group exists
-		if(!$this->groupManager->groupExists($group)) {
-			return new OC_OCS_Result(null, 102, 'Group:'.$group.' does not exist');
+		if($group === null) {
+			return new OC_OCS_Result(null, 102, 'Group:'.$_POST['groupid'].' does not exist');
 		}
 		// Check if trying to make subadmin of admin group
-		if(strtolower($group) === 'admin') {
+		if(strtolower($_POST['groupid']) === 'admin') {
 			return new OC_OCS_Result(null, 103, 'Cannot create subadmins for admin group');
 		}
+
+		$subAdminManager = $this->groupManager->getSubAdmin();
+
 		// We cannot be subadmin twice
-		if (OC_Subadmin::isSubAdminOfGroup($user, $group)) {
+		if ($subAdminManager->isSubAdminofGroup($user, $group)) {
 			return new OC_OCS_Result(null, 100);
 		}
 		// Go
-		if(OC_Subadmin::createSubAdmin($user, $group)) {
+		if($subAdminManager->createSubAdmin($user, $group)) {
 			return new OC_OCS_Result(null, 100);
 		} else {
-			return new OC_OCS_Result(null, 103, 'Unknown error occured');
+			return new OC_OCS_Result(null, 103, 'Unknown error occurred');
 		}
-
 	}
 
 	/**
@@ -437,18 +471,25 @@ class Users {
 	 * @return OC_OCS_Result
 	 */
 	public function removeSubAdmin($parameters) {
-		$group = $parameters['_delete']['groupid'];
-		$user = $parameters['userid'];	
+		$group = $this->groupManager->get($parameters['_delete']['groupid']);
+		$user = $this->userManager->get($parameters['userid']);
+		$subAdminManager = $this->groupManager->getSubAdmin();
+
 		// Check if the user exists
-		if(!$this->userManager->userExists($user)) {
+		if($user === null) {
 			return new OC_OCS_Result(null, 101, 'User does not exist');
 		}
+		// Check if the group exists
+		if($group === null) {
+			return new OC_OCS_Result(null, 101, 'Group does not exist');
+		}
 		// Check if they are a subadmin of this said group
-		if(!OC_SubAdmin::isSubAdminofGroup($user, $group)) {
+		if(!$subAdminManager->isSubAdminofGroup($user, $group)) {
 			return new OC_OCS_Result(null, 102, 'User is not a subadmin of this group');
 		}
+
 		// Go
-		if(OC_Subadmin::deleteSubAdmin($user, $group)) {
+		if($subAdminManager->deleteSubAdmin($user, $group)) {
 			return new OC_OCS_Result(null, 100);
 		} else {
 			return new OC_OCS_Result(null, 103, 'Unknown error occurred');
@@ -462,13 +503,19 @@ class Users {
 	 * @return OC_OCS_Result
 	 */
 	public function getUserSubAdminGroups($parameters) {
-		$user = $parameters['userid'];
+		$user = $this->userManager->get($parameters['userid']);
 		// Check if the user exists
-		if(!$this->userManager->userExists($user)) {
+		if($user === null) {
 			return new OC_OCS_Result(null, 101, 'User does not exist');
 		}
+
 		// Get the subadmin groups
-		if(!$groups = OC_SubAdmin::getSubAdminsGroups($user)) {
+		$groups = $this->groupManager->getSubAdmin()->getSubAdminsGroups($user);
+		foreach ($groups as $key => $group) {
+			$groups[$key] = $group->getGID();
+		}
+
+		if(!$groups) {
 			return new OC_OCS_Result(null, 102, 'Unknown error occurred');
 		} else {
 			return new OC_OCS_Result($groups);
@@ -477,12 +524,10 @@ class Users {
 
 	/**
 	 * @param string $userId
-	 * @param array $data
-	 * @return mixed
+	 * @return array
 	 * @throws \OCP\Files\NotFoundException
 	 */
-	private static function fillStorageInfo($userId) {
-		$data = [];
+	protected function fillStorageInfo($userId) {
 		try {
 			\OC_Util::tearDownFS();
 			\OC_Util::setupFS($userId);
diff --git a/apps/provisioning_api/tests/groupstest.php b/apps/provisioning_api/tests/groupstest.php
index c75ba76bd35433241ea9f8b1cb3e6e4f5c9023d2..f67ed1c36aec01a18e3a34787a9b0fe054cb9a32 100644
--- a/apps/provisioning_api/tests/groupstest.php
+++ b/apps/provisioning_api/tests/groupstest.php
@@ -1,6 +1,7 @@
 <?php
 /**
  * @author Joas Schilling <nickvergessen@owncloud.com>
+ * @author Lukas Reschke <lukas@owncloud.com>
  * @author Morris Jobke <hey@morrisjobke.de>
  * @author Roeland Jago Douma <rullzer@owncloud.com>
  * @author Tom Needham <tom@owncloud.com>
@@ -29,15 +30,14 @@ use OCP\IGroupManager;
 use OCP\IUserSession;
 
 class GroupsTest extends TestCase {
-	
 	/** @var IUserManager */
 	protected $userManager;
-
 	/** @var IGroupManager */
 	protected $groupManager;
-
 	/** @var IUserSession */
 	protected $userSession;
+	/** @var \OCA\Provisioning_API\Groups */
+	protected $api;
 
 	protected function setup() {
 		parent::setup();
@@ -114,7 +114,7 @@ class GroupsTest extends TestCase {
 		$group->addUser($users[0]);
 		$group->addUser($users[1]);
 
-		\OC_SubAdmin::createSubAdmin($users[0]->getUID(), $group->getGID());
+		$this->groupManager->getSubAdmin()->createSubAdmin($users[0], $group);
 
 		$result = $this->api->getGroup([
 			'groupid' => $group->getGID(),
@@ -147,7 +147,7 @@ class GroupsTest extends TestCase {
 		$group1->addUser($users[1]);
 		$group2->addUser($users[0]);
 
-		\OC_SubAdmin::createSubAdmin($users[0]->getUID(), $group2->getGID());
+		$this->groupManager->getSubAdmin()->createSubAdmin($users[0], $group2);
 
 		$result = $this->api->getGroup([
 			'groupid' => $group1->getGID(),
@@ -196,7 +196,7 @@ class GroupsTest extends TestCase {
 		$this->userSession->setUser($user1);
 		$this->groupManager->get('admin')->addUser($user1);
 		$group1 = $this->groupManager->createGroup($this->getUniqueID());
-		\OC_SubAdmin::createSubAdmin($user2->getUID(), $group1->getGID());
+		$this->groupManager->getSubAdmin()->createSubAdmin($user2, $group1);
 		$result = $this->api->getSubAdminsOfGroup([
 			'groupid' => $group1->getGID(),
 		]);
diff --git a/apps/provisioning_api/tests/userstest.php b/apps/provisioning_api/tests/userstest.php
index 607e6f118ae5abc4a4e2dd803928d286b858abaa..c5a1ac3061e0ad0d217c9714de181243deeb01a1 100644
--- a/apps/provisioning_api/tests/userstest.php
+++ b/apps/provisioning_api/tests/userstest.php
@@ -1,11 +1,11 @@
 <?php
 /**
  * @author Joas Schilling <nickvergessen@owncloud.com>
+ * @author Lukas Reschke <lukas@owncloud.com>
  * @author Morris Jobke <hey@morrisjobke.de>
  * @author Roeland Jago Douma <rullzer@owncloud.com>
  * @author Thomas Müller <thomas.mueller@tmit.eu>
  * @author Tom Needham <tom@owncloud.com>
- * @author Vincent Petry <pvince81@owncloud.com>
  *
  * @copyright Copyright (c) 2015, ownCloud, Inc.
  * @license AGPL-3.0
@@ -26,1248 +26,1886 @@
 
 namespace OCA\Provisioning_API\Tests;
 
+use OCA\Provisioning_API\Users;
 use OCP\IUserManager;
 use OCP\IConfig;
 use OCP\IGroupManager;
 use OCP\IUserSession;
+use Test\TestCase as OriginalTest;
+use OCP\ILogger;
 
-class UsersTest extends TestCase {
+class UsersTest extends OriginalTest {
 	
 	/** @var IUserManager */
 	protected $userManager;
-
 	/** @var IConfig */
 	protected $config;
-
-	/** @var IGroupManager */
+	/** @var \OC\Group\Manager */
 	protected $groupManager;
-
 	/** @var IUserSession */
 	protected $userSession;
+	/** @var ILogger */
+	protected $logger;
+	/** @var Users */
+	protected $api;
 
-	protected function resetParams() {
+	protected function tearDown() {
 		$_GET = null;
 		$_POST = null;
+		parent::tearDown();
 	}
 
 	protected function setup() {
 		parent::setup();
 
-		$this->userManager = \OC::$server->getUserManager();
-		$this->config = \OC::$server->getConfig();
-		$this->groupManager = \OC::$server->getGroupManager();
-		$this->userSession = \OC::$server->getUserSession();
-		$this->api = new \OCA\Provisioning_Api\Users(
-			$this->userManager, 
-			$this->config, 
-			$this->groupManager,
-			$this->userSession
-		);
+		$this->userManager = $this->getMock('\OCP\IUserManager');
+		$this->config = $this->getMock('\OCP\IConfig');
+		$this->groupManager = $this->getMockBuilder('\OC\Group\Manager')
+		->disableOriginalConstructor()->getMock();
+		$this->userSession = $this->getMock('\OCP\IUserSession');
+		$this->logger = $this->getMock('\OCP\ILogger');
+		$this->api = $this->getMockBuilder('\OCA\Provisioning_API\Users')
+			->setConstructorArgs([
+					$this->userManager,
+					$this->config,
+					$this->groupManager,
+					$this->userSession,
+					$this->logger,
+				]
+			)
+			->setMethods(['fillStorageInfo'])
+			->getMock();
+	}
 
-		$this->userSession->setUser(null);
+	public function testGetUsersNotLoggedIn() {
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue(null));
+
+		$expected = new \OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED);
+		$this->assertEquals($expected, $this->api->getUsers());
 	}
 
-	// Test getting the list of users
 	public function testGetUsersAsAdmin() {
-		$user = $this->generateUsers();
-		$this->groupManager->get('admin')->addUser($user);
-		$this->userSession->setUser($user);
-
-		$result = $this->api->getUsers();
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertTrue($result->succeeded());
-		$count = $result->getData();
-		$count = count($count['users']);
-		$this->assertEquals(count($this->userManager->search('', null, null)), $count);
-
-		$user = $this->generateUsers();
-		$_GET['search'] = $user->getUID();
-		$result = $this->api->getUsers();
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertTrue($result->succeeded());
-		$data = $result->getData();
-		$this->assertEquals($user->getUID(), reset($data['users']));
-
-		// Add several users
-		$this->generateUsers(10);
-		$this->resetParams();
-		$_GET['limit'] = 2;
-		$result = $this->api->getUsers();
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertTrue($result->succeeded());
-		$count = $result->getData();
-		$count = count($count['users']);
-		$this->assertEquals(2, $count);
-
-		$this->resetParams();
-		$_GET['limit'] = 1;
-		$_GET['offset'] = 1;
-		$result = $this->api->getUsers(array());
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertTrue($result->succeeded());
-		$data = $result->getData();
-		$this->assertEquals(array_keys($this->userManager->search('', 1, 1)), $data['users']);
+		$_GET['search'] = 'MyCustomSearch';
+
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->once())
+			->method('getUID')
+			->will($this->returnValue('admin'));
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('isAdmin')
+			->will($this->returnValue(true));
+		$this->userManager
+			->expects($this->once())
+			->method('search')
+			->with('MyCustomSearch', null, null)
+			->will($this->returnValue(['Admin' => [], 'Foo' => [], 'Bar' => []]));
+
+		$expected = new \OC_OCS_Result([
+			'users' => [
+				'Admin',
+				'Foo',
+				'Bar',
+			],
+		]);
+		$this->assertEquals($expected, $this->api->getUsers());
 	}
 
 	public function testGetUsersAsSubAdmin() {
-		$user = $this->generateUsers(10);
-		$this->userSession->setUser($user[0]);
-		$group = $this->groupManager->createGroup($this->getUniqueID());
-		\OC_SubAdmin::createSubAdmin($user[0]->getUID(), $group->getGID());
-
-		//Empty list
-		$result = $this->api->getUsers([]);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertTrue($result->succeeded());
-		$this->assertEquals(['users' => []], $result->getData());
-
-		//Some users in group
-		$group->addUser($user[1]);
-		$group->addUser($user[2]);
-		$group->addUser($user[3]);
-		$group->addUser($user[4]);
-
-		$result = $this->api->getUsers([]);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertTrue($result->succeeded());
-		$this->assertArrayHasKey('users', $result->getData());
-
-		$this->assertContains($user[1]->getUID(), $result->getData()['users']);
-		$this->assertContains($user[2]->getUID(), $result->getData()['users']);
-		$this->assertContains($user[3]->getUID(), $result->getData()['users']);
-		$this->assertContains($user[4]->getUID(), $result->getData()['users']);
-
-		$uids = [
-			$user[1]->getUID(),
-			$user[2]->getUID(),
-			$user[3]->getUID(),
-			$user[4]->getUID()
-		];
-		sort($uids);
-
-		$_GET['limit'] = 2;
-		$_GET['offset'] = 1;
-		$result = $this->api->getUsers([]);
-
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertTrue($result->succeeded());
-
-		// Disable this test for now since sorting is not done the same on all backends
-		//$this->assertEquals(['users' => array_slice($uids, 1, 2)], $result->getData());
-
-		$this->assertCount(2, $result->getData()['users']);
-
-		$counter = 0;
-		foreach ($uids as $uid) {
-			if (in_array($uid, $result->getData()['users'], true)) {
-				$counter += 1;
-			}
-		}
-
-		$this->assertEquals(2, $counter);
-	}
-
-	public function testGetUsersNoUser() {
-		$result = $this->api->getUsers([]);
-
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-		$this->assertEquals(\OCP\API::RESPOND_UNAUTHORISED, $result->getStatusCode());
-	}
-
-	public function testGetUsersAsUser() {
-		$user = $this->generateUsers();
-		$this->userSession->setUser($user);
-
-		$result = $this->api->getUsers();
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-		$this->assertEquals(\OCP\API::RESPOND_UNAUTHORISED, $result->getStatusCode());
-
-	}
-
-	public function testAddUser() {
-		$this->resetParams();
-		$_POST['userid'] = $this->getUniqueID();
-		$_POST['password'] = 'password';
-		$result = $this->api->addUser();
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertTrue($result->succeeded());
-		$this->assertTrue($this->userManager->userExists($_POST['userid']));
-		$this->assertEquals($_POST['userid'], $this->userManager->checkPassword($_POST['userid'], $_POST['password'])->getUID());
-		$this->users[] = $this->userManager->get($_POST['userid']);
-	}
-
-	public function testAddUserTwice() {
-		$this->resetParams();
-		$_POST['userid'] = $this->getUniqueID();
-		$_POST['password'] = 'password';
-		$this->api->addUser();
-		$result = $this->api->addUser();
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-		$this->assertEquals(102, $result->getStatusCode());
-		$this->assertEquals('User already exists', $result->getMeta()['message']);
-	}
-
-	public function testAddUserFails() {
-		$uid = $this->getUniqueID();
+		$_GET['search'] = 'MyCustomSearch';
 
-		$userManager = $this->getMockBuilder('\OCP\IUserManager')
-			->disableOriginalConstructor()
-			->getMock();
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->once())
+			->method('getUID')
+			->will($this->returnValue('subadmin'));
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('isAdmin')
+			->will($this->returnValue(false));
+		$firstGroup = $this->getMock('\OCP\IGroup');
+		$firstGroup
+			->expects($this->once())
+			->method('getGID')
+			->will($this->returnValue('FirstGroup'));
+		$secondGroup = $this->getMock('\OCP\IGroup');
+		$secondGroup
+			->expects($this->once())
+			->method('getGID')
+			->will($this->returnValue('SecondGroup'));
+		$subAdminManager = $this->getMockBuilder('\OC\Subadmin')
+			->disableOriginalConstructor()->getMock();
+		$subAdminManager
+			->expects($this->once())
+			->method('isSubAdmin')
+			->with($loggedInUser)
+			->will($this->returnValue(true));
+		$subAdminManager
+			->expects($this->once())
+			->method('getSubAdminsGroups')
+			->with($loggedInUser)
+			->will($this->returnValue([$firstGroup, $secondGroup]));
+		$this->groupManager
+			->expects($this->once())
+			->method('getSubAdmin')
+			->will($this->returnValue($subAdminManager));
+		$this->groupManager
+			->expects($this->any())
+			->method('displayNamesInGroup')
+			->will($this->onConsecutiveCalls(['AnotherUserInTheFirstGroup' => []], ['UserInTheSecondGroup' => []]));
+
+		$expected = new \OC_OCS_Result([
+			'users' => [
+				'AnotherUserInTheFirstGroup',
+				'UserInTheSecondGroup',
+			],
+		]);
+		$this->assertEquals($expected, $this->api->getUsers());
+	}
+
+	public function testGetUsersAsRegularUser() {
+		$_GET['search'] = 'MyCustomSearch';
+
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->once())
+			->method('getUID')
+			->will($this->returnValue('regularUser'));
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('isAdmin')
+			->will($this->returnValue(false));
+		$subAdminManager = $this->getMockBuilder('\OC\Subadmin')
+			->disableOriginalConstructor()->getMock();
+		$subAdminManager
+			->expects($this->once())
+			->method('isSubAdmin')
+			->with($loggedInUser)
+			->will($this->returnValue(false));
+		$this->groupManager
+			->expects($this->once())
+			->method('getSubAdmin')
+			->will($this->returnValue($subAdminManager));
+
+		$expected = new \OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED);
+		$this->assertEquals($expected, $this->api->getUsers());
+	}
+
+	public function testAddUserAlreadyExisting() {
+		$_POST['userid'] = 'AlreadyExistingUser';
+		$this->userManager
+			->expects($this->once())
+			->method('userExists')
+			->with('AlreadyExistingUser')
+			->will($this->returnValue(true));
+		$this->logger
+			->expects($this->once())
+			->method('error')
+			->with('Failed addUser attempt: User already exists.', ['app' => 'ocs_api']);
+
+		$expected = new \OC_OCS_Result(null, 102, 'User already exists');
+		$this->assertEquals($expected, $this->api->addUser());
+	}
 
-		$userManager->expects($this->once())
+	public function testAddUserSuccessful() {
+		$_POST['userid'] = 'NewUser';
+		$_POST['password'] = 'PasswordOfTheNewUser';
+		$this->userManager
+			->expects($this->once())
 			->method('userExists')
-			->with($uid)
-			->willReturn(false);
-		$userManager->expects($this->once())
+			->with('NewUser')
+			->will($this->returnValue(false));
+		$this->userManager
+			->expects($this->once())
 			->method('createUser')
-			->with($uid, 'password')
-			->will($this->throwException(new \Exception));
-
-		$api = new \OCA\Provisioning_Api\Users(
-			$userManager, 
-			$this->config, 
-			$this->groupManager,
-			$this->userSession
-		);
+			->with('NewUser', 'PasswordOfTheNewUser');
+		$this->logger
+			->expects($this->once())
+			->method('info')
+			->with('Successful addUser call with userid: NewUser', ['app' => 'ocs_api']);
+
+		$expected = new \OC_OCS_Result(null, 100);
+		$this->assertEquals($expected, $this->api->addUser());
+	}
 
-		$this->resetParams();
-		$_POST['userid'] = $uid;
-		$_POST['password'] = 'password';
-		$result = $api->addUser();
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-		$this->assertEquals(101, $result->getStatusCode());
-		$this->assertEquals('Bad request', $result->getMeta()['message']);
-	}
-
-	public function testGetUserOnSelf() {
-		$user = $this->generateUsers();
-		$user->setDisplayName('foobar');
-		$this->userSession->setUser($user);
-		$params = ['userid' => $user->getUID()];
-		$result = $this->api->getUser($params);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertTrue($result->succeeded());
-		$data = $result->getData();
-		
-		$this->assertEquals('foobar', $data['displayname']);
-	}
-
-	public function testGetUserOnNonExistingUser() {
-		$user = $this->generateUsers();
-		$this->groupManager->get('admin')->addUser($user);
-		$this->userSession->setUser($user);
-		$params = array();
-		$params['userid'] = $this->getUniqueID();
-		while($this->userManager->userExists($params['userid'])) {
-			$params['userid'] = $this->getUniqueID();
-		}
-		$result = $this->api->getUser($params);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-		$this->assertEquals(\OCP\API::RESPOND_NOT_FOUND, $result->getStatusCode());
-
-	}
-
-	public function testGetUserOnOtherUser() {
-		$users = $this->generateUsers(2);
-		$params = ['userid' => $users[0]->getUID()];
-		$this->userSession->setUser($users[1]);
-		$result = $this->api->getUser($params);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-
-		// Now as as admin
-		$users = $this->generateUsers(2);
-		$params['userid'] = $users[0]->getUID();
-		// login to generate home
-		$this->userSession->setUser($users[0]);
-		$this->groupManager->get('admin')->addUser($users[1]);
-		$this->userSession->setUser($users[1]);
-		$result = $this->api->getUser($params);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertTrue($result->succeeded());
-		$data = $result->getData();
-		$this->assertEquals(\OC::$server->getConfig()->getUserValue($users[0]->getUID(), 'core', 'enabled', 'true'), $data['enabled']);
-	}
-
-	public function testEditOwnDisplayName() {
-		// Test editing own name
-		$user = $this->generateUsers();
-		$this->userSession->setUser($user);
-		$result = $this->api->editUser(
-			array(
-				'userid' => $user->getUID(),
-				'_put' => array(
-					'key' => 'display',
-					'value' => 'newname',
-					),
-				)
-			);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertTrue($result->succeeded());
-		$this->assertEquals('newname', $user->getDisplayName());
-
-	}
-
-	public function testAdminEditDisplayNameOfUser() {
-		// Test admin editing users name
-		$user = $this->generateUsers();
-		$this->groupManager->get('admin')->addUser($user);
-		$this->userSession->setUser($user);
-		$user2 = $this->generateUsers();
-		$result = $this->api->editUser(
-			[
-				'userid' => $user2->getUID(),
-				'_put' => [
-					'key' => 'display',
-					'value' => 'newname',
-				],
-			]
-			);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertTrue($result->succeeded());
-		$this->assertEquals('newname', $user2->getDisplayName());
-
-	}
-
-	public function testUserEditOtherUserDisplayName() {
-		// Test editing other users name
-		$user = $this->generateUsers();
-		$this->userSession->setUser($user);
-		$user2 = $this->generateUsers();
-		$result = $this->api->editUser(
-			array(
-				'userid' => $user2->getUID(),
-				'_put' => array(
-					'key' => 'display',
-					'value' => 'newname',
-					),
-				)
-			);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-
-	}
-
-	/**
-	 * @dataProvider providesQuotas
-	 * @param $expected
-	 * @param $quota
-	 */
-	public function testEditOwnQuota($expected, $quota) {
-		$user = $this->generateUsers();
-		$this->userSession->setUser($user);
-		$result = $this->api->editUser(
+	public function testAddUserUnsuccessful() {
+		$_POST['userid'] = 'NewUser';
+		$_POST['password'] = 'PasswordOfTheNewUser';
+		$this->userManager
+			->expects($this->once())
+			->method('userExists')
+			->with('NewUser')
+			->will($this->returnValue(false));
+		$this->userManager
+			->expects($this->once())
+			->method('createUser')
+			->with('NewUser', 'PasswordOfTheNewUser')
+			->will($this->throwException(new \Exception('User backend not found.')));
+		$this->logger
+			->expects($this->once())
+			->method('error')
+			->with('Failed addUser attempt with exception: User backend not found.', ['app' => 'ocs_api']);
+
+		$expected = new \OC_OCS_Result(null, 101, 'Bad request');
+		$this->assertEquals($expected, $this->api->addUser());
+	}
+
+	public function testGetUserNotLoggedIn() {
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue(null));
+
+		$expected = new \OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED);
+		$this->assertEquals($expected, $this->api->getUser(['userid' => 'UserToGet']));
+	}
+
+	public function testGetUserTargetDoesNotExist() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('UserToGet')
+			->will($this->returnValue(null));
+
+		$expected = new \OC_OCS_Result(null, \OCP\API::RESPOND_NOT_FOUND, 'The requested user could not be found');
+		$this->assertEquals($expected, $this->api->getUser(['userid' => 'UserToGet']));
+	}
+
+	public function testGetUserAsAdmin() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->once())
+			->method('getUID')
+			->will($this->returnValue('admin'));
+		$targetUser = $this->getMock('\OCP\IUser');
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('UserToGet')
+			->will($this->returnValue($targetUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('isAdmin')
+			->with('admin')
+			->will($this->returnValue(true));
+		$this->config
+			->expects($this->at(0))
+			->method('getUserValue')
+			->with('UserToGet', 'core', 'enabled', 'true')
+			->will($this->returnValue('true'));
+		$this->api
+			->expects($this->once())
+			->method('fillStorageInfo')
+			->with('UserToGet')
+			->will($this->returnValue(['DummyValue']));
+		$this->config
+			->expects($this->at(1))
+			->method('getUserValue')
+			->with('UserToGet', 'settings', 'email')
+			->will($this->returnValue('demo@owncloud.org'));
+		$targetUser
+			->expects($this->once())
+			->method('getDisplayName')
+			->will($this->returnValue('Demo User'));
+
+		$expected = new \OC_OCS_Result(
 			[
-				'userid' => $user->getUID(),
-				'_put' => [
-					'key' => 'quota',
-					'value' => $quota,
-				],
+				'enabled' => 'true',
+				'quota' => ['DummyValue'],
+				'email' => 'demo@owncloud.org',
+				'displayname' => 'Demo User',
 			]
-			);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-		$this->assertEquals(997, $result->getStatusCode());
-	}
-
-	/**
-	 * @dataProvider providesQuotas
-	 * @param $expected
-	 * @param $quota
-	 */
-	public function testEditOwnQuotaAsAdmin($expected, $quota) {
-		$user = $this->generateUsers();
-		$this->groupManager->get('admin')->addUser($user);
-		$this->userSession->setUser($user);
-		$result = $this->api->editUser(
+		);
+		$this->assertEquals($expected, $this->api->getUser(['userid' => 'UserToGet']));
+	}
+
+	public function testGetUserAsSubAdminAndUserIsAccessible() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->once())
+			->method('getUID')
+			->will($this->returnValue('subadmin'));
+		$targetUser = $this->getMock('\OCP\IUser');
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('UserToGet')
+			->will($this->returnValue($targetUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('isAdmin')
+			->with('subadmin')
+			->will($this->returnValue(false));
+		$subAdminManager = $this->getMockBuilder('\OC\Subadmin')
+			->disableOriginalConstructor()
+			->getMock();
+		$subAdminManager
+			->expects($this->once())
+			->method('isUserAccessible')
+			->with($loggedInUser, $targetUser)
+			->will($this->returnValue(true));
+		$this->groupManager
+			->expects($this->once())
+			->method('getSubAdmin')
+			->will($this->returnValue($subAdminManager));
+		$this->config
+			->expects($this->at(0))
+			->method('getUserValue')
+			->with('UserToGet', 'core', 'enabled', 'true')
+			->will($this->returnValue('true'));
+		$this->api
+			->expects($this->once())
+			->method('fillStorageInfo')
+			->with('UserToGet')
+			->will($this->returnValue(['DummyValue']));
+		$this->config
+			->expects($this->at(1))
+			->method('getUserValue')
+			->with('UserToGet', 'settings', 'email')
+			->will($this->returnValue('demo@owncloud.org'));
+		$targetUser
+			->expects($this->once())
+			->method('getDisplayName')
+			->will($this->returnValue('Demo User'));
+
+		$expected = new \OC_OCS_Result(
 			[
-				'userid' => $user->getUID(),
-				'_put' => [
-					'key' => 'quota',
-					'value' => $quota,
-				],
+				'enabled' => 'true',
+				'quota' => ['DummyValue'],
+				'email' => 'demo@owncloud.org',
+				'displayname' => 'Demo User',
 			]
-			);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertEquals($expected, $result->succeeded());
-	}
-
-	public function providesQuotas() {
-		return [
-			[true, '20G'],
-			[true, '1234567'],
-			[true, 'none'],
-			[true, 'default'],
-			[false, 'qwertzu'],
-			[true, 0],
-			[true, -1]
-		];
-	}
-
-	public function testAdminEditOwnQuota() {
-		$user = $this->generateUsers();
-		$this->groupManager->get('admin')->addUser($user);
-		$this->userSession->setUser($user);
-		$result = $this->api->editUser(
-			array(
-				'userid' => $user->getUID(),
-				'_put' => array(
-					'key' => 'quota',
-					'value' => '20G',
-					),
-				)
-			);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertTrue($result->succeeded());
-	}
-
-	public function testAdminEditOtherUserQuota() {
-		$user = $this->generateUsers();
-		$this->groupManager->get('admin')->addUser($user);
-		$this->userSession->setUser($user);
-		$user2 = $this->generateUsers();
-		$result = $this->api->editUser(
-			array(
-				'userid' => $user2->getUID(),
-				'_put' => array(
-					'key' => 'quota',
-					'value' => '20G',
-					),
-				)
-			);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertTrue($result->succeeded());
-	}
-
-	public function testUserEditOtherUserQuota() {
-		$user = $this->generateUsers();
-		$this->userSession->setUser($user);
-		$user2 = $this->generateUsers();
-		$result = $this->api->editUser(
-			array(
-				'userid' => $user2->getUID(),
-				'_put' => array(
-					'key' => 'quota',
-					'value' => '20G',
-					),
-				)
-			);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-	}
-
-	public function testUserEditOwnEmail() {
-		$user = $this->generateUsers();
-		$email = 'test@example.com';
-		$this->userSession->setUser($user);
-		$result = $this->api->editUser(
-			array(
-				'userid' => $user->getUID(),
-				'_put' => array(
-					'key' => 'email',
-					'value' => $email,
-					),
-				)
-			);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertTrue($result->succeeded());
-		$this->assertEquals($email, \OC::$server->getConfig()->getUserValue($user->getUID(), 'settings', 'email', null));
-	}
-
-	public function testUserEditOwnEmailInvalid() {
-		$user = $this->generateUsers();
-		$email = 'test@example';
-		$this->userSession->setUser($user);
-		$result = $this->api->editUser([
-			'userid' => $user->getUID(),
-			'_put' => [
-				'key' => 'email',
-				'value' => $email,
-			],
-		]);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-		$this->assertEquals(102, $result->getStatusCode());
-	}
-
-	public function testUserEditOtherUserEmailAsUser() {
-		$users = $this->generateUsers(2);
-		$email = 'test@example.com';
-		$this->userSession->setUser($users[0]);
-		$result = $this->api->editUser(
-			array(
-				'userid' => $users[1]->getUID(),
-				'_put' => array(
-					'key' => 'email',
-					'value' => $email,
-					),
-				)
-			);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-	}
-
-	public function testUserEditOtherUserEmailAsAdmin() {
-		$users = $this->generateUsers(2);
-		$email = 'test@example.com';
-		$this->userSession->setUser($users[0]);
-		$this->groupManager->get('admin')->addUser($users[0]);
-		$result = $this->api->editUser(
-			array(
-				'userid' => $users[1]->getUID(),
-				'_put' => array(
-					'key' => 'email',
-					'value' => $email,
-					),
-				)
-			);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertTrue($result->succeeded());
-		$this->assertEquals($email, \OC::$server->getConfig()->getUserValue($users[1]->getUID(), 'settings', 'email', null));
-	}
-
-	public function testUserEditOwnPassword() {
-		$user = $this->generateUsers();
-		$password = 'foo';
-		$this->userSession->setUser($user);
-		$result = $this->api->editUser([
-			'userid' => $user->getUID(),
-			'_put' => [
-				'key' => 'password',
-				'value' => $password,
-			],
-		]);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertTrue($result->succeeded());
-	}
-
-	public function testUserEditOtherUserPasswordAsUser() {
-		$users = $this->generateUsers(2);
-		$password = 'foo';
-		$this->userSession->setUser($users[0]);
-		$result = $this->api->editUser([
-			'userid' => $users[1]->getUID(),
-			'_put' => [
-				'key' => 'password',
-				'value' => $password,
-			],
-		]);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-	}
-
-	public function testUserEditOtherUserPasswordAsAdmin() {
-		$users = $this->generateUsers(2);
-		$password = 'foo';
-		$this->userSession->setUser($users[0]);
-		$this->groupManager->get('admin')->addUser($users[0]);
-		$result = $this->api->editUser([
-			'userid' => $users[1]->getUID(),
-			'_put' => [
-				'key' => 'password',
-				'value' => $password,
-			],
-		]);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertTrue($result->succeeded());
-	}
-
-	public function testDeleteSelf() {
-		$user = $this->generateUsers();
-		$this->userSession->setUser($user);
-		$result = $this->api->deleteUser(array(
-			'userid' => $user->getUID(),
-			));
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-	}
-
-	public function testDeleteOtherAsUser() {
-		$user = $this->generateUsers();
-		$this->userSession->setUser($user);
-		$user2 = $this->generateUsers();
-		$result = $this->api->deleteUser(array(
-			'userid' => $user2->getUID(),
-			));
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-	}
-
-	public function testDeleteOtherAsSubAdmin() {
-		$user = $this->generateUsers();
-		$this->userSession->setUser($user);
-		$user2 = $this->generateUsers();
-		$group = $this->groupManager->createGroup($this->getUniqueID());
-		$group->addUser($user);
-		$group->addUser($user2);
-		\OC_SubAdmin::createSubAdmin($user->getUID(), $group->getGID());
-		$result = $this->api->deleteUser(array(
-			'userid' => $user2->getUID(),
-			));
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertTrue($result->succeeded());
-		$group->delete();
-	}
-
-	public function testDeleteOtherAsIrelevantSubAdmin() {
-		$user = $this->generateUsers();
-		$this->userSession->setUser($user);
-		$user2 = $this->generateUsers();
-		$group = $this->groupManager->createGroup($this->getUniqueID());
-		$group2 = $this->groupManager->createGroup($this->getUniqueID());
-		$group->addUser($user);
-		$group2->addUser($user2);
-		\OC_SubAdmin::createSubAdmin($user->getUID(), $group->getGID());
-		$result = $this->api->deleteUser(array(
-			'userid' => $user2->getUID(),
-		));
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-		$group->delete();
-		$group2->delete();
-	}
-
-	public function testDeleteOtherAsAdmin() {
-		$user = $this->generateUsers();
-		$this->groupManager->get('admin')->addUser($user);
-		$this->userSession->setUser($user);
-		$user2 = $this->generateUsers();
-		$result = $this->api->deleteUser(array(
-			'userid' => $user2->getUID(),
-			));
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertTrue($result->succeeded());
-	}
-
-	public function testDeleteSelfAsAdmin() {
-		$user = $this->generateUsers();
-		$this->groupManager->get('admin')->addUser($user);
-		$this->userSession->setUser($user);
-		$result = $this->api->deleteUser(array(
-			'userid' => $user->getUID(),
-			));
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-	}
-
-	public function testDeleteFails() {
-		$user = $this->getMockBuilder('\OCP\IUser')
+		);
+		$this->assertEquals($expected, $this->api->getUser(['userid' => 'UserToGet']));
+	}
+
+	public function testGetUserAsSubAdminAndUserIsNotAccessible() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->exactly(2))
+			->method('getUID')
+			->will($this->returnValue('subadmin'));
+		$targetUser = $this->getMock('\OCP\IUser');
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('UserToGet')
+			->will($this->returnValue($targetUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('isAdmin')
+			->with('subadmin')
+			->will($this->returnValue(false));
+		$subAdminManager = $this->getMockBuilder('\OC\Subadmin')
 			->disableOriginalConstructor()
 			->getMock();
-		$user->expects($this->once())
-			->method('delete')
-			->willReturn(false);
+		$subAdminManager
+			->expects($this->once())
+			->method('isUserAccessible')
+			->with($loggedInUser, $targetUser)
+			->will($this->returnValue(false));
+		$this->groupManager
+			->expects($this->once())
+			->method('getSubAdmin')
+			->will($this->returnValue($subAdminManager));
+
+		$expected = new \OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED);
+		$this->assertEquals($expected, $this->api->getUser(['userid' => 'UserToGet']));
+	}
 
-		$user2 = $this->getMockBuilder('\OCP\IUser')
+	public function testGetUserAsSubAdminSelfLookup() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->exactly(2))
+			->method('getUID')
+			->will($this->returnValue('subadmin'));
+		$targetUser = $this->getMock('\OCP\IUser');
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('subadmin')
+			->will($this->returnValue($targetUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('isAdmin')
+			->with('subadmin')
+			->will($this->returnValue(false));
+		$subAdminManager = $this->getMockBuilder('\OC\Subadmin')
 			->disableOriginalConstructor()
 			->getMock();
-		$user2->expects($this->any())
+		$subAdminManager
+			->expects($this->once())
+			->method('isUserAccessible')
+			->with($loggedInUser, $targetUser)
+			->will($this->returnValue(false));
+		$this->groupManager
+			->expects($this->once())
+			->method('getSubAdmin')
+			->will($this->returnValue($subAdminManager));
+		$this->api
+			->expects($this->once())
+			->method('fillStorageInfo')
+			->with('subadmin')
+			->will($this->returnValue(['DummyValue']));
+		$this->config
+			->expects($this->once())
+			->method('getUserValue')
+			->with('subadmin', 'settings', 'email')
+			->will($this->returnValue('subadmin@owncloud.org'));
+		$targetUser
+			->expects($this->once())
+			->method('getDisplayName')
+			->will($this->returnValue('Subadmin User'));
+
+		$expected = new \OC_OCS_Result([
+			'quota' => ['DummyValue'],
+			'email' => 'subadmin@owncloud.org',
+			'displayname' => 'Subadmin User',
+		]);
+		$this->assertEquals($expected, $this->api->getUser(['userid' => 'subadmin']));
+	}
+
+	public function testEditUserNotLoggedIn() {
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue(null));
+
+		$expected = new \OC_OCS_Result(null, \OCP\API::RESPOND_UNAUTHORISED);
+		$this->assertEquals($expected, $this->api->editUser(['userid' => 'UserToEdit']));
+	}
+
+	public function testEditUserRegularUserSelfEditChangeDisplayName() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->any())
+			->method('getUID')
+			->will($this->returnValue('UserToEdit'));
+		$targetUser = $this->getMock('\OCP\IUser');
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('UserToEdit')
+			->will($this->returnValue($targetUser));
+		$targetUser
+			->expects($this->once())
+			->method('setDisplayName')
+			->with('NewDisplayName');
+
+		$expected = new \OC_OCS_Result(null, 100);
+		$this->assertEquals($expected, $this->api->editUser(['userid' => 'UserToEdit', '_put' => ['key' => 'display', 'value' => 'NewDisplayName']]));
+	}
+
+	public function testEditUserRegularUserSelfEditChangeEmailValid() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->any())
+			->method('getUID')
+			->will($this->returnValue('UserToEdit'));
+		$targetUser = $this->getMock('\OCP\IUser');
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('UserToEdit')
+			->will($this->returnValue($targetUser));
+		$this->config
+			->expects($this->once())
+			->method('setUserValue')
+			->with('UserToEdit', 'settings', 'email', 'demo@owncloud.org');
+
+		$expected = new \OC_OCS_Result(null, 100);
+		$this->assertEquals($expected, $this->api->editUser(['userid' => 'UserToEdit', '_put' => ['key' => 'email', 'value' => 'demo@owncloud.org']]));
+	}
+
+	public function testEditUserRegularUserSelfEditChangeEmailInvalid() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->any())
+			->method('getUID')
+			->will($this->returnValue('UserToEdit'));
+		$targetUser = $this->getMock('\OCP\IUser');
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('UserToEdit')
+			->will($this->returnValue($targetUser));
+
+		$expected = new \OC_OCS_Result(null, 102);
+		$this->assertEquals($expected, $this->api->editUser(['userid' => 'UserToEdit', '_put' => ['key' => 'email', 'value' => 'demo.org']]));
+	}
+
+	public function testEditUserRegularUserSelfEditChangePassword() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->any())
+			->method('getUID')
+			->will($this->returnValue('UserToEdit'));
+		$targetUser = $this->getMock('\OCP\IUser');
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('UserToEdit')
+			->will($this->returnValue($targetUser));
+		$targetUser
+			->expects($this->once())
+			->method('setPassword')
+			->with('NewPassword');
+
+		$expected = new \OC_OCS_Result(null, 100);
+		$this->assertEquals($expected, $this->api->editUser(['userid' => 'UserToEdit', '_put' => ['key' => 'password', 'value' => 'NewPassword']]));
+	}
+
+	public function testEditUserRegularUserSelfEditChangeQuota() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->any())
+			->method('getUID')
+			->will($this->returnValue('UserToEdit'));
+		$targetUser = $this->getMock('\OCP\IUser');
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('UserToEdit')
+			->will($this->returnValue($targetUser));
+
+		$expected = new \OC_OCS_Result(null, 997);
+		$this->assertEquals($expected, $this->api->editUser(['userid' => 'UserToEdit', '_put' => ['key' => 'quota', 'value' => 'NewQuota']]));
+	}
+
+	public function testEditUserAdminUserSelfEditChangeValidQuota() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->any())
+			->method('getUID')
+			->will($this->returnValue('UserToEdit'));
+		$targetUser = $this->getMock('\OCP\IUser');
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('UserToEdit')
+			->will($this->returnValue($targetUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('isAdmin')
+			->with('UserToEdit')
+			->will($this->returnValue(true));
+		$this->config
+			->expects($this->once())
+			->method('setUserValue')
+			->with('UserToEdit', 'files', 'quota', '2.9 MB');
+
+		$expected = new \OC_OCS_Result(null, 100);
+		$this->assertEquals($expected, $this->api->editUser(['userid' => 'UserToEdit', '_put' => ['key' => 'quota', 'value' => '3042824']]));
+	}
+
+	public function testEditUserAdminUserSelfEditChangeInvalidQuota() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->any())
 			->method('getUID')
-			->willReturn('user2');
+			->will($this->returnValue('UserToEdit'));
+		$targetUser = $this->getMock('\OCP\IUser');
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('UserToEdit')
+			->will($this->returnValue($targetUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('isAdmin')
+			->with('UserToEdit')
+			->will($this->returnValue(true));
+
+		$expected = new \OC_OCS_Result(null, 103, 'Invalid quota value ABC');
+		$this->assertEquals($expected, $this->api->editUser(['userid' => 'UserToEdit', '_put' => ['key' => 'quota', 'value' => 'ABC']]));
+	}
 
-		$userManager = $this->getMockBuilder('\OCP\IUserManager')
+	public function testEditUserAdminUserEditChangeValidQuota() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->any())
+			->method('getUID')
+			->will($this->returnValue('admin'));
+		$targetUser = $this->getMock('\OCP\IUser');
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('UserToEdit')
+			->will($this->returnValue($targetUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('isAdmin')
+			->with('admin')
+			->will($this->returnValue(true));
+		$subAdminManager = $this->getMockBuilder('\OC\Subadmin')
 			->disableOriginalConstructor()
 			->getMock();
-		$userManager->expects($this->once())
-			->method('userExists')
-			->with('user')
-			->willReturn(true);
-		$userManager->expects($this->once())
-			->method('get')
-			->with('user')
-			->willReturn($user);
+		$this->groupManager
+			->expects($this->once())
+			->method('getSubAdmin')
+			->will($this->returnValue($subAdminManager));
+		$this->config
+			->expects($this->once())
+			->method('setUserValue')
+			->with('UserToEdit', 'files', 'quota', '2.9 MB');
+
+		$expected = new \OC_OCS_Result(null, 100);
+		$this->assertEquals($expected, $this->api->editUser(['userid' => 'UserToEdit', '_put' => ['key' => 'quota', 'value' => '3042824']]));
+	}
 
-		$userSession = $this->getMockBuilder('\OCP\IUserSession')
+	public function testEditUserSubadminUserAccessible() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->any())
+			->method('getUID')
+			->will($this->returnValue('subadmin'));
+		$targetUser = $this->getMock('\OCP\IUser');
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('UserToEdit')
+			->will($this->returnValue($targetUser));
+		$subAdminManager = $this->getMockBuilder('\OC\Subadmin')
 			->disableOriginalConstructor()
 			->getMock();
-		$userSession->expects($this->once())
+		$subAdminManager
+			->expects($this->once())
+			->method('isUserAccessible')
+			->with($loggedInUser, $targetUser)
+			->will($this->returnValue(true));
+		$this->groupManager
+			->expects($this->once())
+			->method('getSubAdmin')
+			->will($this->returnValue($subAdminManager));
+		$this->config
+			->expects($this->once())
+			->method('setUserValue')
+			->with('UserToEdit', 'files', 'quota', '2.9 MB');
+
+		$expected = new \OC_OCS_Result(null, 100);
+		$this->assertEquals($expected, $this->api->editUser(['userid' => 'UserToEdit', '_put' => ['key' => 'quota', 'value' => '3042824']]));
+	}
+
+	public function testEditUserSubadminUserInaccessible() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->any())
+			->method('getUID')
+			->will($this->returnValue('subadmin'));
+		$targetUser = $this->getMock('\OCP\IUser');
+		$this->userSession
+			->expects($this->once())
 			->method('getUser')
-			->willReturn($user2);
-	
-		$groupManager = $this->getMockBuilder('\OCP\IGroupManager')
+			->will($this->returnValue($loggedInUser));
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('UserToEdit')
+			->will($this->returnValue($targetUser));
+		$subAdminManager = $this->getMockBuilder('\OC\Subadmin')
 			->disableOriginalConstructor()
 			->getMock();
-		$groupManager->expects($this->once())
+		$subAdminManager
+			->expects($this->once())
+			->method('isUserAccessible')
+			->with($loggedInUser, $targetUser)
+			->will($this->returnValue(false));
+		$this->groupManager
+			->expects($this->once())
+			->method('getSubAdmin')
+			->will($this->returnValue($subAdminManager));
+
+		$expected = new \OC_OCS_Result(null, 997);
+		$this->assertEquals($expected, $this->api->editUser(['userid' => 'UserToEdit', '_put' => ['key' => 'quota', 'value' => '3042824']]));
+	}
+
+	public function testDeleteUserNotLoggedIn() {
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue(null));
+
+		$expected = new \OC_OCS_Result(null, 997);
+		$this->assertEquals($expected, $this->api->deleteUser(['userid' => 'UserToDelete']));
+	}
+
+	public function testDeleteUserNotExistingUser() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->any())
+			->method('getUID')
+			->will($this->returnValue('UserToEdit'));
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('UserToDelete')
+			->will($this->returnValue(null));
+
+		$expected = new \OC_OCS_Result(null, 101);
+		$this->assertEquals($expected, $this->api->deleteUser(['userid' => 'UserToDelete']));
+	}
+
+	public function testDeleteUserSelf() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->any())
+			->method('getUID')
+			->will($this->returnValue('UserToDelete'));
+		$targetUser = $this->getMock('\OCP\IUser');
+		$targetUser
+			->expects($this->once())
+			->method('getUID')
+			->will($this->returnValue('UserToDelete'));
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('UserToDelete')
+			->will($this->returnValue($targetUser));
+
+		$expected = new \OC_OCS_Result(null, 101);
+		$this->assertEquals($expected, $this->api->deleteUser(['userid' => 'UserToDelete']));
+	}
+
+	public function testDeleteSuccessfulUserAsAdmin() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->any())
+			->method('getUID')
+			->will($this->returnValue('admin'));
+		$targetUser = $this->getMock('\OCP\IUser');
+		$targetUser
+			->expects($this->once())
+			->method('getUID')
+			->will($this->returnValue('UserToDelete'));
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('UserToDelete')
+			->will($this->returnValue($targetUser));
+		$this->groupManager
+			->expects($this->once())
 			->method('isAdmin')
-			->with('user2')
-			->willReturn(true);
-
-		$api = new \OCA\Provisioning_Api\Users(
-			$userManager, 
-			$this->config, 
-			$groupManager,
-			$userSession
-		);
+			->with('admin')
+			->will($this->returnValue(true));
+		$targetUser
+			->expects($this->once())
+			->method('delete')
+			->will($this->returnValue(true));
 
-		$result = $api->deleteUser([
-			'userid' => 'user',
-		]);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-		$this->assertEquals(101, $result->getStatusCode());
-	}
-
-	public function testGetUsersGroupsOnSelf() {
-		$user = $this->generateUsers();
-		$this->userSession->setUser($user);
-		$group = $this->getUniqueID();
-		$group = $this->groupManager->createGroup($group);
-		$group->addUser($user);
-		$result = $this->api->getUsersGroups(array(
-			'userid' => $user->getUID(),
-			));
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertTrue($result->succeeded());
-		$data = $result->getData();
-		$this->assertEquals($group->getGID(), reset($data['groups']));
-		$this->assertEquals(1, count($data['groups']));
-		$group->delete();
-	}
-
-	public function testGetUsersGroupOnOther() {
-		$user1 = $this->generateUsers();
-		$user2 = $this->generateUsers();
-		$this->userSession->setUser($user1);
-		$group = $this->getUniqueID();
-		$group = $this->groupManager->createGroup($group);
-		$group->addUser($user2);
-		$result = $this->api->getUsersGroups(array(
-			'userid' => $user2->getUID(),
-			));
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-		$group->delete();
-	}
-
-	public function testGetUsersGroupOnOtherAsAdmin() {
-		$user1 = $this->generateUsers();
-		$this->groupManager->get('admin')->addUser($user1);
-		$user2 = $this->generateUsers();
-		$this->userSession->setUser($user1);
-		$group = $this->getUniqueID();
-		$group = $this->groupManager->createGroup($group);
-		$group->addUser($user2);
-		$result = $this->api->getUsersGroups(array(
-			'userid' => $user2->getUID(),
-			));
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertTrue($result->succeeded());
-		$data = $result->getData();
-		$this->assertEquals($group->getGID(), reset($data['groups']));
-		$this->assertEquals(1, count($data['groups']));
-		$group->delete();
-	}
-
-	public function testGetUsersGroupsOnOtherAsSubAdmin() {
-		$user1 = $this->generateUsers();
-		$user2 = $this->generateUsers();
-		$this->userSession->setUser($user1);
-		$group1 = $this->getUniqueID();
-		$group2 = $this->getUniqueID();
-		$group1 = $this->groupManager->createGroup($group1);
-		$group2 = $this->groupManager->createGroup($group2);
-		$group1->addUser($user2);
-		$group2->addUser($user2);
-		$group1->addUser($user1);
-		\OC_SubAdmin::createSubAdmin($user1->getUID(), $group1->getGID());
-		$result = $this->api->getUsersGroups(array(
-			'userid' => $user2->getUID(),
-			));
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertTrue($result->succeeded());
-		$data = $result->getData();
-		$this->assertEquals($group1->getGID(), reset($data['groups']));
-		$this->assertEquals(1, count($data['groups']));
-		$group1->delete();
-		$group2->delete();
-	}
-
-	public function testGetUsersGroupsOnOtherAsIrelevantSubAdmin() {
-		$user1 = $this->generateUsers();
-		$user2 = $this->generateUsers();
-		$this->userSession->setUser($user1);
-		$group1 = $this->getUniqueID();
-		$group2 = $this->getUniqueID();
-		$group1 = $this->groupManager->createGroup($group1);
-		$group2 = $this->groupManager->createGroup($group2);
-		$group2->addUser($user2);
-		$group1->addUser($user1);
-		\OC_SubAdmin::createSubAdmin($user1->getUID(), $group1->getGID());
-		$result = $this->api->getUsersGroups(array(
-			'userid' => $user2->getUID(),
-			));
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-		$group1->delete();
-		$group2->delete();
-	}
-
-	public function testAddToGroup() {
-		$user = $this->generateUsers();
-		$group = $this->getUniqueID();
-		$group = $this->groupManager->createGroup($group);
-		$this->userSession->setUser($user);
-		$_POST['groupid'] = $group->getGID();
-		$result = $this->api->addToGroup(array(
-			'userid' => $user->getUID(),
-			));
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-		$this->assertFalse($group->inGroup($user));
-		$group->delete();
-	}
-
-	public function testAddToGroupAsAdmin() {
-		$user = $this->generateUsers();
-		$this->groupManager->get('admin')->addUser($user);
-		$group = $this->getUniqueID();
-		$group = $this->groupManager->createGroup($group);
-		$user2 = $this->generateUsers();
-		$this->userSession->setUser($user);
-		$_POST['groupid'] = $group->getGID();
-		$result = $this->api->addToGroup(array(
-			'userid' => $user2->getUID(),
-			));
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertTrue($result->succeeded());
-		$this->assertTrue($group->inGroup($user2));
-		$group->delete();
-	}
-
-	public function testAddToGroupAsSubAdmin() {
-		$user1 = $this->generateUsers();
-		$user2 = $this->generateUsers();
-		$this->userSession->setUser($user1);
-		$group1 = $this->getUniqueID();
-		$group1 = $this->groupManager->createGroup($group1);
-		\OC_SubAdmin::createSubAdmin($user1->getUID(), $group1->getGID());
-		$_POST['groupid'] = $group1->getGID();
-		$result = $this->api->addToGroup(array(
-			'userid' => $user2->getUID(),
-			));
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-		$this->assertFalse($group1->inGroup($user2));
-		$group1->delete();
-	}
-
-	public function testAddToGroupAsIrelevantSubAdmin() {
-		$user1 = $this->generateUsers();
-		$user2 = $this->generateUsers();
-		$this->userSession->setUser($user1);
-		$group1 = $this->getUniqueID();
-		$group2 = $this->getUniqueID();
-		$group1 = $this->groupManager->createGroup($group1);
-		$group2 = $this->groupManager->createGroup($group2);
-		\OC_SubAdmin::createSubAdmin($user1->getUID(), $group1->getGID());
-		$_POST['groupid'] = $group2->getGID();
-		$result = $this->api->addToGroup(array(
-			'userid' => $user2->getUID(),
-			));
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-		$this->assertFalse($group2->inGroup($user2));
-		$group1->delete();
-		$group2->delete();
-	}
-
-	public function testAddToGroupNoGroupId() {
-		$user = $this->generateUsers();
-		$this->userSession->setUser($user);
-
-		$_POST['groupid'] = '';
-		$result = $this->api->addToGroup([
-			'userid' => $this->getUniqueID(),
-		]);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-		$this->assertEquals(101, $result->getStatusCode());
+		$expected = new \OC_OCS_Result(null, 100);
+		$this->assertEquals($expected, $this->api->deleteUser(['userid' => 'UserToDelete']));
 	}
 
-	public function testAddToNonExistingGroup() {
-		$user = $this->generateUsers();
-		$this->groupManager->get('admin')->addUser($user);
-		$this->userSession->setUser($user);
+	public function testDeleteUnsuccessfulUserAsAdmin() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->any())
+			->method('getUID')
+			->will($this->returnValue('admin'));
+		$targetUser = $this->getMock('\OCP\IUser');
+		$targetUser
+			->expects($this->once())
+			->method('getUID')
+			->will($this->returnValue('UserToDelete'));
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('UserToDelete')
+			->will($this->returnValue($targetUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('isAdmin')
+			->with('admin')
+			->will($this->returnValue(true));
+		$targetUser
+			->expects($this->once())
+			->method('delete')
+			->will($this->returnValue(false));
 
-		$group = $this->groupManager->createGroup($this->getUniqueID());
-		$_POST['groupid'] = $group->getGID();
-		$result = $this->api->addToGroup([
-			'userid' => $this->getUniqueID(),
-		]);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-		$this->assertEquals(103, $result->getStatusCode());
+		$expected = new \OC_OCS_Result(null, 101);
+		$this->assertEquals($expected, $this->api->deleteUser(['userid' => 'UserToDelete']));
 	}
 
-	public function testAddNonExistingUserToGroup() {
-		$user = $this->generateUsers();
-		$this->groupManager->get('admin')->addUser($user);
-		$this->userSession->setUser($user);
+	public function testDeleteSuccessfulUserAsSubadmin() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->any())
+			->method('getUID')
+			->will($this->returnValue('subadmin'));
+		$targetUser = $this->getMock('\OCP\IUser');
+		$targetUser
+			->expects($this->once())
+			->method('getUID')
+			->will($this->returnValue('UserToDelete'));
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('UserToDelete')
+			->will($this->returnValue($targetUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('isAdmin')
+			->with('subadmin')
+			->will($this->returnValue(false));
+		$subAdminManager = $this->getMockBuilder('\OC\Subadmin')
+			->disableOriginalConstructor()->getMock();
+		$subAdminManager
+			->expects($this->once())
+			->method('isUserAccessible')
+			->with($loggedInUser, $targetUser)
+			->will($this->returnValue(true));
+		$this->groupManager
+			->expects($this->once())
+			->method('getSubAdmin')
+			->will($this->returnValue($subAdminManager));
+		$targetUser
+			->expects($this->once())
+			->method('delete')
+			->will($this->returnValue(true));
+
+		$expected = new \OC_OCS_Result(null, 100);
+		$this->assertEquals($expected, $this->api->deleteUser(['userid' => 'UserToDelete']));
+	}
 
-		$_POST['groupid'] = $this->getUniqueID();
-		$result = $this->api->addToGroup([
-			'userid' => $this->getUniqueID(),
-		]);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-		$this->assertEquals(102, $result->getStatusCode());
-	}
-
-	// test delete /cloud/users/{userid}/groups
-	public function testRemoveFromGroupAsSelf() {
-		$user1 = $this->generateUsers();
-		$this->userSession->setUser($user1);
-		$group1 = $this->getUniqueID();
-		$group1 = $this->groupManager->createGroup($group1);
-		$group1->addUser($user1);
-		$result = $this->api->removeFromGroup(array(
-			'userid' => $user1->getUID(),
-			'_delete' => array(
-				'groupid' => $group1->getGID(),
-				),
-			));
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-		$this->assertTrue($group1->inGroup($user1));
-		$group1->delete();
-	}
-
-	public function testRemoveFromGroupAsAdmin() {
-		$user1 = $this->generateUsers();
-		$user2 = $this->generateUsers();
-		$this->userSession->setUser($user1);
-		$group1 = $this->getUniqueID();
-		$group1 = $this->groupManager->createGroup($group1);
-		$group1->addUser($user2);
-		$this->groupManager->get('admin')->addUser($user1);
-		$result = $this->api->removeFromGroup(array(
-			'userid' => $user2->getUID(),
-			'_delete' => array(
-				'groupid' => $group1->getGID(),
-				),
-			));
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertTrue($result->succeeded());
-		$this->assertFalse($group1->inGroup($user2));
-		$group1->delete();
-	}
-
-	public function testRemoveSelfFromGroupAsAdmin() {
-		$user1 = $this->generateUsers();
-		$this->userSession->setUser($user1);
-		$group1 = $this->groupManager->createGroup($this->getUniqueID());
-		$group1->addUser($user1);
-		$this->groupManager->get('admin')->addUser($user1);
-		$result = $this->api->removeFromGroup([
-			'userid' => $user1->getUID(),
-			'_delete' => [
-				'groupid' => $group1->getGID(),
-			],
-		]);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertTrue($result->succeeded());
-		$this->assertFalse($group1->inGroup($user1));
-		$group1->delete();
-	}
-
-	public function testRemoveFromGroupAsSubAdmin() {
-		$user1 = $this->generateUsers();
-		$this->userSession->setUser($user1);
-		$user2 = $this->generateUsers();
-		$group1 = $this->getUniqueID();
-		$group1 = $this->groupManager->createGroup($group1);
-		$group1->addUser($user1);
-		$group1->addUser($user2);
-		\OC_SubAdmin::createSubAdmin($user1->getUID(), $group1->getGID());
-		$result = $this->api->removeFromGroup(array(
-			'userid' => $user2->getUID(),
-			'_delete' => array(
-				'groupid' => $group1->getGID(),
-				),
-			));
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertTrue($result->succeeded());
-		$this->assertFalse($group1->inGroup($user2));
-		$group1->delete();
-	}
-
-	public function testRemoveFromGroupAsIrelevantSubAdmin() {
-		$user1 = $this->generateUsers();
-		$this->userSession->setUser($user1);
-		$user2 = $this->generateUsers();
-		$group1 = $this->getUniqueID();
-		$group2 = $this->getUniqueID();
-		$group1 = $this->groupManager->createGroup($group1);
-		$group2 = $this->groupManager->createGroup($group2);
-		$group1->addUser($user1);
-		$group2->addUser($user2);
-		\OC_SubAdmin::createSubAdmin($user1->getUID(), $group1->getGID());
-		$result = $this->api->removeFromGroup(array(
-			'userid' => $user2->getUID(),
-			'_delete' => array(
-				'groupid' => $group2->getGID(),
-				),
-			));
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-		$this->assertTrue($group2->inGroup($user2));
-		$group1->delete();
-		$group2->delete();
-	}
-
-	public function testRemoveFromGroupNoGroupId() {
-		$user = $this->generateUsers();
-		$this->userSession->setUser($user);
-
-		$result = $this->api->removeFromGroup([
-			'_delete' => [
-				'groupid' => ''
-			],
-		]);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-		$this->assertEquals(101, $result->getStatusCode());
+	public function testDeleteUnsuccessfulUserAsSubadmin() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->any())
+			->method('getUID')
+			->will($this->returnValue('subadmin'));
+		$targetUser = $this->getMock('\OCP\IUser');
+		$targetUser
+			->expects($this->once())
+			->method('getUID')
+			->will($this->returnValue('UserToDelete'));
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('UserToDelete')
+			->will($this->returnValue($targetUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('isAdmin')
+			->with('subadmin')
+			->will($this->returnValue(false));
+		$subAdminManager = $this->getMockBuilder('\OC\Subadmin')
+			->disableOriginalConstructor()->getMock();
+		$subAdminManager
+			->expects($this->once())
+			->method('isUserAccessible')
+			->with($loggedInUser, $targetUser)
+			->will($this->returnValue(true));
+		$this->groupManager
+			->expects($this->once())
+			->method('getSubAdmin')
+			->will($this->returnValue($subAdminManager));
+		$targetUser
+			->expects($this->once())
+			->method('delete')
+			->will($this->returnValue(false));
+
+		$expected = new \OC_OCS_Result(null, 101);
+		$this->assertEquals($expected, $this->api->deleteUser(['userid' => 'UserToDelete']));
 	}
 
-	public function testRemoveSelfFromAdminAsAdmin() {
-		$user = $this->generateUsers();
-		$this->userSession->setUser($user);
-		$this->groupManager->get('admin')->addUser($user);
+	public function testDeleteUserAsSubAdminAndUserIsNotAccessible() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->any())
+			->method('getUID')
+			->will($this->returnValue('subadmin'));
+		$targetUser = $this->getMock('\OCP\IUser');
+		$targetUser
+			->expects($this->once())
+			->method('getUID')
+			->will($this->returnValue('UserToDelete'));
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('UserToDelete')
+			->will($this->returnValue($targetUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('isAdmin')
+			->with('subadmin')
+			->will($this->returnValue(false));
+		$subAdminManager = $this->getMockBuilder('\OC\Subadmin')
+			->disableOriginalConstructor()->getMock();
+		$subAdminManager
+			->expects($this->once())
+			->method('isUserAccessible')
+			->with($loggedInUser, $targetUser)
+			->will($this->returnValue(false));
+		$this->groupManager
+			->expects($this->once())
+			->method('getSubAdmin')
+			->will($this->returnValue($subAdminManager));
+
+		$expected = new \OC_OCS_Result(null, 997);
+		$this->assertEquals($expected, $this->api->deleteUser(['userid' => 'UserToDelete']));
+	}
 
-		$result = $this->api->removeFromGroup([
-			'userid' => $user->getUID(),
-			'_delete' => [
-				'groupid' => 'admin'
-			],
-		]);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-		$this->assertEquals(105, $result->getStatusCode());
-		$this->assertEquals('Cannot remove yourself from the admin group', $result->getMeta()['message']);
-	}
-
-	public function testRemoveSelfFromSubAdminGroupAsSubAdmin() {
-		$user = $this->generateUsers();
-		$this->userSession->setUser($user);
-		$group = $this->groupManager->createGroup($this->getUniqueID());
-		\OC_SubAdmin::createSubAdmin($user->getUID(), $group->getGID());
-
-		$result = $this->api->removeFromGroup([
-			'userid' => $user->getUID(),
-			'_delete' => [
-				'groupid' => $group->getGID()
-			],
-		]);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-		$this->assertEquals(105, $result->getStatusCode());
-		$this->assertEquals('Cannot remove yourself from this group as you are a SubAdmin', $result->getMeta()['message']);
-		$group->delete();
-	}
-
-	public function testRemoveFromNonExistingGroup() {
-		$user1 = $this->generateUsers();
-		$this->userSession->setUser($user1);
-		$this->groupManager->get('admin')->addUser($user1);
-
-		$user2 = $this->generateUsers();
-		$result = $this->api->removeFromGroup([
-			'userid' => $user2->getUID(),
-			'_delete' => [
-				'groupid' => $this->getUniqueID()
-			],
-		]);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-		$this->assertEquals(102, $result->getStatusCode());
+	public function testGetUsersGroupsNotLoggedIn() {
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue(null));
+
+		$expected = new \OC_OCS_Result(null, 997);
+		$this->assertEquals($expected, $this->api->getUsersGroups(['userid' => 'UserToLookup']));
 	}
 
-	public function testRemoveFromNonGroupNonExistingUser() {
-		$user = $this->generateUsers();
-		$this->userSession->setUser($user);
-		$this->groupManager->get('admin')->addUser($user);
+	public function testGetUsersGroupsTargetUserNotExisting() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
 
-		$group = $this->groupManager->createGroup($this->getUniqueID());
+		$expected = new \OC_OCS_Result(null, 998);
+		$this->assertEquals($expected, $this->api->getUsersGroups(['userid' => 'UserToLookup']));
+	}
 
-		$result = $this->api->removeFromGroup([
-			'userid' => $this->getUniqueID(),
-			'_delete' => [
-				'groupid' => $group->getGID()
-			],
-		]);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-		$this->assertEquals(103, $result->getStatusCode());
-	}
-
-
-	public function testCreateSubAdmin() {
-		$user1 = $this->generateUsers();
-		$user2 = $this->generateUsers();
-		$this->userSession->setUser($user1);
-		$this->groupManager->get('admin')->addUser($user1);
-		$group1 = $this->getUniqueID();
-		$group1 = $this->groupManager->createGroup($group1);
-		$_POST['groupid'] = $group1->getGID();
-		$result = $this->api->addSubAdmin(array(
-			'userid' => $user2->getUID(),
-			));
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertTrue($result->succeeded());
-		$this->assertTrue(\OC_SubAdmin::isSubAdminofGroup($user2->getUID(), $group1->getGID()));
-		$group1->delete();
-
-		$this->resetParams();
-
-		$user1 = $this->generateUsers();
-		$user2 = $this->generateUsers();
-		$this->userSession->setUser($user1);
-		$this->groupManager->get('admin')->addUser($user1);
-		$_POST['groupid'] = 'admin';
-		$result = $this->api->addSubAdmin(array(
-			'userid' => $user2->getUID(),
-			));
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertEquals(103, $result->getStatusCode());
-		$this->assertFalse($result->succeeded());
-
-		$this->resetParams();
-
-		$user1 = $this->generateUsers();
-		$this->userSession->setUser($user1);
-		$this->groupManager->get('admin')->addUser($user1);
-		$group1 = $this->getUniqueID();
-		$group1 = $this->groupManager->createGroup($group1);
-		$_POST['groupid'] = $group1->getGID();
-		$result = $this->api->addSubAdmin(array(
-			'userid' => $this->getUniqueID(),
-			));
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-		$this->assertEquals(101, $result->getStatusCode());
-		$group1->delete();
-
-		$user1 = $this->generateUsers();
-		$this->userSession->setUser($user1);
-		$group = $this->getUniqueID();
-		$_POST['groupid'] = $group;
-		$result = $this->api->addSubAdmin([
-			'userid' => $user1->getUID()
-		]);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-		$this->assertEquals(102, $result->getStatusCode());
-		$this->assertEquals('Group:'.$group.' does not exist', $result->getMeta()['message']);
-	}
-
-	public function testRemoveSubAdmin() {
-		$user1 = $this->generateUsers();
-		$user2 = $this->generateUsers();
-		$this->userSession->setUser($user1);
-		$this->groupManager->get('admin')->addUser($user1);
-		$group1 = $this->getUniqueID();
-		$group1 = $this->groupManager->createGroup($group1);
-		\OC_SubAdmin::createSubAdmin($user2->getUID(), $group1->getGID());
-		$result = $this->api->removeSubAdmin(array(
-			'userid' => $user2->getUID(),
-			'_delete' => array(
-				'groupid' => $group1->getGID(),
-				),
-			));
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertTrue($result->succeeded());
-		$this->assertTrue(!\OC_SubAdmin::isSubAdminofGroup($user2->getUID(), $group1->getGID()));
-		$group1->delete();
-
-		$user1 = $this->generateUsers();
-		$this->userSession->setUser($user1);
-		$this->groupManager->get('admin')->addUser($user1);
-		$result = $this->api->removeSubAdmin(array(
-			'userid' => $this->getUniqueID(),
-			'_delete' => array(
-				'groupid' => $group1->getGID(),
-				),
-			));
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertEquals(101, $result->getStatusCode());
-		$this->assertFalse($result->succeeded());
-
-		$this->resetParams();
-
-		$user1 = $this->generateUsers();
-		$user2 = $this->generateUsers();
-		$this->userSession->setUser($user1);
-		$this->groupManager->get('admin')->addUser($user1);
-		$group1 = $this->getUniqueID();
-		$group1 = $this->groupManager->createGroup($group1);
-		$_POST['groupid'] = $group1->getGID();
-		$result = $this->api->removeSubAdmin(array(
-			'userid' => $user2->getUID(),
-			'_delete' => array(
-				'groupid' => $group1->getGID(),
-				),
-			));
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-		$this->assertEquals(102, $result->getStatusCode());
-		$group1->delete();
-	}
-
-	public function testGetSubAdminGroups() {
-		$user1 = $this->generateUsers();
-		$user2 = $this->generateUsers();
-		$this->userSession->setUser($user1);
-		$this->groupManager->get('admin')->addUser($user1);
-		$group1 = $this->getUniqueID();
-		$group1 = $this->groupManager->createGroup($group1);
-		\OC_SubAdmin::createSubAdmin($user2->getUID(), $group1->getGID());
-		$result = $this->api->getUserSubAdminGroups(array(
-			'userid' => $user2->getUID(),
-			));
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertTrue($result->succeeded());
-		$data = $result->getData();
-		$this->assertEquals($group1->getGID(), reset($data));
-		$group1->delete();
-
-		$user1 = $this->generateUsers();
-		$this->userSession->setUser($user1);
-		$this->groupManager->get('admin')->addUser($user1);
-		$result = $this->api->getUserSubAdminGroups(array(
-			'userid' => $this->getUniqueID(),
-			));
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertFalse($result->succeeded());
-		$this->assertEquals(101, $result->getStatusCode());
-	}
-
-	public function testSubAdminOfGroupAlreadySubAdmin() {
-		$user1 = $this->generateUsers();
-		$user2 = $this->generateUsers();
-		$this->userSession->setUser($user1);
-		$this->groupManager->get('admin')->addUser($user1);
-		$group1 = $this->groupManager->createGroup($this->getUniqueID());
-
-		//Make user2 subadmin of group1
-		$_POST['groupid'] = $group1->getGID();
-		$result = $this->api->addSubAdmin([
-			'userid' => $user2->getUID(),
-		]);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertTrue($result->succeeded());
+	public function testGetUsersGroupsSelfTargetted() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->once())
+			->method('getUID')
+			->will($this->returnValue('UserToLookup'));
+		$targetUser = $this->getMock('\OCP\IUser');
+		$targetUser
+			->expects($this->once())
+			->method('getUID')
+			->will($this->returnValue('UserToLookup'));
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('UserToLookup')
+			->will($this->returnValue($targetUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('getUserGroupIds')
+			->with($targetUser)
+			->will($this->returnValue(['DummyValue']));
+
+		$expected = new \OC_OCS_Result(['groups' => ['DummyValue']]);
+		$this->assertEquals($expected, $this->api->getUsersGroups(['userid' => 'UserToLookup']));
+	}
 
-		//Make user2 subadmin of group1 again
-		$_POST['groupid'] = $group1->getGID();
-		$result = $this->api->addSubAdmin([
-			'userid' => $user2->getUID(),
-		]);
-		$this->assertInstanceOf('OC_OCS_Result', $result);
-		$this->assertTrue($result->succeeded());
-		$group1->delete();
+	public function testGetUsersGroupsForAdminUser() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->exactly(2))
+			->method('getUID')
+			->will($this->returnValue('admin'));
+		$targetUser = $this->getMock('\OCP\IUser');
+		$targetUser
+			->expects($this->once())
+			->method('getUID')
+			->will($this->returnValue('UserToLookup'));
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('UserToLookup')
+			->will($this->returnValue($targetUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('getUserGroupIds')
+			->with($targetUser)
+			->will($this->returnValue(['DummyValue']));
+		$this->groupManager
+			->expects($this->once())
+			->method('isAdmin')
+			->with('admin')
+			->will($this->returnValue(true));
+
+		$expected = new \OC_OCS_Result(['groups' => ['DummyValue']]);
+		$this->assertEquals($expected, $this->api->getUsersGroups(['userid' => 'UserToLookup']));
+	}
+
+	public function testGetUsersGroupsForSubAdminUserAndUserIsAccessible() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->exactly(2))
+			->method('getUID')
+			->will($this->returnValue('subadmin'));
+		$targetUser = $this->getMock('\OCP\IUser');
+		$targetUser
+			->expects($this->once())
+			->method('getUID')
+			->will($this->returnValue('UserToLookup'));
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('UserToLookup')
+			->will($this->returnValue($targetUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('isAdmin')
+			->with('subadmin')
+			->will($this->returnValue(false));
+		$subAdminManager = $this->getMockBuilder('\OC\Subadmin')
+			->disableOriginalConstructor()->getMock();
+		$subAdminManager
+			->expects($this->once())
+			->method('isUserAccessible')
+			->with($loggedInUser, $targetUser)
+			->will($this->returnValue(true));
+		$this->groupManager
+			->expects($this->once())
+			->method('getSubAdmin')
+			->will($this->returnValue($subAdminManager));
+		$group1 = $this->getMock('\OCP\IGroup');
+		$group1
+			->expects($this->any())
+			->method('getGID')
+			->will($this->returnValue('Group1'));
+		$group2 = $this->getMock('\OCP\IGroup');
+		$group2
+			->expects($this->any())
+			->method('getGID')
+			->will($this->returnValue('Group2'));
+		$subAdminManager
+			->expects($this->once())
+			->method('getSubAdminsGroups')
+			->with($loggedInUser)
+			->will($this->returnValue([$group1, $group2]));
+		$this->groupManager
+			->expects($this->any())
+			->method('getUserGroupIds')
+			->with($targetUser)
+			->will($this->returnValue(['Group1']));
+
+		$expected = new \OC_OCS_Result(['groups' => ['Group1']]);
+		$this->assertEquals($expected, $this->api->getUsersGroups(['userid' => 'UserToLookup']));
+	}
+
+
+	public function testGetUsersGroupsForSubAdminUserAndUserIsInaccessible() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->exactly(2))
+			->method('getUID')
+			->will($this->returnValue('subadmin'));
+		$targetUser = $this->getMock('\OCP\IUser');
+		$targetUser
+			->expects($this->once())
+			->method('getUID')
+			->will($this->returnValue('UserToLookup'));
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('UserToLookup')
+			->will($this->returnValue($targetUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('isAdmin')
+			->with('subadmin')
+			->will($this->returnValue(false));
+		$subAdminManager = $this->getMockBuilder('\OC\Subadmin')
+			->disableOriginalConstructor()->getMock();
+		$subAdminManager
+			->expects($this->once())
+			->method('isUserAccessible')
+			->with($loggedInUser, $targetUser)
+			->will($this->returnValue(false));
+		$this->groupManager
+			->expects($this->once())
+			->method('getSubAdmin')
+			->will($this->returnValue($subAdminManager));
+		$this->groupManager
+			->expects($this->any())
+			->method('getUserGroupIds')
+			->with($targetUser)
+			->will($this->returnValue(['Group1']));
+
+		$expected = new \OC_OCS_Result(null, 997);
+		$this->assertEquals($expected, $this->api->getUsersGroups(['userid' => 'UserToLookup']));
+	}
+
+	public function testAddToGroupNotLoggedIn() {
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue(null));
+
+		$expected = new \OC_OCS_Result(null, 997);
+		$this->assertEquals($expected, $this->api->addToGroup([]));
+	}
+
+	public function testAddToGroupWithTargetGroupNotExisting() {
+		$_POST['groupid'] = 'GroupToAddTo';
+
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->once())
+			->method('getUID')
+			->will($this->returnValue('admin'));
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('get')
+			->with('GroupToAddTo')
+			->will($this->returnValue(null));
+		$this->groupManager
+			->expects($this->once())
+			->method('isAdmin')
+			->with('admin')
+			->will($this->returnValue(true));
+
+		$expected = new \OC_OCS_Result(null, 102);
+		$this->assertEquals($expected, $this->api->addToGroup(['userid' => 'TargetUser']));
+	}
+
+	public function testAddToGroupWithNoGroupSpecified() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->once())
+			->method('getUID')
+			->will($this->returnValue('admin'));
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('isAdmin')
+			->with('admin')
+			->will($this->returnValue(true));
+
+		$expected = new \OC_OCS_Result(null, 101);
+		$this->assertEquals($expected, $this->api->addToGroup(['userid' => 'TargetUser']));
+	}
+
+	public function testAddToGroupWithTargetUserNotExisting() {
+		$_POST['groupid'] = 'GroupToAddTo';
+
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->once())
+			->method('getUID')
+			->will($this->returnValue('admin'));
+		$targetGroup = $this->getMock('\OCP\IGroup');
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('get')
+			->with('GroupToAddTo')
+			->will($this->returnValue($targetGroup));
+		$this->groupManager
+			->expects($this->once())
+			->method('isAdmin')
+			->with('admin')
+			->will($this->returnValue(true));
+
+		$expected = new \OC_OCS_Result(null, 103);
+		$this->assertEquals($expected, $this->api->addToGroup(['userid' => 'TargetUser']));
+	}
+
+	public function testAddToGroupWithoutPermission() {
+		$_POST['groupid'] = 'GroupToAddTo';
+
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->once())
+			->method('getUID')
+			->will($this->returnValue('admin'));
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('isAdmin')
+			->with('admin')
+			->will($this->returnValue(false));
+
+		$expected = new \OC_OCS_Result(null, 997);
+		$this->assertEquals($expected, $this->api->addToGroup(['userid' => 'TargetUser']));
+	}
+
+	public function testRemoveFromGroupWithoutLogIn() {
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue(null));
+
+		$expected = new \OC_OCS_Result(null, 997);
+		$this->assertEquals($expected, $this->api->removeFromGroup(['userid' => 'TargetUser', '_delete' => ['groupid' => 'TargetGroup']]));
+	}
+
+	public function testRemoveFromGroupWithNotExistingTargetGroup() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('get')
+			->with('TargetGroup')
+			->will($this->returnValue(null));
+
+		$expected = new \OC_OCS_Result(null, 101);
+		$this->assertEquals($expected, $this->api->removeFromGroup(['userid' => 'TargetUser', '_delete' => ['groupid' => 'TargetGroup']]));
+	}
+
+	public function testRemoveFromGroupWithNotExistingTargetUser() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$targetGroup = $this->getMock('\OCP\IGroup');
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('get')
+			->with('TargetGroup')
+			->will($this->returnValue($targetGroup));
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('TargetUser')
+			->will($this->returnValue(null));
+
+		$expected = new \OC_OCS_Result(null, 103);
+		$this->assertEquals($expected, $this->api->removeFromGroup(['userid' => 'TargetUser', '_delete' => ['groupid' => 'TargetGroup']]));
+	}
+
+	public function testRemoveFromGroupWithoutPermission() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->once())
+			->method('getUID')
+			->will($this->returnValue('unauthorizedUser'));
+		$targetUser = $this->getMock('\OCP\IUser');
+		$targetGroup = $this->getMock('\OCP\IGroup');
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('get')
+			->with('TargetGroup')
+			->will($this->returnValue($targetGroup));
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('TargetUser')
+			->will($this->returnValue($targetUser));
+		$subAdminManager = $this->getMockBuilder('\OC\Subadmin')
+			->disableOriginalConstructor()->getMock();
+		$this->groupManager
+			->expects($this->once())
+			->method('getSubAdmin')
+			->will($this->returnValue($subAdminManager));
+		$this->groupManager
+			->expects($this->once())
+			->method('isAdmin')
+			->with('unauthorizedUser')
+			->will($this->returnValue(false));
+
+		$expected = new \OC_OCS_Result(null, 104);
+		$this->assertEquals($expected, $this->api->removeFromGroup(['userid' => 'TargetUser', '_delete' => ['groupid' => 'TargetGroup']]));
+	}
+
+	public function testRemoveFromGroupAsAdminFromAdmin() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->any())
+			->method('getUID')
+			->will($this->returnValue('admin'));
+		$targetUser = $this->getMock('\OCP\IUser');
+		$targetGroup = $this->getMock('\OCP\IGroup');
+		$targetGroup
+			->expects($this->once())
+			->method('getGID')
+			->will($this->returnValue('admin'));
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('get')
+			->with('admin')
+			->will($this->returnValue($targetGroup));
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('admin')
+			->will($this->returnValue($targetUser));
+		$subAdminManager = $this->getMockBuilder('\OC\Subadmin')
+			->disableOriginalConstructor()->getMock();
+		$this->groupManager
+			->expects($this->once())
+			->method('getSubAdmin')
+			->will($this->returnValue($subAdminManager));
+		$this->groupManager
+			->expects($this->any())
+			->method('isAdmin')
+			->with('admin')
+			->will($this->returnValue(true));
+
+		$expected = new \OC_OCS_Result(null, 105, 'Cannot remove yourself from the admin group');
+		$this->assertEquals($expected, $this->api->removeFromGroup(['userid' => 'admin', '_delete' => ['groupid' => 'admin']]));
+	}
+
+	public function testRemoveFromGroupAsSubAdminFromSubAdmin() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->any())
+			->method('getUID')
+			->will($this->returnValue('subadmin'));
+		$targetUser = $this->getMock('\OCP\IUser');
+		$targetGroup = $this->getMock('\OCP\IGroup');
+		$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('subadmin')
+			->will($this->returnValue($targetUser));
+		$subAdminManager = $this->getMockBuilder('\OC\Subadmin')
+			->disableOriginalConstructor()->getMock();
+		$subAdminManager
+			->expects($this->once())
+			->method('isSubAdminofGroup')
+			->with($loggedInUser, $targetGroup)
+			->will($this->returnValue(true));
+		$subAdminManager
+			->expects($this->once())
+			->method('getSubAdminsGroups')
+			->with($loggedInUser)
+			->will($this->returnValue([$targetGroup]));
+		$this->groupManager
+			->expects($this->once())
+			->method('getSubAdmin')
+			->will($this->returnValue($subAdminManager));
+		$this->groupManager
+			->expects($this->any())
+			->method('isAdmin')
+			->with('subadmin')
+			->will($this->returnValue(false));
+
+		$expected = new \OC_OCS_Result(null, 105, 'Cannot remove yourself from this group as you are a SubAdmin');
+		$this->assertEquals($expected, $this->api->removeFromGroup(['userid' => 'subadmin', '_delete' => ['groupid' => 'subadmin']]));
+	}
+
+	public function testRemoveFromGroupSuccessful() {
+		$loggedInUser = $this->getMock('\OCP\IUser');
+		$loggedInUser
+			->expects($this->any())
+			->method('getUID')
+			->will($this->returnValue('admin'));
+		$targetUser = $this->getMock('\OCP\IUser');
+		$targetGroup = $this->getMock('\OCP\IGroup');
+		$this->userSession
+			->expects($this->once())
+			->method('getUser')
+			->will($this->returnValue($loggedInUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('get')
+			->with('admin')
+			->will($this->returnValue($targetGroup));
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('AnotherUser')
+			->will($this->returnValue($targetUser));
+		$subAdminManager = $this->getMockBuilder('\OC\Subadmin')
+			->disableOriginalConstructor()->getMock();
+		$this->groupManager
+			->expects($this->once())
+			->method('getSubAdmin')
+			->will($this->returnValue($subAdminManager));
+		$this->groupManager
+			->expects($this->any())
+			->method('isAdmin')
+			->with('admin')
+			->will($this->returnValue(true));
+		$targetGroup
+			->expects($this->once())
+			->method('removeUser')
+			->with($targetUser);
+
+		$expected = new \OC_OCS_Result(null, 100);
+		$this->assertEquals($expected, $this->api->removeFromGroup(['userid' => 'AnotherUser', '_delete' => ['groupid' => 'admin']]));
+	}
+
+	public function testAddSubAdminWithNotExistingTargetUser() {
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('NotExistingUser')
+			->will($this->returnValue(null));
+
+		$expected = new \OC_OCS_Result(null, 101, 'User does not exist');
+		$this->assertEquals($expected, $this->api->addSubAdmin(['userid' => 'NotExistingUser']));
+	}
+
+	public function testAddSubAdminWithNotExistingTargetGroup() {
+		$_POST['groupid'] = 'NotExistingGroup';
+
+		$targetUser = $this->getMock('\OCP\IUser');
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('ExistingUser')
+			->will($this->returnValue($targetUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('get')
+			->with('NotExistingGroup')
+			->will($this->returnValue(null));
+
+		$expected = new \OC_OCS_Result(null, 102, 'Group:NotExistingGroup does not exist');
+		$this->assertEquals($expected, $this->api->addSubAdmin(['userid' => 'ExistingUser']));
+	}
+
+	public function testAddSubAdminToAdminGroup() {
+		$_POST['groupid'] = 'ADmiN';
+
+		$targetUser = $this->getMock('\OCP\IUser');
+		$targetGroup = $this->getMock('\OCP\IGroup');
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('ExistingUser')
+			->will($this->returnValue($targetUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('get')
+			->with('ADmiN')
+			->will($this->returnValue($targetGroup));
+
+		$expected = new \OC_OCS_Result(null, 103, 'Cannot create subadmins for admin group');
+		$this->assertEquals($expected, $this->api->addSubAdmin(['userid' => 'ExistingUser']));
+	}
+
+	public function testAddSubAdminTwice() {
+		$_POST['groupid'] = 'TargetGroup';
+
+		$targetUser = $this->getMock('\OCP\IUser');
+		$targetGroup = $this->getMock('\OCP\IGroup');
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('ExistingUser')
+			->will($this->returnValue($targetUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('get')
+			->with('TargetGroup')
+			->will($this->returnValue($targetGroup));
+		$subAdminManager = $this->getMockBuilder('\OC\Subadmin')
+			->disableOriginalConstructor()->getMock();
+		$subAdminManager
+			->expects($this->once())
+			->method('isSubAdminOfGroup')
+			->with($targetUser, $targetGroup)
+			->will($this->returnValue(true));
+		$this->groupManager
+			->expects($this->once())
+			->method('getSubAdmin')
+			->will($this->returnValue($subAdminManager));
+
+		$expected = new \OC_OCS_Result(null, 100);
+		$this->assertEquals($expected, $this->api->addSubAdmin(['userid' => 'ExistingUser']));
+	}
+
+	public function testAddSubAdminSuccessful() {
+		$_POST['groupid'] = 'TargetGroup';
+
+		$targetUser = $this->getMock('\OCP\IUser');
+		$targetGroup = $this->getMock('\OCP\IGroup');
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('ExistingUser')
+			->will($this->returnValue($targetUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('get')
+			->with('TargetGroup')
+			->will($this->returnValue($targetGroup));
+		$subAdminManager = $this->getMockBuilder('\OC\Subadmin')
+			->disableOriginalConstructor()->getMock();
+		$subAdminManager
+			->expects($this->once())
+			->method('isSubAdminOfGroup')
+			->with($targetUser, $targetGroup)
+			->will($this->returnValue(false));
+		$subAdminManager
+			->expects($this->once())
+			->method('createSubAdmin')
+			->with($targetUser, $targetGroup)
+			->will($this->returnValue(true));
+		$this->groupManager
+			->expects($this->once())
+			->method('getSubAdmin')
+			->will($this->returnValue($subAdminManager));
+
+		$expected = new \OC_OCS_Result(null, 100);
+		$this->assertEquals($expected, $this->api->addSubAdmin(['userid' => 'ExistingUser']));
+	}
+
+	public function testAddSubAdminUnsuccessful() {
+		$_POST['groupid'] = 'TargetGroup';
+
+		$targetUser = $this->getMock('\OCP\IUser');
+		$targetGroup = $this->getMock('\OCP\IGroup');
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('ExistingUser')
+			->will($this->returnValue($targetUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('get')
+			->with('TargetGroup')
+			->will($this->returnValue($targetGroup));
+		$subAdminManager = $this->getMockBuilder('\OC\Subadmin')
+			->disableOriginalConstructor()->getMock();
+		$subAdminManager
+			->expects($this->once())
+			->method('isSubAdminOfGroup')
+			->with($targetUser, $targetGroup)
+			->will($this->returnValue(false));
+		$subAdminManager
+			->expects($this->once())
+			->method('createSubAdmin')
+			->with($targetUser, $targetGroup)
+			->will($this->returnValue(false));
+		$this->groupManager
+			->expects($this->once())
+			->method('getSubAdmin')
+			->will($this->returnValue($subAdminManager));
+
+		$expected = new \OC_OCS_Result(null, 103, 'Unknown error occurred');
+		$this->assertEquals($expected, $this->api->addSubAdmin(['userid' => 'ExistingUser']));
+	}
+
+	public function testRemoveSubAdminNotExistingTargetUser() {
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('NotExistingUser')
+			->will($this->returnValue(null));
+
+		$expected = new \OC_OCS_Result(null, 101, 'User does not exist');
+		$this->assertEquals($expected, $this->api->removeSubAdmin(['userid' => 'NotExistingUser', '_delete' => ['groupid' => 'GroupToDeleteFrom']]));
+	}
+
+	public function testRemoveSubAdminNotExistingTargetGroup() {
+		$targetUser = $this->getMock('\OCP\IUser');
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('ExistingUser')
+			->will($this->returnValue($targetUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('get')
+			->with('GroupToDeleteFrom')
+			->will($this->returnValue(null));
+
+		$expected = new \OC_OCS_Result(null, 101, 'Group does not exist');
+		$this->assertEquals($expected, $this->api->removeSubAdmin(['userid' => 'ExistingUser', '_delete' => ['groupid' => 'GroupToDeleteFrom']]));
+	}
+
+	public function testRemoveSubAdminFromNotASubadmin() {
+		$targetUser = $this->getMock('\OCP\IUser');
+		$targetGroup = $this->getMock('\OCP\IGroup');
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('ExistingUser')
+			->will($this->returnValue($targetUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('get')
+			->with('GroupToDeleteFrom')
+			->will($this->returnValue($targetGroup));
+		$subAdminManager = $this->getMockBuilder('\OC\Subadmin')
+			->disableOriginalConstructor()->getMock();
+		$subAdminManager
+			->expects($this->once())
+			->method('isSubAdminOfGroup')
+			->with($targetUser, $targetGroup)
+			->will($this->returnValue(false));
+		$this->groupManager
+			->expects($this->once())
+			->method('getSubAdmin')
+			->will($this->returnValue($subAdminManager));
+
+		$expected = new \OC_OCS_Result(null, 102, 'User is not a subadmin of this group');
+		$this->assertEquals($expected, $this->api->removeSubAdmin(['userid' => 'ExistingUser', '_delete' => ['groupid' => 'GroupToDeleteFrom']]));
+	}
+
+	public function testRemoveSubAdminSuccessful() {
+		$targetUser = $this->getMock('\OCP\IUser');
+		$targetGroup = $this->getMock('\OCP\IGroup');
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('ExistingUser')
+			->will($this->returnValue($targetUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('get')
+			->with('GroupToDeleteFrom')
+			->will($this->returnValue($targetGroup));
+		$subAdminManager = $this->getMockBuilder('\OC\Subadmin')
+			->disableOriginalConstructor()->getMock();
+		$subAdminManager
+			->expects($this->once())
+			->method('isSubAdminOfGroup')
+			->with($targetUser, $targetGroup)
+			->will($this->returnValue(true));
+		$subAdminManager
+			->expects($this->once())
+			->method('deleteSubAdmin')
+			->with($targetUser, $targetGroup)
+			->will($this->returnValue(true));
+		$this->groupManager
+			->expects($this->once())
+			->method('getSubAdmin')
+			->will($this->returnValue($subAdminManager));
+
+		$expected = new \OC_OCS_Result(null, 100);
+		$this->assertEquals($expected, $this->api->removeSubAdmin(['userid' => 'ExistingUser', '_delete' => ['groupid' => 'GroupToDeleteFrom']]));
+	}
+
+	public function testRemoveSubAdminUnsuccessful() {
+		$targetUser = $this->getMock('\OCP\IUser');
+		$targetGroup = $this->getMock('\OCP\IGroup');
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('ExistingUser')
+			->will($this->returnValue($targetUser));
+		$this->groupManager
+			->expects($this->once())
+			->method('get')
+			->with('GroupToDeleteFrom')
+			->will($this->returnValue($targetGroup));
+		$subAdminManager = $this->getMockBuilder('\OC\Subadmin')
+			->disableOriginalConstructor()->getMock();
+		$subAdminManager
+			->expects($this->once())
+			->method('isSubAdminOfGroup')
+			->with($targetUser, $targetGroup)
+			->will($this->returnValue(true));
+		$subAdminManager
+			->expects($this->once())
+			->method('deleteSubAdmin')
+			->with($targetUser, $targetGroup)
+			->will($this->returnValue(false));
+		$this->groupManager
+			->expects($this->once())
+			->method('getSubAdmin')
+			->will($this->returnValue($subAdminManager));
+
+		$expected = new \OC_OCS_Result(null, 103, 'Unknown error occurred');
+		$this->assertEquals($expected, $this->api->removeSubAdmin(['userid' => 'ExistingUser', '_delete' => ['groupid' => 'GroupToDeleteFrom']]));
+	}
+
+	public function testGetUserSubAdminGroupsNotExistingTargetUser() {
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('RequestedUser')
+			->will($this->returnValue(null));
+
+		$expected = new \OC_OCS_Result(null, 101, 'User does not exist');
+		$this->assertEquals($expected, $this->api->getUserSubAdminGroups(['userid' => 'RequestedUser']));
+	}
+
+	public function testGetUserSubAdminGroupsWithGroups() {
+		$targetUser = $this->getMock('\OCP\IUser');
+		$targetGroup = $this->getMock('\OCP\IGroup');
+		$targetGroup
+			->expects($this->once())
+			->method('getGID')
+			->will($this->returnValue('TargetGroup'));
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('RequestedUser')
+			->will($this->returnValue($targetUser));
+		$subAdminManager = $this->getMockBuilder('\OC\Subadmin')
+			->disableOriginalConstructor()->getMock();
+		$subAdminManager
+			->expects($this->once())
+			->method('getSubAdminsGroups')
+			->with($targetUser)
+			->will($this->returnValue([$targetGroup]));
+		$this->groupManager
+			->expects($this->once())
+			->method('getSubAdmin')
+			->will($this->returnValue($subAdminManager));
+
+		$expected = new \OC_OCS_Result(['TargetGroup'], 100);
+		$this->assertEquals($expected, $this->api->getUserSubAdminGroups(['userid' => 'RequestedUser']));
+	}
+
+	public function testGetUserSubAdminGroupsWithoutGroups() {
+		$targetUser = $this->getMock('\OCP\IUser');
+		$this->userManager
+			->expects($this->once())
+			->method('get')
+			->with('RequestedUser')
+			->will($this->returnValue($targetUser));
+		$subAdminManager = $this->getMockBuilder('\OC\Subadmin')
+			->disableOriginalConstructor()->getMock();
+		$subAdminManager
+			->expects($this->once())
+			->method('getSubAdminsGroups')
+			->with($targetUser)
+			->will($this->returnValue([]));
+		$this->groupManager
+			->expects($this->once())
+			->method('getSubAdmin')
+			->will($this->returnValue($subAdminManager));
+
+		$expected = new \OC_OCS_Result(null, 102, 'Unknown error occurred');
+		$this->assertEquals($expected, $this->api->getUserSubAdminGroups(['userid' => 'RequestedUser']));
 	}
 }
diff --git a/lib/private/api.php b/lib/private/api.php
index 6d7354c71938700d462a26da718225ed412dcc4a..edee30dfc961b8e80b579160c68599a9bd00d0dd 100644
--- a/lib/private/api.php
+++ b/lib/private/api.php
@@ -303,9 +303,13 @@ class OC_API {
 				if(!$user) {
 					return false;
 				} else {
-					$subAdmin = OC_SubAdmin::isSubAdmin($user);
+					$userObject = \OC::$server->getUserSession()->getUser();
+					if($userObject === null) {
+						return false;
+					}
+					$isSubAdmin = \OC::$server->getGroupManager()->getSubAdmin()->isSubAdmin($userObject);
 					$admin = OC_User::isAdminUser($user);
-					if($subAdmin || $admin) {
+					if($isSubAdmin || $admin) {
 						return true;
 					} else {
 						return false;
diff --git a/lib/private/app.php b/lib/private/app.php
index d7e62dfd852134df36092b059c8c997dab7d436f..c6e235eda4db1af80bb9fd4beacaec53aabf12c8 100644
--- a/lib/private/app.php
+++ b/lib/private/app.php
@@ -430,7 +430,12 @@ class OC_App {
 			);
 
 			//SubAdmins are also allowed to access user management
-			if (OC_SubAdmin::isSubAdmin(OC_User::getUser())) {
+			$userObject = \OC::$server->getUserSession()->getUser();
+			$isSubAdmin = false;
+			if($userObject !== null) {
+				$isSubAdmin = \OC::$server->getGroupManager()->getSubAdmin()->isSubAdmin($userObject);
+			}
+			if ($isSubAdmin) {
 				// admin users menu
 				$settings[] = array(
 					"id" => "core_users",
diff --git a/lib/private/group/metadata.php b/lib/private/group/metadata.php
index 63447012b0c0d0e62bdd0056b8bcdbc6c8142654..63ac092856318d3da637ad2a7f7ff003dac3d4d4 100644
--- a/lib/private/group/metadata.php
+++ b/lib/private/group/metadata.php
@@ -26,49 +26,42 @@
 
 namespace OC\Group;
 
+use OCP\IUserSession;
+
 class MetaData {
 	const SORT_NONE = 0;
 	const SORT_USERCOUNT = 1; // May have performance issues on LDAP backends
 	const SORT_GROUPNAME = 2;
 
-	/**
-	 * @var string $user
-	 */
+	/** @var string */
 	protected $user;
-
-	/**
-	 * @var bool $isAdmin
-	 */
+	/** @var bool */
 	protected $isAdmin;
-
-	/**
-	 * @var array $metaData
-	 */
+	/** @var array */
 	protected $metaData = array();
-
-	/**
-	 * @var \OCP\IGroupManager $groupManager
-	 */
+	/** @var \OCP\IGroupManager */
 	protected $groupManager;
-
-	/**
-	 * @var int $sorting
-	 */
+	/** @var bool */
 	protected $sorting = false;
+	/** @var IUserSession */
+	protected $userSession;
 
 	/**
 	 * @param string $user the uid of the current user
 	 * @param bool $isAdmin whether the current users is an admin
 	 * @param \OCP\IGroupManager $groupManager
+	 * @param IUserSession $userSession
 	 */
 	public function __construct(
 			$user,
 			$isAdmin,
-			\OCP\IGroupManager $groupManager
+			\OCP\IGroupManager $groupManager,
+			IUserSession $userSession
 			) {
 		$this->user = $user;
 		$this->isAdmin = (bool)$isAdmin;
 		$this->groupManager = $groupManager;
+		$this->userSession = $userSession;
 	}
 
 	/**
@@ -190,23 +183,15 @@ class MetaData {
 	 * @param string $search a search string
 	 * @return \OCP\IGroup[]
 	 */
-	private function getGroups($search = '') {
+	protected function getGroups($search = '') {
 		if($this->isAdmin) {
 			return $this->groupManager->search($search);
 		} else {
-			// FIXME: Remove static method call
-			$groupIds = \OC_SubAdmin::getSubAdminsGroups($this->user);
-
-			/* \OC_SubAdmin::getSubAdminsGroups() returns an array of GIDs, but this
-			* method is expected to return an array with the GIDs as keys and group objects as
-			* values, so we need to convert this information.
-			*/
-			$groups = array();
-			foreach($groupIds as $gid) {
-				$group = $this->groupManager->get($gid);
-				if (!is_null($group)) {
-					$groups[$gid] = $group;
-				}
+			$userObject = $this->userSession->getUser();
+			if($userObject !== null) {
+				$groups = $this->groupManager->getSubAdmin()->getSubAdminsGroups($userObject);
+			} else {
+				$groups = [];
 			}
 
 			return $groups;
diff --git a/lib/private/json.php b/lib/private/json.php
index ac72f02f60930b3d958d83ebed13c4ea1d6346fd..eba374f4da2b1df308504375404f0a0cce21c292 100644
--- a/lib/private/json.php
+++ b/lib/private/json.php
@@ -114,7 +114,13 @@ class OC_JSON{
 	 * @deprecated Use annotation based ACLs from the AppFramework instead
 	 */
 	public static function checkSubAdminUser() {
-		if(!OC_SubAdmin::isSubAdmin(OC_User::getUser())) {
+		$userObject = \OC::$server->getUserSession()->getUser();
+		$isSubAdmin = false;
+		if($userObject !== null) {
+			$isSubAdmin = \OC::$server->getGroupManager()->getSubAdmin()->isSubAdmin($userObject);
+		}
+
+		if(!$isSubAdmin) {
 			$l = \OC::$server->getL10N('lib');
 			self::error(array( 'data' => array( 'message' => $l->t('Authentication error'), 'error' => 'authentication_error' )));
 			exit();
diff --git a/lib/private/legacy/subadmin.php b/lib/private/legacy/subadmin.php
deleted file mode 100644
index aa8e035ed3e66aaab5f26e80768de631c6fef69f..0000000000000000000000000000000000000000
--- a/lib/private/legacy/subadmin.php
+++ /dev/null
@@ -1,166 +0,0 @@
-<?php
-/**
- * @author Roeland Jago Douma <rullzer@owncloud.com>
- *
- * @copyright Copyright (c) 2015, ownCloud, Inc.
- * @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/>
- *
- */
-
-/**
- * This class provides all methods needed for managing groups.
- *
- * Hooks provided:
- *   post_createSubAdmin($gid)
- *   post_deleteSubAdmin($gid)
- */
-class OC_SubAdmin{
-
-	/**
-	 * add a SubAdmin
-	 * @param string $uid uid of the SubAdmin
-	 * @param string $gid gid of the group
-	 * @return boolean
-	 */
-	public static function createSubAdmin($uid, $gid) {
-		$groupManager = \OC::$server->getGroupManager();
-		$userManager = \OC::$server->getUserManager();
-		$subAdmin = $groupManager->getSubAdmin();
-
-		return $subAdmin->createSubAdmin($userManager->get($uid), $groupManager->get($gid));
-	}
-
-	/**
-	 * delete a SubAdmin
-	 * @param string $uid uid of the SubAdmin
-	 * @param string $gid gid of the group
-	 * @return boolean
-	 */
-	public static function deleteSubAdmin($uid, $gid) {
-		$groupManager = \OC::$server->getGroupManager();
-		$userManager = \OC::$server->getUserManager();
-		$subAdmin = $groupManager->getSubAdmin();
-
-		return $subAdmin->deleteSubAdmin($userManager->get($uid), $groupManager->get($gid));
-	}
-
-	/**
-	 * get groups of a SubAdmin
-	 * @param string $uid uid of the SubAdmin
-	 * @return array
-	 */
-	public static function getSubAdminsGroups($uid) {
-		$groupManager = \OC::$server->getGroupManager();
-		$userManager = \OC::$server->getUserManager();
-		$subAdmin = $groupManager->getSubAdmin();
-
-		$groups = $subAdmin->getSubAdminsGroups($userManager->get($uid));
-
-		// New class returns IGroup[] so convert back
-		$gids = [];
-		foreach ($groups as $group) {
-			$gids[] = $group->getGID();
-		}
-		return $gids;
-	}
-
-	/**
-	 * get SubAdmins of a group
-	 * @param string $gid gid of the group
-	 * @return array
-	 */
-	public static function getGroupsSubAdmins($gid) {
-		$groupManager = \OC::$server->getGroupManager();
-		$subAdmin = $groupManager->getSubAdmin();
-
-		$users = $subAdmin->getGroupsSubAdmins($groupManager->get($gid));
-
-		// New class returns IUser[] so convert back
-		$uids = [];
-		foreach ($users as $user) {
-			$uids[] = $user->getUID();
-		}
-		return $uids;
-	}
-
-	/**
-	 * get all SubAdmins
-	 * @return array
-	 */
-	public static function getAllSubAdmins() {
-		$groupManager = \OC::$server->getGroupManager();
-		$subAdmin = $groupManager->getSubAdmin();
-
-		$subAdmins = $subAdmin->getAllSubAdmins();
-
-		// New class returns IUser[] so convert back
-		$result = [];
-		foreach ($subAdmins as $subAdmin) {
-			$result[] = [
-				'gid' => $subAdmin['group']->getGID(),
-				'uid' => $subAdmin['user']->getUID(),
-			];
-		}
-		return $result;
-	}
-
-	/**
-	 * checks if a user is a SubAdmin of a group
-	 * @param string $uid uid of the subadmin
-	 * @param string $gid gid of the group
-	 * @return bool
-	 */
-	public static function isSubAdminofGroup($uid, $gid) {
-		$groupManager = \OC::$server->getGroupManager();
-		$userManager = \OC::$server->getUserManager();
-		$subAdmin = $groupManager->getSubAdmin();
-
-		return $subAdmin->isSubAdminOfGroup($userManager->get($uid), $groupManager->get($gid));
-	}
-
-	/**
-	 * checks if a user is a SubAdmin
-	 * @param string $uid uid of the subadmin
-	 * @return bool
-	 */
-	public static function isSubAdmin($uid) {
-		$groupManager = \OC::$server->getGroupManager();
-		$userManager = \OC::$server->getUserManager();
-		$subAdmin = $groupManager->getSubAdmin();
-
-		return $subAdmin->isSubAdmin($userManager->get($uid));
-	}
-
-	/**
-	 * checks if a user is a accessible by a subadmin
-	 * @param string $subadmin uid of the subadmin
-	 * @param string $user uid of the user
-	 * @return bool
-	 */
-	public static function isUserAccessible($subadmin, $user) {
-		$groupManager = \OC::$server->getGroupManager();
-		$userManager = \OC::$server->getUserManager();
-		$subAdmin = $groupManager->getSubAdmin();
-
-		return $subAdmin->isUserAccessible($userManager->get($subadmin), $userManager->get($user));
-	}
-
-	/*
-	 * alias for self::isSubAdminofGroup()
-	 */
-	public static function isGroupAccessible($subadmin, $group) {
-		return self::isSubAdminofGroup($subadmin, $group);
-	}
-}
diff --git a/lib/private/subadmin.php b/lib/private/subadmin.php
index 6bf960661b5eea497efd004608dd4d6670107e90..c00a2b24669d144d23159bc2a4d6070aa22cc7d1 100644
--- a/lib/private/subadmin.php
+++ b/lib/private/subadmin.php
@@ -44,6 +44,11 @@ class SubAdmin extends PublicEmitter {
 	/** @var IDBConnection */
 	private $dbConn;
 
+	/**
+	 * @param IUserManager $userManager
+	 * @param IGroupManager $groupManager
+	 * @param IDBConnection $dbConn
+	 */
 	public function __construct(IUserManager $userManager,
 	                            IGroupManager $groupManager,
 								IDBConnection $dbConn) {
@@ -68,7 +73,7 @@ class SubAdmin extends PublicEmitter {
 	public function createSubAdmin(IUser $user, IGroup $group) {
 		$qb = $this->dbConn->getQueryBuilder();
 
-		$result = $qb->insert('group_admin')
+		$qb->insert('group_admin')
 			->values([
 				'gid' => $qb->createNamedParameter($group->getGID()),
 				'uid' => $qb->createNamedParameter($user->getUID())
@@ -89,7 +94,7 @@ class SubAdmin extends PublicEmitter {
 	public function deleteSubAdmin(IUser $user, IGroup $group) {
 		$qb = $this->dbConn->getQueryBuilder();
 
-		$result = $qb->delete('group_admin')
+		$qb->delete('group_admin')
 			->where($qb->expr()->eq('gid', $qb->createNamedParameter($group->getGID())))
 			->andWhere($qb->expr()->eq('uid', $qb->createNamedParameter($user->getUID())))
 			->execute();
@@ -231,9 +236,9 @@ class SubAdmin extends PublicEmitter {
 		if($this->groupManager->isAdmin($user->getUID())) {
 			return false;
 		}
-		$accessiblegroups = $this->getSubAdminsGroups($subadmin);
-		foreach($accessiblegroups as $accessiblegroup) {
-			if($accessiblegroup->inGroup($user)) {
+		$accessibleGroups = $this->getSubAdminsGroups($subadmin);
+		foreach($accessibleGroups as $accessibleGroup) {
+			if($accessibleGroup->inGroup($user)) {
 				return true;
 			}
 		}
@@ -248,7 +253,7 @@ class SubAdmin extends PublicEmitter {
 	private function post_deleteUser($user) {
 		$qb = $this->dbConn->getQueryBuilder();
 
-		$result = $qb->delete('group_admin')
+		$qb->delete('group_admin')
 			->where($qb->expr()->eq('uid', $qb->createNamedParameter($user->getUID())))
 			->execute();
 
@@ -263,7 +268,7 @@ class SubAdmin extends PublicEmitter {
 	private function post_deleteGroup($group) {
 		$qb = $this->dbConn->getQueryBuilder();
 
-		$result = $qb->delete('group_admin')
+		$qb->delete('group_admin')
 			->where($qb->expr()->eq('gid', $qb->createNamedParameter($group->getGID())))
 			->execute();
 
diff --git a/lib/private/util.php b/lib/private/util.php
index 0b6cfb099d176a5b0ea885224c8adb2f91c67654..41f3c26e405fb3e58f24399a2f7ce2bbadf81673 100644
--- a/lib/private/util.php
+++ b/lib/private/util.php
@@ -1025,7 +1025,13 @@ class OC_Util {
 	 */
 	public static function checkSubAdminUser() {
 		OC_Util::checkLoggedIn();
-		if (!OC_SubAdmin::isSubAdmin(OC_User::getUser())) {
+		$userObject = \OC::$server->getUserSession()->getUser();
+		$isSubAdmin = false;
+		if($userObject !== null) {
+			$isSubAdmin = \OC::$server->getGroupManager()->getSubAdmin()->isSubAdmin($userObject);
+		}
+
+		if (!$isSubAdmin) {
 			header('Location: ' . OC_Helper::linkToAbsolute('', 'index.php'));
 			exit();
 		}
diff --git a/settings/ajax/changedisplayname.php b/settings/ajax/changedisplayname.php
index 36c36e73184c4719d06fefa0542a64cf62d5e15d..380cbac43dadea1a35ca7f3afec23141237f7b56 100644
--- a/settings/ajax/changedisplayname.php
+++ b/settings/ajax/changedisplayname.php
@@ -37,7 +37,15 @@ $userstatus = null;
 if(OC_User::isAdminUser(OC_User::getUser())) {
 	$userstatus = 'admin';
 }
-if(OC_SubAdmin::isUserAccessible(OC_User::getUser(), $username)) {
+
+$isUserAccessible = false;
+$subadminUserObject = \OC::$server->getUserManager()->get(\OC_User::getUser());
+$targetUserObject = \OC::$server->getUserManager()->get($username);
+if($subadminUserObject !== null && $targetUserObject !== null) {
+	$isUserAccessible = \OC::$server->getGroupManager()->getSubAdmin()->isUserAccessible($subadminUserObject, $targetUserObject);
+}
+
+if($isUserAccessible) {
 	$userstatus = 'subadmin';
 }
 
diff --git a/settings/ajax/geteveryonecount.php b/settings/ajax/geteveryonecount.php
index 659c8466f7217fb0926f77c067d69b1967836034..002c849fd393c64f121783614031aa75d1302de3 100644
--- a/settings/ajax/geteveryonecount.php
+++ b/settings/ajax/geteveryonecount.php
@@ -29,7 +29,12 @@ $userCount = 0;
 $currentUser = \OC::$server->getUserSession()->getUser()->getUID();
 
 if (!OC_User::isAdminUser($currentUser)) {
-	$groups = OC_SubAdmin::getSubAdminsGroups($currentUser);
+	$groups = \OC::$server->getGroupManager()->getSubAdmin()->getSubAdminsGroups(\OC::$server->getUserSession()->getUser());
+	// New class returns IGroup[] so convert back
+	foreach ($groups as $key => $group) {
+		$groups[$key] = $group->getGID();
+	}
+
 
 	foreach ($groups as $group) {
 		$userCount += count(OC_Group::usersInGroup($group));
diff --git a/settings/ajax/setquota.php b/settings/ajax/setquota.php
index a9012a5534589b69b6f7781b2c5009da60fecbac..8e6d44c2d8dab123dfbe253668b4dea4b36cf397 100644
--- a/settings/ajax/setquota.php
+++ b/settings/ajax/setquota.php
@@ -32,9 +32,16 @@ OCP\JSON::callCheck();
 
 $username = isset($_POST["username"]) ? (string)$_POST["username"] : '';
 
+$isUserAccessible = false;
+$currentUserObject = \OC::$server->getUserSession()->getUser();
+$targetUserObject = \OC::$server->getUserManager()->get($username);
+if($targetUserObject !== null && $currentUserObject !== null) {
+	$isUserAccessible = \OC::$server->getGroupManager()->getSubAdmin()->isUserAccessible($currentUserObject, $targetUserObject);
+}
+
 if(($username === '' && !OC_User::isAdminUser(OC_User::getUser()))
 	|| (!OC_User::isAdminUser(OC_User::getUser())
-		&& !OC_SubAdmin::isUserAccessible(OC_User::getUser(), $username))) {
+		&& !$isUserAccessible)) {
 	$l = \OC::$server->getL10N('core');
 	OC_JSON::error(array( 'data' => array( 'message' => $l->t('Authentication error') )));
 	exit();
diff --git a/settings/ajax/togglegroups.php b/settings/ajax/togglegroups.php
index 4d248408db03ffdb2457e611d71a6674c3b95e16..f46fa35654994f074abc78ee68d561c97ebc08b7 100644
--- a/settings/ajax/togglegroups.php
+++ b/settings/ajax/togglegroups.php
@@ -37,9 +37,19 @@ if($username === OC_User::getUser() && $group === "admin" &&  OC_User::isAdminUs
 	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())
-	&& (!OC_SubAdmin::isUserAccessible(OC_User::getUser(), $username)
-		|| !OC_SubAdmin::isGroupAccessible(OC_User::getUser(), $group))) {
+	&& (!$isUserAccessible
+		|| !$isGroupAccessible)) {
 	$l = \OC::$server->getL10N('core');
 	OC_JSON::error(array( 'data' => array( 'message' => $l->t('Authentication error') )));
 	exit();
diff --git a/settings/ajax/togglesubadmins.php b/settings/ajax/togglesubadmins.php
index 767baa9f3eed3e303fbcd10dc8e6182fa442a2ef..6d6bf6d67244f8d6924e45087871afecb22f052e 100644
--- a/settings/ajax/togglesubadmins.php
+++ b/settings/ajax/togglesubadmins.php
@@ -27,11 +27,20 @@ OCP\JSON::callCheck();
 $username = (string)$_POST['username'];
 $group = (string)$_POST['group'];
 
+$subAdminManager = \OC::$server->getGroupManager()->getSubAdmin();
+$targetUserObject = \OC::$server->getUserManager()->get($username);
+$targetGroupObject = \OC::$server->getGroupManager()->get($group);
+
+$isSubAdminOfGroup = false;
+if($targetUserObject !== null && $targetUserObject !== null) {
+	$isSubAdminOfGroup = $subAdminManager->isSubAdminofGroup($targetUserObject, $targetGroupObject);
+}
+
 // Toggle group
-if(OC_SubAdmin::isSubAdminofGroup($username, $group)) {
-	OC_SubAdmin::deleteSubAdmin($username, $group);
-}else{
-	OC_SubAdmin::createSubAdmin($username, $group);
+if($isSubAdminOfGroup) {
+	$subAdminManager->deleteSubAdmin($targetUserObject, $targetGroupObject);
+} else {
+	$subAdminManager->createSubAdmin($targetUserObject, $targetGroupObject);
 }
 
 OC_JSON::success();
diff --git a/settings/application.php b/settings/application.php
index 155cc39d0416bd84771dd36522583bbcee75ecaf..c876065fffa6115747a002927c971b783e6d117c 100644
--- a/settings/application.php
+++ b/settings/application.php
@@ -36,7 +36,6 @@ use OC\Settings\Controller\LogSettingsController;
 use OC\Settings\Controller\MailSettingsController;
 use OC\Settings\Controller\SecuritySettingsController;
 use OC\Settings\Controller\UsersController;
-use OC\Settings\Factory\SubAdminFactory;
 use OC\Settings\Middleware\SubadminMiddleware;
 use \OCP\AppFramework\App;
 use OCP\IContainer;
@@ -136,8 +135,7 @@ class Application extends App {
 				$c->query('Mailer'),
 				$c->query('DefaultMailAddress'),
 				$c->query('URLGenerator'),
-				$c->query('OCP\\App\\IAppManager'),
-				$c->query('SubAdminFactory')
+				$c->query('OCP\\App\\IAppManager')
 			);
 		});
 		$container->registerService('LogSettingsController', function(IContainer $c) {
@@ -199,11 +197,12 @@ class Application extends App {
 		});
 		/** FIXME: Remove once OC_SubAdmin is non-static and mockable */
 		$container->registerService('IsSubAdmin', function(IContainer $c) {
-			return \OC_Subadmin::isSubAdmin(\OC_User::getUser());
-		});
-		/** FIXME: Remove once OC_SubAdmin is non-static and mockable */
-		$container->registerService('SubAdminFactory', function(IContainer $c) {
-			return new SubAdminFactory();
+			$userObject = \OC::$server->getUserSession()->getUser();
+			$isSubAdmin = false;
+			if($userObject !== null) {
+				$isSubAdmin = \OC::$server->getGroupManager()->getSubAdmin()->isSubAdmin($userObject);
+			}
+			return $isSubAdmin;
 		});
 		$container->registerService('Mailer', function(IContainer $c) {
 			return $c->query('ServerContainer')->getMailer();
diff --git a/settings/changepassword/controller.php b/settings/changepassword/controller.php
index 3fa3ac67edb45828fd83038e5a4dff3e3e4bf11e..695914683dbb85e439dd577f841c32c2fa23573b 100644
--- a/settings/changepassword/controller.php
+++ b/settings/changepassword/controller.php
@@ -66,9 +66,16 @@ class Controller {
 		$password = isset($_POST['password']) ? $_POST['password'] : null;
 		$recoveryPassword = isset($_POST['recoveryPassword']) ? $_POST['recoveryPassword'] : null;
 
+		$isUserAccessible = false;
+		$currentUserObject = \OC::$server->getUserSession()->getUser();
+		$targetUserObject = \OC::$server->getUserManager()->get($username);
+		if($currentUserObject !== null && $targetUserObject !== null) {
+			$isUserAccessible = \OC::$server->getGroupManager()->getSubAdmin()->isUserAccessible($currentUserObject, $targetUserObject);
+		}
+
 		if (\OC_User::isAdminUser(\OC_User::getUser())) {
 			$userstatus = 'admin';
-		} elseif (\OC_SubAdmin::isUserAccessible(\OC_User::getUser(), $username)) {
+		} elseif ($isUserAccessible) {
 			$userstatus = 'subadmin';
 		} else {
 			$l = new \OC_L10n('settings');
diff --git a/settings/controller/groupscontroller.php b/settings/controller/groupscontroller.php
index 218a9c0d51c096c000e0988f3af989e002b45c00..93dcc7358a98824c90645d74ff2c587d9696d046 100644
--- a/settings/controller/groupscontroller.php
+++ b/settings/controller/groupscontroller.php
@@ -77,8 +77,12 @@ class GroupsController extends Controller {
 	public function index($pattern = '', $filterGroups = false, $sortGroups = MetaData::SORT_USERCOUNT) {
 		$groupPattern = $filterGroups ? $pattern : '';
 
-		$groupsInfo = new MetaData($this->userSession->getUser()->getUID(),
-			$this->isAdmin, $this->groupManager);
+		$groupsInfo = new MetaData(
+			$this->userSession->getUser()->getUID(),
+			$this->isAdmin,
+			$this->groupManager,
+			$this->userSession
+		);
 		$groupsInfo->setSorting($sortGroups);
 		list($adminGroups, $groups) = $groupsInfo->get($groupPattern, $pattern);
 
diff --git a/settings/controller/userscontroller.php b/settings/controller/userscontroller.php
index 1a77172db9b4413875c4a25161fe46cb8a0bcb8f..8183bc4739bc0bbbe48e7916202b05987112a6df 100644
--- a/settings/controller/userscontroller.php
+++ b/settings/controller/userscontroller.php
@@ -74,8 +74,6 @@ class UsersController extends Controller {
 	private $isEncryptionAppEnabled;
 	/** @var bool contains the state of the admin recovery setting */
 	private $isRestoreEnabled = false;
-	/** @var SubAdminFactory */
-	private $subAdminFactory;
 
 	/**
 	 * @param string $appName
@@ -92,7 +90,6 @@ class UsersController extends Controller {
 	 * @param string $fromMailAddress
 	 * @param IURLGenerator $urlGenerator
 	 * @param IAppManager $appManager
-	 * @param SubAdminFactory $subAdminFactory
 	 */
 	public function __construct($appName,
 								IRequest $request,
@@ -107,8 +104,7 @@ class UsersController extends Controller {
 								IMailer $mailer,
 								$fromMailAddress,
 								IURLGenerator $urlGenerator,
-								IAppManager $appManager,
-								SubAdminFactory $subAdminFactory) {
+								IAppManager $appManager) {
 		parent::__construct($appName, $request);
 		$this->userManager = $userManager;
 		$this->groupManager = $groupManager;
@@ -121,7 +117,6 @@ class UsersController extends Controller {
 		$this->mailer = $mailer;
 		$this->fromMailAddress = $fromMailAddress;
 		$this->urlGenerator = $urlGenerator;
-		$this->subAdminFactory = $subAdminFactory;
 
 		// check for encryption state - TODO see formatUserForIndex
 		$this->isEncryptionAppEnabled = $appManager->isEnabledForUser('encryption');
@@ -164,11 +159,16 @@ class UsersController extends Controller {
 			$restorePossible = true;
 		}
 
+		$subAdminGroups = $this->groupManager->getSubAdmin()->getSubAdminsGroups($user);
+		foreach($subAdminGroups as $key => $subAdminGroup) {
+			$subAdminGroups[$key] = $subAdminGroup->getGID();
+		}
+
 		return [
 			'name' => $user->getUID(),
 			'displayname' => $user->getDisplayName(),
 			'groups' => (empty($userGroups)) ? $this->groupManager->getUserGroupIds($user) : $userGroups,
-			'subadmin' => $this->subAdminFactory->getSubAdminsOfGroups($user->getUID()),
+			'subadmin' => $subAdminGroups,
 			'quota' => $this->config->getUserValue($user->getUID(), 'files', 'quota', 'default'),
 			'storageLocation' => $user->getHome(),
 			'lastLogin' => $user->getLastLogin() * 1000,
@@ -234,9 +234,14 @@ class UsersController extends Controller {
 			}
 
 		} else {
-			$subAdminOfGroups = $this->subAdminFactory->getSubAdminsOfGroups(
-				$this->userSession->getUser()->getUID()
-			);
+			$subAdminOfGroups = $this->groupManager->getSubAdmin()->getSubAdminsGroups($this->userSession->getUser());
+			// New class returns IGroup[] so convert back
+			$gids = [];
+			foreach ($subAdminOfGroups as $group) {
+				$gids[] = $group->getGID();
+			}
+			$subAdminOfGroups = $gids;
+
 			// Set the $gid parameter to an empty value if the subadmin has no rights to access a specific group
 			if($gid !== '' && !in_array($gid, $subAdminOfGroups)) {
 				$gid = '';
@@ -247,6 +252,7 @@ class UsersController extends Controller {
 			if($gid === '') {
 				foreach($subAdminOfGroups as $group) {
 					$groupUsers = $this->groupManager->displayNamesInGroup($group, $pattern, $limit, $offset);
+
 					foreach($groupUsers as $uid => $displayName) {
 						$batch[$uid] = $displayName;
 					}
@@ -288,17 +294,31 @@ class UsersController extends Controller {
 			);
 		}
 
+		$currentUser = $this->userSession->getUser();
+
 		if (!$this->isAdmin) {
-			$userId = $this->userSession->getUser()->getUID();
 			if (!empty($groups)) {
 				foreach ($groups as $key => $group) {
-					if (!$this->subAdminFactory->isGroupAccessible($userId, $group)) {
+					$groupObject = $this->groupManager->get($group);
+					if($groupObject === null) {
+						unset($groups[$key]);
+						continue;
+					}
+
+					if (!$this->groupManager->getSubAdmin()->isSubAdminofGroup($currentUser, $groupObject)) {
 						unset($groups[$key]);
 					}
 				}
 			}
+
 			if (empty($groups)) {
-				$groups = $this->subAdminFactory->getSubAdminsOfGroups($userId);
+				$groups = $this->groupManager->getSubAdmin()->getSubAdminsGroups($currentUser);
+				// New class returns IGroup[] so convert back
+				$gids = [];
+				foreach ($groups as $group) {
+					$gids[] = $group->getGID();
+				}
+				$groups = $gids;
 			}
 		}
 
@@ -391,6 +411,8 @@ class UsersController extends Controller {
 	 */
 	public function destroy($id) {
 		$userId = $this->userSession->getUser()->getUID();
+		$user = $this->userManager->get($id);
+
 		if($userId === $id) {
 			return new DataResponse(
 				array(
@@ -403,7 +425,7 @@ class UsersController extends Controller {
 			);
 		}
 
-		if(!$this->isAdmin && !$this->subAdminFactory->isUserAccessible($userId, $id)) {
+		if(!$this->isAdmin && !$this->groupManager->getSubAdmin()->isUserAccessible($this->userSession->getUser(), $user)) {
 			return new DataResponse(
 				array(
 					'status' => 'error',
@@ -415,7 +437,6 @@ class UsersController extends Controller {
 			);
 		}
 
-		$user = $this->userManager->get($id);
 		if($user) {
 			if($user->delete()) {
 				return new DataResponse(
@@ -453,9 +474,11 @@ class UsersController extends Controller {
 	 */
 	public function setMailAddress($id, $mailAddress) {
 		$userId = $this->userSession->getUser()->getUID();
+		$user = $this->userManager->get($id);
+
 		if($userId !== $id
 			&& !$this->isAdmin
-			&& !$this->subAdminFactory->isUserAccessible($userId, $id)) {
+			&& !$this->groupManager->getSubAdmin()->isUserAccessible($this->userSession->getUser(), $user)) {
 			return new DataResponse(
 				array(
 					'status' => 'error',
@@ -479,7 +502,6 @@ class UsersController extends Controller {
 			);
 		}
 
-		$user = $this->userManager->get($id);
 		if(!$user){
 			return new DataResponse(
 				array(
diff --git a/settings/factory/subadminfactory.php b/settings/factory/subadminfactory.php
deleted file mode 100644
index 5a0f6e4e1e4d7d9624ab48770e3f7976275c4d7f..0000000000000000000000000000000000000000
--- a/settings/factory/subadminfactory.php
+++ /dev/null
@@ -1,57 +0,0 @@
-<?php
-/**
- * @author Lukas Reschke <lukas@owncloud.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- *
- * @copyright Copyright (c) 2015, ownCloud, Inc.
- * @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/>
- *
- */
-
-namespace OC\Settings\Factory;
-
-/**
- * @package OC\Settings\Factory
- */
-class SubAdminFactory {
-	/**
-	 * Get the groups $uid is SubAdmin of
-	 * @param string $uid
-	 * @return array Array of groups that $uid is subadmin of
-	 */
-	function getSubAdminsOfGroups($uid) {
-		return \OC_SubAdmin::getSubAdminsGroups($uid);
-	}
-
-	/**
-	 * Whether the $group is accessible to $uid as subadmin
-	 * @param string $uid
-	 * @param string $group
-	 * @return bool
-	 */
-	function isGroupAccessible($uid, $group) {
-		return \OC_SubAdmin::isGroupAccessible($uid, $group);
-	}
-
-	/**
-	 * Whether $uid is accessible to $subAdmin
-	 * @param string $subAdmin
-	 * @param string $uid
-	 * @return bool
-	 */
-	function isUserAccessible($subAdmin, $uid) {
-		return \OC_SubAdmin::isUserAccessible($subAdmin, $uid);
-	}
-}
diff --git a/settings/users.php b/settings/users.php
index 59cc94f502313bd0f0b40a313112f402a2682569..dac649aa828e2b50c5b575a5a6b3c5f58f15a7b9 100644
--- a/settings/users.php
+++ b/settings/users.php
@@ -57,7 +57,12 @@ $config = \OC::$server->getConfig();
 
 $isAdmin = OC_User::isAdminUser(OC_User::getUser());
 
-$groupsInfo = new \OC\Group\MetaData(OC_User::getUser(), $isAdmin, $groupManager);
+$groupsInfo = new \OC\Group\MetaData(
+	OC_User::getUser(),
+	$isAdmin,
+	$groupManager,
+	\OC::$server->getUserSession()
+);
 $groupsInfo->setSorting($sortGroupsBy);
 list($adminGroup, $groups) = $groupsInfo->get();
 
@@ -65,7 +70,16 @@ $recoveryAdminEnabled = OC_App::isEnabled('encryption') &&
 					    $config->getAppValue( 'encryption', 'recoveryAdminEnabled', null );
 
 if($isAdmin) {
-	$subadmins = OC_SubAdmin::getAllSubAdmins();
+	$subadmins = \OC::$server->getGroupManager()->getSubAdmin()->getAllSubAdmins();
+	// New class returns IUser[] so convert back
+	$result = [];
+	foreach ($subAdmins as $subAdmin) {
+		$result[] = [
+			'gid' => $subAdmin['group']->getGID(),
+			'uid' => $subAdmin['user']->getUID(),
+		];
+	}
+	$subadmins = $result;
 }else{
 	/* Retrieve group IDs from $groups array, so we can pass that information into OC_Group::displayNamesInGroups() */
 	$gids = array();
diff --git a/tests/lib/group/metadata.php b/tests/lib/group/metadata.php
index 3f4019c2facfc89d0a3766c3dcd2c381a8b8c1f1..233463c71eb7f0623169e8bd530423220be5c876 100644
--- a/tests/lib/group/metadata.php
+++ b/tests/lib/group/metadata.php
@@ -1,19 +1,49 @@
 <?php
-
 /**
- * Copyright (c) 2014 Arthur Schiwon <blizzz@owncloud.com>
- * This file is licensed under the Affero General Public License version 3 or
- * later.
- * See the COPYING-README file.
+ * @author Arthur Schiwon <blizzz@owncloud.com>
+ * @author Lukas Reschke <lukas@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @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/>
+ *
  */
 
 namespace Test\Group;
 
 class Test_MetaData extends \Test\TestCase {
-	private function getGroupManagerMock() {
-		return $this->getMockBuilder('\OC\Group\Manager')
+	/** @var \OC\Group\Manager */
+	private $groupManager;
+	/** @var \OCP\IUserSession */
+	private $userSession;
+	/** @var \OC\Group\MetaData */
+	private $groupMetadata;
+	/** @var bool */
+	private $isAdmin = true;
+
+	public function setUp() {
+		parent::setUp();
+		$this->groupManager = $this->getMockBuilder('\OC\Group\Manager')
 			->disableOriginalConstructor()
 			->getMock();
+		$this->userSession = $this->getMock('\OCP\IUserSession');
+		$this->groupMetadata = new \OC\Group\MetaData(
+			'foo',
+			$this->isAdmin,
+			$this->groupManager,
+			$this->userSession
+		);
 	}
 
 	private function getGroupMock($countCallCount = 0) {
@@ -38,17 +68,15 @@ class Test_MetaData extends \Test\TestCase {
 
 
 	public function testGet() {
-		$groupManager = $this->getGroupManagerMock();
-		$groupMetaData = new \OC\Group\MetaData('foo', true, $groupManager);
 		$group = $this->getGroupMock();
 		$groups = array_fill(0, 3, $group);
 
-		$groupManager->expects($this->once())
+		$this->groupManager->expects($this->once())
 			->method('search')
 			->with('')
 			->will($this->returnValue($groups));
 
-		list($adminGroups, $ordinaryGroups) = $groupMetaData->get();
+		list($adminGroups, $ordinaryGroups) = $this->groupMetadata->get();
 
 		$this->assertSame(1, count($adminGroups));
 		$this->assertSame(2, count($ordinaryGroups));
@@ -59,18 +87,16 @@ class Test_MetaData extends \Test\TestCase {
 	}
 
 	public function testGetWithSorting() {
-		$groupManager = $this->getGroupManagerMock();
-		$groupMetaData = new \OC\Group\MetaData('foo', true, $groupManager);
-		$groupMetaData->setSorting($groupMetaData::SORT_USERCOUNT);
+		$this->groupMetadata->setSorting(1);
 		$group = $this->getGroupMock(3);
 		$groups = array_fill(0, 3, $group);
 
-		$groupManager->expects($this->once())
+		$this->groupManager->expects($this->once())
 			->method('search')
 			->with('')
 			->will($this->returnValue($groups));
 
-		list($adminGroups, $ordinaryGroups) = $groupMetaData->get();
+		list($adminGroups, $ordinaryGroups) = $this->groupMetadata->get();
 
 		$this->assertSame(1, count($adminGroups));
 		$this->assertSame(2, count($ordinaryGroups));
@@ -80,23 +106,31 @@ class Test_MetaData extends \Test\TestCase {
 	}
 
 	public function testGetWithCache() {
-		$groupManager = $this->getGroupManagerMock();
-		$groupMetaData = new \OC\Group\MetaData('foo', true, $groupManager);
 		$group = $this->getGroupMock();
 		$groups = array_fill(0, 3, $group);
 
-		$groupManager->expects($this->once())
+		$this->groupManager->expects($this->once())
 			->method('search')
 			->with('')
 			->will($this->returnValue($groups));
 
 		//two calls, if caching fails call counts for group and groupmanager
 		//are exceeded
-		$groupMetaData->get();
-		$groupMetaData->get();
+		$this->groupMetadata->get();
+		$this->groupMetadata->get();
 	}
 
 	//get() does not need to be tested with search parameters, because they are
 	//solely and only passed to GroupManager and Group.
 
+	public function testGetGroupsAsAdmin() {
+		$this->groupManager
+			->expects($this->once())
+			->method('search')
+			->with('Foo')
+			->will($this->returnValue(['DummyValue']));
+
+		$expected = ['DummyValue'];
+		$this->assertSame($expected, $this->invokePrivate($this->groupMetadata, 'getGroups', ['Foo']));
+	}
 }
diff --git a/tests/settings/controller/userscontrollertest.php b/tests/settings/controller/userscontrollertest.php
index 408ddc455891dfa620bbccd50887b8e6c8fdd634..e30a98447aebe054976243a20a6bfef034413d59 100644
--- a/tests/settings/controller/userscontrollertest.php
+++ b/tests/settings/controller/userscontrollertest.php
@@ -25,7 +25,7 @@ class UsersControllerTest extends \Test\TestCase {
 		$app = new Application();
 		$this->container = $app->getContainer();
 		$this->container['AppName'] = 'settings';
-		$this->container['GroupManager'] = $this->getMockBuilder('\OCP\IGroupManager')
+		$this->container['GroupManager'] = $this->getMockBuilder('\OC\Group\Manager')
 			->disableOriginalConstructor()->getMock();
 		$this->container['UserManager'] = $this->getMockBuilder('\OCP\IUserManager')
 			->disableOriginalConstructor()->getMock();
@@ -33,8 +33,6 @@ class UsersControllerTest extends \Test\TestCase {
 			->disableOriginalConstructor()->getMock();
 		$this->container['L10N'] = $this->getMockBuilder('\OCP\IL10N')
 			->disableOriginalConstructor()->getMock();
-		$this->container['SubAdminFactory'] = $this->getMockBuilder('\OC\Settings\Factory\SubAdminFactory')
-			->disableOriginalConstructor()->getMock();
 		$this->container['Config'] = $this->getMockBuilder('\OCP\IConfig')
 			->disableOriginalConstructor()->getMock();
 		$this->container['L10N']
@@ -62,7 +60,7 @@ class UsersControllerTest extends \Test\TestCase {
 		$foo = $this->getMockBuilder('\OC\User\User')
 			->disableOriginalConstructor()->getMock();
 		$foo
-			->expects($this->exactly(4))
+			->expects($this->exactly(3))
 			->method('getUID')
 			->will($this->returnValue('foo'));
 		$foo
@@ -82,7 +80,7 @@ class UsersControllerTest extends \Test\TestCase {
 		$admin = $this->getMockBuilder('\OC\User\User')
 			->disableOriginalConstructor()->getMock();
 		$admin
-			->expects($this->exactly(4))
+			->expects($this->exactly(3))
 			->method('getUID')
 			->will($this->returnValue('admin'));
 		$admin
@@ -104,7 +102,7 @@ class UsersControllerTest extends \Test\TestCase {
 		$bar = $this->getMockBuilder('\OC\User\User')
 			->disableOriginalConstructor()->getMock();
 		$bar
-			->expects($this->exactly(4))
+			->expects($this->exactly(3))
 			->method('getUID')
 			->will($this->returnValue('bar'));
 		$bar
@@ -153,21 +151,29 @@ class UsersControllerTest extends \Test\TestCase {
 											404, 'admin@bar.com',
 											2323, 'bar@dummy.com'));
 
-		$this->container['SubAdminFactory']
-			->expects($this->at(0))
-			->method('getSubAdminsOfGroups')
-			->with('foo')
+		$subadmin = $this->getMockBuilder('\OC\SubAdmin')
+			->disableOriginalConstructor()
+			->getMock();
+		$subadmin
+			->expects($this->any())
+			->method('getSubAdminsGroups')
+			->with($foo)
 			->will($this->returnValue([]));
-		$this->container['SubAdminFactory']
-			->expects($this->at(1))
-			->method('getSubAdminsOfGroups')
-			->with('admin')
+		$subadmin
+			->expects($this->any())
+			->method('getSubAdminsGroups')
+			->with($admin)
 			->will($this->returnValue([]));
-		$this->container['SubAdminFactory']
-			->expects($this->at(2))
-			->method('getSubAdminsOfGroups')
-			->with('bar')
+		$subadmin
+			->expects($this->any())
+			->method('getSubAdminsGroups')
+			->with($bar)
 			->will($this->returnValue([]));
+		$this->container['GroupManager']
+			->expects($this->any())
+			->method('getSubAdmin')
+			->will($this->returnValue($subadmin));
+
 
 		$expectedResponse = new DataResponse(
 			array(
@@ -218,10 +224,6 @@ class UsersControllerTest extends \Test\TestCase {
 
 		$user = $this->getMockBuilder('\OC\User\User')
 			->disableOriginalConstructor()->getMock();
-		$user
-			->expects($this->once())
-			->method('getUID')
-			->will($this->returnValue('username'));
 		$this->container['UserSession']
 			->expects($this->once())
 			->method('getUser')
@@ -230,7 +232,7 @@ class UsersControllerTest extends \Test\TestCase {
 		$foo = $this->getMockBuilder('\OC\User\User')
 			->disableOriginalConstructor()->getMock();
 		$foo
-			->expects($this->exactly(4))
+			->expects($this->exactly(3))
 			->method('getUID')
 			->will($this->returnValue('foo'));
 		$foo
@@ -250,7 +252,7 @@ class UsersControllerTest extends \Test\TestCase {
 		$admin = $this->getMockBuilder('\OC\User\User')
 			->disableOriginalConstructor()->getMock();
 		$admin
-			->expects($this->exactly(4))
+			->expects($this->exactly(3))
 			->method('getUID')
 			->will($this->returnValue('admin'));
 		$admin
@@ -272,7 +274,7 @@ class UsersControllerTest extends \Test\TestCase {
 		$bar = $this->getMockBuilder('\OC\User\User')
 			->disableOriginalConstructor()->getMock();
 		$bar
-			->expects($this->exactly(4))
+			->expects($this->exactly(3))
 			->method('getUID')
 			->will($this->returnValue('bar'));
 		$bar
@@ -291,59 +293,90 @@ class UsersControllerTest extends \Test\TestCase {
 			->will($this->returnValue('\Test\Util\User\Dummy'));
 
 		$this->container['GroupManager']
-			->expects($this->at(0))
+			->expects($this->at(2))
 			->method('displayNamesInGroup')
-			->with('SubGroup1', 'pattern')
+			->with('SubGroup2', 'pattern')
 			->will($this->returnValue(['foo' => 'M. Foo', 'admin' => 'S. Admin']));
 		$this->container['GroupManager']
 			->expects($this->at(1))
 			->method('displayNamesInGroup')
-			->with('SubGroup2', 'pattern')
+			->with('SubGroup1', 'pattern')
 			->will($this->returnValue(['bar' => 'B. Ar']));
 		$this->container['GroupManager']
 			->expects($this->exactly(3))
 			->method('getUserGroupIds')
 			->will($this->onConsecutiveCalls(
+				['admin', 'SubGroup1', 'testGroup'],
 				['SubGroup2', 'SubGroup1'],
-				['SubGroup2', 'Foo'],
-				['admin', 'SubGroup1', 'testGroup']
+				['SubGroup2', 'Foo']
 			));
 		$this->container['UserManager']
 			->expects($this->at(0))
 			->method('get')
-			->with('foo')
-			->will($this->returnValue($foo));
+			->with('bar')
+			->will($this->returnValue($bar));
 		$this->container['UserManager']
 			->expects($this->at(1))
 			->method('get')
-			->with('admin')
-			->will($this->returnValue($admin));
+			->with('foo')
+			->will($this->returnValue($foo));
 		$this->container['UserManager']
 			->expects($this->at(2))
 			->method('get')
-			->with('bar')
-			->will($this->returnValue($bar));
+			->with('admin')
+			->will($this->returnValue($admin));
 		$this->container['Config']
 			->expects($this->exactly(6))
 			->method('getUserValue')
 			->will($this->onConsecutiveCalls(
+				2323, 'bar@dummy.com',
 				1024, 'foo@bar.com',
-				404, 'admin@bar.com',
-				2323, 'bar@dummy.com'
+				404, 'admin@bar.com'
 			));
 
-		$this->container['SubAdminFactory']
-			->method('getSubAdminsOfGroups')
-			->will($this->returnValueMap([
-				['username' , ['SubGroup1', 'SubGroup2']],
-				['foo', []],
-				['admin', []],
-				['bar', []],
-			]));
+		$subgroup1 = $this->getMockBuilder('\OCP\IGroup')
+			->disableOriginalConstructor()
+			->getMock();
+		$subgroup1->expects($this->any())
+			->method('getGID')
+			->will($this->returnValue('SubGroup1'));
+		$subgroup2 = $this->getMockBuilder('\OCP\IGroup')
+			->disableOriginalConstructor()
+			->getMock();
+		$subgroup2->expects($this->any())
+			->method('getGID')
+			->will($this->returnValue('SubGroup2'));
+		$subadmin = $this->getMockBuilder('\OC\SubAdmin')
+			->disableOriginalConstructor()
+			->getMock();
+		$subadmin
+			->expects($this->at(0))
+			->method('getSubAdminsGroups')
+			->will($this->returnValue([$subgroup1, $subgroup2]));
+		$subadmin
+			->expects($this->any())
+			->method('getSubAdminsGroups')
+			->will($this->returnValue([]));
+		$this->container['GroupManager']
+			->expects($this->any())
+			->method('getSubAdmin')
+			->will($this->returnValue($subadmin));
 
 		$expectedResponse = new DataResponse(
 			[
 				0 => [
+					'name' => 'bar',
+					'displayname' => 'B. Ar',
+					'groups' => ['SubGroup1'],
+					'subadmin' => [],
+					'quota' => 2323,
+					'storageLocation' => '/home/bar',
+					'lastLogin' => 3999000,
+					'backend' => '\Test\Util\User\Dummy',
+					'email' => 'bar@dummy.com',
+					'isRestoreDisabled' => false,
+				],
+				1=> [
 					'name' => 'foo',
 					'displayname' => 'M. Foo',
 					'groups' => ['SubGroup2', 'SubGroup1'],
@@ -355,7 +388,7 @@ class UsersControllerTest extends \Test\TestCase {
 					'email' => 'foo@bar.com',
 					'isRestoreDisabled' => false,
 				],
-				1 => [
+				2 => [
 					'name' => 'admin',
 					'displayname' => 'S. Admin',
 					'groups' => ['SubGroup2'],
@@ -367,18 +400,6 @@ class UsersControllerTest extends \Test\TestCase {
 					'email' => 'admin@bar.com',
 					'isRestoreDisabled' => false,
 				],
-				2 => [
-					'name' => 'bar',
-					'displayname' => 'B. Ar',
-					'groups' => ['SubGroup1'],
-					'subadmin' => [],
-					'quota' => 2323,
-					'storageLocation' => '/home/bar',
-					'lastLogin' => 3999000,
-					'backend' => '\Test\Util\User\Dummy',
-					'email' => 'bar@dummy.com',
-					'isRestoreDisabled' => false,
-				],
 			]
 		);
 
@@ -396,7 +417,7 @@ class UsersControllerTest extends \Test\TestCase {
 		$foo = $this->getMockBuilder('\OC\User\User')
 			->disableOriginalConstructor()->getMock();
 		$foo
-			->expects($this->exactly(4))
+			->expects($this->exactly(3))
 			->method('getUID')
 			->will($this->returnValue('foo'));
 		$foo
@@ -416,7 +437,7 @@ class UsersControllerTest extends \Test\TestCase {
 		$admin = $this->getMockBuilder('\OC\User\User')
 			->disableOriginalConstructor()->getMock();
 		$admin
-			->expects($this->exactly(4))
+			->expects($this->exactly(3))
 			->method('getUID')
 			->will($this->returnValue('admin'));
 		$admin
@@ -438,7 +459,7 @@ class UsersControllerTest extends \Test\TestCase {
 		$bar = $this->getMockBuilder('\OC\User\User')
 			->disableOriginalConstructor()->getMock();
 		$bar
-			->expects($this->exactly(4))
+			->expects($this->exactly(3))
 			->method('getUID')
 			->will($this->returnValue('bar'));
 		$bar
@@ -472,22 +493,16 @@ class UsersControllerTest extends \Test\TestCase {
 				404, 'admin@bar.com',
 				2323, 'bar@dummy.com'));
 
-		$this->container['SubAdminFactory']
-			->expects($this->at(0))
-			->method('getSubAdminsOfGroups')
-			->with('foo')
-			->will($this->returnValue([]));
-		$this->container['SubAdminFactory']
-			->expects($this->at(1))
-			->method('getSubAdminsOfGroups')
-			->with('admin')
+		$subadmin = $this->getMockBuilder('\OC\SubAdmin')
+			->disableOriginalConstructor()
+			->getMock();
+		$subadmin->expects($this->any())
+			->method('getSubAdminsGroups')
 			->will($this->returnValue([]));
-		$this->container['SubAdminFactory']
-			->expects($this->at(2))
-			->method('getSubAdminsOfGroups')
-			->with('bar')
-			->will($this->returnValue([]));
-
+		$this->container['GroupManager']
+			->expects($this->any())
+			->method('getSubAdmin')
+			->will($this->returnValue($subadmin));
 
 		$expectedResponse = new DataResponse(
 			array(
@@ -539,7 +554,7 @@ class UsersControllerTest extends \Test\TestCase {
 		$user = $this->getMockBuilder('\OC\User\User')
 			->disableOriginalConstructor()->getMock();
 		$user
-			->expects($this->exactly(4))
+			->expects($this->exactly(3))
 			->method('getUID')
 			->will($this->returnValue('foo'));
 		$user
@@ -569,11 +584,16 @@ class UsersControllerTest extends \Test\TestCase {
 			->with('')
 			->will($this->returnValue([$user]));
 
-		$this->container['SubAdminFactory']
-			->expects($this->once())
-			->method('getSubAdminsOfGroups')
-			->with('foo')
+		$subadmin = $this->getMockBuilder('\OC\SubAdmin')
+			->disableOriginalConstructor()
+			->getMock();
+		$subadmin->expects($this->once())
+			->method('getSubAdminsGroups')
 			->will($this->returnValue([]));
+		$this->container['GroupManager']
+			->expects($this->any())
+			->method('getSubAdmin')
+			->will($this->returnValue($subadmin));
 
 		$expectedResponse = new DataResponse(
 			array(
@@ -634,11 +654,18 @@ class UsersControllerTest extends \Test\TestCase {
 			->method('createUser')
 			->will($this->onConsecutiveCalls($user));
 
-		$this->container['SubAdminFactory']
-			->expects($this->once())
-			->method('getSubAdminsOfGroups')
-			->with('foo')
+		$subadmin = $this->getMockBuilder('\OC\SubAdmin')
+			->disableOriginalConstructor()
+			->getMock();
+		$subadmin
+			->expects($this->any())
+			->method('getSubAdminsGroups')
+			->with($user)
 			->will($this->returnValue([]));
+		$this->container['GroupManager']
+			->expects($this->any())
+			->method('getSubAdmin')
+			->will($this->returnValue($subadmin));
 
 		$expectedResponse = new DataResponse(
 			array(
@@ -663,47 +690,45 @@ class UsersControllerTest extends \Test\TestCase {
 		$this->container['IsAdmin'] = false;
 		$user = $this->getMockBuilder('\OC\User\User')
 			->disableOriginalConstructor()->getMock();
-		$user
-			->expects($this->once())
-			->method('getUID')
-			->will($this->returnValue('username'));
 		$this->container['UserSession']
 			->expects($this->once())
 			->method('getUser')
 			->will($this->returnValue($user));
 
-		$user = $this->getMockBuilder('\OC\User\User')
+		$newUser = $this->getMockBuilder('\OC\User\User')
 			->disableOriginalConstructor()->getMock();
-		$user
+		$newUser
+			->method('getUID')
+			->will($this->returnValue('foo'));
+		$newUser
 			->method('getHome')
 			->will($this->returnValue('/home/user'));
-		$user
+		$newUser
 			->method('getHome')
 			->will($this->returnValue('/home/user'));
-		$user
-			->method('getUID')
-			->will($this->returnValue('foo'));
-		$user
+		$newUser
 			->expects($this->once())
 			->method('getBackendClassName')
 			->will($this->returnValue('bar'));
+		$user = $this->getMockBuilder('\OC\User\User')
+			->disableOriginalConstructor()->getMock();
 		$subGroup1 = $this->getMockBuilder('\OCP\IGroup')
 			->disableOriginalConstructor()->getMock();
 		$subGroup1
 			->expects($this->once())
 			->method('addUser')
-			->with($user);
+			->with($newUser);
 		$subGroup2 = $this->getMockBuilder('\OCP\IGroup')
 			->disableOriginalConstructor()->getMock();
 		$subGroup2
 			->expects($this->once())
 			->method('addUser')
-			->with($user);
+			->with($newUser);
 
 		$this->container['UserManager']
 			->expects($this->once())
 			->method('createUser')
-			->will($this->onConsecutiveCalls($user));
+			->will($this->returnValue($newUser));
 		$this->container['GroupManager']
 			->expects($this->exactly(2))
 			->method('get')
@@ -714,12 +739,21 @@ class UsersControllerTest extends \Test\TestCase {
 			->with($user)
 			->will($this->onConsecutiveCalls(['SubGroup1', 'SubGroup2']));
 
-		$this->container['SubAdminFactory']
-			->method('getSubAdminsOfGroups')
-			->will($this->returnValueMap([
-				['username', ['SubGroup1', 'SubGroup2']],
-				['foo', []],
-			]));
+		$subadmin = $this->getMockBuilder('\OC\SubAdmin')
+			->disableOriginalConstructor()
+			->getMock();
+		$subadmin
+			->expects($this->at(0))
+			->method('getSubAdminsGroups')
+			->will($this->returnValue([$subGroup1, $subGroup2]));
+		$subadmin
+			->expects($this->at(1))
+			->method('getSubAdminsGroups')
+			->will($this->returnValue([]));
+		$this->container['GroupManager']
+			->expects($this->any())
+			->method('getSubAdmin')
+			->will($this->returnValue($subadmin));
 
 		$expectedResponse = new DataResponse(
 			array(
@@ -727,7 +761,7 @@ class UsersControllerTest extends \Test\TestCase {
 				'groups' => ['SubGroup1', 'SubGroup2'],
 				'storageLocation' => '/home/user',
 				'backend' => 'bar',
-				'lastLogin' => null,
+				'lastLogin' => 0,
 				'displayname' => null,
 				'quota' => null,
 				'subadmin' => [],
@@ -790,11 +824,18 @@ class UsersControllerTest extends \Test\TestCase {
 			->with($user)
 			->will($this->onConsecutiveCalls(array('NewGroup', 'ExistingGroup')));
 
-		$this->container['SubAdminFactory']
+		$subadmin = $this->getMockBuilder('\OC\SubAdmin')
+			->disableOriginalConstructor()
+			->getMock();
+		$subadmin
 			->expects($this->once())
-			->method('getSubAdminsOfGroups')
-			->with('foo')
+			->method('getSubAdminsGroups')
+			->with($user)
 			->will($this->returnValue([]));
+		$this->container['GroupManager']
+			->expects($this->any())
+			->method('getSubAdmin')
+			->will($this->returnValue($subadmin));
 
 		$expectedResponse = new DataResponse(
 			array(
@@ -819,63 +860,77 @@ class UsersControllerTest extends \Test\TestCase {
 		$this->container['IsAdmin'] = false;
 		$user = $this->getMockBuilder('\OC\User\User')
 			->disableOriginalConstructor()->getMock();
-		$user
-			->expects($this->once())
-			->method('getUID')
-			->will($this->returnValue('username'));
 		$this->container['UserSession']
 			->expects($this->once())
 			->method('getUser')
 			->will($this->returnValue($user));
-
 		$user = $this->getMockBuilder('\OC\User\User')
 			->disableOriginalConstructor()->getMock();
-		$user
+		$newUser = $this->getMockBuilder('\OC\User\User')
+			->disableOriginalConstructor()->getMock();
+		$newUser
 			->method('getHome')
 			->will($this->returnValue('/home/user'));
-		$user
+		$newUser
 			->method('getHome')
 			->will($this->returnValue('/home/user'));
-		$user
+		$newUser
 			->method('getUID')
 			->will($this->returnValue('foo'));
-		$user
+		$newUser
 			->expects($this->once())
 			->method('getBackendClassName')
 			->will($this->returnValue('bar'));
 		$subGroup1 = $this->getMockBuilder('\OCP\IGroup')
 			->disableOriginalConstructor()->getMock();
+		$subGroup1
+			->expects($this->any())
+			->method('getGID')
+			->will($this->returnValue('SubGroup1'));
 		$subGroup1
 			->expects($this->once())
 			->method('addUser')
 			->with($user);
-		$subGroup2 = $this->getMockBuilder('\OCP\IGroup')
-			->disableOriginalConstructor()->getMock();
-		$subGroup2
-			->expects($this->once())
-			->method('addUser')
-			->with($user);
-
 		$this->container['UserManager']
 			->expects($this->once())
 			->method('createUser')
-			->will($this->onConsecutiveCalls($user));
+			->will($this->returnValue($newUser));
 		$this->container['GroupManager']
-			->expects($this->exactly(2))
+			->expects($this->at(0))
 			->method('get')
-			->will($this->onConsecutiveCalls($subGroup1, $subGroup2));
+			->with('SubGroup1')
+			->will($this->returnValue($subGroup1));
+		$this->container['GroupManager']
+			->expects($this->at(4))
+			->method('get')
+			->with('SubGroup1')
+			->will($this->returnValue($subGroup1));
 		$this->container['GroupManager']
 			->expects($this->once())
 			->method('getUserGroupIds')
 			->with($user)
 			->will($this->onConsecutiveCalls(['SubGroup1']));
+		$this->container['GroupManager']
+			->expects($this->once())
+			->method('getUserGroupIds')
+			->with($newUser)
+			->will($this->onConsecutiveCalls(['SubGroup1']));
 
-		$this->container['SubAdminFactory']
-			->method('getSubAdminsOfGroups')
-			->will($this->returnValueMap([
-				['username', ['SubGroup1', 'SubGroup2']],
-				['foo', []],
-			]));
+		$subadmin = $this->getMockBuilder('\OC\SubAdmin')
+			->disableOriginalConstructor()
+			->getMock();
+		$subadmin->expects($this->at(1))
+			->method('getSubAdminsGroups')
+			->with($user)
+			->will($this->returnValue([$subGroup1]));
+		$subadmin->expects($this->at(2))
+			->method('getSubAdminsGroups')
+			->with($newUser)
+			->will($this->returnValue([]));
+		$this->container['GroupManager']
+			->expects($this->any())
+			->method('getSubAdmin')
+			->will($this->returnValue($subadmin));
 
 		$expectedResponse = new DataResponse(
 			array(
@@ -883,7 +938,7 @@ class UsersControllerTest extends \Test\TestCase {
 				'groups' => ['SubGroup1'],
 				'storageLocation' => '/home/user',
 				'backend' => 'bar',
-				'lastLogin' => null,
+				'lastLogin' => 0,
 				'displayname' => null,
 				'quota' => null,
 				'subadmin' => [],
@@ -915,15 +970,10 @@ class UsersControllerTest extends \Test\TestCase {
 
 	public function testCreateUnsuccessfulSubAdmin() {
 		$this->container['IsAdmin'] = false;
-		$this->container['SubAdminFactory']
-			->expects($this->once())
-			->method('getSubAdminsOfGroups')
-			->with('username')
-			->will($this->returnValue(['SubGroup1', 'SubGroup2']));
 		$user = $this->getMockBuilder('\OC\User\User')
 			->disableOriginalConstructor()->getMock();
 		$user
-			->expects($this->once())
+			->expects($this->any())
 			->method('getUID')
 			->will($this->returnValue('username'));
 		$this->container['UserSession']
@@ -935,6 +985,30 @@ class UsersControllerTest extends \Test\TestCase {
 			->method('createUser')
 			->will($this->throwException(new \Exception()));
 
+		$subgroup1 = $this->getMockBuilder('\OCP\IGroup')
+			->disableOriginalConstructor()
+			->getMock();
+		$subgroup1->expects($this->once())
+			->method('getGID')
+			->will($this->returnValue('SubGroup1'));
+		$subgroup2 = $this->getMockBuilder('\OCP\IGroup')
+			->disableOriginalConstructor()
+			->getMock();
+		$subgroup2->expects($this->once())
+			->method('getGID')
+			->will($this->returnValue('SubGroup2'));
+		$subadmin = $this->getMockBuilder('\OC\SubAdmin')
+			->disableOriginalConstructor()
+			->getMock();
+		$subadmin->expects($this->once())
+			->method('getSubAdminsGroups')
+			->with($user)
+			->will($this->returnValue([$subgroup1, $subgroup2]));
+		$this->container['GroupManager']
+			->expects($this->any())
+			->method('getSubAdmin')
+			->will($this->returnValue($subadmin));
+
 		$expectedResponse = new DataResponse(
 			[
 				'message' => 'Unable to create user.'
@@ -1035,11 +1109,6 @@ class UsersControllerTest extends \Test\TestCase {
 
 	public function testDestroySubAdmin() {
 		$this->container['IsAdmin'] = false;
-		$this->container['SubAdminFactory']
-			->expects($this->once())
-			->method('isUserAccessible')
-			->with('myself', 'UserToDelete')
-			->will($this->returnValue(true));
 		$user = $this->getMockBuilder('\OC\User\User')
 			->disableOriginalConstructor()->getMock();
 		$user
@@ -1066,6 +1135,18 @@ class UsersControllerTest extends \Test\TestCase {
 			->with('UserToDelete')
 			->will($this->returnValue($toDeleteUser));
 
+		$subadmin = $this->getMockBuilder('\OC\SubAdmin')
+			->disableOriginalConstructor()
+			->getMock();
+		$subadmin->expects($this->once())
+			->method('isUserAccessible')
+			->with($user, $toDeleteUser)
+			->will($this->returnValue(true));
+		$this->container['GroupManager']
+			->expects($this->any())
+			->method('getSubAdmin')
+			->will($this->returnValue($subadmin));
+
 		$expectedResponse = new DataResponse(
 			[
 				'status' => 'success',
@@ -1117,11 +1198,6 @@ class UsersControllerTest extends \Test\TestCase {
 
 	public function testDestroyUnsuccessfulSubAdmin() {
 		$this->container['IsAdmin'] = false;
-		$this->container['SubAdminFactory']
-			->expects($this->once())
-			->method('isUserAccessible')
-			->with('myself', 'UserToDelete')
-			->will($this->returnValue(true));
 		$user = $this->getMockBuilder('\OC\User\User')
 			->disableOriginalConstructor()->getMock();
 		$user
@@ -1146,6 +1222,18 @@ class UsersControllerTest extends \Test\TestCase {
 			->with('UserToDelete')
 			->will($this->returnValue($toDeleteUser));
 
+		$subadmin = $this->getMockBuilder('\OC\SubAdmin')
+			->disableOriginalConstructor()
+			->getMock();
+		$subadmin->expects($this->once())
+			->method('isUserAccessible')
+			->with($user, $toDeleteUser)
+			->will($this->returnValue(true));
+		$this->container['GroupManager']
+			->expects($this->any())
+			->method('getSubAdmin')
+			->will($this->returnValue($subadmin));
+
 		$expectedResponse = new DataResponse(
 			[
 				'status' => 'error',
@@ -1161,11 +1249,7 @@ class UsersControllerTest extends \Test\TestCase {
 
 	public function testDestroyNotAccessibleToSubAdmin() {
 		$this->container['IsAdmin'] = false;
-		$this->container['SubAdminFactory']
-			->expects($this->once())
-			->method('isUserAccessible')
-			->with('myself', 'UserToDelete')
-			->will($this->returnValue(false));
+
 		$user = $this->getMockBuilder('\OC\User\User')
 			->disableOriginalConstructor()->getMock();
 		$user
@@ -1186,6 +1270,18 @@ class UsersControllerTest extends \Test\TestCase {
 			->with('UserToDelete')
 			->will($this->returnValue($toDeleteUser));
 
+		$subadmin = $this->getMockBuilder('\OC\SubAdmin')
+			->disableOriginalConstructor()
+			->getMock();
+		$subadmin->expects($this->once())
+			->method('isUserAccessible')
+			->with($user, $toDeleteUser)
+			->will($this->returnValue(false));
+		$this->container['GroupManager']
+			->expects($this->any())
+			->method('getSubAdmin')
+			->will($this->returnValue($subadmin));
+
 		$expectedResponse = new DataResponse(
 			[
 				'status' => 'error',
@@ -1294,7 +1390,17 @@ class UsersControllerTest extends \Test\TestCase {
 			->expects($this->once())
 			->method('createUser')
 			->will($this->onConsecutiveCalls($user));
-
+		$subadmin = $this->getMockBuilder('\OC\SubAdmin')
+			->disableOriginalConstructor()
+			->getMock();
+		$subadmin->expects($this->once())
+			->method('getSubAdminsGroups')
+			->with($user)
+			->will($this->returnValue([]));
+		$this->container['GroupManager']
+			->expects($this->any())
+			->method('getSubAdmin')
+			->will($this->returnValue($subadmin));
 
 		$response = $this->container['UsersController']->create('foo', 'password', [], 'validMail@Adre.ss');
 		$this->assertEquals(Http::STATUS_CREATED, $response->getStatus());
@@ -1344,10 +1450,17 @@ class UsersControllerTest extends \Test\TestCase {
 
 		list($user, $expectedResult) = $this->mockUser();
 
-		$this->container['SubAdminFactory']
-			->method('getSubAdminsOfGroups')
-			->with($user->getUID())
+		$subadmin = $this->getMockBuilder('\OC\SubAdmin')
+			->disableOriginalConstructor()
+			->getMock();
+		$subadmin->expects($this->once())
+			->method('getSubAdminsGroups')
+			->with($user)
 			->will($this->returnValue([]));
+		$this->container['GroupManager']
+			->expects($this->any())
+			->method('getSubAdmin')
+			->will($this->returnValue($subadmin));
 
 		$result = self::invokePrivate($this->container['UsersController'], 'formatUserForIndex', [$user]);
 		$this->assertEquals($expectedResult, $result);
@@ -1386,10 +1499,17 @@ class UsersControllerTest extends \Test\TestCase {
 			)
 			->will($this->returnValue('1'));
 
-		$this->container['SubAdminFactory']
-			->method('getSubAdminsOfGroups')
-			->with($user->getUID())
+		$subadmin = $this->getMockBuilder('\OC\SubAdmin')
+			->disableOriginalConstructor()
+			->getMock();
+		$subadmin->expects($this->once())
+			->method('getSubAdminsGroups')
+			->with($user)
 			->will($this->returnValue([]));
+		$this->container['GroupManager']
+			->expects($this->any())
+			->method('getSubAdmin')
+			->will($this->returnValue($subadmin));
 
 		$result = self::invokePrivate($this->container['UsersController'], 'formatUserForIndex', [$user]);
 		$this->assertEquals($expectedResult, $result);
@@ -1409,10 +1529,17 @@ class UsersControllerTest extends \Test\TestCase {
 
 		$expectedResult['isRestoreDisabled'] = true;
 
-		$this->container['SubAdminFactory']
-			->method('getSubAdminsOfGroups')
-			->with($user->getUID())
+		$subadmin = $this->getMockBuilder('\OC\SubAdmin')
+			->disableOriginalConstructor()
+			->getMock();
+		$subadmin->expects($this->once())
+			->method('getSubAdminsGroups')
+			->with($user)
 			->will($this->returnValue([]));
+		$this->container['GroupManager']
+			->expects($this->any())
+			->method('getSubAdmin')
+			->will($this->returnValue($subadmin));
 
 		$result = self::invokePrivate($this->container['UsersController'], 'formatUserForIndex', [$user]);
 		$this->assertEquals($expectedResult, $result);
@@ -1453,15 +1580,25 @@ class UsersControllerTest extends \Test\TestCase {
 
 		$expectedResult['isRestoreDisabled'] = true;
 
-		$this->container['SubAdminFactory']
-			->method('getSubAdminsOfGroups')
-			->with($user->getUID())
+		$subadmin = $this->getMockBuilder('\OC\SubAdmin')
+			->disableOriginalConstructor()
+			->getMock();
+		$subadmin->expects($this->once())
+			->method('getSubAdminsGroups')
+			->with($user)
 			->will($this->returnValue([]));
+		$this->container['GroupManager']
+			->expects($this->any())
+			->method('getSubAdmin')
+			->will($this->returnValue($subadmin));
 
 		$result = self::invokePrivate($this->container['UsersController'], 'formatUserForIndex', [$user]);
 		$this->assertEquals($expectedResult, $result);
 	}
 
+	/**
+	 * @return array
+	 */
 	public function setEmailAddressData() {
 		return [
 			/* mailAddress,    isValid, expectsUpdate, expectsDelete, canChangeDisplayName, responseCode */