From 88b21461358b9478c8f3a0dfea237c27c012cc05 Mon Sep 17 00:00:00 2001 From: Skylar Ittner Date: Sat, 24 Nov 2018 12:32:59 -0700 Subject: [PATCH] Implement Nextcloud Notes API, close #2 --- .htaccess | 5 ++ action.php | 10 ++-- database.mwb | Bin 6602 -> 7096 bytes lib/Note.lib.php | 113 +++++++++++++++++++++++++++++++++++++---- lib/nextcloudnotes.php | 112 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 226 insertions(+), 14 deletions(-) create mode 100644 .htaccess create mode 100644 lib/nextcloudnotes.php diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..b91932b --- /dev/null +++ b/.htaccess @@ -0,0 +1,5 @@ +# Rewrite for Nextcloud Notes API + + RewriteEngine on + RewriteRule index.php/apps/notes/api/v0.2 lib/nextcloudnotes.php [PT] + \ No newline at end of file diff --git a/action.php b/action.php index f5d196e..e983f9f 100644 --- a/action.php +++ b/action.php @@ -35,13 +35,13 @@ switch ($VARS['action']) { header('Location: index.php'); die("Logged out."); case "savenote": - if (empty($VARS['content']) || empty($VARS['noteid'])) { - die($Strings->get("invalid parameters")); + if (!isset($VARS['content']) || empty($VARS['noteid'])) { + die($Strings->get("invalid parameters", false)); } http_response_code(204); $note = Note::loadNote($VARS['noteid']); - if ($note->getOwnerID() != $_SESSION['uid']) { - die($Strings->get("invalid parameters")); + if (!$note->hasWriteAccess(new User($_SESSION['uid']))) { + die($Strings->get("invalid parameters", false)); } $note->setText($VARS['content']); $note->setColor($VARS['color']); @@ -52,7 +52,7 @@ switch ($VARS['action']) { die($Strings->get("invalid parameters")); } $note = Note::loadNote($VARS['noteid']); - if ($note->getOwnerID() != $_SESSION['uid']) { + if (!$note->hasWriteAccess(new User($_SESSION['uid']))) { die($Strings->get("invalid parameters")); } $note->deleteNote(); diff --git a/database.mwb b/database.mwb index 62603e01f9322c4d8c98733750d5550e58b62294..63826da0208122210eea1bfb5df0559dcd614130 100644 GIT binary patch delta 7002 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 UO@XXrNg#4+q)v*Y7;@?V0&f*vu>b%7 delta 6504 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 zget('notes', ['noteid', 'ownerid', 'color', 'content'], ['noteid' => $noteid]); + $notedata = $database->get('notes', ['noteid', 'ownerid', 'color', 'content', 'title', 'modified'], ['noteid' => $noteid]); - return new Note($notedata['content'], $notedata['color'], $notedata['ownerid'], $notedata['noteid']); + $note = new Note($notedata['content'], $notedata['color'], $notedata['ownerid'], $notedata['noteid']); + $note->setTitle(is_null($notedata['title']) ? "" : $notedata['title']); + $note->setModified(is_null($notedata['modified']) ? date("Y-m-d H:i:s") : $notedata['modified']); + + return $note; } /** @@ -57,9 +63,11 @@ class Note { global $database; $data = [ - 'ownerid' => $this->ownerid, - 'color' => $this->color, - 'content' => $this->content + 'ownerid' => $this->getOwnerID(), + 'color' => $this->getColor(), + 'content' => $this->getText(), + 'title' => $this->getTitle(), + 'modified' => $this->getModified() ]; // We can't UPDATE the database, so use save as for INSERT @@ -142,6 +150,34 @@ class Note { return new User($this->ownerid); } + /** + * Get the note title + * @return string + */ + public function getTitle(): string { + global $Strings; + $title = $this->title; + if (empty($title)) { + if (empty($this->getText())) { + $title = $Strings->get("New note", false); + } else { + $title = explode("\n", $this->getText())[0]; + } + } + return $title; + } + + /** + * Get the last modified date/time as "Y-m-d H:i:s" + * @return string + */ + public function getModified(): string { + if (empty($this->modified)) { + return date("Y-m-d H:i:s"); + } + return date("Y-m-d H:i:s", strtotime($this->modified)); + } + /** * Set the note content * @param string $markdown @@ -174,6 +210,22 @@ class Note { $this->ownerid = $owner->getUID(); } + /** + * Set the note title + * @param string $title + */ + public function setTitle(string $title) { + $this->title = $title; + } + + /** + * Set the last modified date/time + * @param string $datetime + */ + public function setModified(string $datetime) { + $this->modified = date("Y-m-d H:i:s", strtotime($datetime)); + } + /** * Get this note as an array. * @return string @@ -181,9 +233,11 @@ class Note { public function toArray(): array { $owner = new User($this->ownerid); $arr = [ - 'noteid' => $this->noteid, - 'color' => $this->color, - 'content' => $this->content, + 'noteid' => $this->getID(), + 'color' => $this->getColor(), + 'content' => $this->getText(), + 'title' => $this->getTitle(), + 'modified' => $this->getModified(), 'owner' => [ 'uid' => $owner->getUID(), 'username' => $owner->getUsername(), @@ -194,13 +248,54 @@ class Note { return $arr; } + /** + * Get an array suitable for returning via the Nextcloud Notes API + * https://github.com/nextcloud/notes/wiki/Notes-0.2#get-a-note + * @return array + */ + public function toNextcloud(): array { + return [ + "id" => $this->getID(), + "modified" => strtotime($this->getModified()), + "title" => $this->getTitle(), + "category" => null, + "content" => $this->getText(), + "favorite" => false + ]; + } + + /** + * Check whether the given User has read access to this note. + * @param User $user + */ + public function hasReadAccess(User $user): bool { + if ($this->getOwnerID() == $user->getUID()) { + return true; + } + return false; + } + + /** + * Check whether the given User has write access to this note. + * @param User $user + */ + public function hasWriteAccess(User $user): bool { + if ($this->getOwnerID() == $user->getUID()) { + return true; + } + return false; + } + /** * Read an array with the structure from toArray(). * @param array $arr * @return \Note A Note constructed from the array data. */ public static function fromArray(array $arr): Note { - return new Note($arr['content'], $arr['color'], $arr['owner']['uid'], $arr['noteid']); + $note = new Note($arr['content'], $arr['color'], $arr['owner']['uid'], $arr['noteid']); + $note->setTitle($arr['title']); + $note->setModified($arr['modified']); + return $note; } } diff --git a/lib/nextcloudnotes.php b/lib/nextcloudnotes.php new file mode 100644 index 0000000..abe047c --- /dev/null +++ b/lib/nextcloudnotes.php @@ -0,0 +1,112 @@ +checkPassword($_SERVER['PHP_AUTH_PW'])) { + header('HTTP/1.0 401 Unauthorized'); + die($Strings->get("login incorrect")); + } +} + +header("Content-Type: application/json"); + +$requestdata = $_GET; +$requestbody = file_get_contents('php://input'); +$requestjson = json_decode($requestbody, TRUE); +if (json_last_error() == JSON_ERROR_NONE) { + $requestdata = array_merge($requestdata, $requestjson); +} + +switch ($_SERVER['REQUEST_METHOD']) { + case "GET": + if (count($route) == 1) { + $noteids = $database->select('notes', 'noteid', ['ownerid' => $user->getUID()]); + $notes = []; + foreach ($noteids as $n) { + $notes[] = Note::loadNote($n)->toNextcloud(); + } + exit(json_encode($notes)); + } else if (count($route) == 2 && is_numeric($route[1])) { + try { + $note = Note::loadNote($route[1]); + if ($note->getOwner()->getUID() == $user->getUID()) { + exit(json_encode($note->toNextcloud())); + } else { + http_response_code(401); + } + } catch (NoSuchNoteException $ex) { + http_response_code(404); + } + } + break; + case "POST": + $note = new Note($requestdata['content']); + + if (empty($requestdata['modified']) || !is_numeric($requestdata['modified'])) { + $note->setModified(date("Y-m-d H:i:s")); + } else { + $note->setModified($requestdata['modified']); + } + + $note->setOwner($user); + + $note->saveNote(); + + exit(json_encode($note->toNextcloud())); + break; + case "PUT": + if (count($route) == 2 && is_numeric($route[1])) { + try { + $note = Note::loadNote($route[1]); + if ($note->hasWriteAccess($user)) { + $note->setText($requestdata['content']); + if (empty($requestdata['modified']) || !is_numeric($requestdata['modified'])) { + $note->setModified(date("Y-m-d H:i:s")); + } else { + $note->setModified($requestdata['modified']); + } + $note->saveNote(); + exit(json_encode($note->toNextcloud())); + } else { + http_response_code(401); + } + } catch (NoSuchNoteException $ex) { + http_response_code(404); + } + } + break; + case "DELETE": + if (count($route) == 2 && is_numeric($route[1])) { + try { + $note = Note::loadNote($route[1]); + if ($note->hasWriteAccess($user)) { + $note->deleteNote(); + exit; + } else { + http_response_code(401); + } + } catch (NoSuchNoteException $ex) { + http_response_code(404); + } + } + break; +} \ No newline at end of file