aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryemkareems <yemkareems@gmail.com>2024-06-06 16:35:44 +0530
committeryemkareems <yemkareems@gmail.com>2024-07-08 15:42:55 +0530
commit4cb85f7c9e37af742d170373602709f8db2d525d (patch)
tree8d63eaabb24787cda4afc4c8b44b3914c4351dec
parent76c875a5882753e37ef39015a1711b68e7ea0d0b (diff)
downloadnextcloud-server-4cb85f7c9e37af742d170373602709f8db2d525d.tar.gz
nextcloud-server-4cb85f7c9e37af742d170373602709f8db2d525d.zip
fix: rebased the branch with master and resolved conflicts
fix: added a new endpoint users/recent and getting users based on last login info in the same. Reverted old code that was breaking LDAP Signed-off-by: yemkareems <yemkareems@gmail.com>
-rw-r--r--apps/provisioning_api/appinfo/routes.php1
-rw-r--r--apps/provisioning_api/lib/Controller/UsersController.php102
-rw-r--r--lib/private/AllConfig.php43
-rw-r--r--lib/private/Group/Manager.php4
-rw-r--r--lib/private/User/Backend.php8
-rw-r--r--lib/private/User/Database.php30
-rw-r--r--lib/private/User/Manager.php27
-rw-r--r--lib/public/IConfig.php2
-rw-r--r--lib/public/IUserManager.php1
-rw-r--r--lib/public/UserInterface.php6
10 files changed, 183 insertions, 41 deletions
diff --git a/apps/provisioning_api/appinfo/routes.php b/apps/provisioning_api/appinfo/routes.php
index b44685af175..78526ce6402 100644
--- a/apps/provisioning_api/appinfo/routes.php
+++ b/apps/provisioning_api/appinfo/routes.php
@@ -28,6 +28,7 @@ return [
['root' => '/cloud', 'name' => 'Users#getUsers', 'url' => '/users', 'verb' => 'GET'],
['root' => '/cloud', 'name' => 'Users#getUsersDetails', 'url' => '/users/details', 'verb' => 'GET'],
['root' => '/cloud', 'name' => 'Users#getDisabledUsersDetails', 'url' => '/users/disabled', 'verb' => 'GET'],
+ ['root' => '/cloud', 'name' => 'Users#getLastLoggedInUsers', 'url' => '/users/recent', 'verb' => 'GET'],
['root' => '/cloud', 'name' => 'Users#searchByPhoneNumbers', 'url' => '/users/search/by-phone', 'verb' => 'POST'],
['root' => '/cloud', 'name' => 'Users#addUser', 'url' => '/users', 'verb' => 'POST'],
['root' => '/cloud', 'name' => 'Users#getUser', 'url' => '/users/{userId}', 'verb' => 'GET'],
diff --git a/apps/provisioning_api/lib/Controller/UsersController.php b/apps/provisioning_api/lib/Controller/UsersController.php
index eced881516f..ec57d3e9b23 100644
--- a/apps/provisioning_api/lib/Controller/UsersController.php
+++ b/apps/provisioning_api/lib/Controller/UsersController.php
@@ -94,7 +94,7 @@ class UsersController extends AUserData {
*
* 200: Users returned
*/
- public function getUsers(string $search = '', ?int $limit = null, int $offset = 0, string $sortMode = 'uid', string $sortOrder = 'asc'): DataResponse {
+ public function getUsers(string $search = '', ?int $limit = null, int $offset = 0): DataResponse {
$user = $this->userSession->getUser();
$users = [];
@@ -102,7 +102,7 @@ class UsersController extends AUserData {
$uid = $user->getUID();
$subAdminManager = $this->groupManager->getSubAdmin();
if ($this->groupManager->isAdmin($uid)) {
- $users = $this->userManager->search($search, $limit, $offset, $sortMode, $sortOrder);
+ $users = $this->userManager->search($search, $limit, $offset);
} elseif ($subAdminManager->isSubAdmin($user)) {
$subAdminOfGroups = $subAdminManager->getSubAdminsGroups($user);
foreach ($subAdminOfGroups as $key => $group) {
@@ -131,13 +131,11 @@ class UsersController extends AUserData {
* @param string $search Text to search for
* @param int|null $limit Limit the amount of groups returned
* @param int $offset Offset for searching for groups
- * @param string $sortMode Field to order the results with
- * @param string $sortOrder asc or desc
* @return DataResponse<Http::STATUS_OK, array{users: array<string, Provisioning_APIUserDetails|array{id: string}>}, array{}>
*
* 200: Users details returned
*/
- public function getUsersDetails(string $search = '', ?int $limit = null, int $offset = 0, string $sortMode = 'uid', string $sortOrder = 'asc'): DataResponse {
+ public function getUsersDetails(string $search = '', ?int $limit = null, int $offset = 0): DataResponse {
$currentUser = $this->userSession->getUser();
$users = [];
@@ -145,7 +143,7 @@ class UsersController extends AUserData {
$uid = $currentUser->getUID();
$subAdminManager = $this->groupManager->getSubAdmin();
if ($this->groupManager->isAdmin($uid)) {
- $users = $this->userManager->search($search, $limit, $offset, $sortMode, $sortOrder);
+ $users = $this->userManager->search($search, $limit, $offset);
$users = array_keys($users);
} elseif ($subAdminManager->isSubAdmin($currentUser)) {
$subAdminOfGroups = $subAdminManager->getSubAdminsGroups($currentUser);
@@ -155,7 +153,7 @@ class UsersController extends AUserData {
$users = [];
foreach ($subAdminOfGroups as $group) {
- $users[] = array_keys($this->groupManager->displayNamesInGroup($group, $search, $limit, $offset, $sortMode, $sortOrder));
+ $users[] = array_keys($this->groupManager->displayNamesInGroup($group, $search, $limit, $offset));
}
$users = array_merge(...$users);
}
@@ -267,6 +265,96 @@ class UsersController extends AUserData {
]);
}
+ /**
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ *
+ * Get the list of disabled users and their details
+ *
+ * @param string $search Text to search for
+ * @param ?int $limit Limit the amount of users returned
+ * @param int $offset Offset
+ * @param string $sortMode Field to order the results with
+ * @param string $sortOrder asc or desc
+ * @return DataResponse<Http::STATUS_OK, array{users: array<string, Provisioning_APIUserDetails|array{id: string}>}, array{}>
+ *
+ * 200: Users details returned based on last logged in information
+ */
+ public function getLastLoggedInUsers(string $search = '',
+ ?int $limit = null,
+ int $offset = 0,
+ string $sortMode = 'lastLogin',
+ string $sortOrder = 'desc'
+ ): DataResponse {
+ $currentUser = $this->userSession->getUser();
+ if ($currentUser === null) {
+ return new DataResponse(['users' => []]);
+ }
+ if ($limit !== null && $limit < 0) {
+ throw new InvalidArgumentException("Invalid limit value: $limit");
+ }
+ if ($offset < 0) {
+ throw new InvalidArgumentException("Invalid offset value: $offset");
+ }
+
+ $users = [];
+
+ // Admin? Or SubAdmin?
+ $uid = $currentUser->getUID();
+ $subAdminManager = $this->groupManager->getSubAdmin();
+ if ($this->groupManager->isAdmin($uid)) {
+ $users = $this->userManager->getUsersSortedByLastLogin($limit, $offset, $search, $sortMode, $sortOrder);
+ $users = array_map(fn (IUser $user): string => $user->getUID(), $users);
+ } elseif ($subAdminManager->isSubAdmin($currentUser)) {
+ $subAdminOfGroups = $subAdminManager->getSubAdminsGroups($currentUser);
+
+ $users = [];
+ /* We have to handle offset ourselve for correctness */
+ $tempLimit = ($limit === null ? null : $limit + $offset);
+ foreach ($subAdminOfGroups as $group) {
+ $users = array_merge(
+ $users,
+ array_map(
+ fn (IUser $user): string => $user->getUID(),
+ array_filter(
+ $group->searchUsers($search, ($tempLimit === null ? null : $tempLimit - count($users))),
+ fn (IUser $user): bool => !$user->isEnabled()
+ )
+ )
+ );
+ if (($tempLimit !== null) && (count($users) >= $tempLimit)) {
+ break;
+ }
+ }
+ $users = array_slice($users, $offset);
+ }
+
+ $usersDetails = [];
+ foreach ($users as $userId) {
+ try {
+ $userData = $this->getUserData($userId);
+ } catch (OCSNotFoundException $e) {
+ // We still want to return all other accounts, but this one was removed from the backends
+ // yet they are still in our database. Might be a LDAP remnant.
+ $userData = null;
+ $this->logger->warning('Found one disabled account that was removed from its backend, but still exists in Nextcloud database', ['accountId' => $userId]);
+ }
+ // Do not insert empty entry
+ if ($userData !== null) {
+ $usersDetails[$userId] = $userData;
+ } else {
+ // Currently logged in user does not have permissions to see this user
+ // only showing its id
+ $usersDetails[$userId] = ['id' => $userId];
+ }
+ }
+
+ return new DataResponse([
+ 'users' => $usersDetails
+ ]);
+ }
+
+
/**
* @NoAdminRequired
diff --git a/lib/private/AllConfig.php b/lib/private/AllConfig.php
index d05fe440202..7fbc4c1e148 100644
--- a/lib/private/AllConfig.php
+++ b/lib/private/AllConfig.php
@@ -491,6 +491,49 @@ class AllConfig implements IConfig {
return $userIDs;
}
+ public function getLastLoggedInUsers($search, $sortMode, $sortOrder): array {
+ // TODO - FIXME
+ $this->fixDIInit();
+
+ $query = $this->connection->getQueryBuilder();
+
+ if ($sortMode === 'lastLogin') {
+ $lastLoginSubSelect = $this->connection->getQueryBuilder();
+ $lastLoginSubSelect->select('configvalue')
+ ->from('preferences', 'p2')
+ ->where($lastLoginSubSelect->expr()->andX(
+ $lastLoginSubSelect->expr()->eq('p2.userid', 'uid'),
+ $lastLoginSubSelect->expr()->eq('p2.appid', $lastLoginSubSelect->expr()->literal('login')),
+ $lastLoginSubSelect->expr()->eq('p2.configkey', $lastLoginSubSelect->expr()->literal('lastLogin')),
+ ));
+ $orderByExpression = $query->createFunction('(' . $lastLoginSubSelect->getSQL() .')');
+ } else {
+ $orderByExpression = $query->func()->lower('displayname');
+ }
+
+ $query->select('uid', 'displayname', $orderByExpression)
+ ->from('users', 'u')
+ ->leftJoin('u', 'preferences', 'p', $query->expr()->andX(
+ $query->expr()->eq('userid', 'uid'),
+ $query->expr()->eq('appid', $query->expr()->literal('settings')),
+ $query->expr()->eq('configkey', $query->expr()->literal('email')))
+ )
+ // sqlite doesn't like re-using a single named parameter here
+ ->where($query->expr()->iLike('uid', $query->createPositionalParameter('%' . $this->connection->escapeLikeParameter($search) . '%')))
+ ->orWhere($query->expr()->iLike('displayname', $query->createPositionalParameter('%' . $this->connection->escapeLikeParameter($search) . '%')))
+ ->orWhere($query->expr()->iLike('configvalue', $query->createPositionalParameter('%' . $this->connection->escapeLikeParameter($search) . '%')))
+ ->orderBy($orderByExpression, $sortOrder)
+ ->addOrderBy('uid_lower', 'ASC');
+
+ $result = $query->executeQuery();
+ $displayNames = [];
+ while ($row = $result->fetch()) {
+ $displayNames[(string)$row['uid']] = (string)$row['uid'];
+ }
+
+ return $displayNames;
+ }
+
/**
* Determines the users that have the given value set for a specific app-key-pair
*
diff --git a/lib/private/Group/Manager.php b/lib/private/Group/Manager.php
index 362d7424e45..0ab64907c8b 100644
--- a/lib/private/Group/Manager.php
+++ b/lib/private/Group/Manager.php
@@ -401,7 +401,7 @@ class Manager extends PublicEmitter implements IGroupManager {
* @param int $offset
* @return array an array of display names (value) and user ids (key)
*/
- public function displayNamesInGroup($gid, $search = '', $limit = -1, $offset = 0, $sortMode = 'uid', $sortOrder = 'asc') {
+ public function displayNamesInGroup($gid, $search = '', $limit = -1, $offset = 0) {
$group = $this->get($gid);
if (is_null($group)) {
return [];
@@ -419,7 +419,7 @@ class Manager extends PublicEmitter implements IGroupManager {
}
do {
- $filteredUsers = $this->userManager->searchDisplayName($search, $searchLimit, $searchOffset, $sortMode, $sortOrder);
+ $filteredUsers = $this->userManager->searchDisplayName($search, $searchLimit, $searchOffset);
foreach ($filteredUsers as $filteredUser) {
if ($group->inGroup($filteredUser)) {
$groupUsers[] = $filteredUser;
diff --git a/lib/private/User/Backend.php b/lib/private/User/Backend.php
index 5d06b54c28b..98b291e5dee 100644
--- a/lib/private/User/Backend.php
+++ b/lib/private/User/Backend.php
@@ -89,11 +89,9 @@ abstract class Backend implements UserInterface {
* @param string $search
* @param null|int $limit
* @param null|int $offset
- * @param string $sortMode
- * @param string $sortOrder
* @return string[] an array of all uids
*/
- public function getUsers($search = '', $limit = null, $offset = null, string $sortMode = 'uid', string $sortOrder = 'asc') {
+ public function getUsers($search = '', $limit = null, $offset = null) {
return [];
}
@@ -130,11 +128,9 @@ abstract class Backend implements UserInterface {
* @param string $search
* @param int|null $limit
* @param int|null $offset
- * @param string $sortMode
- * @param string $sortOrder
* @return array an array of all displayNames (value) and the corresponding uids (key)
*/
- public function getDisplayNames($search = '', $limit = null, $offset = null, string $sortMode = 'uid', string $sortOrder = 'asc'): array {
+ public function getDisplayNames($search = '', $limit = null, $offset = null) {
$displayNames = [];
$users = $this->getUsers($search, $limit, $offset);
foreach ($users as $user) {
diff --git a/lib/private/User/Database.php b/lib/private/User/Database.php
index 9a62bcf3e12..cc7050f2da8 100644
--- a/lib/private/User/Database.php
+++ b/lib/private/User/Database.php
@@ -227,32 +227,16 @@ class Database extends ABackend implements
* @param string $search
* @param int|null $limit
* @param int|null $offset
- * @param string $sortMode
- * @param string $sortOrder
* @return array an array of all displayNames (value) and the corresponding uids (key)
*/
- public function getDisplayNames($search = '', $limit = null, $offset = null, string $sortMode = 'uid', string $sortOrder = 'asc'): array {
+ public function getDisplayNames($search = '', $limit = null, $offset = null) {
$limit = $this->fixLimit($limit);
$this->fixDI();
$query = $this->dbConn->getQueryBuilder();
- if ($sortMode === 'lastLogin') {
- $lastLoginSubSelect = $this->dbConn->getQueryBuilder();
- $lastLoginSubSelect->select('configvalue')
- ->from('preferences', 'p2')
- ->where($lastLoginSubSelect->expr()->andX(
- $lastLoginSubSelect->expr()->eq('p2.userid', 'uid'),
- $lastLoginSubSelect->expr()->eq('p2.appid', $lastLoginSubSelect->expr()->literal('login')),
- $lastLoginSubSelect->expr()->eq('p2.configkey', $lastLoginSubSelect->expr()->literal('lastLogin')),
- ));
- $orderByExpression = $query->createFunction('(' . $lastLoginSubSelect->getSQL() .')');
- } else {
- $orderByExpression = $query->func()->lower('displayname');
- }
-
- $query->select('uid', 'displayname', $orderByExpression)
+ $query->select('uid', 'displayname')
->from($this->table, 'u')
->leftJoin('u', 'preferences', 'p', $query->expr()->andX(
$query->expr()->eq('userid', 'uid'),
@@ -263,7 +247,7 @@ class Database extends ABackend implements
->where($query->expr()->iLike('uid', $query->createPositionalParameter('%' . $this->dbConn->escapeLikeParameter($search) . '%')))
->orWhere($query->expr()->iLike('displayname', $query->createPositionalParameter('%' . $this->dbConn->escapeLikeParameter($search) . '%')))
->orWhere($query->expr()->iLike('configvalue', $query->createPositionalParameter('%' . $this->dbConn->escapeLikeParameter($search) . '%')))
- ->orderBy($orderByExpression, $sortOrder)
+ ->orderBy($query->func()->lower('displayname'), 'ASC')
->addOrderBy('uid_lower', 'ASC')
->setMaxResults($limit)
->setFirstResult($offset);
@@ -397,13 +381,15 @@ class Database extends ABackend implements
* @param null|int $offset
* @return string[] an array of all uids
*/
- public function getUsers($search = '', $limit = null, $offset = null, $orderBy = 'lastLogin', $sort = 'DESC'): array {
+ public function getUsers($search = '', $limit = null, $offset = null) {
$limit = $this->fixLimit($limit);
- $users = $this->getDisplayNames($search, $limit, $offset, $orderBy, $sort);
- return array_map(function ($uid) {
+ $users = $this->getDisplayNames($search, $limit, $offset);
+ $userIds = array_map(function ($uid) {
return (string)$uid;
}, array_keys($users));
+ sort($userIds, SORT_STRING | SORT_FLAG_CASE);
+ return $userIds;
}
/**
diff --git a/lib/private/User/Manager.php b/lib/private/User/Manager.php
index 49f96c25a05..2efb93e65be 100644
--- a/lib/private/User/Manager.php
+++ b/lib/private/User/Manager.php
@@ -402,6 +402,33 @@ class Manager extends PublicEmitter implements IUserManager {
return array_slice($users, $offset, $limit);
}
+ public function getUsersSortedByLastLogin(?int $limit = null, int $offset = 0, $search = '', $sortMode = 'lastLogin', $sortOrder = 'desc'): array {
+ $users = $this->config->getLastLoggedInUsers($search, $sortMode, $sortOrder);
+ $users = array_combine(
+ $users,
+ array_map(
+ fn (string $uid): IUser => new LazyUser($uid, $this),
+ $users
+ )
+ );
+
+ $tempLimit = ($limit === null ? null : $limit + $offset);
+ foreach ($this->backends as $backend) {
+ if (($tempLimit !== null) && (count($users) >= $tempLimit)) {
+ break;
+ }
+ if ($backend instanceof IProvideEnabledStateBackend) {
+ $backendUsers = $backend->getDisabledUserList(($tempLimit === null ? null : $tempLimit - count($users)));
+ foreach ($backendUsers as $uid) {
+ $users[$uid] = new LazyUser($uid, $this, null, $backend);
+ }
+ }
+ }
+
+ return array_slice($users, $offset, $limit);
+ }
+
+
/**
* Search known users (from phonebook sync) by displayName
*
diff --git a/lib/public/IConfig.php b/lib/public/IConfig.php
index b7feabd0ef5..39f9ecff94c 100644
--- a/lib/public/IConfig.php
+++ b/lib/public/IConfig.php
@@ -249,4 +249,6 @@ interface IConfig {
* @since 8.0.0
*/
public function getUsersForUserValue($appName, $key, $value);
+
+ public function getLastLoggedInUsers($search, $sortMode, $sortOrder);
}
diff --git a/lib/public/IUserManager.php b/lib/public/IUserManager.php
index b4fb265f6eb..70420dc7c7a 100644
--- a/lib/public/IUserManager.php
+++ b/lib/public/IUserManager.php
@@ -124,6 +124,7 @@ interface IUserManager {
*/
public function getDisabledUsers(?int $limit = null, int $offset = 0, string $search = ''): array;
+ public function getUsersSortedByLastLogin(?int $limit = null, int $offset = 0, $search = '', $sortMode = 'lastLogin', $sortOrder = 'desc'): array;
/**
* Search known users (from phonebook sync) by displayName
*
diff --git a/lib/public/UserInterface.php b/lib/public/UserInterface.php
index a28e9ffe726..34e7a09feb7 100644
--- a/lib/public/UserInterface.php
+++ b/lib/public/UserInterface.php
@@ -45,7 +45,7 @@ interface UserInterface {
* @return string[] an array of all uids
* @since 4.5.0
*/
- public function getUsers($search = '', $limit = null, $offset = null, string $sortMode = 'uid', string $sortOrder = 'asc');
+ public function getUsers($search = '', $limit = null, $offset = null);
/**
* check if a user exists
@@ -69,12 +69,10 @@ interface UserInterface {
* @param string $search
* @param int|null $limit
* @param int|null $offset
- * @param string $sortMode
- * @param string $sortOrder
* @return array an array of all displayNames (value) and the corresponding uids (key)
* @since 4.5.0
*/
- public function getDisplayNames($search = '', $limit = null, $offset = null, string $sortMode = 'uid', string $sortOrder = 'asc');
+ public function getDisplayNames($search = '', $limit = null, $offset = null);
/**
* Check if a user list is available or not