]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/EmailRegistration/emailregister.php
1b0902587f78be6507149449ff684b53b4f5ccb6
[quix0rs-gnu-social.git] / plugins / EmailRegistration / emailregister.php
1 <?php
2 /**
3  * StatusNet - the distributed open-source microblogging tool
4  * Copyright (C) 2011, StatusNet, Inc.
5  *
6  * Register a user by their email address
7  *
8  * PHP version 5
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU Affero General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Affero General Public License for more details.
19  *
20  * You should have received a copy of the GNU Affero General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  * @category  Email registration
24  * @package   StatusNet
25  * @author    Evan Prodromou <evan@status.net>
26  * @copyright 2011 StatusNet, Inc.
27  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
28  * @link      http://status.net/
29  */
30
31 if (!defined('STATUSNET')) {
32     // This check helps protect against security problems;
33     // your code file can't be executed directly from the web.
34     exit(1);
35 }
36
37 /**
38  * Email registration
39  *
40  * There are four cases where we're called:
41  *
42  * 1. GET, no arguments. Initial registration; ask for an email address.
43  * 2. POST, email address argument. Initial registration; send an email to confirm.
44  * 3. GET, code argument. Confirming an invitation or a registration; look them up,
45  *    create the relevant user if possible, login as that user, and
46  *    show a password-entry form.
47  * 4. POST, password argument. After confirmation, set the password for the new
48  *    user, and redirect to a registration complete action with some instructions.
49  *
50  * @category  Action
51  * @package   StatusNet
52  * @author    Evan Prodromou <evan@status.net>
53  * @copyright 2011 StatusNet, Inc.
54  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
55  * @link      http://status.net/
56  */
57 class EmailregisterAction extends Action
58 {
59     const NEWEMAIL = 1;
60     const SETPASSWORD = 2;
61     const NEWREGISTER = 3;
62     const CONFIRMINVITE = 4;
63     const CONFIRMREGISTER = 5;
64
65     const CONFIRMTYPE = 'register';
66
67     protected $user;
68     protected $email;
69     protected $code;
70     protected $invitation;
71     protected $confirmation;
72     protected $password1;
73     protected $password2;
74     protected $state;
75     protected $error;
76     protected $complete;
77
78     function prepare($argarray)
79     {
80         parent::prepare($argarray);
81
82         if (common_config('site', 'closed')) {
83             throw new ClientException(_('Registration not allowed.'), 403);
84         }
85
86         if ($this->isPost()) {
87
88             $this->checkSessionToken();
89
90             $this->email = $this->trimmed('email');
91
92             if (!empty($this->email)) {
93                 if (common_config('site', 'inviteonly')) {
94                     throw new ClientException(_('Sorry, only invited people can register.'), 403);
95                 }
96                 $this->email = common_canonical_email($this->email);
97                 $this->state = self::NEWEMAIL;
98             } else {
99                 $this->state = self::SETPASSWORD;
100
101                 $this->code = $this->trimmed('code');
102
103                 if (empty($this->code)) {
104                     // TRANS: Client exception thrown when no confirmation code was provided.
105                     throw new ClientException(_m('No confirmation code.'));
106                 }
107
108                 $this->invitation = Invitation::staticGet('code', $this->code);
109
110                 if (!empty($this->invitation)) {
111                     if (!empty($this->invitation->registered_user_id)) {
112                         throw new ClientException(_m('Invitation already used.'), 403);
113                     }
114                 } else {
115
116                     $this->confirmation = Confirm_address::staticGet('code', $this->code);
117
118                     if (empty($this->confirmation)) {
119                         // TRANS: Client exception thrown when given confirmation code was not issued.
120                         throw new ClientException(_m('No such confirmation code.'), 403);
121                     }
122                 }
123
124                 $this->password1 = $this->trimmed('password1');
125                 $this->password2 = $this->trimmed('password2');
126
127                 $this->tos = $this->boolean('tos');
128             }
129         } else { // GET
130             $this->code = $this->trimmed('code');
131
132             if (empty($this->code)) {
133                 if (common_config('site', 'inviteonly')) {
134                     throw new ClientException(_('Sorry, only invited people can register.'), 403);
135                 }
136                 $this->state = self::NEWREGISTER;
137             } else {
138                 $this->invitation = Invitation::staticGet('code', $this->code);
139                 if (!empty($this->invitation)) {
140                     if (!empty($this->invitation->registered_user_id)) {
141                         throw new ClientException(_m('Invitation already used.'), 403);
142                     }
143                     $this->state = self::CONFIRMINVITE;
144                 } else {
145                     $this->state = self::CONFIRMREGISTER;
146                     $this->confirmation = Confirm_address::staticGet('code', $this->code);
147
148                     if (empty($this->confirmation)) {
149                         // TRANS: Client exception thrown when given confirmation code was not issued.
150                         throw new ClientException(_m('No such confirmation code.'), 405);
151                     }
152                 }
153             }
154         }
155
156         return true;
157     }
158
159     function title()
160     {
161         switch ($this->state) {
162         case self::NEWREGISTER:
163         case self::NEWEMAIL:
164             // TRANS: Title for registration page.
165             return _m('TITLE','Register');
166             break;
167         case self::SETPASSWORD:
168         case self::CONFIRMINVITE:
169         case self::CONFIRMREGISTER:
170             // TRANS: Title for page where to register with a confirmation code.
171             return _m('TITLE','Complete registration');
172             break;
173         }
174     }
175
176     /**
177      * Handler method
178      *
179      * @param array $argarray is ignored since it's now passed in in prepare()
180      *
181      * @return void
182      */
183
184     function handle($argarray=null)
185     {
186         $cur = common_current_user();
187
188         if (!empty($cur)) {
189             common_redirect(common_local_url('all', array('nickname' => $cur->nickname)));
190             return;
191         }
192
193         switch ($this->state) {
194         case self::NEWREGISTER:
195             $this->showRegistrationForm();
196             break;
197         case self::NEWEMAIL:
198             $this->registerUser();
199             break;
200         case self::CONFIRMINVITE:
201             $this->confirmRegistration();
202             break;
203         case self::CONFIRMREGISTER:
204             $this->confirmRegistration();
205             break;
206         case self::SETPASSWORD:
207             $this->setPassword();
208             break;
209         }
210         return;
211     }
212
213     function showRegistrationForm()
214     {
215         $this->form = new EmailRegistrationForm($this, $this->email);
216         $this->showPage();
217     }
218
219     function registerUser()
220     {
221         try {
222             $confirm = EmailRegistrationPlugin::registerEmail($this->email);
223         } catch (ClientException $ce) {
224             $this->error = $ce->getMessage();
225             $this->showRegistrationForm();
226             return;
227         }
228
229         EmailRegistrationPlugin::sendConfirmEmail($confirm);
230
231         // TRANS: Confirmation text after initial registration.
232         // TRANS: %s an e-mail address.
233         $prompt = sprintf(_m('An email was sent to %s to confirm that address. Check your email inbox for instructions.'),
234                           $this->email);
235
236         $this->complete = $prompt;
237
238         $this->showPage();
239     }
240
241     function confirmRegistration()
242     {
243         if (!empty($this->invitation)) {
244             $email = $this->invitation->address;
245         } else if (!empty($this->confirmation)) {
246             $email = $this->confirmation->address;
247         }
248
249         $nickname = $this->nicknameFromEmail($email);
250
251         $this->form = new ConfirmRegistrationForm($this,
252                                                   $nickname,
253                                                   $email,
254                                                   $this->code);
255         $this->showPage();
256     }
257
258     function setPassword()
259     {
260         if (Event::handle('StartRegistrationTry', array($this))) {
261             if (!empty($this->invitation)) {
262                 $email = trim($this->invitation->address);
263             } else if (!empty($this->confirmation)) {
264                 $email = trim($this->confirmation->address);
265             } else {
266                 throw new Exception('No confirmation thing.');
267             }
268
269             if (!$this->tos) {
270                 // TRANS: Error text when trying to register without agreeing to the terms.
271                 $this->error = _m('You must accept the terms of service and privacy policy to register.');
272             } else if (empty($this->password1)) {
273                 // TRANS: Error text when trying to register without a password.
274                 $this->error = _m('You must set a password');
275             } else if (strlen($this->password1) < 6) {
276                 // TRANS: Error text when trying to register with too short a password.
277                 $this->error = _m('Password must be 6 or more characters.');
278             } else if ($this->password1 != $this->password2) {
279                 // TRANS: Error text when trying to register without providing the same password twice.
280                 $this->error = _m('Passwords do not match.');
281             }
282
283             if (!empty($this->error)) {
284                 $nickname = $this->nicknameFromEmail($email);
285                 $this->form = new ConfirmRegistrationForm($this, $nickname, $email, $this->code);
286                 $this->showPage();
287                 return;
288             }
289
290             $nickname = $this->nicknameFromEmail($email);
291
292             try {
293                 $fields = array('nickname' => $nickname,
294                                 'email' => $email,
295                                 'password' => $this->password1,
296                                 'email_confirmed' => true);
297
298                 if (!empty($this->invitation)) {
299                     $fields['code'] = $this->invitation->code;
300                 }
301                 $this->user = User::register($fields);
302             } catch (ClientException $e) {
303                 $this->error = $e->getMessage();
304                 $nickname = $this->nicknameFromEmail($email);
305                 $this->form = new ConfirmRegistrationForm($this, $nickname, $email, $this->code);
306                 $this->showPage();
307                 return;
308             }
309
310             if (empty($this->user)) {
311                 throw new Exception('Failed to register user.');
312             }
313
314             common_set_user($this->user);
315             // this is a real login
316             common_real_login(true);
317
318             // Re-init language env in case it changed (not yet, but soon)
319             common_init_language();
320
321             if (!empty($this->confirmation)) {
322                 $this->confirmation->delete();
323             }
324
325             Event::handle('EndRegistrationTry', array($this));
326         }
327
328         if (Event::handle('StartRegisterSuccess', array($this))) {
329             common_redirect(common_local_url('doc', array('title' => 'welcome')),
330                             303);
331             Event::handle('EndRegisterSuccess', array($this));
332         }
333     }
334
335     function sendConfirmEmail($confirm)
336     {
337         $sitename = common_config('site', 'name');
338
339         $recipients = array($confirm->address);
340
341         $headers['From'] = mail_notify_from();
342         $headers['To'] = trim($confirm->address);
343          // TRANS: Subject for confirmation e-mail.
344          // TRANS: %s is the StatusNet sitename.
345         $headers['Subject'] = sprintf(_m('Confirm your registration on %s'), $sitename);
346
347         $confirmUrl = common_local_url('register', array('code' => $confirm->code));
348
349          // TRANS: Body for confirmation e-mail.
350          // TRANS: %1$s is the StatusNet sitename, %2$s is the confirmation URL.
351         $body = sprintf(_m('Someone (probably you) has requested an account on %1$s using this email address.'.
352                           "\n".
353                           'To confirm the address, click the following URL or copy it into the address bar of your browser.'.
354                           "\n".
355                           '%2$s'.
356                           "\n".
357                           'If it was not you, you can safely ignore this message.'),
358                         $sitename,
359                         $confirmUrl);
360
361         mail_send($recipients, $headers, $body);
362     }
363
364     function showContent()
365     {
366         if ($this->complete) {
367             $this->elementStart('p', 'success');
368             $this->raw($this->complete);
369             $this->elementEnd('p');
370         } else {
371             if ($this->error) {
372                 $this->elementStart('p', 'error');
373                 $this->raw($this->error);
374                 $this->elementEnd('p');
375             }
376
377             if (!empty($this->form)) {
378                 $this->form->show();
379             }
380         }
381     }
382
383     /**
384      * Return true if read only.
385      *
386      * MAY override
387      *
388      * @param array $args other arguments
389      *
390      * @return boolean is read only action?
391      */
392     function isReadOnly($args)
393     {
394         return false;
395     }
396
397     function nicknameFromEmail($email)
398     {
399         return EmailRegistrationPlugin::nicknameFromEmail($email);
400     }
401
402     /**
403      * A local menu
404      *
405      * Shows different login/register actions.
406      *
407      * @return void
408      */
409     function showLocalNav()
410     {
411         $nav = new LoginGroupNav($this);
412         $nav->show();
413     }
414 }