Implement Nextcloud Notes API, close #2
This commit is contained in:
parent
f7d443b954
commit
88b2146135
5
.htaccess
Normal file
5
.htaccess
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Rewrite for Nextcloud Notes API
|
||||||
|
<IfModule mod_rewrite.c>
|
||||||
|
RewriteEngine on
|
||||||
|
RewriteRule index.php/apps/notes/api/v0.2 lib/nextcloudnotes.php [PT]
|
||||||
|
</IfModule>
|
10
action.php
10
action.php
@ -35,13 +35,13 @@ switch ($VARS['action']) {
|
|||||||
header('Location: index.php');
|
header('Location: index.php');
|
||||||
die("Logged out.");
|
die("Logged out.");
|
||||||
case "savenote":
|
case "savenote":
|
||||||
if (empty($VARS['content']) || empty($VARS['noteid'])) {
|
if (!isset($VARS['content']) || empty($VARS['noteid'])) {
|
||||||
die($Strings->get("invalid parameters"));
|
die($Strings->get("invalid parameters", false));
|
||||||
}
|
}
|
||||||
http_response_code(204);
|
http_response_code(204);
|
||||||
$note = Note::loadNote($VARS['noteid']);
|
$note = Note::loadNote($VARS['noteid']);
|
||||||
if ($note->getOwnerID() != $_SESSION['uid']) {
|
if (!$note->hasWriteAccess(new User($_SESSION['uid']))) {
|
||||||
die($Strings->get("invalid parameters"));
|
die($Strings->get("invalid parameters", false));
|
||||||
}
|
}
|
||||||
$note->setText($VARS['content']);
|
$note->setText($VARS['content']);
|
||||||
$note->setColor($VARS['color']);
|
$note->setColor($VARS['color']);
|
||||||
@ -52,7 +52,7 @@ switch ($VARS['action']) {
|
|||||||
die($Strings->get("invalid parameters"));
|
die($Strings->get("invalid parameters"));
|
||||||
}
|
}
|
||||||
$note = Note::loadNote($VARS['noteid']);
|
$note = Note::loadNote($VARS['noteid']);
|
||||||
if ($note->getOwnerID() != $_SESSION['uid']) {
|
if (!$note->hasWriteAccess(new User($_SESSION['uid']))) {
|
||||||
die($Strings->get("invalid parameters"));
|
die($Strings->get("invalid parameters"));
|
||||||
}
|
}
|
||||||
$note->deleteNote();
|
$note->deleteNote();
|
||||||
|
BIN
database.mwb
BIN
database.mwb
Binary file not shown.
113
lib/Note.lib.php
113
lib/Note.lib.php
@ -11,6 +11,8 @@ class Note {
|
|||||||
private $noteid;
|
private $noteid;
|
||||||
private $ownerid;
|
private $ownerid;
|
||||||
private $content = "";
|
private $content = "";
|
||||||
|
private $title = "";
|
||||||
|
private $modified = "";
|
||||||
private $color = "FFFFFF";
|
private $color = "FFFFFF";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,9 +42,13 @@ class Note {
|
|||||||
throw new NoSuchNoteException();
|
throw new NoSuchNoteException();
|
||||||
}
|
}
|
||||||
|
|
||||||
$notedata = $database->get('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;
|
global $database;
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'ownerid' => $this->ownerid,
|
'ownerid' => $this->getOwnerID(),
|
||||||
'color' => $this->color,
|
'color' => $this->getColor(),
|
||||||
'content' => $this->content
|
'content' => $this->getText(),
|
||||||
|
'title' => $this->getTitle(),
|
||||||
|
'modified' => $this->getModified()
|
||||||
];
|
];
|
||||||
|
|
||||||
// We can't UPDATE the database, so use save as for INSERT
|
// We can't UPDATE the database, so use save as for INSERT
|
||||||
@ -142,6 +150,34 @@ class Note {
|
|||||||
return new User($this->ownerid);
|
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
|
* Set the note content
|
||||||
* @param string $markdown
|
* @param string $markdown
|
||||||
@ -174,6 +210,22 @@ class Note {
|
|||||||
$this->ownerid = $owner->getUID();
|
$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.
|
* Get this note as an array.
|
||||||
* @return string
|
* @return string
|
||||||
@ -181,9 +233,11 @@ class Note {
|
|||||||
public function toArray(): array {
|
public function toArray(): array {
|
||||||
$owner = new User($this->ownerid);
|
$owner = new User($this->ownerid);
|
||||||
$arr = [
|
$arr = [
|
||||||
'noteid' => $this->noteid,
|
'noteid' => $this->getID(),
|
||||||
'color' => $this->color,
|
'color' => $this->getColor(),
|
||||||
'content' => $this->content,
|
'content' => $this->getText(),
|
||||||
|
'title' => $this->getTitle(),
|
||||||
|
'modified' => $this->getModified(),
|
||||||
'owner' => [
|
'owner' => [
|
||||||
'uid' => $owner->getUID(),
|
'uid' => $owner->getUID(),
|
||||||
'username' => $owner->getUsername(),
|
'username' => $owner->getUsername(),
|
||||||
@ -194,13 +248,54 @@ class Note {
|
|||||||
return $arr;
|
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().
|
* Read an array with the structure from toArray().
|
||||||
* @param array $arr
|
* @param array $arr
|
||||||
* @return \Note A Note constructed from the array data.
|
* @return \Note A Note constructed from the array data.
|
||||||
*/
|
*/
|
||||||
public static function fromArray(array $arr): Note {
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
112
lib/nextcloudnotes.php
Normal file
112
lib/nextcloudnotes.php
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require __DIR__ . "/../required.php";
|
||||||
|
|
||||||
|
header("Content-Security-Policy: default-src '*';");
|
||||||
|
header('Access-Control-Allow-Origin: *');
|
||||||
|
|
||||||
|
// Get the API route/action
|
||||||
|
$route = explode("/", substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_URI'], "api/v0.2/") + 9));
|
||||||
|
|
||||||
|
// HTTP authentication
|
||||||
|
if (!isset($_SERVER['PHP_AUTH_USER'])) {
|
||||||
|
header('WWW-Authenticate: Basic realm="' . SITE_TITLE . '"');
|
||||||
|
header('HTTP/1.0 401 Unauthorized');
|
||||||
|
exit;
|
||||||
|
} else {
|
||||||
|
$user = User::byUsername($_SERVER['PHP_AUTH_USER']);
|
||||||
|
if (!$user->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;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user