* @link http://cweiske.de/grauphel.htm
*/
namespace OCA\Grauphel\Controller;
+
use \OCP\AppFramework\Controller;
+use \OCP\AppFramework\Http\JSONResponse;
+
+use \OCA\Grauphel\Lib\Client;
+use \OCA\Grauphel\Lib\NoteStorage;
+use \OCA\Grauphel\Lib\OAuth;
+use \OCA\Grauphel\Lib\OAuthException;
+use \OCA\Grauphel\Lib\Dependencies;
+use \OCA\Grauphel\Lib\Response\ErrorResponse;
/**
* Tomboy's REST API
*/
class ApiController extends Controller
{
+ /**
+ * constructor of the controller
+ *
+ * @param string $appName Name of the app
+ * @param IRequest $request Instance of the request
+ */
+ public function __construct($appName, \OCP\IRequest $request, $user)
+ {
+ parent::__construct($appName, $request);
+ $this->user = $user;
+ $this->deps = Dependencies::get();
+ $this->notes = new NoteStorage($this->deps->urlGen);
+
+ //default http header: we assume something is broken
+ header('HTTP/1.0 500 Internal Server Error');
+ }
+
/**
* /api/1.0
+ *
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ * @PublicPage
*/
- public function index()
+ public function index($route = 'grauphel.api.index')
{
- var_dump('asd');die();
+ $deps = Dependencies::get();
$authenticated = false;
$oauth = new OAuth();
- $oauth->setDeps($this->deps);
- $urlGen = $this->deps->urlGen;
+ $oauth->setDeps($deps);
+ $urlGen = $deps->urlGen;
try {
- $provider = new \OAuthProvider();
+ $provider = OAuth::getProvider();
$oauth->registerHandler($provider)
->registerAccessTokenHandler($provider);
- $provider->checkOAuthRequest($urlGen->fullPath());
+ $provider->checkOAuthRequest(
+ $urlGen->getAbsoluteURL(
+ $urlGen->linkToRoute($route)
+ )
+ );
$authenticated = true;
- $token = $this->deps->tokens->load('access', $provider->token);
+ $token = $deps->tokens->load('access', $provider->token);
$username = $token->user;
- } catch (OAuth_Exception $e) {
- $this->deps->renderer->errorOut($e->getMessage());
+ } catch (OAuthException $e) {
+ return new ErrorResponse($e->getMessage());
} catch (\OAuthException $e) {
if ($e->getCode() != OAUTH_PARAMETER_ABSENT) {
$oauth->error($e);
}
+ if ($this->user !== null) {
+ $username = $this->user->getUID();
+ $authenticated = true;
+ }
}
$data = array(
- 'oauth_request_token_url' => $urlGen->oauthRequestToken(),
- 'oauth_authorize_url' => $urlGen->oauthAuthorize(),
- 'oauth_access_token_url' => $urlGen->oauthAccessToken(),
+ 'oauth_request_token_url' => $urlGen->getAbsoluteURL(
+ $urlGen->linkToRoute('grauphel.oauth.requestToken')
+ ),
+ 'oauth_authorize_url' => $urlGen->getAbsoluteURL(
+ $urlGen->linkToRoute('grauphel.oauth.authorize')
+ ),
+ 'oauth_access_token_url' => $urlGen->getAbsoluteURL(
+ $urlGen->linkToRoute('grauphel.oauth.accessToken')
+ ),
'api-version' => '1.0',
);
+ $cl = new Client();
+ $client = $cl->getClient();
+ if ($client !== false) {
+ $data['oauth_authorize_url'] .= '?client=' . urlencode($client);
+ }
+
if ($authenticated) {
$data['user-ref'] = array(
- 'api-ref' => $urlGen->user($username),
- 'href' => $urlGen->userHtml($username),
+ 'api-ref' => $urlGen->getAbsoluteURL(
+ $urlGen->linkToRoute(
+ 'grauphel.api.user', array('username' => $username)
+ )
+ ),
+ 'href' => null,
);
}
- $this->deps->renderer->sendJson($data);
+ return new JSONResponse($data);
}
/**
- * GET /api/1.0/$user/notes/$noteguid
+ * /api/1.0/
+ *
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ * @PublicPage
*/
- public function note()
+ public function indexSlash()
{
- $username = $this->deps->urlGen->loadUsername();
- $guid = $this->deps->urlGen->loadGuid();
- $oauth = new OAuth();
- $oauth->setDeps($this->deps);
- $oauth->verifyOAuthUser($username, $this->deps->urlGen->note($username, $guid));
+ return $this->index('grauphel.api.indexSlash');
+ }
- $note = $this->deps->notes->load($username, $guid, false);
- if ($note === null) {
- header('HTTP/1.0 404 Not Found');
- header('Content-type: text/plain');
- echo "Note does not exist\n";
- exit(1);
- }
+ /**
+ * GET /api/1.0/$user
+ *
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ * @PublicPage
+ */
+ public function user($username)
+ {
+ $this->verifyUser(
+ $username,
+ $this->deps->urlGen->getAbsoluteURL(
+ $this->deps->urlGen->linkToRoute(
+ 'grauphel.api.user', array('username' => $username)
+ )
+ )
+ );
+ $syncdata = $this->notes->loadSyncData();
- $data = array('note' => array($note));
- $this->deps->renderer->sendJson($data);
+ $data = array(
+ 'user-name' => $username,
+ 'first-name' => null,
+ 'last-name' => null,
+ 'notes-ref' => array(
+ 'api-ref' => $this->deps->urlGen->getAbsoluteURL(
+ $this->deps->urlGen->linkToRoute(
+ 'grauphel.api.notes', array('username' => $username)
+ )
+ ),
+ 'href' => $this->deps->urlGen->getAbsoluteURL(
+ $this->deps->urlGen->linkToRoute('grauphel.gui.index')
+ ),
+ ),
+ 'latest-sync-revision' => $syncdata->latestSyncRevision,
+ 'current-sync-guid' => $syncdata->currentSyncGuid,
+ );
+ return new JSONResponse($data);
}
/**
- * GET|PUT /api/1.0/$user/notes
+ * GET /api/1.0/$user/notes
+ *
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ * @PublicPage
*/
- public function notes()
+ public function notes($username)
{
- $username = $this->deps->urlGen->loadUsername();
- $oauth = new OAuth();
- $oauth->setDeps($this->deps);
- $oauth->verifyOAuthUser($username, $this->deps->urlGen->notes($username));
+ $this->verifyUser(
+ $username,
+ $this->deps->urlGen->getAbsoluteURL(
+ $this->deps->urlGen->linkToRoute(
+ 'grauphel.api.notes', array('username' => $username)
+ )
+ )
+ );
+ $syncdata = $this->notes->loadSyncData();
+ return $this->fetchNotes($syncdata);
+ }
- $syncdata = $this->deps->notes->loadSyncData($username);
+ /**
+ * PUT /api/1.0/$user/notes
+ *
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ * @PublicPage
+ */
+ public function notesSave($username)
+ {
+ $this->verifyUser(
+ $username,
+ $this->deps->urlGen->getAbsoluteURL(
+ $this->deps->urlGen->linkToRoute(
+ 'grauphel.api.notesSave', array('username' => $username)
+ )
+ )
+ );
+ $syncdata = $this->notes->loadSyncData();
- $this->handleNoteSave($username, $syncdata);
+ $res = $this->handleNoteSave($username, $syncdata);
+ if ($res instanceof \OCP\AppFramework\Http\Response) {
+ return $res;
+ }
+
+ return $this->fetchNotes($syncdata);
+ }
+ protected function fetchNotes($syncdata)
+ {
$since = null;
if (isset($_GET['since'])) {
$since = (int) $_GET['since'];
}
if (isset($_GET['include_notes']) && $_GET['include_notes']) {
- $notes = $this->deps->notes->loadNotesFull($username, $since);
+ $notes = $this->notes->loadNotesFull($since);
} else {
- $notes = $this->deps->notes->loadNotesOverview($username, $since);
+ $notes = $this->notes->loadNotesOverview($since);
}
//work around bug https://bugzilla.gnome.org/show_bug.cgi?id=734313
'latest-sync-revision' => $syncdata->latestSyncRevision,
'notes' => $notes,
);
- $this->deps->renderer->sendJson($data);
+ return new JSONResponse($data);
}
protected function handleNoteSave($username, $syncdata)
return;
}
- $data = file_get_contents('php://input');
- $putObj = json_decode($data);
- if ($putObj === NULL) {
- errorOut('Invalid JSON data in PUT request');
- }
+ //Note that we have more data in $arPut than just our JSON.
+ // The request object merges it with other data.
+ $arPut = $this->request->put;
//structural validation
- if (!isset($putObj->{'latest-sync-revision'})) {
- errorOut('Missing "latest-sync-revision"');
+ if (!isset($arPut['latest-sync-revision'])) {
+ return new ErrorResponse('Missing "latest-sync-revision"');
}
- if (!isset($putObj->{'note-changes'})) {
- errorOut('Missing "note-changes"');
+ if (!isset($arPut['note-changes'])) {
+ return new ErrorResponse('Missing "note-changes"');
}
- foreach ($putObj->{'note-changes'} as $note) {
+ foreach ($arPut['note-changes'] as $note) {
+ //owncloud converts object to array, so we reverse
+ $note = (object) $note;
if (!isset($note->guid) || $note->guid == '') {
- errorOut('Missing "guid" on note');
+ return new ErrorResponse('Missing "guid" on note');
}
}
//content validation
- if ($putObj->{'latest-sync-revision'} != $syncdata->latestSyncRevision +1
+ if ($arPut['latest-sync-revision'] != $syncdata->latestSyncRevision +1
&& $syncdata->latestSyncRevision != -1
) {
- errorOut('Wrong "latest-sync-revision". You are not up to date.');
+ return new ErrorResponse(
+ 'Wrong "latest-sync-revision". You are not up to date.'
+ );
}
//update
- ++$syncdata->latestSyncRevision;
- foreach ($putObj->{'note-changes'} as $noteUpdate) {
- $note = $this->deps->notes->load($username, $noteUpdate->guid);
- if (isset($noteUpdate->command) && $noteUpdate->command == 'delete') {
- $this->deps->notes->delete($username, $noteUpdate->guid);
- } else {
- $this->deps->notes->update(
- $note, $noteUpdate, $syncdata->latestSyncRevision
- );
- $this->deps->notes->save($username, $note);
+ $db = \OC::$server->getDatabaseConnection();
+ $db->beginTransaction();
+ try {
+ ++$syncdata->latestSyncRevision;
+ foreach ($arPut['note-changes'] as $noteUpdate) {
+ //owncloud converts object to array, so we reverse
+ $noteUpdate = (object) $noteUpdate;
+
+ $note = $this->notes->load($noteUpdate->guid);
+ if (isset($noteUpdate->command) && $noteUpdate->command == 'delete') {
+ $this->notes->delete($noteUpdate->guid);
+ } else {
+ $this->notes->update(
+ $note, $noteUpdate, $syncdata->latestSyncRevision
+ );
+ $this->notes->save($note);
+ }
}
+
+ $this->notes->saveSyncData($syncdata);
+ $db->commit();
+ } catch (\DatabaseException $e) {
+ $db->rollBack();
+ throw $e;
}
+ }
- $this->deps->notes->saveSyncData($username, $syncdata);
+ /**
+ * GET /api/1.0/$user/notes/$noteguid
+ *
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ * @PublicPage
+ */
+ public function note($username, $guid)
+ {
+ $this->verifyUser(
+ $username,
+ $this->deps->urlGen->getAbsoluteURL(
+ $this->deps->urlGen->linkToRoute(
+ 'grauphel.api.note',
+ array('username' => $username, 'guid' => $guid)
+ )
+ )
+ );
+
+ $note = $this->notes->load($guid, false);
+ if ($note === null) {
+ header('HTTP/1.0 404 Not Found');
+ header('Content-type: text/plain');
+ echo "Note does not exist\n";
+ exit(1);
+ }
+
+ return new JSONResponse($note);
}
/**
- * GET /api/1.0/$user
+ * Checks if the given user is authorized (by oauth token or normal login)
+ *
+ * @param string $username Username to verify
+ *
+ * @return boolean True if all is fine, Response in case of an error
*/
- public function user()
+ protected function verifyUser($username, $curUrl)
{
- $username = $this->deps->urlGen->loadUsername();
+ if ($this->user !== null && $this->user->getUid() == $username) {
+ $this->notes->setUsername($username);
+ return true;
+ }
$oauth = new OAuth();
$oauth->setDeps($this->deps);
- $oauth->verifyOAuthUser($username, $this->deps->urlGen->user($username));
+ $oauth->verifyOAuthUser($username, $curUrl);
- $syncdata = $this->deps->notes->loadSyncData($username);
-
- $data = array(
- 'user-name' => $username,
- 'first-name' => null,
- 'last-name' => null,
- 'notes-ref' => array(
- 'api-ref' => $this->deps->urlGen->notes($username),
- 'href' => null,
- ),
- 'latest-sync-revision' => $syncdata->latestSyncRevision,
- 'current-sync-guid' => $syncdata->currentSyncGuid,
- );
- $this->deps->renderer->sendJson($data);
+ $this->notes->setUsername($username);
+ return true;
}
}
?>