oauth dance works
[grauphel.git] / controller / apicontroller.php
1 <?php
2 /**
3  * Part of grauphel
4  *
5  * PHP version 5
6  *
7  * @category  Tools
8  * @package   Grauphel
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
13  */
14 namespace OCA\Grauphel\Controller;
15
16 use \OCP\AppFramework\Controller;
17 use \OCP\AppFramework\Http\JSONResponse;
18
19 use \OCA\Grauphel\Lib\OAuth;
20 use \OCA\Grauphel\Lib\Dependencies;
21
22 /**
23  * Tomboy's REST API
24  *
25  * @category  Tools
26  * @package   Grauphel
27  * @author    Christian Weiske <cweiske@cweiske.de>
28  * @copyright 2014 Christian Weiske
29  * @license   http://www.gnu.org/licenses/agpl.html GNU AGPL v3
30  * @version   Release: @package_version@
31  * @link      http://cweiske.de/grauphel.htm
32  */
33 class ApiController extends Controller
34 {
35     /**
36      * /api/1.0
37      *
38      * @NoAdminRequired
39      * @NoCSRFRequired
40      * @PublicPage
41      */
42     public function index()
43     {
44         $deps = Dependencies::get();
45         $authenticated = false;
46         $oauth = new OAuth();
47         $oauth->setDeps($deps);
48         $urlGen = $deps->urlGen;
49
50         try {
51             $provider = new \OAuthProvider();
52             $oauth->registerHandler($provider)
53                 ->registerAccessTokenHandler($provider);
54             $provider->checkOAuthRequest(
55                 $urlGen->getAbsoluteURL(
56                     $urlGen->linkToRoute('grauphel.api.index')
57                 )
58             );
59             $authenticated = true;
60             $token = $deps->tokens->load('access', $provider->token);
61             $username = $token->user;
62
63         } catch (\OAuth_Exception $e) {
64             $deps->renderer->errorOut($e->getMessage());
65         } catch (\OAuthException $e) {
66             if ($e->getCode() != OAUTH_PARAMETER_ABSENT) {
67                 $oauth->error($e);
68             }
69         }
70
71         $data = array(
72             'oauth_request_token_url' => $urlGen->getAbsoluteURL(
73                 $urlGen->linkToRoute('grauphel.oauth.requestToken')
74             ),
75             'oauth_authorize_url'     => $urlGen->getAbsoluteURL(
76                 $urlGen->linkToRoute('grauphel.oauth.authorize')
77             ),
78             'oauth_access_token_url'  => $urlGen->getAbsoluteURL(
79                 $urlGen->linkToRoute('grauphel.oauth.accessToken')
80             ),
81             'api-version' => '1.0',
82         );
83
84         if ($authenticated) {
85             $data['user-ref'] = array(
86                 'api-ref' => $urlGen->getAbsoluteURL(
87                     $urlGen->linkToRoute(
88                         'grauphel.api.user', array('user' => $username)
89                     )
90                 ),
91                 'href' => null,//FIXME
92             );
93         }
94
95         return new JSONResponse($data);
96         $deps->renderer->sendJson($data);
97     }
98
99     /**
100      * GET /api/1.0/$user/notes/$noteguid
101      *
102      * @NoAdminRequired
103      * @NoCSRFRequired
104      * @PublicPage
105      */
106     public function note()
107     {
108         $deps = Dependencies::get();
109         $username = $deps->urlGen->loadUsername();
110         $guid     = $deps->urlGen->loadGuid();
111         $oauth = new \OAuth();
112         $oauth->setDeps($deps);
113         $oauth->verifyOAuthUser($username, $deps->urlGen->note($username, $guid));
114
115         $note = $deps->notes->load($username, $guid, false);
116         if ($note === null) {
117             header('HTTP/1.0 404 Not Found');
118             header('Content-type: text/plain');
119             echo "Note does not exist\n";
120             exit(1);
121         }
122
123         $data = array('note' => array($note));
124         $deps->renderer->sendJson($data);
125     }
126
127     /**
128      * GET|PUT /api/1.0/$user/notes
129      *
130      * @NoAdminRequired
131      * @NoCSRFRequired
132      * @PublicPage
133      */
134     public function notes()
135     {
136         $deps = Dependencies::get();
137         $username = $deps->urlGen->loadUsername();
138         $oauth = new \OAuth();
139         $oauth->setDeps($deps);
140         $oauth->verifyOAuthUser($username, $deps->urlGen->notes($username));
141
142         $syncdata = $deps->notes->loadSyncData($username);
143
144         $this->handleNoteSave($username, $syncdata);
145
146         $since = null;
147         if (isset($_GET['since'])) {
148             $since = (int) $_GET['since'];
149         }
150
151         if (isset($_GET['include_notes']) && $_GET['include_notes']) {
152             $notes = $deps->notes->loadNotesFull($username, $since);
153         } else {
154             $notes = $deps->notes->loadNotesOverview($username, $since);
155         }
156
157         //work around bug https://bugzilla.gnome.org/show_bug.cgi?id=734313
158         foreach ($notes as $note) {
159             if (isset($note->{'note-content-version'})) {
160                 $note->{'note-content-version'} = 0.3;
161             }
162         }
163
164         $data = array(
165             'latest-sync-revision' => $syncdata->latestSyncRevision,
166             'notes' => $notes,
167         );
168         $deps->renderer->sendJson($data);
169     }
170
171     protected function handleNoteSave($username, $syncdata)
172     {
173         if ($_SERVER['REQUEST_METHOD'] != 'PUT') {
174             return;
175         }
176
177         $data = file_get_contents('php://input');
178         $putObj = json_decode($data);
179         if ($putObj === NULL) {
180             errorOut('Invalid JSON data in PUT request');
181         }
182
183         //structural validation
184         if (!isset($putObj->{'latest-sync-revision'})) {
185             errorOut('Missing "latest-sync-revision"');
186         }
187         if (!isset($putObj->{'note-changes'})) {
188             errorOut('Missing "note-changes"');
189         }
190         foreach ($putObj->{'note-changes'} as $note) {
191             if (!isset($note->guid) || $note->guid == '') {
192                 errorOut('Missing "guid" on note');
193             }
194         }
195
196         //content validation
197         if ($putObj->{'latest-sync-revision'} != $syncdata->latestSyncRevision +1
198             && $syncdata->latestSyncRevision != -1
199         ) {
200             errorOut('Wrong "latest-sync-revision". You are not up to date.');
201         }
202
203         //update
204         $deps = Dependencies::get();
205         ++$syncdata->latestSyncRevision;
206         foreach ($putObj->{'note-changes'} as $noteUpdate) {
207             $note = $deps->notes->load($username, $noteUpdate->guid);
208             if (isset($noteUpdate->command) && $noteUpdate->command == 'delete') {
209                 $deps->notes->delete($username, $noteUpdate->guid);
210             } else {
211                 $deps->notes->update(
212                     $note, $noteUpdate, $syncdata->latestSyncRevision
213                 );
214                 $deps->notes->save($username, $note);
215             }
216         }
217
218         $deps->notes->saveSyncData($username, $syncdata);
219     }
220
221     /**
222      * GET /api/1.0/$user
223      *
224      * @NoAdminRequired
225      * @NoCSRFRequired
226      * @PublicPage
227      */
228     public function user()
229     {
230         $deps = Dependencies::get();
231         $username = $deps->urlGen->loadUsername();
232
233         $oauth = new \OAuth();
234         $oauth->setDeps($deps);
235         $oauth->verifyOAuthUser($username, $deps->urlGen->user($username));
236
237         $syncdata = $deps->notes->loadSyncData($username);
238
239         $data = array(
240             'user-name'  => $username,
241             'first-name' => null,
242             'last-name'  => null,
243             'notes-ref'  => array(
244                 'api-ref' => $deps->urlGen->notes($username),
245                 'href'    => null,
246             ),
247             'latest-sync-revision' => $syncdata->latestSyncRevision,
248             'current-sync-guid'    => $syncdata->currentSyncGuid,
249         );
250         $deps->renderer->sendJson($data);
251     }
252 }
253 ?>