9 * @author Christian Weiske <cweiske@cweiske.de>
10 * @copyright 2014 Christian Weiske
11 * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3
12 * @link http://cweiske.de/grauphel.htm
14 namespace OCA\Grauphel\Controller;
16 use \OCP\AppFramework\Controller;
17 use \OCP\AppFramework\Http\JSONResponse;
19 use \OCA\Grauphel\Lib\Client;
20 use \OCA\Grauphel\Lib\NoteStorage;
21 use \OCA\Grauphel\Lib\OAuth;
22 use \OCA\Grauphel\Lib\OAuthException;
23 use \OCA\Grauphel\Lib\Dependencies;
24 use \OCA\Grauphel\Lib\Response\ErrorResponse;
31 * @author Christian Weiske <cweiske@cweiske.de>
32 * @copyright 2014 Christian Weiske
33 * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3
34 * @version Release: @package_version@
35 * @link http://cweiske.de/grauphel.htm
37 class ApiController extends Controller
40 * constructor of the controller
42 * @param string $appName Name of the app
43 * @param IRequest $request Instance of the request
45 public function __construct($appName, \OCP\IRequest $request, $user)
47 parent::__construct($appName, $request);
49 $this->deps = Dependencies::get();
50 $this->notes = new NoteStorage($this->deps->urlGen);
52 //default http header: we assume something is broken
53 header('HTTP/1.0 500 Internal Server Error');
63 public function index($route = 'grauphel.api.index')
65 $deps = Dependencies::get();
66 $authenticated = false;
68 $oauth->setDeps($deps);
69 $urlGen = $deps->urlGen;
72 $provider = OAuth::getProvider();
73 $oauth->registerHandler($provider)
74 ->registerAccessTokenHandler($provider);
75 $provider->checkOAuthRequest(
76 $urlGen->getAbsoluteURL(
77 $urlGen->linkToRoute($route)
80 $authenticated = true;
81 $token = $deps->tokens->load('access', $provider->token);
82 $username = $token->user;
84 } catch (OAuthException $e) {
85 return new ErrorResponse($e->getMessage());
86 } catch (\OAuthException $e) {
87 if ($e->getCode() != OAUTH_PARAMETER_ABSENT) {
90 if ($this->user !== null) {
91 $username = $this->user->getUID();
92 $authenticated = true;
97 'oauth_request_token_url' => $urlGen->getAbsoluteURL(
98 $urlGen->linkToRoute('grauphel.oauth.requestToken')
100 'oauth_authorize_url' => $urlGen->getAbsoluteURL(
101 $urlGen->linkToRoute('grauphel.oauth.authorize')
103 'oauth_access_token_url' => $urlGen->getAbsoluteURL(
104 $urlGen->linkToRoute('grauphel.oauth.accessToken')
106 'api-version' => '1.0',
110 $client = $cl->getClient();
111 if ($client !== false) {
112 $data['oauth_authorize_url'] .= '?client=' . urlencode($client);
115 if ($authenticated) {
116 $data['user-ref'] = array(
117 'api-ref' => $urlGen->getAbsoluteURL(
118 $urlGen->linkToRoute(
119 'grauphel.api.user', array('username' => $username)
126 return new JSONResponse($data);
136 public function indexSlash()
138 return $this->index('grauphel.api.indexSlash');
148 public function user($username)
152 $this->deps->urlGen->getAbsoluteURL(
153 $this->deps->urlGen->linkToRoute(
154 'grauphel.api.user', array('username' => $username)
158 $syncdata = $this->notes->loadSyncData();
161 'user-name' => $username,
162 'first-name' => null,
164 'notes-ref' => array(
165 'api-ref' => $this->deps->urlGen->getAbsoluteURL(
166 $this->deps->urlGen->linkToRoute(
167 'grauphel.api.notes', array('username' => $username)
170 'href' => $this->deps->urlGen->getAbsoluteURL(
171 $this->deps->urlGen->linkToRoute('grauphel.gui.index')
174 'latest-sync-revision' => $syncdata->latestSyncRevision,
175 'current-sync-guid' => $syncdata->currentSyncGuid,
177 return new JSONResponse($data);
181 * GET /api/1.0/$user/notes
187 public function notes($username)
191 $this->deps->urlGen->getAbsoluteURL(
192 $this->deps->urlGen->linkToRoute(
193 'grauphel.api.notes', array('username' => $username)
197 $syncdata = $this->notes->loadSyncData();
198 return $this->fetchNotes($syncdata);
202 * PUT /api/1.0/$user/notes
208 public function notesSave($username)
212 $this->deps->urlGen->getAbsoluteURL(
213 $this->deps->urlGen->linkToRoute(
214 'grauphel.api.notesSave', array('username' => $username)
218 $syncdata = $this->notes->loadSyncData();
220 $res = $this->handleNoteSave($username, $syncdata);
221 if ($res instanceof \OCP\AppFramework\Http\Response) {
225 return $this->fetchNotes($syncdata);
228 protected function fetchNotes($syncdata)
231 if (isset($_GET['since'])) {
232 $since = (int) $_GET['since'];
235 if (isset($_GET['include_notes']) && $_GET['include_notes']) {
236 $notes = $this->notes->loadNotesFull($since);
238 $notes = $this->notes->loadNotesOverview($since);
241 //work around bug https://bugzilla.gnome.org/show_bug.cgi?id=734313
242 foreach ($notes as $note) {
243 if (isset($note->{'note-content-version'})) {
244 $note->{'note-content-version'} = 0.3;
249 'latest-sync-revision' => $syncdata->latestSyncRevision,
252 return new JSONResponse($data);
255 protected function handleNoteSave($username, $syncdata)
257 if ($_SERVER['REQUEST_METHOD'] != 'PUT') {
261 //Note that we have more data in $arPut than just our JSON.
262 // The request object merges it with other data.
263 $arPut = $this->request->put;
265 //structural validation
266 if (!isset($arPut['latest-sync-revision'])) {
267 return new ErrorResponse('Missing "latest-sync-revision"');
269 if (!isset($arPut['note-changes'])) {
270 return new ErrorResponse('Missing "note-changes"');
272 foreach ($arPut['note-changes'] as $note) {
273 //owncloud converts object to array, so we reverse
274 $note = (object) $note;
275 if (!isset($note->guid) || $note->guid == '') {
276 return new ErrorResponse('Missing "guid" on note');
281 if ($arPut['latest-sync-revision'] != $syncdata->latestSyncRevision +1
282 && $syncdata->latestSyncRevision != -1
284 return new ErrorResponse(
285 'Wrong "latest-sync-revision". You are not up to date.'
290 $db = \OC::$server->getDatabaseConnection();
291 $db->beginTransaction();
293 ++$syncdata->latestSyncRevision;
294 foreach ($arPut['note-changes'] as $noteUpdate) {
295 //owncloud converts object to array, so we reverse
296 $noteUpdate = (object) $noteUpdate;
298 $note = $this->notes->load($noteUpdate->guid);
299 if (isset($noteUpdate->command) && $noteUpdate->command == 'delete') {
300 $this->notes->delete($noteUpdate->guid);
302 $this->notes->update(
303 $note, $noteUpdate, $syncdata->latestSyncRevision
305 $this->notes->save($note);
309 $this->notes->saveSyncData($syncdata);
311 } catch (\DatabaseException $e) {
318 * GET /api/1.0/$user/notes/$noteguid
324 public function note($username, $guid)
328 $this->deps->urlGen->getAbsoluteURL(
329 $this->deps->urlGen->linkToRoute(
331 array('username' => $username, 'guid' => $guid)
336 $note = $this->notes->load($guid, false);
337 if ($note === null) {
338 header('HTTP/1.0 404 Not Found');
339 header('Content-type: text/plain');
340 echo "Note does not exist\n";
344 return new JSONResponse($note);
348 * Checks if the given user is authorized (by oauth token or normal login)
350 * @param string $username Username to verify
352 * @return boolean True if all is fine, Response in case of an error
354 protected function verifyUser($username, $curUrl)
356 if ($this->user !== null && $this->user->getUid() == $username) {
357 $this->notes->setUsername($username);
361 $oauth = new OAuth();
362 $oauth->setDeps($this->deps);
363 $oauth->verifyOAuthUser($username, $curUrl);
365 $this->notes->setUsername($username);