From 799ce1b3718cbeb1a113c163bfc4e66d503db04a Mon Sep 17 00:00:00 2001 From: Lukas Metzger Date: Wed, 25 Apr 2018 19:35:11 +0200 Subject: [PATCH] Added /remote/changepw --- backend/src/controllers/Remote.php | 26 +++++++ backend/src/exceptions/ForbiddenException.php | 9 +++ backend/src/operations/Remote.php | 68 +++++++++++++++++++ backend/src/public/index.php | 1 + backend/test/db.sql | 2 +- backend/test/tests/remote-changepw.js | 36 ++++++++++ 6 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 backend/src/exceptions/ForbiddenException.php create mode 100644 backend/src/operations/Remote.php create mode 100644 backend/test/tests/remote-changepw.js diff --git a/backend/src/controllers/Remote.php b/backend/src/controllers/Remote.php index 1712072..d022ad6 100644 --- a/backend/src/controllers/Remote.php +++ b/backend/src/controllers/Remote.php @@ -27,4 +27,30 @@ class Remote 'ip' => $req->getAttribute('clientIp') ], 200); } + + public function updatePassword(Request $req, Response $res, array $args) + { + $record = $req->getParam('record'); + $content = $req->getParam('content'); + $password = $req->getParam('password'); + + if ($record === null || $content === null || $password === null) { + return $res->withJson(['error' => 'One of the required fields is missing.'], 422); + } + + $remote = new \Operations\Remote($this->c); + + try { + $remote->updatePassword(intval($record), $content, $password); + } catch (\Exceptions\NotFoundException $e) { + $this->logger->debug('User tried to update non existent record via changepw api.'); + return $res->withJson(['error' => 'The given record does not exist.'], 404); + } catch (\Exceptions\ForbiddenException $e) { + $this->logger->debug('User tried to update an record via changepw api with incorrect password.'); + return $res->withJson(['error' => 'The provided password was invalid.'], 403); + } + + $this->logger->info('Record ' . $record . ' was changed via the changepw api.'); + return $res->withStatus(204); + } } diff --git a/backend/src/exceptions/ForbiddenException.php b/backend/src/exceptions/ForbiddenException.php new file mode 100644 index 0000000..778457f --- /dev/null +++ b/backend/src/exceptions/ForbiddenException.php @@ -0,0 +1,9 @@ +logger = $c->logger; + $this->db = $c->db; + $this->c = $c; + } + + /** + * Add new record + * + * @param $record Name of the new record + * @param $content Type of the new record + * @param $password Content of the new record + * + * @throws NotFoundException if the record does not exist + * @throws ForbiddenException if the password is not valid for the record + */ + public function updatePassword(int $record, string $content, string $password) : void + { + $query = $this->db->prepare('SELECT id FROM records WHERE id=:record'); + $query->bindValue(':record', $record, \PDO::PARAM_INT); + $query->execute(); + + if ($query->fetch() === false) { + throw new \Exceptions\NotFoundException(); + } + + $query = $this->db->prepare('SELECT security FROM remote WHERE record=:record AND type=\'password\''); + $query->bindValue(':record', $record, \PDO::PARAM_INT); + $query->execute(); + + $validPwFound = false; + + while ($row = $query->fetch()) { + if (password_verify($password, $row['security'])) { + $validPwFound = true; + break; + } + } + + if (!$validPwFound) { + throw new \Exceptions\ForbiddenException(); + } + + $records = new \Operations\Records($this->c); + $records->updateRecord($record, null, null, $content, null, null); + } +} diff --git a/backend/src/public/index.php b/backend/src/public/index.php index fd1b28d..d310c37 100644 --- a/backend/src/public/index.php +++ b/backend/src/public/index.php @@ -31,6 +31,7 @@ $app->group('/v1', function () { $this->post('/sessions', '\Controllers\Sessions:post'); $this->get('/remote/ip', '\Controllers\Remote:ip'); + $this->get('/remote/updatepw', '\Controllers\Remote:updatePassword'); $this->group('', function () { $this->delete('/sessions/{sessionId}', '\Controllers\Sessions:delete'); diff --git a/backend/test/db.sql b/backend/test/db.sql index b71dd74..6bb215f 100644 --- a/backend/test/db.sql +++ b/backend/test/db.sql @@ -167,7 +167,7 @@ CREATE TABLE `remote` ( -- INSERT INTO `remote` (`id`, `record`, `description`, `type`, `security`, `nonce`) VALUES -(1, 1, 'Password Test', 'password', '$2y$10$5Gxh6yus9yi/FHpKD4k8Zez.OAhGZoa7JgwOWZ059/kDyBP3vI9aK', NULL), +(1, 1, 'Password Test', 'password', '$2y$10$abocd6jj/Tw4jzDtqTnjreNzwcerzkXwoVc.JvZBoZ6p0grEKDWoW', NULL), (2, 4, 'Key Test', 'key', '-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA5mu3aH90uSXY9sVLgVSz\nKj4FEctrpFDPyVC4ufbJa/44fuLABFe+IizgZUheNBBO7FjpLJYvsL24o6TEeht4\no5j0KHrRHXqp4WQuAL3ZREv/AhNaOC9/xyjoGwUkKkdC2bIfh0J/ACkezxvUrPsh\nbzhzY+co/M9PqlgTbjKjvlv/pRj2dSp98FzUme3HCh7Nn1EOM3yPMtaKNA9Qkkz1\noalfR3xmJjIanoS9zcK77/yyQ8VwI//CgxvnpnWbORZG0B9W2ZBoI8Bj4zprbbFG\nKNmrb403wfDijYF3MXpSMjKvJ5YVuZsn35EWIi5tqFc0oV7Ryy9nBHzKeoYN7Szs\nrXIS5+ZcQDLuN+pqJ7ByVaw4aVn85py8IdO0IYD5xeKd1i0iqm+KSoFTS1jiNSZu\n6iVl4odixWtW7oPLYBbd/vD2F7Ua5cLd12Rs+6kEVtlpnIf7txyFQL4QHYJxB7fI\ny+m70mfufVvKbFh/mHkhe+Arv71ERDMfAV3AD8++axLqYfU/LLFzanjwIBctAA9a\nj++G0lwl1adURwnBeq8+YrMU4/wg9efquKXLR40dU9nkMJOm5tPm+XHt4o3wio4X\n2FqnD57I7qJCWVc00HtpeWno5vHL+eJu0TdxjBuYXnQfwa1z9pWvGaoBtg7tyHgv\ng7YZJzF1MW5N9ZqnkdFJVEsCAwEAAQ==\n-----END PUBLIC KEY-----', NULL), (3, 1, 'Key Test 2', 'key', '-----BEGIN PUBLIC KEY-----\r\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA5mu3aH90uSXY9sVLgVSz\r\nKj4FEctrpFDPyVC4ufbJa/44fuLABFe+IizgZUheNBBO7FjpLJYvsL24o6TEeht4\r\no5j0KHrRHXqp4WQuAL3ZREv/AhNaOC9/xyjoGwUkKkdC2bIfh0J/ACkezxvUrPsh\r\nbzhzY+co/M9PqlgTbjKjvlv/pRj2dSp98FzUme3HCh7Nn1EOM3yPMtaKNA9Qkkz1\r\noalfR3xmJjIanoS9zcK77/yyQ8VwI//CgxvnpnWbORZG0B9W2ZBoI8Bj4zprbbFG\r\nKNmrb403wfDijYF3MXpSMjKvJ5YVuZsn35EWIi5tqFc0oV7Ryy9nBHzKeoYN7Szs\r\nrXIS5+ZcQDLuN+pqJ7ByVaw4aVn85py8IdO0IYD5xeKd1i0iqm+KSoFTS1jiNSZu\r\n6iVl4odixWtW7oPLYBbd/vD2F7Ua5cLd12Rs+6kEVtlpnIf7txyFQL4QHYJxB7fI\r\ny+m70mfufVvKbFh/mHkhe+Arv71ERDMfAV3AD8++axLqYfU/LLFzanjwIBctAA9a\r\nj++G0lwl1adURwnBeq8+YrMU4/wg9efquKXLR40dU9nkMJOm5tPm+XHt4o3wio4X\r\n2FqnD57I7qJCWVc00HtpeWno5vHL+eJu0TdxjBuYXnQfwa1z9pWvGaoBtg7tyHgv\r\ng7YZJzF1MW5N9ZqnkdFJVEsCAwEAAQ==\r\n-----END PUBLIC KEY-----', NULL); diff --git a/backend/test/tests/remote-changepw.js b/backend/test/tests/remote-changepw.js new file mode 100644 index 0000000..513c014 --- /dev/null +++ b/backend/test/tests/remote-changepw.js @@ -0,0 +1,36 @@ +const test = require('../testlib'); + +test.run(async function () { + await test('admin', async function (assert, req) { + // Test updating + var res = await req({ + url: '/remote/updatepw?record=1&content=foobarbaz&password=test', + method: 'get' + }); + + assert.equal(res.status, 204); + + var res = await req({ + url: '/records/1', + method: 'get' + }); + + assert.equal(res.data.content, 'foobarbaz', 'Updating should change content.'); + + // Test updating with invalid password + var res = await req({ + url: '/remote/updatepw?record=1&content=foobarbaz&password=foo', + method: 'get' + }); + + assert.equal(res.status, 403); + + // Test updating non existing record + var res = await req({ + url: '/remote/updatepw?record=100&content=foobarbaz&password=foo', + method: 'get' + }); + + assert.equal(res.status, 404); + }); +}); \ No newline at end of file