Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/lookup-server.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjörn Schießle <bjoern@schiessle.org>2017-03-03 14:50:32 +0300
committerGitHub <noreply@github.com>2017-03-03 14:50:32 +0300
commitcd051fc1062f5e3feee3230fa1069f9a64af2028 (patch)
treecb6e14c3c2013dd5e7f2908ef9203059e0a34269
parent386ae4a3e571ec4f7d5abde54e69fbed35090d02 (diff)
parent5ac35b822c6ab679cac37885affa9fb5dd001985 (diff)
Merge pull request #9 from nextcloud/add-delete
Add delete
-rwxr-xr-xdoc/architecture.md14
-rw-r--r--server/index.php1
-rw-r--r--server/lib/UserManager.php151
3 files changed, 122 insertions, 44 deletions
diff --git a/doc/architecture.md b/doc/architecture.md
index 80ae78c..32f0b82 100755
--- a/doc/architecture.md
+++ b/doc/architecture.md
@@ -32,7 +32,7 @@ calls. The following REST calls exists:
This can be used by a user to create a record and initially publish their own
information.
-Endpoint: http://dev/nextcloud/lookup-server/server/
+Endpoint: http://dev/nextcloud/lookup-server/server/users
Method: POST
Data: JSON blob
@@ -61,7 +61,7 @@ Updating a record is the same as publishing a new record. Unchanged fields will
not be touched. New fields will be added (and if possible verified). And fields
no longer in the update request will be removed.
-Endpoint: http://dev/nextcloud/lookup-server/server/
+Endpoint: http://dev/nextcloud/lookup-server/server/users
Method: POST
Data: JSON blob
@@ -88,8 +88,8 @@ Data: JSON blob
### Delete user
Deleting is simply removing all additional info.
-Endpoint: http://dev/nextcloud/lookup-server/server/
-Method: POST
+Endpoint: http://dev/nextcloud/lookup-server/server/users
+Method:DELETE
Data: JSON blob
```
@@ -106,13 +106,13 @@ Data: JSON blob
}
```
-Note that a database entry will still remain on the lookup server. In order to
-properly propagat this.
+Note the server will still keep the cloud id in order to properly propagate this.
+But all other personal data will be removed.
### Search users
This call can be used to search for a user in a fuzzy way
Example:
-curl -X GET http://dev/nextcloud/lookup-server/server/?search=searchstring
+curl -X GET http://dev/nextcloud/lookup-server/server/users?search=searchstring
### Get replication log
This call is used for master-master replication between different nodes.
diff --git a/server/index.php b/server/index.php
index 59129d4..de9c028 100644
--- a/server/index.php
+++ b/server/index.php
@@ -18,6 +18,7 @@ $app->add($container->get('BruteForceMiddleware'));
$app->get('/users', 'UserManager:search');
$app->post('/users', 'UserManager:register');
+$app->delete('/users', 'UserManager:delete');
$app->get('/validate/email/{token}', 'EmailValidator:validate')->setName('validateEmail');
$app->get('/status', 'Status:status');
diff --git a/server/lib/UserManager.php b/server/lib/UserManager.php
index ef24616..8c995d5 100644
--- a/server/lib/UserManager.php
+++ b/server/lib/UserManager.php
@@ -3,7 +3,6 @@
namespace LookupServer;
use GuzzleHttp\Client;
-use GuzzleHttp\Exception\RequestException;
use LookupServer\Validator\Email;
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;
@@ -221,43 +220,14 @@ LIMIT 50');
$cloudId = $body['message']['data']['federationId'];
- // Get fed id
- list($user, $host) = $this->splitCloudId($cloudId);
-
- // Retrieve public key && store
- $ocsreq = new \GuzzleHttp\Psr7\Request(
- 'GET',
- 'https://'.$host . '/ocs/v2.php/identityproof/key/' . $user,
- [
- 'OCS-APIREQUEST' => 'true',
- 'Accept' => 'application/json',
- ]);
-
- $client = new Client();
try {
- $ocsresponse = $client->send($ocsreq, ['timeout' => 10]);
- } catch(RequestException $e) {
- $response->withStatus(400);
- return $response;
- }
-
- $ocsresponse = json_decode($ocsresponse->getBody(), true);
+ $verified = $this->verifyRequest($cloudId, $body['message'], $body['signature']);
+ } catch(\Exception $e) {
+ $response->withStatus(400);
+ return $response;
+ }
- if ($ocsresponse === null || !isset($ocsresponse['ocs']) ||
- !isset($ocsresponse['ocs']['data']) || !isset($ocsresponse['ocs']['data']['public'])) {
- $response->withStatus(400);
- return $response;
- }
-
- $key = $ocsresponse['ocs']['data']['public'];
-
- // verify message
- $message = json_encode($body['message']);
- $signature= base64_decode($body['signature']);
-
- $res = openssl_verify($message, $signature, $key, OPENSSL_ALGO_SHA512);
-
- if ($res === 1) {
+ if ($verified) {
$result = $this->insertOrUpdate($cloudId, $body['message']['data'], $body['message']['timestamp']);
if ($result === false) {
$response->withStatus(403);
@@ -270,7 +240,85 @@ LIMIT 50');
return $response;
}
- /**
+ public function delete(Request $request, Response $response) {
+ $body = json_decode($request->getBody(), true);
+
+ if ($body === null || !isset($body['message']) || !isset($body['message']['data']) ||
+ !isset($body['message']['data']['federationId']) || !isset($body['signature']) ||
+ !isset($body['message']['timestamp'])) {
+ $response->withStatus(400);
+ return $response;
+ }
+
+ $cloudId = $body['message']['data']['federationId'];
+
+ try {
+ $verified = $this->verifyRequest($cloudId, $body['message'], $body['signature']);
+ } catch(\Exception $e) {
+ $response->withStatus(400);
+ return $response;
+ }
+
+
+ if ($verified) {
+ $result = $this->deleteDBRecord($cloudId);
+ if ($result === false) {
+ $response->withStatus(404);
+ }
+ } else {
+ // ERROR OUT
+ $response->withStatus(403);
+ }
+
+ return $response;
+ }
+
+ /**
+ * check signature of incoming request
+ *
+ * @param string $cloudId
+ * @param string $message
+ * @param string $signature
+ * @return bool
+ * @throws \Exception
+ */
+ protected function verifyRequest($cloudId, $message, $signature) {
+ // Get fed id
+ list($user, $host) = $this->splitCloudId($cloudId);
+
+ // Retrieve public key && store
+ $ocsreq = new \GuzzleHttp\Psr7\Request(
+ 'GET',
+ 'http://'.$host . '/ocs/v2.php/identityproof/key/' . $user,
+ [
+ 'OCS-APIREQUEST' => 'true',
+ 'Accept' => 'application/json',
+ ]);
+
+ $client = new Client();
+ $ocsresponse = $client->send($ocsreq, ['timeout' => 10]);
+
+ $ocsresponse = json_decode($ocsresponse->getBody(), true);
+
+ if ($ocsresponse === null || !isset($ocsresponse['ocs']) ||
+ !isset($ocsresponse['ocs']['data']) || !isset($ocsresponse['ocs']['data']['public'])) {
+ throw new \BadMethodCallException();
+ }
+
+ $key = $ocsresponse['ocs']['data']['public'];
+
+ // verify message
+ $message = json_encode($message);
+ $signature= base64_decode($signature);
+
+ $res = openssl_verify($message, $signature, $key, OPENSSL_ALGO_SHA512);
+
+ return $res === 1;
+
+ }
+
+
+ /**
* @param string $cloudId
* @param string[] $data
* @param int $timestamp
@@ -300,4 +348,33 @@ LIMIT 50');
return true;
}
+
+ /**
+ * Delete all personal data. We keep the basic user entry with the
+ * federated cloud ID in order to propagate the changes
+ *
+ * @param string $cloudId
+ * @return bool
+ */
+ private function deleteDBRecord($cloudId) {
+
+ $stmt = $this->db->prepare('SELECT * FROM users WHERE federationId = :federationId');
+ $stmt->bindParam(':federationId', $cloudId);
+ $stmt->execute();
+ $row = $stmt->fetch();
+ $stmt->closeCursor();
+
+ // If we can't find the user
+ if ($row === false) {
+ return false;
+ }
+
+ // delete user data
+ $stmt = $this->db->prepare('DELETE FROM store WHERE userId = :userId');
+ $stmt->bindParam(':userId', $row['id']);
+ $stmt->execute();
+ $stmt->closeCursor();
+
+ return true;
+ }
}