account activation and password recovery implemented
[living-lab-site.git] / application / controllers / user.php
1 <?php
2
3 /**
4  * Class User controls video hierarchy and searching
5  *
6  * @category    Controller
7  * @author              Călin-Andrei Burloiu
8  */
9 class User extends CI_Controller {
10
11         private $import = FALSE;
12         private $activated_account = TRUE;
13         private $user_id = NULL;
14
15         public function __construct()
16         {
17                 parent::__construct();
18
19                 $this->lang->load('user');
20                 $this->load->model('users_model');
21         }
22
23         public function index()
24         {
25         }
26         
27         public function test($user_id = 1)
28         {
29                 echo sha1('hQwCUEPQZcN8c4Es');
30         }
31
32         /**
33         * Login a user and then redirect it to the last page which must be encoded
34         * in $redirect.
35         *
36         * @param string $redirect       contains the last page URI segments encoded
37         * with helper url_encode_segments.
38         */
39         public function login($redirect = '')
40         {
41                 $this->load->library('form_validation');
42                         
43                 $this->form_validation->set_error_delimiters('<span class="error">',
44                         '</span>');
45
46                 if ($this->form_validation->run('login') === FALSE)
47                 {
48                         $params = array(        'title' =>
49                                                                         $this->lang->line('ui_nav_menu_login')
50                                                                                 .' &ndash; '
51                                                                                 . $this->config->item('site_name'),
52                                                                 //'metas' => array('description'=>'')
53                         );
54                         $this->load->library('html_head_params', $params);
55                                 
56                         // **
57                         // ** LOADING VIEWS
58                         // **
59                         $this->load->view('html_begin', $this->html_head_params);
60                         $this->load->view('header', array('selected_menu' => 'login'));
61
62                         $main_params['content'] = $this->load->view('user/login_view',
63                                 array('redirect'=> $redirect), TRUE);
64                         $main_params['side'] = $this->load->view('side_default', NULL, TRUE);
65                         $this->load->view('main', $main_params);
66                                 
67                         $this->load->view('footer');
68                         $this->load->view('html_end');
69                 }
70                 else
71                 {
72                         if (! $this->activated_account)
73                                 header('Location: '
74                                         . site_url("user/activate/{$this->user_id}"));
75                         else if (! $this->import)
76                         {
77                                 // Redirect to last page before login. 
78                                 header('Location: '. site_url(urldecode_segments($redirect)));
79                         }
80                         else
81                         {
82                                 // Redirect to account page because an user authenticates here
83                                 // for the first time with external authentication. The page
84                                 // will display imported data.
85                                 header('Location: '. site_url('user/account'));
86                         }
87                 }
88         }
89         
90         /**
91          * Logout user and then redirect it to the last page which must be encoded
92          * in $redirect.
93          * 
94          * @param string $redirect      contains the last page URI segments encoded
95          * with helper url_encode_segments.
96          */
97         public function logout($redirect = '')
98         {
99                 $this->session->unset_userdata('user_id');
100                 $this->session->unset_userdata('username');
101                 $this->session->unset_userdata('auth_src');
102                 $this->session->unset_userdata('time_zone');
103                 
104                 header('Location: '. site_url(urldecode_segments($redirect)));
105         }
106         
107         public function register($redirect = '')
108         {
109                 $this->load->library('form_validation');
110                 $this->load->helper('localization');
111                 $this->load->helper('date');
112                         
113                 $this->form_validation->set_error_delimiters('<span class="error">',
114                                         '</span>');
115                 
116                 if ($this->form_validation->run('register') === FALSE)
117                 {
118                         // Edit account data if logged in, otherwise register.
119                         if ($user_id = $this->session->userdata('user_id'))
120                         {
121                                 $userdata = $this->users_model->get_userdata(intval($user_id));
122                                 $selected_menu = 'account';
123                         }
124                         else
125                         {
126                                 $userdata = FALSE;
127                                 $selected_menu = 'register';
128                         }
129                         
130                         $params = array('title' =>
131                                                                 $this->lang->line('ui_nav_menu_register')
132                                                                         .' &ndash; '
133                                                                         . $this->config->item('site_name'),
134                                                         //'metas' => array('description'=>'')
135                         );
136                         $this->load->library('html_head_params', $params);
137                 
138                         // **
139                         // ** LOADING VIEWS
140                         // **
141                         $this->load->view('html_begin', $this->html_head_params);
142                         $this->load->view('header', 
143                                 array('selected_menu' => $selected_menu));
144                         
145                         $main_params['content'] = $this->load->view('user/register_view', 
146                                 array('userdata'=> $userdata, 'redirect'=> $redirect),
147                                 TRUE);
148                         $main_params['side'] = $this->load->view('side_default', NULL, TRUE);
149                         $this->load->view('main', $main_params);
150                 
151                         $this->load->view('footer');
152                         $this->load->view('html_end');
153                 }
154                 else
155                 {
156                         $user_id = $this->input->post('user-id');
157                         $data['email'] = $this->input->post('email');
158                         $data['first_name'] = $this->input->post('first-name');
159                         $data['last_name'] = $this->input->post('last-name');
160                         $data['birth_date'] = $this->input->post('birth-date');
161                         $data['country'] = $this->input->post('country');
162                         $data['locality'] = $this->input->post('locality');
163                         $data['ui_lang'] = $this->input->post('ui-lang');
164                         $data['time_zone'] = $this->input->post('time-zone');
165                         
166                         // Update session user data.
167                         $this->_update_session_userdata($data);
168                         
169                         // Edit account data
170                         if ($user_id)
171                         {
172                                 $password = $this->input->post('new-password');
173                                 if ($password)
174                                         $data['password'] = $this->input->post('new-password');
175                                 
176                                 $this->users_model->set_userdata($user_id, $data);
177                                 
178                                 // Redirect to last page before login.
179                                 header('Location: '. site_url(urldecode_segments($redirect)));
180                         }
181                         // Registration
182                         else
183                         {
184                                 $data['username'] = $this->input->post('username');
185                                 $data['password'] = $this->input->post('password');
186                                 
187                                 $this->users_model->register($data);
188                                 $user_id = $this->users_model->get_userdata($data['username'],
189                                                 "id");
190                                 $user_id = $user_id['id'];
191                                 
192                                 // Redirect account activation page.
193                                 header('Location: '. site_url("user/activate/$user_id"));
194                         }
195                 }
196         }
197         
198         public function account($redirect = '')
199         {
200                 $this->register($redirect);
201         }
202         
203         public function profile($username, $videos_offset = 0)
204         {
205                 // TODO handle user not found
206                 
207                 $this->load->config('localization');
208                 $this->load->helper('date');
209                 $this->lang->load('date');
210                 
211                 // **
212                 // ** LOADING MODEL
213                 // **
214                 // Logged in user time zone
215                 $time_zone = $this->session->userdata('time_zone');
216                 if (! $time_zone)
217                         $time_zone = 'UTC';
218                 
219                 // User data
220                 $userdata = $this->users_model->get_userdata($username);
221                 $userdata['roles'] = Users_model::roles_to_string($userdata['roles']);
222                 $country_list = $this->config->item('country_list');
223                 $userdata['country_name'] = $country_list[ $userdata['country'] ];
224                 $userdata['last_login'] = date('Y-m-d H:i:s',  
225                         gmt_to_local(
226                                 strtotime($userdata['last_login']), 
227                                 $time_zone, 
228                                 TRUE)) . ($time_zone == 'UTC' ? ' (UTC)' : '');
229                 $userdata['time_zone'] = $this->lang->line($userdata['time_zone']);
230                 
231                 // User's videos
232                 $this->load->model('videos_model');
233                 $vs_data['videos'] = $this->videos_model->get_videos_summary(
234                         NULL, $username, intval($videos_offset),
235                         $this->config->item('videos_per_page'));
236                 
237                 // Pagination
238                 $this->load->library('pagination');
239                 $pg_config['base_url'] = site_url("user/profile/$username/");
240                 $pg_config['uri_segment'] = 4;
241                 $pg_config['total_rows'] = $this->videos_model->get_videos_count(
242                         NULL, $username);
243                 $pg_config['per_page'] = $this->config->item('videos_per_page');
244                 $this->pagination->initialize($pg_config);
245                 $vs_data['pagination'] = $this->pagination->create_links();
246                 $vs_data['title'] = NULL;
247                 $vs_data['category_name'] = ''; // TODO videos_summary with AJAX
248                 
249                 $params = array(
250                         'title'=> $this->lang->line('user_appelation').' '.$username
251                                 .' &ndash; '
252                                 . $this->config->item('site_name'),
253                         'css'=> array('catalog.css')
254                         //'metas' => array('description'=>'')
255                 );
256                 $this->load->library('html_head_params', $params);
257                 
258                 // Current user profile tab
259                 $tab = (! $videos_offset ? 0 : 1);
260                 
261                 // **
262                 // ** LOADING VIEWS
263                 // **
264                 $this->load->view('html_begin', $this->html_head_params);
265                 $this->load->view('header', array());
266                 
267                 $vs = $this->load->view('catalog/videos_summary_view', $vs_data, TRUE);
268                 
269                 $main_params['content'] = $this->load->view('user/profile_view',
270                         array('userdata'=> $userdata, 'videos_summary'=> $vs, 'tab'=>$tab),
271                         TRUE);
272                 $main_params['side'] = $this->load->view('side_default', NULL, TRUE);
273                 $this->load->view('main', $main_params);
274                 
275                 $this->load->view('footer');
276                 $this->load->view('html_end');
277         }
278         
279         public function activate($user_id, $method='', $activation_code='')
280         {
281                 $user_id = intval($user_id);            
282                 $res_form_validation = FALSE;
283                 
284                 if ($method == 'code')
285                 {
286                         if (! $activation_code)
287                                 $res_form_validation = $this->form_validation->run('activate');
288                         // Activation code is provided in URL.
289                         else
290                         {
291                                 if ($this->_valid_activation_code($activation_code)
292                                                 && $this->users_model->activate_account($user_id,
293                                                         $activation_code))
294                                 {
295                                         $this->session->set_flashdata('msg', sprintf(
296                                                 $this->lang->line('user_msg_activated_account'), 
297                                                 site_url('user/login')));
298                                         header('Location: '. site_url('message/info'));
299                                         return;
300                                 }
301                                 else
302                                 {
303                                         $this->session->set_flashdata('msg',
304                                                 $this->lang->line('user_msg_wrong_activation_code'));
305                                         header('Location: '. site_url('message/error'));
306                                         return;
307                                 }
308                         }
309                 }
310                 else if ($method == 'resend')
311                 {
312                         $res_form_validation =
313                                 $this->form_validation->run('resend_activation');
314                 }
315                 
316                 $userdata = $this->users_model->get_userdata($user_id,
317                                 'email, a.activation_code');
318                 $email = $userdata['email'];
319                 $activated_account = ($userdata['activation_code'] == NULL);
320                 
321                 if ($activated_account)
322                 {
323                         $this->session->set_flashdata('msg', sprintf(
324                                                 $this->lang->line('user_msg_activated_account'), 
325                                                 site_url('user/login')));
326                         header('Location: '. site_url('message/info'));
327                         return;
328                 }
329                 
330                 $this->load->library('form_validation');
331                         
332                 $this->form_validation->set_error_delimiters('<span class="error">',
333                                         '</span>');
334                 
335                 if ($res_form_validation === FALSE)
336                 {
337                         $params = array(
338                                 'title'=> $this->lang->line('user_title_activation')
339                                         .' &ndash; '
340                                         . $this->config->item('site_name'),
341                                 //'metas' => array('description'=>'')
342                         );
343                         $this->load->library('html_head_params', $params);
344                 
345                         // **
346                         // ** LOADING VIEWS
347                         // **
348                         $this->load->view('html_begin', $this->html_head_params);
349                         $this->load->view('header', array());
350
351                         // Show form
352                         $main_params['content'] = 
353                                 $this->load->view('user/activate_view',
354                                 array(  'user_id'=> $user_id,
355                                                 'email'=> $userdata['email']),
356                                 TRUE);
357                         
358                         $main_params['side'] = $this->load->view('side_default', NULL, TRUE);
359                         $this->load->view('main', $main_params);
360                 
361                         $this->load->view('footer');
362                         $this->load->view('html_end');
363                 }
364                 else
365                 {
366                         if ($method == 'code')
367                         {
368                                 // Redirect to a message which tells the user that the
369                                 // activation was successful.
370                                 $this->session->set_flashdata('msg', sprintf(
371                                                 $this->lang->line('user_msg_activated_account'), 
372                                                 site_url('user/login')));
373                                 header('Location: '. site_url('message/info'));
374                                 return;
375                         }
376                         else if ($method == 'resend')
377                         {
378                                 // Redirect to resent message
379                                 $this->session->set_flashdata('msg', sprintf(
380                                                 $this->lang->line('user_msg_activation_resent'),
381                                                 $this->input->post('email')));
382                                 header('Location: '. site_url('message/info'));
383                                 return;
384                         }
385                 }
386         }
387         
388         public function recover_password()
389         {
390                 $this->load->library('form_validation');
391                         
392                 $this->form_validation->set_error_delimiters('<span class="error">',
393                         '</span>');
394
395                 if ($this->form_validation->run('recover_password') === FALSE)
396                 {
397                         $params = array(        'title' =>
398                                                                         $this->lang->line(
399                                                                                 'user_title_password_recovery')
400                                                                                 .' &ndash; '
401                                                                                 . $this->config->item('site_name'),
402                                                                 //'metas' => array('description'=>'')
403                         );
404                         $this->load->library('html_head_params', $params);
405                                 
406                         // **
407                         // ** LOADING VIEWS
408                         // **
409                         $this->load->view('html_begin', $this->html_head_params);
410                         $this->load->view('header', array('selected_menu' => 
411                                         'recover_password'));
412
413                         $main_params['content'] = $this->load->view(
414                                 'user/recover_password_view', array(),
415                                 TRUE);
416                         
417                         $main_params['side'] = $this->load->view('side_default', NULL, TRUE);
418                         $this->load->view('main', $main_params);
419                                 
420                         $this->load->view('footer');
421                         $this->load->view('html_end');
422                 }
423                 else
424                 {
425                         // Redirect to resent message
426                         $this->session->set_flashdata('msg', sprintf(
427                                         $this->lang->line('user_msg_password_recovery_email_sent'),
428                                         $this->input->post('username'),
429                                         $this->input->post('email')));
430                         header('Location: '. site_url('message/info'));
431                         return;
432                 }
433         }
434         
435         public function _update_session_userdata($data)
436         {
437                 foreach ($data as $key=> $val)
438                         $this->session->set_userdata($key, $val);
439         }
440         
441         public function _valid_username($username)
442         {
443                 return (preg_match('/^[a-z0-9\._]+$/', $username) === 1);
444         }
445
446         public function _valid_username_or_email($username)
447         {
448                 $this->load->helper('email');
449
450                 if (valid_email($username))
451                         return TRUE;
452                 else
453                         return $this->_valid_username($username);
454         }
455         
456         public function _valid_date($date)
457         {
458                 if (! $date)
459                         return TRUE;
460                 
461                 return (preg_match('/[\d]{4}-[\d]{2}-[\d]{2}/', $date) === 1);
462         }
463         
464         public function _valid_old_password($old_password, $field_username)
465         {
466                 if (! $old_password)
467                         return TRUE;
468                 
469                 $username= $this->input->post($field_username);
470                 
471                 if ($this->users_model->login($username, $old_password))
472                         return TRUE;
473                 
474                 return FALSE;
475         }
476         
477         public function _change_password_cond($param)
478         {
479                 $old = $this->input->post('old-password');
480                 $new = $this->input->post('new-password');
481                 $newc = $this->input->post('new-password-confirmation');
482                 
483                 return (!$old && !$new && !$newc)
484                         || ($old && $new && $newc);
485         }
486         
487         public function _required_by_register($param)
488         {
489                 $user_id = $this->input->post('user-id');
490                 
491                 if (! $user_id && ! $param)
492                         return FALSE;
493                 
494                 return TRUE;
495         }
496         
497         public function _valid_activation_code($activation_code)
498         {
499                 return (preg_match('/^[a-fA-F0-9]{16}$/', $activation_code) == 1);
500         }
501
502         public function _do_login($username, $field_password)
503         {
504                 $password = $this->input->post($field_password);
505
506                 $user = $this->users_model->login($username, $password);
507
508                 // Authentication failed.
509                 if ($user === FALSE)
510                         return FALSE;
511                 
512                 // User has not activated the account.
513                 if ($user['activation_code'] !== NULL)
514                 {
515                         $this->activated_account = FALSE;
516                         $this->user_id = $user['id'];
517                         return TRUE;
518                 }
519                 
520                 // Authentication successful: set session with user data.
521                 $this->session->set_userdata(array(
522                         'user_id'=> $user['id'],
523                         'username'=> $user['username'],
524                         'auth_src'=> $user['auth_src'],
525                         'time_zone'=> $user['time_zone']
526                 ));
527                 $this->import = (isset($user['import']) ? $user['import'] : FALSE);
528                 return TRUE;
529         }
530         
531         public function _do_activate($activation_code)
532         {
533                 $user_id = $this->input->post('user-id');
534                 if ($user_id === FALSE)
535                         return FALSE;
536                 $user_id = intval($user_id);
537                 
538                 return $this->users_model->activate_account($user_id,
539                                 $activation_code);
540         }
541         
542         public function _do_resend_activation($email)
543         {
544                 $user_id = $this->input->post('user-id');
545                 if ($user_id === FALSE)
546                         return FALSE;
547                 $user_id = intval($user_id);
548                 
549                 $this->users_model->set_userdata($user_id,
550                         array('email'=> $email));
551                 
552                 return $this->users_model->send_activation_email($user_id, $email);
553         }
554         
555         public function _username_exists($username)
556         {
557                 $userdata = $this->users_model->get_userdata($username);
558                 
559                 if (! $userdata)
560                         return FALSE;
561                 
562                 return TRUE;
563         }
564         
565         public function _internal_account($username)
566         {
567                 $userdata = $this->users_model->get_userdata($username, 'auth_src');
568                 if (! $userdata)
569                         return FALSE;
570
571                 if ($userdata['auth_src'] != 'internal')
572                         return FALSE;
573                 
574                 return TRUE;
575         }
576         
577         public function _do_recover_password($username)
578         {
579                 $email = $this->input->post('email');
580                 if (! $email)
581                         return FALSE;
582                 
583                 return $this->users_model->recover_password($username, $email);
584         }
585 }
586
587 /* End of file user.php */
588 /* Location: ./application/controllers/user.php */