From 7ec825e8021a00d5f4c5b2b8fb07e8d6239c12a4 Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Tue, 20 Jun 2017 12:02:34 +0200 Subject: allow the global site selector to search one specific user across all user data Signed-off-by: Bjoern Schiessle --- server/lib/UserManager.php | 44 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/server/lib/UserManager.php b/server/lib/UserManager.php index 1ad85ba..cf04e40 100644 --- a/server/lib/UserManager.php +++ b/server/lib/UserManager.php @@ -64,16 +64,17 @@ class UserManager { } $search = $params['search']; - $searchCloudId = $params['exactCloudId']; + $searchCloudId = isset($params['exactCloudId']) ? $params['exactCloudId'] : '0'; + $gssSearch = isset($params['gss']) ? $params['gss'] : '0'; if ($searchCloudId === '1') { - $user = $this->getExactCloudId($search); - $response->getBody()->write(json_encode($user)); - return $response; - } - - if ($this->globalScaleMode === true) { + $users = $this->getExactCloudId($search); + } else if ($gssSearch === '1') { + // lookup request from a global site selector to login the user + $users = $this->gssLookup($search); + } else if ($this->globalScaleMode === true) { // in a global scale setup we ignore the karma + // this is used to find people you want to share with $users = $this->searchNoKarma(); } else { $users = $this->searchKarma(); @@ -84,6 +85,7 @@ class UserManager { } /** + * search user, for example to share with them * return all results with karma >= 1 * * @param $search @@ -123,7 +125,10 @@ LIMIT 50'); /** + * search user, for example to share with them * return all results, ignoring the karma + * in a global scale setup we assume that all + * entries are trustworthy * * @param $search * @return array @@ -155,6 +160,31 @@ FROM `store` return $users; } + /** + * find the user who want to login in a global scale setup + * we return the first exact match + * + * @param $search + * @return array + */ + private function gssLookup($search) { + $stmt = $this->db->prepare('SELECT * FROM `store` WHERE v = :search LIMIT 1'); + $stmt->bindParam(':search', $search, \PDO::PARAM_STR); + $stmt->execute(); + + $data = $stmt->fetch(); + $stmt->closeCursor(); + + $user = []; + + if (isset($data['userId'])) { + $user = $this->getForUserId((int)$data['userId']); + } + + return $user; + } + + private function getExactCloudId($cloudId) { $stmt = $this->db->prepare('SELECT id FROM users WHERE federationId = :id'); $stmt->bindParam(':id', $cloudId); -- cgit v1.2.3 From f79f34ef1327a88bcce35df25b0d6ca1c2f11903 Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Thu, 22 Jun 2017 17:14:50 +0200 Subject: cleanup search logic Signed-off-by: Bjoern Schiessle --- server/lib/UserManager.php | 119 +++++++++++++++++---------------------------- 1 file changed, 44 insertions(+), 75 deletions(-) diff --git a/server/lib/UserManager.php b/server/lib/UserManager.php index cf04e40..52a895e 100644 --- a/server/lib/UserManager.php +++ b/server/lib/UserManager.php @@ -64,34 +64,62 @@ class UserManager { } $search = $params['search']; - $searchCloudId = isset($params['exactCloudId']) ? $params['exactCloudId'] : '0'; - $gssSearch = isset($params['gss']) ? $params['gss'] : '0'; + // 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 ($searchCloudId === '1') { + if ($searchCloudId === true) { $users = $this->getExactCloudId($search); - } else if ($gssSearch === '1') { - // lookup request from a global site selector to login the user - $users = $this->gssLookup($search); } else if ($this->globalScaleMode === true) { // in a global scale setup we ignore the karma - // this is used to find people you want to share with - $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 @@ -99,52 +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? - */ +LIMIT ' . $limit); - $users = []; - while($data = $stmt->fetch()) { - $users[] = $this->getForUserId((int)$data['userId']); - } - $stmt->closeCursor(); - - return $users; - } - - - /** - * search user, for example to share with them - * return all results, ignoring the karma - * in a global scale setup we assume that all - * entries are trustworthy - * - * @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(); /* @@ -160,30 +153,6 @@ FROM `store` return $users; } - /** - * find the user who want to login in a global scale setup - * we return the first exact match - * - * @param $search - * @return array - */ - private function gssLookup($search) { - $stmt = $this->db->prepare('SELECT * FROM `store` WHERE v = :search LIMIT 1'); - $stmt->bindParam(':search', $search, \PDO::PARAM_STR); - $stmt->execute(); - - $data = $stmt->fetch(); - $stmt->closeCursor(); - - $user = []; - - if (isset($data['userId'])) { - $user = $this->getForUserId((int)$data['userId']); - } - - return $user; - } - private function getExactCloudId($cloudId) { $stmt = $this->db->prepare('SELECT id FROM users WHERE federationId = :id'); -- cgit v1.2.3 From ad2808c70b4bc7cce9d66b4b77690d5c61f9d1db Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Thu, 22 Jun 2017 17:53:04 +0200 Subject: update documentation with the additional search parameters Signed-off-by: Bjoern Schiessle --- doc/architecture.md | 9 +++++++++ 1 file changed, 9 insertions(+) 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=&exactCloudId=1 + ### Get replication log This call is used for master-master replication between different nodes. Example: -- cgit v1.2.3