diff options
author | Björn Schießle <bjoern@schiessle.org> | 2017-07-17 17:07:59 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-07-17 17:07:59 +0300 |
commit | 1fa5777efe124da2da0cb0ba03ee512b46ce3e41 (patch) | |
tree | 17f56a42101e25fdf919f50ab8539a8af92598a6 | |
parent | 98e8f448626a62aba037c6fec61083c539218b2f (diff) | |
parent | ad2808c70b4bc7cce9d66b4b77690d5c61f9d1db (diff) |
Merge pull request #15 from nextcloud/gss-v2
allow the global site selector to search one specific user across all user data
-rwxr-xr-x | doc/architecture.md | 9 | ||||
-rw-r--r-- | server/lib/UserManager.php | 95 |
2 files changed, 56 insertions, 48 deletions
diff --git a/doc/architecture.md b/doc/architecture.md index 2a39f09..1c47e69 100755 --- a/doc/architecture.md +++ b/doc/architecture.md @@ -113,6 +113,15 @@ This call can be used to search for a user in a fuzzy way Example: curl -X GET http://dev/nextcloud/lookup-server/server/users?search=searchstring +Add a additional parameter to search for an exact match, for example: +curl -X GET http://dev/nextcloud/lookup-server/server/users?search=searchstring&exact=1 + +If you want to limit the exact search to a specific parameter, e.g the email address you can do following: +curl -X GET http://dev/nextcloud/lookup-server/server/users?search=searchstring&exact=1&keys=["email"] + +To get the verification result of a users Twitter account or email address we can search for a specific users cloud ID: +curl -X GET http://dev/nextcloud/lookup-server/server/users?search=<federated-cloud-id>&exactCloudId=1 + ### Get replication log This call is used for master-master replication between different nodes. Example: diff --git a/server/lib/UserManager.php b/server/lib/UserManager.php index 1ad85ba..52a895e 100644 --- a/server/lib/UserManager.php +++ b/server/lib/UserManager.php @@ -64,32 +64,62 @@ class UserManager { } $search = $params['search']; - $searchCloudId = $params['exactCloudId']; - - if ($searchCloudId === '1') { - $user = $this->getExactCloudId($search); - $response->getBody()->write(json_encode($user)); - return $response; + // search for a specific federated cloud ID + $searchCloudId = isset($params['exactCloudId']) ? $params['exactCloudId'] === '1' : '0'; + // return unique exact match, e.g. the user with a specific email address + $exactMatch = isset($params['exact']) ? $params['exact'] === '1' : false; + + // parameters allow you to specify which keys should be checked for a search query + // by default we check all keys, this way you can for example search for email addresses only + $parameters = []; + if ($exactMatch === true) { + $keys = isset($params['keys']) ? $params['keys'] : '{}'; + $keysDecoded = json_decode($keys, false, 2); + if (is_array($keysDecoded)) { + $parameters = $keysDecoded; + } } - if ($this->globalScaleMode === true) { + if ($searchCloudId === true) { + $users = $this->getExactCloudId($search); + } else if ($this->globalScaleMode === true) { // in a global scale setup we ignore the karma - $users = $this->searchNoKarma(); + // the lookup server is populated by the admin and we know + // that it contain only valid user information + $users = $this->performSearch($search, $exactMatch, $parameters, 0); } else { - $users = $this->searchKarma(); + // in a general setup we only return users who validated at least one personal date + $users = $this->performSearch($search, $exactMatch, $parameters, 1); + } + + // if we look for a exact match we return only this one result, not a list of one element + if($exactMatch && !empty($users)) { + $users = $users[0]; } $response->getBody()->write(json_encode($users)); return $response; } + + /** + * search user, for example to share with them * return all results with karma >= 1 * - * @param $search + * @param string $search + * @param bool $exactMatch + * @param array $parameters + * @param int $minKarma * @return array */ - private function searchKarma($search) { + private function performSearch($search, $exactMatch, $parameters, $minKarma) { + + $operator = $exactMatch ? ' = ' : ' LIKE '; + $limit = $exactMatch ? ' 1 ' : ' 50 '; + $constraint = empty($parameters) ? '' : ' AND k IN (\'' . implode( '\', \'', $parameters ) . '\') '; + + $stmt = $this->db->prepare('SELECT * FROM ( SELECT userId AS userId, SUM(valid) AS karma @@ -97,49 +127,17 @@ FROM ( WHERE userId IN ( SELECT DISTINCT userId FROM `store` - WHERE v LIKE :search + WHERE v ' . $operator . ' :search ' . $constraint .' ) GROUP BY userId ) AS tmp -WHERE karma > 0 +WHERE karma >= ' . $minKarma . ' ORDER BY karma -LIMIT 50'); - $search = '%' . $search . '%'; - $stmt->bindParam(':search', $search, \PDO::PARAM_STR); - $stmt->execute(); - - /* - * TODO: Better fuzzy search? - */ - - $users = []; - while($data = $stmt->fetch()) { - $users[] = $this->getForUserId((int)$data['userId']); - } - $stmt->closeCursor(); - - return $users; - } - +LIMIT ' . $limit); - /** - * return all results, ignoring the karma - * - * @param $search - * @return array - */ - private function searchNoKarma($search) { - $stmt = $this->db->prepare('SELECT * -FROM `store` - WHERE userId IN ( - SELECT DISTINCT userId - FROM `store` - WHERE v LIKE :search - ) - GROUP BY userId - LIMIT 50'); - $search = '%' . $search . '%'; + $search = $exactMatch ? $search : '%' . $search . '%'; $stmt->bindParam(':search', $search, \PDO::PARAM_STR); + $stmt->execute(); /* @@ -155,6 +153,7 @@ FROM `store` return $users; } + private function getExactCloudId($cloudId) { $stmt = $this->db->prepare('SELECT id FROM users WHERE federationId = :id'); $stmt->bindParam(':id', $cloudId); |