mirror of
https://github.com/maxpozdeev/mytinytodo.git
synced 2026-03-11 08:55:27 +00:00
* add more compatibility for http api (able to use GET and POST requests only)
This commit is contained in:
parent
b7e060e6db
commit
edfe391e41
6 changed files with 133 additions and 80 deletions
|
|
@ -1,12 +1,16 @@
|
|||
# For Apache
|
||||
# For REST API in Apache
|
||||
#<IfModule mod_rewrite.c>
|
||||
# RewriteEngine On
|
||||
# RewriteCond %{REQUEST_FILENAME} !-f
|
||||
# RewriteCond %{REQUEST_FILENAME} !-d
|
||||
# RewriteRule ^api/(.*)$ api.php/$1 [L,QSA]
|
||||
#</IfModule>
|
||||
#<Limit GET POST PUT DELETE>
|
||||
# Allow from all
|
||||
#</Limit>
|
||||
|
||||
# For Nginx set something like this:
|
||||
|
||||
# In Nginx set something like this:
|
||||
# location /api/ {
|
||||
# rewrite ^/api/(.*) /api.php/$1 last;
|
||||
# }
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ $endpoints = array(
|
|||
'GET' => [ ListsController::class , 'getId' ],
|
||||
'PUT' => [ ListsController::class , 'putId' ],
|
||||
'DELETE' => [ ListsController::class , 'deleteId' ],
|
||||
'POST' => [ ListsController::class , 'putId' ], //compatibility
|
||||
],
|
||||
'/tasks' => [
|
||||
'GET' => [ TasksController::class , 'get' ],
|
||||
|
|
@ -41,6 +42,7 @@ $endpoints = array(
|
|||
'/tasks/(-?\d+)' => [
|
||||
'PUT' => [ TasksController::class , 'putId' ],
|
||||
'DELETE' => [ TasksController::class , 'deleteId' ],
|
||||
'POST' => [ TasksController::class , 'putId' ], //compatibility
|
||||
],
|
||||
'/tasks/parseTitle' => [
|
||||
'POST' => [ TasksController::class , 'postTitleParse' ],
|
||||
|
|
@ -60,6 +62,7 @@ $endpoints = array(
|
|||
'/ext-settings/(.+)' => [
|
||||
'GET' => [ ExtSettingsController::class , 'get' ],
|
||||
'PUT' => [ ExtSettingsController::class , 'put' ],
|
||||
'POST' => [ ExtSettingsController::class , 'put' ], //compatibility
|
||||
]
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
This file is a part of myTinyTodo.
|
||||
(C) Copyright 2010,2020,2022 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
(C) Copyright 2010,2020-2023 Max Pozdeev <maxpozdeev@gmail.com>
|
||||
Licensed under the GNU GPL version 2 or any later. See file COPYRIGHT for details.
|
||||
*/
|
||||
|
||||
|
|
@ -9,10 +9,12 @@
|
|||
"use strict";
|
||||
|
||||
var mtt;
|
||||
var useREST = true;
|
||||
|
||||
function MytinytodoAjaxApi(amtt)
|
||||
{
|
||||
mtt = amtt;
|
||||
useREST = false;
|
||||
}
|
||||
|
||||
window.MytinytodoAjaxApi = MytinytodoAjaxApi;
|
||||
|
|
@ -22,7 +24,9 @@ MytinytodoAjaxApi.prototype =
|
|||
/* required method */
|
||||
request: function(action, params, callback)
|
||||
{
|
||||
if (!this[action]) throw "Unknown ApiDriver action: " + action;
|
||||
if (!this[action] || typeof this[action] !== 'function') {
|
||||
throw "Unknown ApiDriver action: " + action;
|
||||
}
|
||||
|
||||
this[action] (params, function(json){
|
||||
if (json.denied) mtt.errorDenied();
|
||||
|
|
@ -50,7 +54,7 @@ MytinytodoAjaxApi.prototype =
|
|||
method: 'POST',
|
||||
contentType : 'application/json',
|
||||
data: JSON.stringify({
|
||||
action: 'simple',
|
||||
action: 'newSimple',
|
||||
list: params.list,
|
||||
title: params.title,
|
||||
tag: params.tag,
|
||||
|
|
@ -68,7 +72,7 @@ MytinytodoAjaxApi.prototype =
|
|||
method: 'POST',
|
||||
contentType : 'application/json',
|
||||
data: JSON.stringify({
|
||||
action: 'full',
|
||||
action: 'newFull',
|
||||
list: params.list,
|
||||
title: params.title,
|
||||
note: params.note,
|
||||
|
|
@ -87,7 +91,7 @@ MytinytodoAjaxApi.prototype =
|
|||
{
|
||||
$.ajax({
|
||||
url: mtt.apiUrl + 'tasks/' + encodeURIComponent(params.id),
|
||||
method: 'PUT',
|
||||
method: useREST ? 'PUT' : 'POST',
|
||||
contentType : 'application/json',
|
||||
data: JSON.stringify({
|
||||
action: 'edit',
|
||||
|
|
@ -107,7 +111,7 @@ MytinytodoAjaxApi.prototype =
|
|||
{
|
||||
$.ajax({
|
||||
url: mtt.apiUrl + 'tasks/' + encodeURIComponent(params.id),
|
||||
method: 'PUT',
|
||||
method: useREST ? 'PUT' : 'POST',
|
||||
contentType : 'application/json',
|
||||
data: JSON.stringify({
|
||||
action: 'note',
|
||||
|
|
@ -123,7 +127,7 @@ MytinytodoAjaxApi.prototype =
|
|||
{
|
||||
$.ajax({
|
||||
url: mtt.apiUrl + 'tasks/' + encodeURIComponent(params.id),
|
||||
method: 'PUT',
|
||||
method: useREST ? 'PUT' : 'POST',
|
||||
contentType : 'application/json',
|
||||
data: JSON.stringify({
|
||||
action: 'complete',
|
||||
|
|
@ -139,7 +143,11 @@ MytinytodoAjaxApi.prototype =
|
|||
{
|
||||
$.ajax({
|
||||
url: mtt.apiUrl + 'tasks/' + encodeURIComponent(params.id),
|
||||
method: 'DELETE',
|
||||
method: useREST ? 'DELETE' : 'POST',
|
||||
contentType : 'application/json', // contentType and data are required if method is POST
|
||||
data: JSON.stringify({
|
||||
action: 'delete',
|
||||
}),
|
||||
success: callback,
|
||||
dataType: 'json'
|
||||
});
|
||||
|
|
@ -150,7 +158,7 @@ MytinytodoAjaxApi.prototype =
|
|||
{
|
||||
$.ajax({
|
||||
url: mtt.apiUrl + 'tasks/' + encodeURIComponent(params.id),
|
||||
method: 'PUT',
|
||||
method: useREST ? 'PUT' : 'POST',
|
||||
contentType : 'application/json',
|
||||
data: JSON.stringify({
|
||||
action: 'priority',
|
||||
|
|
@ -165,7 +173,7 @@ MytinytodoAjaxApi.prototype =
|
|||
{
|
||||
$.ajax({
|
||||
url: mtt.apiUrl + 'tasks',
|
||||
method: 'PUT',
|
||||
method: useREST ? 'PUT' : 'POST',
|
||||
contentType : 'application/json',
|
||||
data: JSON.stringify({
|
||||
action: 'order',
|
||||
|
|
@ -190,7 +198,7 @@ MytinytodoAjaxApi.prototype =
|
|||
{
|
||||
$.ajax({
|
||||
url: mtt.apiUrl + 'tasks/' + encodeURIComponent(params.id),
|
||||
method: 'PUT',
|
||||
method: useREST ? 'PUT' : 'POST',
|
||||
contentType : 'application/json',
|
||||
data: JSON.stringify({
|
||||
action: 'move',
|
||||
|
|
@ -232,6 +240,7 @@ MytinytodoAjaxApi.prototype =
|
|||
method: 'POST',
|
||||
contentType : 'application/json',
|
||||
data: JSON.stringify({
|
||||
action: 'new',
|
||||
name: params.name,
|
||||
}),
|
||||
success: callback,
|
||||
|
|
@ -244,7 +253,11 @@ MytinytodoAjaxApi.prototype =
|
|||
{
|
||||
$.ajax({
|
||||
url: mtt.apiUrl + 'lists/' + encodeURIComponent(params.list),
|
||||
method: 'DELETE',
|
||||
method: useREST ? 'DELETE' : 'POST',
|
||||
contentType : 'application/json', // contentType and data are required if method is POST
|
||||
data: JSON.stringify({
|
||||
action: 'delete',
|
||||
}),
|
||||
success: callback,
|
||||
dataType: 'json'
|
||||
});
|
||||
|
|
@ -254,7 +267,7 @@ MytinytodoAjaxApi.prototype =
|
|||
{
|
||||
$.ajax({
|
||||
url: mtt.apiUrl + 'lists/' + encodeURIComponent(params.list),
|
||||
method: 'PUT',
|
||||
method: useREST ? 'PUT' : 'POST',
|
||||
contentType : 'application/json',
|
||||
data: JSON.stringify({
|
||||
action: 'rename',
|
||||
|
|
@ -269,7 +282,7 @@ MytinytodoAjaxApi.prototype =
|
|||
{
|
||||
$.ajax({
|
||||
url: mtt.apiUrl + 'lists/' + encodeURIComponent(params.list),
|
||||
method: 'PUT',
|
||||
method: useREST ? 'PUT' : 'POST',
|
||||
contentType : 'application/json',
|
||||
data: JSON.stringify({
|
||||
action: 'sort',
|
||||
|
|
@ -285,7 +298,7 @@ MytinytodoAjaxApi.prototype =
|
|||
{
|
||||
$.ajax({
|
||||
url: mtt.apiUrl + 'lists/' + encodeURIComponent(params.list),
|
||||
method: 'PUT',
|
||||
method: useREST ? 'PUT' : 'POST',
|
||||
contentType : 'application/json',
|
||||
data: JSON.stringify({
|
||||
action: 'publish',
|
||||
|
|
@ -300,7 +313,7 @@ MytinytodoAjaxApi.prototype =
|
|||
{
|
||||
$.ajax({
|
||||
url: mtt.apiUrl + 'lists/' + encodeURIComponent(params.list),
|
||||
method: 'PUT',
|
||||
method: useREST ? 'PUT' : 'POST',
|
||||
contentType : 'application/json',
|
||||
data: JSON.stringify({
|
||||
action: 'enableFeedKey',
|
||||
|
|
@ -315,7 +328,7 @@ MytinytodoAjaxApi.prototype =
|
|||
{
|
||||
$.ajax({
|
||||
url: mtt.apiUrl + 'lists/' + encodeURIComponent(params.list),
|
||||
method: 'PUT',
|
||||
method: useREST ? 'PUT' : 'POST',
|
||||
contentType : 'application/json',
|
||||
data: JSON.stringify({
|
||||
action: 'showNotes',
|
||||
|
|
@ -330,7 +343,7 @@ MytinytodoAjaxApi.prototype =
|
|||
{
|
||||
$.ajax({
|
||||
url: mtt.apiUrl + 'lists/' + encodeURIComponent(params.list),
|
||||
method: 'PUT',
|
||||
method: useREST ? 'PUT' : 'POST',
|
||||
contentType : 'application/json',
|
||||
data: JSON.stringify({
|
||||
action: 'hide',
|
||||
|
|
@ -345,7 +358,7 @@ MytinytodoAjaxApi.prototype =
|
|||
{
|
||||
$.ajax({
|
||||
url: mtt.apiUrl + 'lists',
|
||||
method: 'PUT',
|
||||
method: useREST ? 'PUT' : 'POST',
|
||||
contentType : 'application/json',
|
||||
data: JSON.stringify({
|
||||
action: 'order',
|
||||
|
|
@ -360,7 +373,7 @@ MytinytodoAjaxApi.prototype =
|
|||
{
|
||||
$.ajax({
|
||||
url: mtt.apiUrl + 'lists/' + encodeURIComponent(params.list),
|
||||
method: 'PUT',
|
||||
method: useREST ? 'PUT' : 'POST',
|
||||
contentType : 'application/json',
|
||||
data: JSON.stringify({
|
||||
action: 'clearCompleted',
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ class ListsController extends ApiController {
|
|||
|
||||
|
||||
/**
|
||||
* Create new list
|
||||
* Create new list and Actions with all lists
|
||||
* Code 201 on success
|
||||
* @return void
|
||||
* @throws Exception
|
||||
|
|
@ -48,15 +48,12 @@ class ListsController extends ApiController {
|
|||
function post()
|
||||
{
|
||||
checkWriteAccess();
|
||||
$id = DBCore::default()->createListWithName($this->req->jsonBody['name'] ?? '');
|
||||
$db = DBConnection::instance();
|
||||
$t = array();
|
||||
$t['total'] = 1;
|
||||
$r = $db->sqa("SELECT * FROM {$db->prefix}lists WHERE id=$id");
|
||||
$oo = $this->prepareList($r, true);
|
||||
MTTNotificationCenter::postNotification(MTTNotification::didCreateList, $oo);
|
||||
$t['list'][] = $oo;
|
||||
$this->response->data = $t;
|
||||
$action = $this->req->jsonBody['action'] ?? '';
|
||||
switch ($action) {
|
||||
case 'order': $this->response->data = $this->changeListOrder(); break; //compatibility
|
||||
case 'new':
|
||||
default: $this->response->data = $this->createList();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -105,32 +102,13 @@ class ListsController extends ApiController {
|
|||
function deleteId($id)
|
||||
{
|
||||
checkWriteAccess();
|
||||
$db = DBConnection::instance();
|
||||
$t = array();
|
||||
$t['total'] = 0;
|
||||
$id = (int)$id;
|
||||
$list = null;
|
||||
if (MTTNotificationCenter::hasObserversForNotification(MTTNotification::didDeleteList)) {
|
||||
$list = $this->getListRowById($id);
|
||||
}
|
||||
$db->ex("BEGIN");
|
||||
$db->ex("DELETE FROM {$db->prefix}lists WHERE id=$id");
|
||||
$t['total'] = $db->affected();
|
||||
if ($t['total']) {
|
||||
$db->ex("DELETE FROM {$db->prefix}tag2task WHERE list_id=$id");
|
||||
$db->ex("DELETE FROM {$db->prefix}todolist WHERE list_id=$id");
|
||||
}
|
||||
$db->ex("COMMIT");
|
||||
if ($t['total'] && MTTNotificationCenter::hasObserversForNotification(MTTNotification::didDeleteList)) {
|
||||
MTTNotificationCenter::postNotification(MTTNotification::didDeleteList, $list);
|
||||
}
|
||||
$this->response->data = $t;
|
||||
$this->response->data = $this->deleteList($id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Edit some properties of List
|
||||
* Actions: rename
|
||||
* Actions: rename, ...
|
||||
* @param mixed $id
|
||||
* @return void
|
||||
* @throws Exception
|
||||
|
|
@ -149,6 +127,7 @@ class ListsController extends ApiController {
|
|||
case 'showNotes': $this->response->data = $this->showNotes($id); break;
|
||||
case 'hide': $this->response->data = $this->hideList($id); break;
|
||||
case 'clearCompleted': $this->response->data = $this->clearCompleted($id); break;
|
||||
case 'delete': $this->response->data = $this->deleteList($id); break; //compatibility
|
||||
default: $this->response->data = ['total' => 0];
|
||||
}
|
||||
}
|
||||
|
|
@ -214,6 +193,23 @@ class ListsController extends ApiController {
|
|||
);
|
||||
}
|
||||
|
||||
private function createList(): ?array
|
||||
{
|
||||
$t = array();
|
||||
$t['total'] = 0;
|
||||
$id = DBCore::default()->createListWithName($this->req->jsonBody['name'] ?? '');
|
||||
if (!$id) {
|
||||
return $t;
|
||||
}
|
||||
$db = DBConnection::instance();
|
||||
$t['total'] = 1;
|
||||
$r = $db->sqa("SELECT * FROM {$db->prefix}lists WHERE id=$id");
|
||||
$oo = $this->prepareList($r, true);
|
||||
MTTNotificationCenter::postNotification(MTTNotification::didCreateList, $oo);
|
||||
$t['list'][] = $oo;
|
||||
return $t;
|
||||
}
|
||||
|
||||
private function renameList(int $id): ?array
|
||||
{
|
||||
$db = DBConnection::instance();
|
||||
|
|
@ -371,4 +367,27 @@ class ListsController extends ApiController {
|
|||
return $t;
|
||||
}
|
||||
|
||||
private function deleteList(int $id)
|
||||
{
|
||||
$db = DBConnection::instance();
|
||||
$t = array();
|
||||
$t['total'] = 0;
|
||||
$id = (int)$id;
|
||||
$list = null;
|
||||
if (MTTNotificationCenter::hasObserversForNotification(MTTNotification::didDeleteList)) {
|
||||
$list = $this->getListRowById($id);
|
||||
}
|
||||
$db->ex("BEGIN");
|
||||
$db->ex("DELETE FROM {$db->prefix}lists WHERE id=$id");
|
||||
$t['total'] = $db->affected();
|
||||
if ($t['total']) {
|
||||
$db->ex("DELETE FROM {$db->prefix}tag2task WHERE list_id=$id");
|
||||
$db->ex("DELETE FROM {$db->prefix}todolist WHERE list_id=$id");
|
||||
}
|
||||
$db->ex("COMMIT");
|
||||
if ($t['total'] && MTTNotificationCenter::hasObserversForNotification(MTTNotification::didDeleteList)) {
|
||||
MTTNotificationCenter::postNotification(MTTNotification::didDeleteList, $list);
|
||||
}
|
||||
return $t;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -135,22 +135,27 @@ class TasksController extends ApiController {
|
|||
|
||||
/**
|
||||
* Create new task
|
||||
* action: simple or full
|
||||
* action: newSimple or newFull
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
function post()
|
||||
{
|
||||
$listId = (int)($this->req->jsonBody['list'] ?? 0);
|
||||
checkWriteAccess($listId);
|
||||
$action = $this->req->jsonBody['action'] ?? '';
|
||||
if ($action == 'full') {
|
||||
$this->response->data = $this->fullNewTaskInList($listId);
|
||||
if ($action == 'order') { //compatibility
|
||||
checkWriteAccess();
|
||||
$this->response->data = $this->changeTaskOrder();
|
||||
}
|
||||
else {
|
||||
$this->response->data = $this->newTaskInList($listId);
|
||||
$listId = (int)($this->req->jsonBody['list'] ?? 0);
|
||||
checkWriteAccess($listId);
|
||||
if ($action == 'newFull') {
|
||||
$this->response->data = $this->fullNewTaskInList($listId);
|
||||
}
|
||||
else {
|
||||
$this->response->data = $this->newTaskInList($listId);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -178,25 +183,7 @@ class TasksController extends ApiController {
|
|||
function deleteId($id)
|
||||
{
|
||||
checkWriteAccess();
|
||||
$id = (int)$id;
|
||||
$task = null;
|
||||
if (MTTNotificationCenter::hasObserversForNotification(MTTNotification::didDeleteTask)) {
|
||||
$task = $this->getTaskRowById($id);
|
||||
}
|
||||
$db = DBConnection::instance();
|
||||
$db->ex("BEGIN");
|
||||
$db->ex("DELETE FROM {$db->prefix}tag2task WHERE task_id=$id");
|
||||
//TODO: delete unused tags?
|
||||
$db->dq("DELETE FROM {$db->prefix}todolist WHERE id=$id");
|
||||
$deleted = $db->affected();
|
||||
$db->ex("COMMIT");
|
||||
if ($deleted && MTTNotificationCenter::hasObserversForNotification(MTTNotification::didDeleteTask)) {
|
||||
MTTNotificationCenter::postNotification(MTTNotification::didDeleteTask, $task);
|
||||
}
|
||||
$t = array();
|
||||
$t['total'] = $deleted;
|
||||
$t['list'][] = array('id' => $id);
|
||||
$this->response->data = $t;
|
||||
$this->response->data = $this->deleteTask((int)$id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -222,6 +209,7 @@ class TasksController extends ApiController {
|
|||
case 'note': $this->response->data = $this->editNote($id); break;
|
||||
case 'move': $this->response->data = $this->moveTask($id); break;
|
||||
case 'priority': $this->response->data = $this->priorityTask($id); break;
|
||||
case 'delete': $this->response->data = $this->deleteTask($id); break; //compatibility
|
||||
default: $this->response->data = ['total' => 0];
|
||||
}
|
||||
}
|
||||
|
|
@ -557,6 +545,29 @@ class TasksController extends ApiController {
|
|||
return $t;
|
||||
}
|
||||
|
||||
private function deleteTask(int $id)
|
||||
{
|
||||
$id = (int)$id;
|
||||
$task = null;
|
||||
if (MTTNotificationCenter::hasObserversForNotification(MTTNotification::didDeleteTask)) {
|
||||
$task = $this->getTaskRowById($id);
|
||||
}
|
||||
$db = DBConnection::instance();
|
||||
$db->ex("BEGIN");
|
||||
$db->ex("DELETE FROM {$db->prefix}tag2task WHERE task_id=$id");
|
||||
//TODO: delete unused tags?
|
||||
$db->dq("DELETE FROM {$db->prefix}todolist WHERE id=$id");
|
||||
$deleted = $db->affected();
|
||||
$db->ex("COMMIT");
|
||||
if ($deleted && MTTNotificationCenter::hasObserversForNotification(MTTNotification::didDeleteTask)) {
|
||||
MTTNotificationCenter::postNotification(MTTNotification::didDeleteTask, $task);
|
||||
}
|
||||
$t = array();
|
||||
$t['total'] = $deleted;
|
||||
$t['list'][] = array('id' => $id);
|
||||
return $t;
|
||||
}
|
||||
|
||||
private function getUserListsSimple(bool $readOnly = false): array
|
||||
{
|
||||
$db = DBConnection::instance();
|
||||
|
|
|
|||
|
|
@ -170,10 +170,13 @@ class DBCore
|
|||
return $data;
|
||||
}
|
||||
|
||||
function createListWithName(string $name): int
|
||||
function createListWithName(string $name): ?int
|
||||
{
|
||||
$db = DBConnection::instance();
|
||||
$name = str_replace( ['"',"'",'<','>','&'], '', trim($name) );
|
||||
if ($name == '') {
|
||||
return null;
|
||||
}
|
||||
$ow = 1 + (int)$db->sq("SELECT MAX(ow) FROM {$db->prefix}lists");
|
||||
$time = time();
|
||||
$db->dq("INSERT INTO {$db->prefix}lists (uuid,name,ow,d_created,d_edited,taskview) VALUES (?,?,?,?,?,?)",
|
||||
|
|
|
|||
Loading…
Reference in a new issue