]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - actions/apioauthauthorize.php
Merge branch 'master' of git@gitorious.org:statusnet/mainline into testing
[quix0rs-gnu-social.git] / actions / apioauthauthorize.php
1 <?php
2 /**
3  * StatusNet, the distributed open-source microblogging tool
4  *
5  * Authorize an OAuth request token
6  *
7  * PHP version 5
8  *
9  * LICENCE: This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU Affero General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU Affero General Public License for more details.
18  *
19  * You should have received a copy of the GNU Affero General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  * @category  API
23  * @package   StatusNet
24  * @author    Zach Copley <zach@status.net>
25  * @copyright 2010 StatusNet, Inc.
26  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
27  * @link      http://status.net/
28  */
29
30 if (!defined('STATUSNET')) {
31     exit(1);
32 }
33
34 require_once INSTALLDIR . '/lib/apioauth.php';
35
36 /**
37  * Authorize an OAuth request token
38  *
39  * @category API
40  * @package  StatusNet
41  * @author   Zach Copley <zach@status.net>
42  * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
43  * @link     http://status.net/
44  */
45
46 class ApiOauthAuthorizeAction extends ApiOauthAction
47 {
48     var $oauth_token;
49     var $callback;
50     var $app;
51     var $nickname;
52     var $password;
53     var $store;
54
55     /**
56      * Is this a read-only action?
57      *
58      * @return boolean false
59      */
60
61     function isReadOnly($args)
62     {
63         return false;
64     }
65
66     function prepare($args)
67     {
68         parent::prepare($args);
69
70         $this->nickname    = $this->trimmed('nickname');
71         $this->password    = $this->arg('password');
72         $this->oauth_token = $this->arg('oauth_token');
73         $this->callback    = $this->arg('oauth_callback');
74         $this->store       = new ApiStatusNetOAuthDataStore();
75         $this->app         = $this->store->getAppByRequestToken($this->oauth_token);
76
77         return true;
78     }
79
80     /**
81      * Handle input, produce output
82      *
83      * Switches on request method; either shows the form or handles its input.
84      *
85      * @param array $args $_REQUEST data
86      *
87      * @return void
88      */
89
90     function handle($args)
91     {
92         parent::handle($args);
93
94         if ($_SERVER['REQUEST_METHOD'] == 'POST') {
95
96             $this->handlePost();
97
98         } else {
99
100             if (empty($this->oauth_token)) {
101                 $this->clientError(_('No oauth_token parameter provided.'));
102                 return;
103             }
104
105             if (empty($this->app)) {
106                 $this->clientError(_('Invalid token.'));
107                 return;
108             }
109
110             $name = $this->app->name;
111
112             $this->showForm();
113         }
114     }
115
116     function handlePost()
117     {
118         // check session token for CSRF protection.
119
120         $token = $this->trimmed('token');
121
122         if (!$token || $token != common_session_token()) {
123             $this->showForm(_('There was a problem with your session token. '.
124                               'Try again, please.'));
125             return;
126         }
127
128         // check creds
129
130         $user = null;
131
132         if (!common_logged_in()) {
133             $user = common_check_user($this->nickname, $this->password);
134             if (empty($user)) {
135                 $this->showForm(_("Invalid nickname / password!"));
136                 return;
137             }
138         } else {
139             $user = common_current_user();
140         }
141
142         if ($this->arg('allow')) {
143
144             // mark the req token as authorized
145
146             $this->store->authorize_token($this->oauth_token);
147
148             // Check to see if there was a previous token associated
149             // with this user/app and kill it. If the user is doing this she
150             // probably doesn't want any old tokens anyway.
151
152             $appUser = Oauth_application_user::getByKeys($user, $this->app);
153
154             if (!empty($appUser)) {
155                 $result = $appUser->delete();
156
157                 if (!$result) {
158                     common_log_db_error($appUser, 'DELETE', __FILE__);
159                     throw new ServerException(_('DB error deleting OAuth app user.'));
160                     return;
161                 }
162             }
163
164             // associated the authorized req token with the user and the app
165
166             $appUser = new Oauth_application_user();
167
168             $appUser->profile_id     = $user->id;
169             $appUser->application_id = $this->app->id;
170
171             // Note: do not copy the access type from the application.
172             // The access type should always be 0 when the OAuth app
173             // user record has a request token associated with it.
174             // Access type gets assigned once an access token has been
175             // granted.  The OAuth app user record then gets updated
176             // with the new access token and access type.
177
178             $appUser->token          = $this->oauth_token;
179             $appUser->created        = common_sql_now();
180
181             $result = $appUser->insert();
182
183             if (!$result) {
184                 common_log_db_error($appUser, 'INSERT', __FILE__);
185                 throw new ServerException(_('DB error inserting OAuth app user.'));
186                 return;
187             }
188
189             // if we have a callback redirect and provide the token
190
191             // A callback specified in the app setup overrides whatever
192             // is passed in with the request.
193
194             if (!empty($this->app->callback_url)) {
195                 $this->callback = $this->app->callback_url;
196             }
197
198             if (!empty($this->callback)) {
199
200                 $target_url = $this->getCallback($this->callback,
201                                                  array('oauth_token' => $this->oauth_token));
202
203                 common_redirect($target_url, 303);
204             } else {
205                 common_debug("callback was empty!");
206             }
207
208             // otherwise inform the user that the rt was authorized
209
210             $this->elementStart('p');
211
212             // XXX: Do OAuth 1.0a verifier code
213
214             $this->raw(sprintf(_("The request token %s has been authorized. " .
215                                  'Please exchange it for an access token.'),
216                                $this->oauth_token));
217
218             $this->elementEnd('p');
219
220         } else if ($this->arg('deny')) {
221
222             $datastore = new ApiStatusNetOAuthDataStore();
223             $datastore->revoke_token($this->oauth_token, 0);
224
225             $this->elementStart('p');
226
227             $this->raw(sprintf(_("The request token %s has been denied and revoked."),
228                                $this->oauth_token));
229
230             $this->elementEnd('p');
231         } else {
232             $this->clientError(_('Unexpected form submission.'));
233             return;
234         }
235     }
236
237     function showForm($error=null)
238     {
239         $this->error = $error;
240         $this->showPage();
241     }
242
243     function showScripts()
244     {
245         parent::showScripts();
246         if (!common_logged_in()) {
247             $this->autofocus('nickname');
248         }
249     }
250
251     /**
252      * Title of the page
253      *
254      * @return string title of the page
255      */
256
257     function title()
258     {
259         return _('An application would like to connect to your account');
260     }
261
262     /**
263      * Shows the authorization form.
264      *
265      * @return void
266      */
267
268     function showContent()
269     {
270         $this->elementStart('form', array('method' => 'post',
271                                           'id' => 'form_apioauthauthorize',
272                                           'class' => 'form_settings',
273                                           'action' => common_local_url('apioauthauthorize')));
274         $this->elementStart('fieldset');
275         $this->element('legend', array('id' => 'apioauthauthorize_allowdeny'),
276                                  _('Allow or deny access'));
277
278         $this->hidden('token', common_session_token());
279         $this->hidden('oauth_token', $this->oauth_token);
280         $this->hidden('oauth_callback', $this->callback);
281
282         $this->elementStart('ul', 'form_data');
283         $this->elementStart('li');
284         $this->elementStart('p');
285         if (!empty($this->app->icon)) {
286             $this->element('img', array('src' => $this->app->icon));
287         }
288
289         $access = ($this->app->access_type & Oauth_application::$writeAccess) ?
290           'access and update' : 'access';
291
292         $msg = _('The application <strong>%1$s</strong> by ' .
293                  '<strong>%2$s</strong> would like the ability ' .
294                  'to <strong>%3$s</strong> your %4$s account data. ' .
295                  'You should only give access to your %4$s account ' .
296                  'to third parties you trust.');
297
298         $this->raw(sprintf($msg,
299                            $this->app->name,
300                            $this->app->organization,
301                            $access,
302                            common_config('site', 'name')));
303         $this->elementEnd('p');
304         $this->elementEnd('li');
305         $this->elementEnd('ul');
306
307         if (!common_logged_in()) {
308
309             $this->elementStart('fieldset');
310             $this->element('legend', null, _('Account'));
311             $this->elementStart('ul', 'form_data');
312             $this->elementStart('li');
313             $this->input('nickname', _('Nickname'));
314             $this->elementEnd('li');
315             $this->elementStart('li');
316             $this->password('password', _('Password'));
317             $this->elementEnd('li');
318             $this->elementEnd('ul');
319
320             $this->elementEnd('fieldset');
321
322         }
323
324         $this->element('input', array('id' => 'deny_submit',
325                                       'class' => 'submit submit form_action-primary',
326                                       'name' => 'deny',
327                                       'type' => 'submit',
328                                       'value' => _('Deny')));
329
330         $this->element('input', array('id' => 'allow_submit',
331                                       'class' => 'submit submit form_action-secondary',
332                                       'name' => 'allow',
333                                       'type' => 'submit',
334                                       'value' => _('Allow')));
335
336         $this->elementEnd('fieldset');
337         $this->elementEnd('form');
338     }
339
340     /**
341      * Instructions for using the form
342      *
343      * For "remembered" logins, we make the user re-login when they
344      * try to change settings. Different instructions for this case.
345      *
346      * @return void
347      */
348
349     function getInstructions()
350     {
351         return _('Allow or deny access to your account information.');
352     }
353
354     /**
355      * A local menu
356      *
357      * Shows different login/register actions.
358      *
359      * @return void
360      */
361
362     function showLocalNav()
363     {
364         // NOP
365     }
366
367     /**
368      * Show site notice.
369      *
370      * @return nothing
371      */
372
373     function showSiteNotice()
374     {
375         // NOP
376     }
377
378     /**
379      * Show notice form.
380      *
381      * Show the form for posting a new notice
382      *
383      * @return nothing
384      */
385
386     function showNoticeForm()
387     {
388         // NOP
389     }
390
391 }