From ad4351f13b5771f1af4853b32b537d6e85c1f2e4 Mon Sep 17 00:00:00 2001
From: M Hamza Siddiqui
Date: Tue, 24 Apr 2018 16:55:17 +0500
Subject: [PATCH 1/3] Frontend User Authentication Fixed
Frontend User authentication controller and view added.
---
application/controllers/Auth.php | 834 ++++++
application/models/Ion_auth_model.php | 2257 +++++++++++++++++
application/views/auth/change_password.php | 25 +
application/views/auth/create_group.php | 20 +
application/views/auth/create_user.php | 57 +
application/views/auth/deactivate_user.php | 18 +
application/views/auth/edit_group.php | 20 +
application/views/auth/edit_user.php | 66 +
application/views/auth/email/activate.tpl.php | 6 +
.../views/auth/email/forgot_password.tpl.php | 6 +
.../views/auth/email/new_password.tpl.php | 7 +
application/views/auth/forgot_password.php | 17 +
application/views/auth/index.php | 31 +
application/views/auth/login.php | 16 +
application/views/auth/reset_password.php | 22 +
15 files changed, 3402 insertions(+)
create mode 100644 application/controllers/Auth.php
create mode 100644 application/models/Ion_auth_model.php
create mode 100644 application/views/auth/change_password.php
create mode 100644 application/views/auth/create_group.php
create mode 100644 application/views/auth/create_user.php
create mode 100644 application/views/auth/deactivate_user.php
create mode 100644 application/views/auth/edit_group.php
create mode 100644 application/views/auth/edit_user.php
create mode 100644 application/views/auth/email/activate.tpl.php
create mode 100644 application/views/auth/email/forgot_password.tpl.php
create mode 100644 application/views/auth/email/new_password.tpl.php
create mode 100644 application/views/auth/forgot_password.php
create mode 100644 application/views/auth/index.php
create mode 100644 application/views/auth/login.php
create mode 100644 application/views/auth/reset_password.php
diff --git a/application/controllers/Auth.php b/application/controllers/Auth.php
new file mode 100644
index 00000000..fa2e76cb
--- /dev/null
+++ b/application/controllers/Auth.php
@@ -0,0 +1,834 @@
+load->database();
+ $this->load->library(array('ion_auth','form_validation'));
+ $this->load->helper(array('url','language'));
+
+ //$this->form_validation->set_error_delimiters($this->config->item('error_start_delimiter', 'ion_auth'), $this->config->item('error_end_delimiter', 'ion_auth'));
+ if ($this->ion_auth->logged_in()){
+ $this->mViewData['user'] = $this->ion_auth->user()->row();
+ }
+
+ $this->lang->load('auth');
+ }
+
+ // redirect if needed, otherwise display the user list
+ function index()
+ {
+
+ if (!$this->ion_auth->logged_in())
+ {
+ // redirect them to the login page
+ redirect('auth/login', 'refresh');
+ }
+ /*elseif (!$this->ion_auth->is_admin()) // remove this elseif if you want to enable this for non-admins
+ {
+ // redirect them to the home page because they must be an administrator to view this
+ return show_error('You must be an administrator to view this page.');
+ }*/
+ else
+ {
+ // set the flash data error message if there is one
+ $this->mViewData['message'] = (validation_errors()) ? validation_errors() : $this->session->flashdata('message');
+
+ //list the users
+ $this->mViewData['users'] = $this->ion_auth->users()->result();
+ foreach ($this->mViewData['users'] as $k => $user)
+ {
+ $this->mViewData['users'][$k]->groups = $this->ion_auth->get_users_groups($user->id)->result();
+ }
+
+ $this->render('auth/index');
+ }
+ }
+
+ // log the user in
+ function login()
+ {
+
+ if ($this->ion_auth->logged_in())
+ {
+ // redirect them to the login page
+ redirect('/', 'refresh');
+ }
+
+ $this->mViewData['title'] = "Login";
+
+ $this->load->library('form_builder');
+ $form = $this->form_builder->create_form();
+
+ // the user is not logging in so display the login page
+ // set the flash data error message if there is one
+ $this->mViewData['form'] = $form;
+ $this->render('auth/login');
+ }
+
+ function login_process()
+ {
+
+
+ if ($this->ion_auth->logged_in())
+ {
+ // redirect them to the login page
+ redirect('/', 'refresh');
+ }
+
+ // check to see if the user is logging in
+ // check for "remember me"
+ // passed validation
+ $identity = $this->input->post('username');
+ $password = $this->input->post('password');
+ $remember = ($this->input->post('remember')=='on');
+
+ if ($this->ion_auth->login($identity, $password, $remember))
+ {
+ //if the login is successful
+ //redirect them back to the home page
+ //$this->session->set_flashdata('message', $this->ion_auth->messages());
+ //$messages = $this->ion_auth->messages();
+ //$this->system_message->set_success($messages);
+ //echo "Success";
+ redirect('/');
+ }
+ else
+ {
+ // if the login was un-successful
+ // redirect them back to the login page
+ $this->session->set_flashdata('message', $this->ion_auth->errors());
+ $errors = $this->ion_auth->errors();
+ //print_r($errors);
+ $this->system_message->set_error($errors);
+ //echo "Failed";
+ redirect('/auth/login'); // use redirects instead of loading views for compatibility with MY_Controller libraries
+ }
+ }
+
+ // log the user out
+ function logout()
+ {
+ $this->mViewData['title'] = "Logout";
+
+ // log the user out
+ $logout = $this->ion_auth->logout();
+
+ // redirect them to the login page
+ //$this->session->set_flashdata('message', $this->ion_auth->messages());
+ redirect('auth/login', 'refresh');
+ }
+
+ // change password
+ function change_password()
+ {
+ $this->form_validation->set_rules('old', $this->lang->line('change_password_validation_old_password_label'), 'required');
+ $this->form_validation->set_rules('new', $this->lang->line('change_password_validation_new_password_label'), 'required|min_length[' . $this->config->item('min_password_length', 'ion_auth') . ']|max_length[' . $this->config->item('max_password_length', 'ion_auth') . ']|matches[new_confirm]');
+ $this->form_validation->set_rules('new_confirm', $this->lang->line('change_password_validation_new_password_confirm_label'), 'required');
+
+ if (!$this->ion_auth->logged_in())
+ {
+ redirect('auth/login', 'refresh');
+ }
+
+ $user = $this->ion_auth->user()->row();
+
+ if ($this->form_validation->run() == false)
+ {
+ // display the form
+ // set the flash data error message if there is one
+ $this->mViewData['message'] = (validation_errors()) ? validation_errors() : $this->session->flashdata('message');
+
+ $this->mViewData['min_password_length'] = $this->config->item('min_password_length', 'ion_auth');
+ $this->mViewData['old_password'] = array(
+ 'name' => 'old',
+ 'id' => 'old',
+ 'type' => 'password',
+ );
+ $this->mViewData['new_password'] = array(
+ 'name' => 'new',
+ 'id' => 'new',
+ 'type' => 'password',
+ 'pattern' => '^.{'.$this->mViewData['min_password_length'].'}.*$',
+ );
+ $this->mViewData['new_password_confirm'] = array(
+ 'name' => 'new_confirm',
+ 'id' => 'new_confirm',
+ 'type' => 'password',
+ 'pattern' => '^.{'.$this->mViewData['min_password_length'].'}.*$',
+ );
+ $this->mViewData['user_id'] = array(
+ 'name' => 'user_id',
+ 'id' => 'user_id',
+ 'type' => 'hidden',
+ 'value' => $user->id,
+ );
+
+ // render
+ $this->_render_page('auth/change_password', $this->data);
+ }
+ else
+ {
+ $identity = $this->session->userdata('identity');
+
+ $change = $this->ion_auth->change_password($identity, $this->input->post('old'), $this->input->post('new'));
+
+ if ($change)
+ {
+ //if the password was successfully changed
+ $this->session->set_flashdata('message', $this->ion_auth->messages());
+ $this->logout();
+ }
+ else
+ {
+ $this->session->set_flashdata('message', $this->ion_auth->errors());
+ redirect('auth/change_password', 'refresh');
+ }
+ }
+ }
+
+ // forgot password
+ function forgot_password()
+ {
+ // setting validation rules by checking wheather identity is username or email
+ if($this->config->item('identity', 'ion_auth') != 'email' )
+ {
+ $this->form_validation->set_rules('identity', $this->lang->line('forgot_password_identity_label'), 'required');
+ }
+ else
+ {
+ $this->form_validation->set_rules('identity', $this->lang->line('forgot_password_validation_email_label'), 'required|valid_email');
+ }
+
+
+ if ($this->form_validation->run() == false)
+ {
+ $this->mViewData['type'] = $this->config->item('identity','ion_auth');
+ // setup the input
+ $this->mViewData['identity'] = array('name' => 'identity',
+ 'id' => 'identity',
+ 'class' => 'form-control'
+ );
+
+ if ( $this->config->item('identity', 'ion_auth') != 'email' ){
+ $this->mViewData['identity_label'] = $this->lang->line('forgot_password_identity_label');
+ }
+ else
+ {
+ $this->mViewData['identity_label'] = $this->lang->line('forgot_password_email_identity_label');
+ }
+
+ // set any errors and display the form
+ $this->mViewData['message'] = (validation_errors()) ? validation_errors() : $this->session->flashdata('message');
+ $this->render('auth/forgot_password');
+ }
+ else
+ {
+ $identity_column = $this->config->item('identity','ion_auth');
+ $identity = $this->ion_auth->where($identity_column, $this->input->get('identity'))->users()->row();
+
+ if(empty($identity)) {
+
+ if($this->config->item('identity', 'ion_auth') != 'email')
+ {
+ $this->ion_auth->set_error('forgot_password_identity_not_found');
+ }
+ else
+ {
+ $this->ion_auth->set_error('forgot_password_email_not_found');
+ }
+
+ $this->session->set_flashdata('message', $this->ion_auth->errors());
+ redirect("auth/forgot_password", 'refresh');
+ }
+
+ // run the forgotten password method to email an activation code to the user
+ $forgotten = $this->ion_auth->forgotten_password($identity->{$this->config->item('identity', 'ion_auth')});
+
+ if ($forgotten)
+ {
+ // if there were no errors
+ $this->session->set_flashdata('message', $this->ion_auth->messages());
+ redirect("auth/login", 'refresh'); //we should display a confirmation page here instead of the login page
+ }
+ else
+ {
+ $this->session->set_flashdata('message', $this->ion_auth->errors());
+ redirect("auth/forgot_password", 'refresh');
+ }
+ }
+ }
+
+ // reset password - final step for forgotten password
+ public function reset_password($code = NULL)
+ {
+ if (!$code)
+ {
+ show_404();
+ }
+
+ $user = $this->ion_auth->forgotten_password_check($code);
+
+ if ($user)
+ {
+ // if the code is valid then display the password reset form
+
+ $this->form_validation->set_rules('new', $this->lang->line('reset_password_validation_new_password_label'), 'required|min_length[' . $this->config->item('min_password_length', 'ion_auth') . ']|max_length[' . $this->config->item('max_password_length', 'ion_auth') . ']|matches[new_confirm]');
+ $this->form_validation->set_rules('new_confirm', $this->lang->line('reset_password_validation_new_password_confirm_label'), 'required');
+
+ if ($this->form_validation->run() == false)
+ {
+ // display the form
+
+ // set the flash data error message if there is one
+ $this->mViewData['message'] = (validation_errors()) ? validation_errors() : $this->session->flashdata('message');
+
+ $this->mViewData['min_password_length'] = $this->config->item('min_password_length', 'ion_auth');
+ $this->mViewData['new_password'] = array(
+ 'name' => 'new',
+ 'id' => 'new',
+ 'type' => 'password',
+ 'pattern' => '^.{'.$this->mViewData['min_password_length'].'}.*$',
+ );
+ $this->mViewData['new_password_confirm'] = array(
+ 'name' => 'new_confirm',
+ 'id' => 'new_confirm',
+ 'type' => 'password',
+ 'pattern' => '^.{'.$this->mViewData['min_password_length'].'}.*$',
+ );
+ $this->mViewData['user_id'] = array(
+ 'name' => 'user_id',
+ 'id' => 'user_id',
+ 'type' => 'hidden',
+ 'value' => $user->id,
+ );
+ $this->mViewData['csrf'] = $this->_get_csrf_nonce();
+ $this->mViewData['code'] = $code;
+
+ // render
+ $this->_render_page('auth/reset_password', $this->data);
+ }
+ else
+ {
+ // do we have a valid request?
+ if ($this->_valid_csrf_nonce() === FALSE || $user->id != $this->input->post('user_id'))
+ {
+
+ // something fishy might be up
+ $this->ion_auth->clear_forgotten_password_code($code);
+
+ show_error($this->lang->line('error_csrf'));
+
+ }
+ else
+ {
+ // finally change the password
+ $identity = $user->{$this->config->item('identity', 'ion_auth')};
+
+ $change = $this->ion_auth->reset_password($identity, $this->input->post('new'));
+
+ if ($change)
+ {
+ // if the password was successfully changed
+ $this->session->set_flashdata('message', $this->ion_auth->messages());
+ redirect("auth/login", 'refresh');
+ }
+ else
+ {
+ $this->session->set_flashdata('message', $this->ion_auth->errors());
+ redirect('auth/reset_password/' . $code, 'refresh');
+ }
+ }
+ }
+ }
+ else
+ {
+ // if the code is invalid then send them back to the forgot password page
+ $this->session->set_flashdata('message', $this->ion_auth->errors());
+ redirect("auth/forgot_password", 'refresh');
+ }
+ }
+
+
+ // activate the user
+ function activate($id, $code=false)
+ {
+ if ($code !== false)
+ {
+ $activation = $this->ion_auth->activate($id, $code);
+ }
+ else if ($this->ion_auth->is_admin())
+ {
+ $activation = $this->ion_auth->activate($id);
+ }
+
+ if ($activation)
+ {
+ // redirect them to the auth page
+ $this->session->set_flashdata('message', $this->ion_auth->messages());
+ redirect("auth", 'refresh');
+ }
+ else
+ {
+ // redirect them to the forgot password page
+ $this->session->set_flashdata('message', $this->ion_auth->errors());
+ redirect("auth/forgot_password", 'refresh');
+ }
+ }
+
+ // deactivate the user
+ function deactivate($id = NULL)
+ {
+ if (!$this->ion_auth->logged_in() || !$this->ion_auth->is_admin())
+ {
+ // redirect them to the home page because they must be an administrator to view this
+ return show_error('You must be an administrator to view this page.');
+ }
+
+ $id = (int) $id;
+
+ $this->load->library('form_validation');
+ $this->form_validation->set_rules('confirm', $this->lang->line('deactivate_validation_confirm_label'), 'required');
+ $this->form_validation->set_rules('id', $this->lang->line('deactivate_validation_user_id_label'), 'required|alpha_numeric');
+
+ if ($this->form_validation->run() == FALSE)
+ {
+ // insert csrf check
+ $this->mViewData['csrf'] = $this->_get_csrf_nonce();
+ $this->mViewData['user'] = $this->ion_auth->user($id)->row();
+
+ $this->_render_page('auth/deactivate_user', $this->data);
+ }
+ else
+ {
+ // do we really want to deactivate?
+ if ($this->input->post('confirm') == 'yes')
+ {
+ // do we have a valid request?
+ if ($this->_valid_csrf_nonce() === FALSE || $id != $this->input->post('id'))
+ {
+ show_error($this->lang->line('error_csrf'));
+ }
+
+ // do we have the right userlevel?
+ if ($this->ion_auth->logged_in() && $this->ion_auth->is_admin())
+ {
+ $this->ion_auth->deactivate($id);
+ }
+ }
+
+ // redirect them back to the auth page
+ redirect('auth', 'refresh');
+ }
+ }
+
+ // create a new user
+ function create_user()
+ {
+ $this->mViewData['title'] = "Create User";
+
+ if (!$this->ion_auth->logged_in() || !$this->ion_auth->is_admin())
+ {
+ redirect('auth', 'refresh');
+ }
+
+ $tables = $this->config->item('tables','ion_auth');
+ $identity_column = $this->config->item('identity','ion_auth');
+ $this->mViewData['identity_column'] = $identity_column;
+
+ // validate form input
+ $this->form_validation->set_rules('first_name', $this->lang->line('create_user_validation_fname_label'), 'required');
+ $this->form_validation->set_rules('last_name', $this->lang->line('create_user_validation_lname_label'), 'required');
+ if($identity_column!=='email')
+ {
+ $this->form_validation->set_rules('identity',$this->lang->line('create_user_validation_identity_label'),'required|is_unique['.$tables['users'].'.'.$identity_column.']');
+ $this->form_validation->set_rules('email', $this->lang->line('create_user_validation_email_label'), 'required|valid_email');
+ }
+ else
+ {
+ $this->form_validation->set_rules('email', $this->lang->line('create_user_validation_email_label'), 'required|valid_email|is_unique[' . $tables['users'] . '.email]');
+ }
+ $this->form_validation->set_rules('phone', $this->lang->line('create_user_validation_phone_label'), 'trim');
+ $this->form_validation->set_rules('company', $this->lang->line('create_user_validation_company_label'), 'trim');
+ $this->form_validation->set_rules('password', $this->lang->line('create_user_validation_password_label'), 'required|min_length[' . $this->config->item('min_password_length', 'ion_auth') . ']|max_length[' . $this->config->item('max_password_length', 'ion_auth') . ']|matches[password_confirm]');
+ $this->form_validation->set_rules('password_confirm', $this->lang->line('create_user_validation_password_confirm_label'), 'required');
+
+ if ($this->form_validation->run() == true)
+ {
+ $email = strtolower($this->input->post('email'));
+ $identity = ($identity_column==='email') ? $email : $this->input->post('identity');
+ $password = $this->input->post('password');
+
+ $additional_data = array(
+ 'first_name' => $this->input->post('first_name'),
+ 'last_name' => $this->input->post('last_name'),
+ 'company' => $this->input->post('company'),
+ 'phone' => $this->input->post('phone'),
+ );
+ }
+ if ($this->form_validation->run() == true && $this->ion_auth->register($identity, $password, $email, $additional_data))
+ {
+ // check to see if we are creating the user
+ // redirect them back to the admin page
+ $this->session->set_flashdata('message', $this->ion_auth->messages());
+ redirect("auth", 'refresh');
+ }
+ else
+ {
+ // display the create user form
+ // set the flash data error message if there is one
+ $this->mViewData['message'] = (validation_errors() ? validation_errors() : ($this->ion_auth->errors() ? $this->ion_auth->errors() : $this->session->flashdata('message')));
+
+ $this->mViewData['first_name'] = array(
+ 'name' => 'first_name',
+ 'id' => 'first_name',
+ 'type' => 'text',
+ 'value' => $this->form_validation->set_value('first_name'),
+ );
+ $this->mViewData['last_name'] = array(
+ 'name' => 'last_name',
+ 'id' => 'last_name',
+ 'type' => 'text',
+ 'value' => $this->form_validation->set_value('last_name'),
+ );
+ $this->mViewData['identity'] = array(
+ 'name' => 'identity',
+ 'id' => 'identity',
+ 'type' => 'text',
+ 'value' => $this->form_validation->set_value('identity'),
+ );
+ $this->mViewData['email'] = array(
+ 'name' => 'email',
+ 'id' => 'email',
+ 'type' => 'text',
+ 'value' => $this->form_validation->set_value('email'),
+ );
+ $this->mViewData['company'] = array(
+ 'name' => 'company',
+ 'id' => 'company',
+ 'type' => 'text',
+ 'value' => $this->form_validation->set_value('company'),
+ );
+ $this->mViewData['phone'] = array(
+ 'name' => 'phone',
+ 'id' => 'phone',
+ 'type' => 'text',
+ 'value' => $this->form_validation->set_value('phone'),
+ );
+ $this->mViewData['password'] = array(
+ 'name' => 'password',
+ 'id' => 'password',
+ 'type' => 'password',
+ 'value' => $this->form_validation->set_value('password'),
+ );
+ $this->mViewData['password_confirm'] = array(
+ 'name' => 'password_confirm',
+ 'id' => 'password_confirm',
+ 'type' => 'password',
+ 'value' => $this->form_validation->set_value('password_confirm'),
+ );
+
+ $this->_render_page('auth/create_user', $this->data);
+ }
+ }
+
+ // edit a user
+ function edit_user($id)
+ {
+ $this->mViewData['title'] = "Edit User";
+
+ if (!$this->ion_auth->logged_in() || (!$this->ion_auth->is_admin() && !($this->ion_auth->user()->row()->id == $id)))
+ {
+ redirect('auth', 'refresh');
+ }
+
+ $user = $this->ion_auth->user($id)->row();
+ $groups=$this->ion_auth->groups()->result_array();
+ $currentGroups = $this->ion_auth->get_users_groups($id)->result();
+
+ // validate form input
+ $this->form_validation->set_rules('first_name', $this->lang->line('edit_user_validation_fname_label'), 'required');
+ $this->form_validation->set_rules('last_name', $this->lang->line('edit_user_validation_lname_label'), 'required');
+ $this->form_validation->set_rules('phone', $this->lang->line('edit_user_validation_phone_label'), 'required');
+ $this->form_validation->set_rules('company', $this->lang->line('edit_user_validation_company_label'), 'required');
+
+ if (isset($_POST) && !empty($_POST))
+ {
+ // do we have a valid request?
+ if ($this->_valid_csrf_nonce() === FALSE || $id != $this->input->post('id'))
+ {
+ show_error($this->lang->line('error_csrf'));
+ }
+
+ // update the password if it was posted
+ if ($this->input->post('password'))
+ {
+ $this->form_validation->set_rules('password', $this->lang->line('edit_user_validation_password_label'), 'required|min_length[' . $this->config->item('min_password_length', 'ion_auth') . ']|max_length[' . $this->config->item('max_password_length', 'ion_auth') . ']|matches[password_confirm]');
+ $this->form_validation->set_rules('password_confirm', $this->lang->line('edit_user_validation_password_confirm_label'), 'required');
+ }
+
+ if ($this->form_validation->run() === TRUE)
+ {
+ $data = array(
+ 'first_name' => $this->input->post('first_name'),
+ 'last_name' => $this->input->post('last_name'),
+ 'company' => $this->input->post('company'),
+ 'phone' => $this->input->post('phone'),
+ );
+
+ // update the password if it was posted
+ if ($this->input->post('password'))
+ {
+ $data['password'] = $this->input->post('password');
+ }
+
+
+
+ // Only allow updating groups if user is admin
+ if ($this->ion_auth->is_admin())
+ {
+ //Update the groups user belongs to
+ $groupData = $this->input->post('groups');
+
+ if (isset($groupData) && !empty($groupData)) {
+
+ $this->ion_auth->remove_from_group('', $id);
+
+ foreach ($groupData as $grp) {
+ $this->ion_auth->add_to_group($grp, $id);
+ }
+
+ }
+ }
+
+ // check to see if we are updating the user
+ if($this->ion_auth->update($user->id, $data))
+ {
+ // redirect them back to the admin page if admin, or to the base url if non admin
+ $this->session->set_flashdata('message', $this->ion_auth->messages() );
+ if ($this->ion_auth->is_admin())
+ {
+ redirect('auth', 'refresh');
+ }
+ else
+ {
+ redirect('/', 'refresh');
+ }
+
+ }
+ else
+ {
+ // redirect them back to the admin page if admin, or to the base url if non admin
+ $this->session->set_flashdata('message', $this->ion_auth->errors() );
+ if ($this->ion_auth->is_admin())
+ {
+ redirect('auth', 'refresh');
+ }
+ else
+ {
+ redirect('/', 'refresh');
+ }
+
+ }
+
+ }
+ }
+
+ // display the edit user form
+ $this->mViewData['csrf'] = $this->_get_csrf_nonce();
+
+ // set the flash data error message if there is one
+ $this->mViewData['message'] = (validation_errors() ? validation_errors() : ($this->ion_auth->errors() ? $this->ion_auth->errors() : $this->session->flashdata('message')));
+
+ // pass the user to the view
+ $this->mViewData['user'] = $user;
+ $this->mViewData['groups'] = $groups;
+ $this->mViewData['currentGroups'] = $currentGroups;
+
+ $this->mViewData['first_name'] = array(
+ 'name' => 'first_name',
+ 'id' => 'first_name',
+ 'type' => 'text',
+ 'value' => $this->form_validation->set_value('first_name', $user->first_name),
+ );
+ $this->mViewData['last_name'] = array(
+ 'name' => 'last_name',
+ 'id' => 'last_name',
+ 'type' => 'text',
+ 'value' => $this->form_validation->set_value('last_name', $user->last_name),
+ );
+ $this->mViewData['company'] = array(
+ 'name' => 'company',
+ 'id' => 'company',
+ 'type' => 'text',
+ 'value' => $this->form_validation->set_value('company', $user->company),
+ );
+ $this->mViewData['phone'] = array(
+ 'name' => 'phone',
+ 'id' => 'phone',
+ 'type' => 'text',
+ 'value' => $this->form_validation->set_value('phone', $user->phone),
+ );
+ $this->mViewData['password'] = array(
+ 'name' => 'password',
+ 'id' => 'password',
+ 'type' => 'password'
+ );
+ $this->mViewData['password_confirm'] = array(
+ 'name' => 'password_confirm',
+ 'id' => 'password_confirm',
+ 'type' => 'password'
+ );
+
+ $this->_render_page('auth/edit_user', $this->data);
+ }
+
+ // create a new group
+ function create_group()
+ {
+ $this->mViewData['title'] = $this->lang->line('create_group_title');
+
+ if (!$this->ion_auth->logged_in() || !$this->ion_auth->is_admin())
+ {
+ redirect('auth', 'refresh');
+ }
+
+ // validate form input
+ $this->form_validation->set_rules('group_name', $this->lang->line('create_group_validation_name_label'), 'required|alpha_dash');
+
+ if ($this->form_validation->run() == TRUE)
+ {
+ $new_group_id = $this->ion_auth->create_group($this->input->post('group_name'), $this->input->post('description'));
+ if($new_group_id)
+ {
+ // check to see if we are creating the group
+ // redirect them back to the admin page
+ $this->session->set_flashdata('message', $this->ion_auth->messages());
+ redirect("auth", 'refresh');
+ }
+ }
+ else
+ {
+ // display the create group form
+ // set the flash data error message if there is one
+ $this->mViewData['message'] = (validation_errors() ? validation_errors() : ($this->ion_auth->errors() ? $this->ion_auth->errors() : $this->session->flashdata('message')));
+
+ $this->mViewData['group_name'] = array(
+ 'name' => 'group_name',
+ 'id' => 'group_name',
+ 'type' => 'text',
+ 'value' => $this->form_validation->set_value('group_name'),
+ );
+ $this->mViewData['description'] = array(
+ 'name' => 'description',
+ 'id' => 'description',
+ 'type' => 'text',
+ 'value' => $this->form_validation->set_value('description'),
+ );
+
+ $this->_render_page('auth/create_group', $this->data);
+ }
+ }
+
+ // edit a group
+ function edit_group($id)
+ {
+ // bail if no group id given
+ if(!$id || empty($id))
+ {
+ redirect('auth', 'refresh');
+ }
+
+ $this->mViewData['title'] = $this->lang->line('edit_group_title');
+
+ if (!$this->ion_auth->logged_in() || !$this->ion_auth->is_admin())
+ {
+ redirect('auth', 'refresh');
+ }
+
+ $group = $this->ion_auth->group($id)->row();
+
+ // validate form input
+ $this->form_validation->set_rules('group_name', $this->lang->line('edit_group_validation_name_label'), 'required|alpha_dash');
+
+ if (isset($_POST) && !empty($_POST))
+ {
+ if ($this->form_validation->run() === TRUE)
+ {
+ $group_update = $this->ion_auth->update_group($id, $_POST['group_name'], $_POST['group_description']);
+
+ if($group_update)
+ {
+ $this->session->set_flashdata('message', $this->lang->line('edit_group_saved'));
+ }
+ else
+ {
+ $this->session->set_flashdata('message', $this->ion_auth->errors());
+ }
+ redirect("auth", 'refresh');
+ }
+ }
+
+ // set the flash data error message if there is one
+ $this->mViewData['message'] = (validation_errors() ? validation_errors() : ($this->ion_auth->errors() ? $this->ion_auth->errors() : $this->session->flashdata('message')));
+
+ // pass the user to the view
+ $this->mViewData['group'] = $group;
+
+ $readonly = $this->config->item('admin_group', 'ion_auth') === $group->name ? 'readonly' : '';
+
+ $this->mViewData['group_name'] = array(
+ 'name' => 'group_name',
+ 'id' => 'group_name',
+ 'type' => 'text',
+ 'value' => $this->form_validation->set_value('group_name', $group->name),
+ $readonly => $readonly,
+ );
+ $this->mViewData['group_description'] = array(
+ 'name' => 'group_description',
+ 'id' => 'group_description',
+ 'type' => 'text',
+ 'value' => $this->form_validation->set_value('group_description', $group->description),
+ );
+
+ $this->_render_page('auth/edit_group', $this->data);
+ }
+
+
+ function _get_csrf_nonce()
+ {
+ $this->load->helper('string');
+ $key = random_string('alnum', 8);
+ $value = random_string('alnum', 20);
+ $this->session->set_flashdata('csrfkey', $key);
+ $this->session->set_flashdata('csrfvalue', $value);
+
+ return array($key => $value);
+ }
+
+ function _valid_csrf_nonce()
+ {
+ if ($this->input->post($this->session->flashdata('csrfkey')) !== FALSE &&
+ $this->input->post($this->session->flashdata('csrfkey')) == $this->session->flashdata('csrfvalue'))
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+
+ function _render_page($view, $data=null, $returnhtml=false)//I think this makes more sense
+ {
+
+ $this->viewdata = (empty($data)) ? $this->data: $data;
+
+ $view_html = $this->load->view($view, $this->viewdata, $returnhtml);
+
+ if ($returnhtml) return $view_html;//This will return html on 3rd argument being true
+ }
+
+}
diff --git a/application/models/Ion_auth_model.php b/application/models/Ion_auth_model.php
new file mode 100644
index 00000000..7f6181e5
--- /dev/null
+++ b/application/models/Ion_auth_model.php
@@ -0,0 +1,2257 @@
+load->database();
+ $this->load->config('ion_auth', TRUE);
+ $this->load->helper('cookie');
+ $this->load->helper('date');
+ $this->lang->load('ion_auth');
+
+ // initialize db tables data
+ $this->tables = $this->config->item('tables', 'ion_auth');
+
+ //initialize data
+ $this->identity_column = $this->config->item('identity', 'ion_auth');
+ $this->store_salt = $this->config->item('store_salt', 'ion_auth');
+ $this->salt_length = $this->config->item('salt_length', 'ion_auth');
+ $this->join = $this->config->item('join', 'ion_auth');
+
+
+ // initialize hash method options (Bcrypt)
+ $this->hash_method = $this->config->item('hash_method', 'ion_auth');
+ $this->default_rounds = $this->config->item('default_rounds', 'ion_auth');
+ $this->random_rounds = $this->config->item('random_rounds', 'ion_auth');
+ $this->min_rounds = $this->config->item('min_rounds', 'ion_auth');
+ $this->max_rounds = $this->config->item('max_rounds', 'ion_auth');
+
+
+ // initialize messages and error
+ $this->messages = array();
+ $this->errors = array();
+ $delimiters_source = $this->config->item('delimiters_source', 'ion_auth');
+
+ // load the error delimeters either from the config file or use what's been supplied to form validation
+ if ($delimiters_source === 'form_validation')
+ {
+ // load in delimiters from form_validation
+ // to keep this simple we'll load the value using reflection since these properties are protected
+ $this->load->library('form_validation');
+ $form_validation_class = new ReflectionClass("CI_Form_validation");
+
+ $error_prefix = $form_validation_class->getProperty("_error_prefix");
+ $error_prefix->setAccessible(TRUE);
+ $this->error_start_delimiter = $error_prefix->getValue($this->form_validation);
+ $this->message_start_delimiter = $this->error_start_delimiter;
+
+ $error_suffix = $form_validation_class->getProperty("_error_suffix");
+ $error_suffix->setAccessible(TRUE);
+ $this->error_end_delimiter = $error_suffix->getValue($this->form_validation);
+ $this->message_end_delimiter = $this->error_end_delimiter;
+ }
+ else
+ {
+ // use delimiters from config
+ $this->message_start_delimiter = $this->config->item('message_start_delimiter', 'ion_auth');
+ $this->message_end_delimiter = $this->config->item('message_end_delimiter', 'ion_auth');
+ $this->error_start_delimiter = $this->config->item('error_start_delimiter', 'ion_auth');
+ $this->error_end_delimiter = $this->config->item('error_end_delimiter', 'ion_auth');
+ }
+
+
+ // initialize our hooks object
+ $this->_ion_hooks = new stdClass;
+
+ // load the bcrypt class if needed
+ if ($this->hash_method == 'bcrypt') {
+ if ($this->random_rounds)
+ {
+ $rand = rand($this->min_rounds,$this->max_rounds);
+ $params = array('rounds' => $rand);
+ }
+ else
+ {
+ $params = array('rounds' => $this->default_rounds);
+ }
+
+ $params['salt_prefix'] = $this->config->item('salt_prefix', 'ion_auth');
+ $this->load->library('bcrypt',$params);
+ }
+
+ $this->trigger_events('model_constructor');
+ }
+
+ /**
+ * Misc functions
+ *
+ * Hash password : Hashes the password to be stored in the database.
+ * Hash password db : This function takes a password and validates it
+ * against an entry in the users table.
+ * Salt : Generates a random salt value.
+ *
+ * @author Mathew
+ */
+
+ /**
+ * Hashes the password to be stored in the database.
+ *
+ * @return void
+ * @author Mathew
+ **/
+ public function hash_password($password, $salt=false, $use_sha1_override=FALSE)
+ {
+ if (empty($password))
+ {
+ return FALSE;
+ }
+
+ // bcrypt
+ if ($use_sha1_override === FALSE && $this->hash_method == 'bcrypt')
+ {
+ return $this->bcrypt->hash($password);
+ }
+
+
+ if ($this->store_salt && $salt)
+ {
+ return sha1($password . $salt);
+ }
+ else
+ {
+ $salt = $this->salt();
+ return $salt . substr(sha1($salt . $password), 0, -$this->salt_length);
+ }
+ }
+
+ /**
+ * This function takes a password and validates it
+ * against an entry in the users table.
+ *
+ * @return void
+ * @author Mathew
+ **/
+ public function hash_password_db($id, $password, $use_sha1_override=FALSE)
+ {
+ if (empty($id) || empty($password))
+ {
+ return FALSE;
+ }
+
+ $this->trigger_events('extra_where');
+
+ $query = $this->db->select('password, salt')
+ ->where('id', $id)
+ ->limit(1)
+ ->order_by('id', 'desc')
+ ->get($this->tables['users']);
+
+ $hash_password_db = $query->row();
+
+ if ($query->num_rows() !== 1)
+ {
+ return FALSE;
+ }
+
+ // bcrypt
+ if ($use_sha1_override === FALSE && $this->hash_method == 'bcrypt')
+ {
+ if ($this->bcrypt->verify($password,$hash_password_db->password))
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+ // sha1
+ if ($this->store_salt)
+ {
+ $db_password = sha1($password . $hash_password_db->salt);
+ }
+ else
+ {
+ $salt = substr($hash_password_db->password, 0, $this->salt_length);
+
+ $db_password = $salt . substr(sha1($salt . $password), 0, -$this->salt_length);
+ }
+
+ if($db_password == $hash_password_db->password)
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+
+ /**
+ * Generates a random salt value for forgotten passwords or any other keys. Uses SHA1.
+ *
+ * @return void
+ * @author Mathew
+ **/
+ public function hash_code($password)
+ {
+ return $this->hash_password($password, FALSE, TRUE);
+ }
+
+ /**
+ * Generates a random salt value.
+ *
+ * Salt generation code taken from https://github.com/ircmaxell/password_compat/blob/master/lib/password.php
+ *
+ * @return void
+ * @author Anthony Ferrera
+ **/
+ public function salt()
+ {
+
+ $raw_salt_len = 16;
+
+ $buffer = '';
+ $buffer_valid = false;
+
+ if (function_exists('mcrypt_create_iv') && !defined('PHALANGER')) {
+ $buffer = mcrypt_create_iv($raw_salt_len, MCRYPT_DEV_URANDOM);
+ if ($buffer) {
+ $buffer_valid = true;
+ }
+ }
+
+ if (!$buffer_valid && function_exists('openssl_random_pseudo_bytes')) {
+ $buffer = openssl_random_pseudo_bytes($raw_salt_len);
+ if ($buffer) {
+ $buffer_valid = true;
+ }
+ }
+
+ if (!$buffer_valid && @is_readable('/dev/urandom')) {
+ $f = fopen('/dev/urandom', 'r');
+ $read = strlen($buffer);
+ while ($read < $raw_salt_len) {
+ $buffer .= fread($f, $raw_salt_len - $read);
+ $read = strlen($buffer);
+ }
+ fclose($f);
+ if ($read >= $raw_salt_len) {
+ $buffer_valid = true;
+ }
+ }
+
+ if (!$buffer_valid || strlen($buffer) < $raw_salt_len) {
+ $bl = strlen($buffer);
+ for ($i = 0; $i < $raw_salt_len; $i++) {
+ if ($i < $bl) {
+ $buffer[$i] = $buffer[$i] ^ chr(mt_rand(0, 255));
+ } else {
+ $buffer .= chr(mt_rand(0, 255));
+ }
+ }
+ }
+
+ $salt = $buffer;
+
+ // encode string with the Base64 variant used by crypt
+ $base64_digits = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+ $bcrypt64_digits = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+ $base64_string = base64_encode($salt);
+ $salt = strtr(rtrim($base64_string, '='), $base64_digits, $bcrypt64_digits);
+
+ $salt = substr($salt, 0, $this->salt_length);
+
+
+ return $salt;
+
+ }
+
+ /**
+ * Activation functions
+ *
+ * Activate : Validates and removes activation code.
+ * Deactivae : Updates a users row with an activation code.
+ *
+ * @author Mathew
+ */
+
+ /**
+ * activate
+ *
+ * @return void
+ * @author Mathew
+ **/
+ public function activate($id, $code = false)
+ {
+ $this->trigger_events('pre_activate');
+
+ if ($code !== FALSE)
+ {
+ $query = $this->db->select($this->identity_column)
+ ->where('activation_code', $code)
+ ->where('id', $id)
+ ->limit(1)
+ ->order_by('id', 'desc')
+ ->get($this->tables['users']);
+
+ $result = $query->row();
+
+ if ($query->num_rows() !== 1)
+ {
+ $this->trigger_events(array('post_activate', 'post_activate_unsuccessful'));
+ $this->set_error('activate_unsuccessful');
+ return FALSE;
+ }
+
+ $data = array(
+ 'activation_code' => NULL,
+ 'active' => 1
+ );
+
+ $this->trigger_events('extra_where');
+ $this->db->update($this->tables['users'], $data, array('id' => $id));
+ }
+ else
+ {
+ $data = array(
+ 'activation_code' => NULL,
+ 'active' => 1
+ );
+
+
+ $this->trigger_events('extra_where');
+ $this->db->update($this->tables['users'], $data, array('id' => $id));
+ }
+
+
+ $return = $this->db->affected_rows() == 1;
+ if ($return)
+ {
+ $this->trigger_events(array('post_activate', 'post_activate_successful'));
+ $this->set_message('activate_successful');
+ }
+ else
+ {
+ $this->trigger_events(array('post_activate', 'post_activate_unsuccessful'));
+ $this->set_error('activate_unsuccessful');
+ }
+
+
+ return $return;
+ }
+
+
+ /**
+ * Deactivate
+ *
+ * @return void
+ * @author Mathew
+ **/
+ public function deactivate($id = NULL)
+ {
+ $this->trigger_events('deactivate');
+
+ if (!isset($id))
+ {
+ $this->set_error('deactivate_unsuccessful');
+ return FALSE;
+ }
+
+ $activation_code = sha1(md5(microtime()));
+ $this->activation_code = $activation_code;
+
+ $data = array(
+ 'activation_code' => $activation_code,
+ 'active' => 0
+ );
+
+ $this->trigger_events('extra_where');
+ $this->db->update($this->tables['users'], $data, array('id' => $id));
+
+ $return = $this->db->affected_rows() == 1;
+ if ($return)
+ $this->set_message('deactivate_successful');
+ else
+ $this->set_error('deactivate_unsuccessful');
+
+ return $return;
+ }
+
+ public function clear_forgotten_password_code($code) {
+
+ if (empty($code))
+ {
+ return FALSE;
+ }
+
+ $this->db->where('forgotten_password_code', $code);
+
+ if ($this->db->count_all_results($this->tables['users']) > 0)
+ {
+ $data = array(
+ 'forgotten_password_code' => NULL,
+ 'forgotten_password_time' => NULL
+ );
+
+ $this->db->update($this->tables['users'], $data, array('forgotten_password_code' => $code));
+
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+ /**
+ * reset password
+ *
+ * @return bool
+ * @author Mathew
+ **/
+ public function reset_password($identity, $new) {
+ $this->trigger_events('pre_change_password');
+
+ if (!$this->identity_check($identity)) {
+ $this->trigger_events(array('post_change_password', 'post_change_password_unsuccessful'));
+ return FALSE;
+ }
+
+ $this->trigger_events('extra_where');
+
+ $query = $this->db->select('id, password, salt')
+ ->where($this->identity_column, $identity)
+ ->limit(1)
+ ->order_by('id', 'desc')
+ ->get($this->tables['users']);
+
+ if ($query->num_rows() !== 1)
+ {
+ $this->trigger_events(array('post_change_password', 'post_change_password_unsuccessful'));
+ $this->set_error('password_change_unsuccessful');
+ return FALSE;
+ }
+
+ $result = $query->row();
+
+ $new = $this->hash_password($new, $result->salt);
+
+ // store the new password and reset the remember code so all remembered instances have to re-login
+ // also clear the forgotten password code
+ $data = array(
+ 'password' => $new,
+ 'remember_code' => NULL,
+ 'forgotten_password_code' => NULL,
+ 'forgotten_password_time' => NULL,
+ );
+
+ $this->trigger_events('extra_where');
+ $this->db->update($this->tables['users'], $data, array($this->identity_column => $identity));
+
+ $return = $this->db->affected_rows() == 1;
+ if ($return)
+ {
+ $this->trigger_events(array('post_change_password', 'post_change_password_successful'));
+ $this->set_message('password_change_successful');
+ }
+ else
+ {
+ $this->trigger_events(array('post_change_password', 'post_change_password_unsuccessful'));
+ $this->set_error('password_change_unsuccessful');
+ }
+
+ return $return;
+ }
+
+ /**
+ * change password
+ *
+ * @return bool
+ * @author Mathew
+ **/
+ public function change_password($identity, $old, $new)
+ {
+ $this->trigger_events('pre_change_password');
+
+ $this->trigger_events('extra_where');
+
+ $query = $this->db->select('id, password, salt')
+ ->where($this->identity_column, $identity)
+ ->limit(1)
+ ->order_by('id', 'desc')
+ ->get($this->tables['users']);
+
+ if ($query->num_rows() !== 1)
+ {
+ $this->trigger_events(array('post_change_password', 'post_change_password_unsuccessful'));
+ $this->set_error('password_change_unsuccessful');
+ return FALSE;
+ }
+
+ $user = $query->row();
+
+ $old_password_matches = $this->hash_password_db($user->id, $old);
+
+ if ($old_password_matches === TRUE)
+ {
+ // store the new password and reset the remember code so all remembered instances have to re-login
+ $hashed_new_password = $this->hash_password($new, $user->salt);
+ $data = array(
+ 'password' => $hashed_new_password,
+ 'remember_code' => NULL,
+ );
+
+ $this->trigger_events('extra_where');
+
+ $successfully_changed_password_in_db = $this->db->update($this->tables['users'], $data, array($this->identity_column => $identity));
+ if ($successfully_changed_password_in_db)
+ {
+ $this->trigger_events(array('post_change_password', 'post_change_password_successful'));
+ $this->set_message('password_change_successful');
+ }
+ else
+ {
+ $this->trigger_events(array('post_change_password', 'post_change_password_unsuccessful'));
+ $this->set_error('password_change_unsuccessful');
+ }
+
+ return $successfully_changed_password_in_db;
+ }
+
+ $this->set_error('password_change_unsuccessful');
+ return FALSE;
+ }
+
+ /**
+ * Checks username
+ *
+ * @return bool
+ * @author Mathew
+ **/
+ public function username_check($username = '')
+ {
+ $this->trigger_events('username_check');
+
+ if (empty($username))
+ {
+ return FALSE;
+ }
+
+ $this->trigger_events('extra_where');
+
+ return $this->db->where('username', $username)
+ ->group_by("id")
+ ->order_by("id", "ASC")
+ ->limit(1)
+ ->count_all_results($this->tables['users']) > 0;
+ }
+
+ /**
+ * Checks email
+ *
+ * @return bool
+ * @author Mathew
+ **/
+ public function email_check($email = '')
+ {
+ $this->trigger_events('email_check');
+
+ if (empty($email))
+ {
+ return FALSE;
+ }
+
+ $this->trigger_events('extra_where');
+
+ return $this->db->where('email', $email)
+ ->group_by("id")
+ ->order_by("id", "ASC")
+ ->limit(1)
+ ->count_all_results($this->tables['users']) > 0;
+ }
+
+ /**
+ * Identity check
+ *
+ * @return bool
+ * @author Mathew
+ **/
+ public function identity_check($identity = '')
+ {
+ $this->trigger_events('identity_check');
+
+ if (empty($identity))
+ {
+ return FALSE;
+ }
+
+ return $this->db->where($this->identity_column, $identity)
+ ->count_all_results($this->tables['users']) > 0;
+ }
+
+ /**
+ * Insert a forgotten password key.
+ *
+ * @return bool
+ * @author Mathew
+ * @updated Ryan
+ * @updated 52aa456eef8b60ad6754b31fbdcc77bb
+ **/
+ public function forgotten_password($identity)
+ {
+ if (empty($identity))
+ {
+ $this->trigger_events(array('post_forgotten_password', 'post_forgotten_password_unsuccessful'));
+ return FALSE;
+ }
+
+ // All some more randomness
+ $activation_code_part = "";
+ if(function_exists("openssl_random_pseudo_bytes")) {
+ $activation_code_part = openssl_random_pseudo_bytes(128);
+ }
+
+ for($i=0;$i<1024;$i++) {
+ $activation_code_part = sha1($activation_code_part . mt_rand() . microtime());
+ }
+
+ $key = $this->hash_code($activation_code_part.$identity);
+
+ // If enable query strings is set, then we need to replace any unsafe characters so that the code can still work
+ if ($key != '' && $this->config->item('permitted_uri_chars') != '' && $this->config->item('enable_query_strings') == FALSE)
+ {
+ // preg_quote() in PHP 5.3 escapes -, so the str_replace() and addition of - to preg_quote() is to maintain backwards
+ // compatibility as many are unaware of how characters in the permitted_uri_chars will be parsed as a regex pattern
+ if ( ! preg_match("|^[".str_replace(array('\\-', '\-'), '-', preg_quote($this->config->item('permitted_uri_chars'), '-'))."]+$|i", $key))
+ {
+ $key = preg_replace("/[^".$this->config->item('permitted_uri_chars')."]+/i", "-", $key);
+ }
+ }
+
+ $this->forgotten_password_code = $key;
+
+ $this->trigger_events('extra_where');
+
+ $update = array(
+ 'forgotten_password_code' => $key,
+ 'forgotten_password_time' => time()
+ );
+
+ $this->db->update($this->tables['users'], $update, array($this->identity_column => $identity));
+
+ $return = $this->db->affected_rows() == 1;
+
+ if ($return)
+ $this->trigger_events(array('post_forgotten_password', 'post_forgotten_password_successful'));
+ else
+ $this->trigger_events(array('post_forgotten_password', 'post_forgotten_password_unsuccessful'));
+
+ return $return;
+ }
+
+ /**
+ * Forgotten Password Complete
+ *
+ * @return string
+ * @author Mathew
+ **/
+ public function forgotten_password_complete($code, $salt=FALSE)
+ {
+ $this->trigger_events('pre_forgotten_password_complete');
+
+ if (empty($code))
+ {
+ $this->trigger_events(array('post_forgotten_password_complete', 'post_forgotten_password_complete_unsuccessful'));
+ return FALSE;
+ }
+
+ $profile = $this->where('forgotten_password_code', $code)->users()->row(); //pass the code to profile
+
+ if ($profile) {
+
+ if ($this->config->item('forgot_password_expiration', 'ion_auth') > 0) {
+ //Make sure it isn't expired
+ $expiration = $this->config->item('forgot_password_expiration', 'ion_auth');
+ if (time() - $profile->forgotten_password_time > $expiration) {
+ //it has expired
+ $this->set_error('forgot_password_expired');
+ $this->trigger_events(array('post_forgotten_password_complete', 'post_forgotten_password_complete_unsuccessful'));
+ return FALSE;
+ }
+ }
+
+ $password = $this->salt();
+
+ $data = array(
+ 'password' => $this->hash_password($password, $salt),
+ 'forgotten_password_code' => NULL,
+ 'active' => 1,
+ );
+
+ $this->db->update($this->tables['users'], $data, array('forgotten_password_code' => $code));
+
+ $this->trigger_events(array('post_forgotten_password_complete', 'post_forgotten_password_complete_successful'));
+ return $password;
+ }
+
+ $this->trigger_events(array('post_forgotten_password_complete', 'post_forgotten_password_complete_unsuccessful'));
+ return FALSE;
+ }
+
+ /**
+ * register
+ *
+ * @return bool
+ * @author Mathew
+ **/
+ public function register($identity, $password, $email, $additional_data = array(), $groups = array())
+ {
+ $this->trigger_events('pre_register');
+
+ $manual_activation = $this->config->item('manual_activation', 'ion_auth');
+
+ if ($this->identity_check($identity))
+ {
+ $this->set_error('account_creation_duplicate_identity');
+ return FALSE;
+ }
+ elseif ( !$this->config->item('default_group', 'ion_auth') && empty($groups) )
+ {
+ $this->set_error('account_creation_missing_default_group');
+ return FALSE;
+ }
+
+ // check if the default set in config exists in database
+ $query = $this->db->get_where($this->tables['groups'],array('name' => $this->config->item('default_group', 'ion_auth')),1)->row();
+ if( !isset($query->id) && empty($groups) )
+ {
+ $this->set_error('account_creation_invalid_default_group');
+ return FALSE;
+ }
+
+ // capture default group details
+ $default_group = $query;
+
+ // IP Address
+ $ip_address = $this->_prepare_ip($this->input->ip_address());
+ $salt = $this->store_salt ? $this->salt() : FALSE;
+ $password = $this->hash_password($password, $salt);
+
+ // Users table.
+ $data = array(
+ $this->identity_column => $identity,
+ 'password' => $password,
+ 'email' => $email,
+ 'ip_address' => $ip_address,
+ 'created_on' => time(),
+ 'active' => ($manual_activation === false ? 1 : 0)
+ );
+
+ if ($this->store_salt)
+ {
+ $data['salt'] = $salt;
+ }
+
+ // filter out any data passed that doesnt have a matching column in the users table
+ // and merge the set user data and the additional data
+ $user_data = array_merge($this->_filter_data($this->tables['users'], $additional_data), $data);
+
+ $this->trigger_events('extra_set');
+
+ $this->db->insert($this->tables['users'], $user_data);
+
+ $id = $this->db->insert_id();
+
+ // add in groups array if it doesn't exits and stop adding into default group if default group ids are set
+ if( isset($default_group->id) && empty($groups) )
+ {
+ $groups[] = $default_group->id;
+ }
+
+ if (!empty($groups))
+ {
+ // add to groups
+ foreach ($groups as $group)
+ {
+ $this->add_to_group($group, $id);
+ }
+ }
+
+ $this->trigger_events('post_register');
+
+ return (isset($id)) ? $id : FALSE;
+ }
+
+ /**
+ * login
+ *
+ * @return bool
+ * @author Mathew
+ **/
+ public function login($identity, $password, $remember=FALSE)
+ {
+
+ $this->trigger_events('pre_login');
+
+ if (empty($identity) || empty($password))
+ {
+ $this->set_error('login_unsuccessful');
+ return FALSE;
+ }
+
+ $this->trigger_events('extra_where');
+
+ $query = $this->db->select($this->identity_column . ', email, id, password, active, last_login')
+ ->where($this->identity_column, $identity)
+ ->limit(1)
+ ->order_by('id', 'desc')
+ ->get($this->tables['users']);
+
+ exit;
+ if($this->is_time_locked_out($identity))
+ {
+ // Hash something anyway, just to take up time
+ $this->hash_password($password);
+
+ $this->trigger_events('post_login_unsuccessful');
+ $this->set_error('login_timeout');
+
+ return FALSE;
+ }
+
+ if ($query->num_rows() === 1)
+ {
+ $user = $query->row();
+
+ $password = $this->hash_password_db($user->id, $password);
+
+ if ($password === TRUE)
+ {
+ if ($user->active == 0)
+ {
+ $this->trigger_events('post_login_unsuccessful');
+ $this->set_error('login_unsuccessful_not_active');
+
+ return FALSE;
+ }
+
+ $this->set_session($user);
+
+ $this->update_last_login($user->id);
+
+ $this->clear_login_attempts($identity);
+
+ if ($remember && $this->config->item('remember_users', 'ion_auth'))
+ {
+ $this->remember_user($user->id);
+ }
+
+ $this->trigger_events(array('post_login', 'post_login_successful'));
+ $this->set_message('login_successful');
+
+ return TRUE;
+ }
+ }
+
+ // Hash something anyway, just to take up time
+ $this->hash_password($password);
+
+ $this->increase_login_attempts($identity);
+
+ $this->trigger_events('post_login_unsuccessful');
+ $this->set_error('login_unsuccessful');
+
+ return FALSE;
+ }
+
+ /**
+ * is_max_login_attempts_exceeded
+ * Based on code from Tank Auth, by Ilya Konyukhov (https://github.com/ilkon/Tank-Auth)
+ *
+ * @param string $identity
+ * @return boolean
+ **/
+ public function is_max_login_attempts_exceeded($identity) {
+ if ($this->config->item('track_login_attempts', 'ion_auth')) {
+ $max_attempts = $this->config->item('maximum_login_attempts', 'ion_auth');
+ if ($max_attempts > 0) {
+ $attempts = $this->get_attempts_num($identity);
+ return $attempts >= $max_attempts;
+ }
+ }
+ return FALSE;
+ }
+
+ /**
+ * Get number of attempts to login occured from given IP-address or identity
+ * Based on code from Tank Auth, by Ilya Konyukhov (https://github.com/ilkon/Tank-Auth)
+ *
+ * @param string $identity
+ * @return int
+ */
+ function get_attempts_num($identity)
+ {
+ if ($this->config->item('track_login_attempts', 'ion_auth')) {
+ $ip_address = $this->_prepare_ip($this->input->ip_address());
+ $this->db->select('1', FALSE);
+ if ($this->config->item('track_login_ip_address', 'ion_auth')) {
+ $this->db->where('ip_address', $ip_address);
+ $this->db->where('login', $identity);
+ } else if (strlen($identity) > 0) $this->db->or_where('login', $identity);
+ $qres = $this->db->get($this->tables['login_attempts']);
+ return $qres->num_rows();
+ }
+ return 0;
+ }
+
+ /**
+ * Get a boolean to determine if an account should be locked out due to
+ * exceeded login attempts within a given period
+ *
+ * @return boolean
+ */
+ public function is_time_locked_out($identity) {
+
+ return $this->is_max_login_attempts_exceeded($identity) && $this->get_last_attempt_time($identity) > time() - $this->config->item('lockout_time', 'ion_auth');
+ }
+
+ /**
+ * Get the time of the last time a login attempt occured from given IP-address or identity
+ *
+ * @param string $identity
+ * @return int
+ */
+ public function get_last_attempt_time($identity) {
+ if ($this->config->item('track_login_attempts', 'ion_auth')) {
+ $ip_address = $this->_prepare_ip($this->input->ip_address());
+
+ $this->db->select_max('time');
+ if ($this->config->item('track_login_ip_address', 'ion_auth')) $this->db->where('ip_address', $ip_address);
+ else if (strlen($identity) > 0) $this->db->or_where('login', $identity);
+ $qres = $this->db->get($this->tables['login_attempts'], 1);
+
+ if($qres->num_rows() > 0) {
+ return $qres->row()->time;
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * increase_login_attempts
+ * Based on code from Tank Auth, by Ilya Konyukhov (https://github.com/ilkon/Tank-Auth)
+ *
+ * @param string $identity
+ **/
+ public function increase_login_attempts($identity) {
+ if ($this->config->item('track_login_attempts', 'ion_auth')) {
+ $ip_address = $this->_prepare_ip($this->input->ip_address());
+ return $this->db->insert($this->tables['login_attempts'], array('ip_address' => $ip_address, 'login' => $identity, 'time' => time()));
+ }
+ return FALSE;
+ }
+
+ /**
+ * clear_login_attempts
+ * Based on code from Tank Auth, by Ilya Konyukhov (https://github.com/ilkon/Tank-Auth)
+ *
+ * @param string $identity
+ **/
+ public function clear_login_attempts($identity, $expire_period = 86400) {
+ if ($this->config->item('track_login_attempts', 'ion_auth')) {
+ $ip_address = $this->_prepare_ip($this->input->ip_address());
+
+ $this->db->where(array('ip_address' => $ip_address, 'login' => $identity));
+ // Purge obsolete login attempts
+ $this->db->or_where('time <', time() - $expire_period, FALSE);
+
+ return $this->db->delete($this->tables['login_attempts']);
+ }
+ return FALSE;
+ }
+
+ public function limit($limit)
+ {
+ $this->trigger_events('limit');
+ $this->_ion_limit = $limit;
+
+ return $this;
+ }
+
+ public function offset($offset)
+ {
+ $this->trigger_events('offset');
+ $this->_ion_offset = $offset;
+
+ return $this;
+ }
+
+ public function where($where, $value = NULL)
+ {
+ $this->trigger_events('where');
+
+ if (!is_array($where))
+ {
+ $where = array($where => $value);
+ }
+
+ array_push($this->_ion_where, $where);
+
+ return $this;
+ }
+
+ public function like($like, $value = NULL, $position = 'both')
+ {
+ $this->trigger_events('like');
+
+ if (!is_array($like))
+ {
+ $like = array($like => array(
+ 'value' => $value,
+ 'position' => $position,
+ ));
+ }
+
+ array_push($this->_ion_like, $like);
+
+ return $this;
+ }
+
+ public function select($select)
+ {
+ $this->trigger_events('select');
+
+ $this->_ion_select[] = $select;
+
+ return $this;
+ }
+
+ public function order_by($by, $order='desc')
+ {
+ $this->trigger_events('order_by');
+
+ $this->_ion_order_by = $by;
+ $this->_ion_order = $order;
+
+ return $this;
+ }
+
+ public function row()
+ {
+ $this->trigger_events('row');
+
+ $row = $this->response->row();
+
+ return $row;
+ }
+
+ public function row_array()
+ {
+ $this->trigger_events(array('row', 'row_array'));
+
+ $row = $this->response->row_array();
+
+ return $row;
+ }
+
+ public function result()
+ {
+ $this->trigger_events('result');
+
+ $result = $this->response->result();
+
+ return $result;
+ }
+
+ public function result_array()
+ {
+ $this->trigger_events(array('result', 'result_array'));
+
+ $result = $this->response->result_array();
+
+ return $result;
+ }
+
+ public function num_rows()
+ {
+ $this->trigger_events(array('num_rows'));
+
+ $result = $this->response->num_rows();
+
+ return $result;
+ }
+
+ /**
+ * users
+ *
+ * @return object Users
+ * @author Ben Edmunds
+ **/
+ public function users($groups = NULL)
+ {
+ $this->trigger_events('users');
+
+ if (isset($this->_ion_select) && !empty($this->_ion_select))
+ {
+ foreach ($this->_ion_select as $select)
+ {
+ $this->db->select($select);
+ }
+
+ $this->_ion_select = array();
+ }
+ else
+ {
+ //default selects
+ $this->db->select(array(
+ $this->tables['users'].'.*',
+ $this->tables['users'].'.id as id',
+ $this->tables['users'].'.id as user_id'
+ ));
+ }
+
+ // filter by group id(s) if passed
+ if (isset($groups))
+ {
+ // build an array if only one group was passed
+ if (!is_array($groups))
+ {
+ $groups = Array($groups);
+ }
+
+ // join and then run a where_in against the group ids
+ if (isset($groups) && !empty($groups))
+ {
+ $this->db->distinct();
+ $this->db->join(
+ $this->tables['users_groups'],
+ $this->tables['users_groups'].'.'.$this->join['users'].'='.$this->tables['users'].'.id',
+ 'inner'
+ );
+ }
+
+ // verify if group name or group id was used and create and put elements in different arrays
+ $group_ids = array();
+ $group_names = array();
+ foreach($groups as $group)
+ {
+ if(is_numeric($group)) $group_ids[] = $group;
+ else $group_names[] = $group;
+ }
+ $or_where_in = (!empty($group_ids) && !empty($group_names)) ? 'or_where_in' : 'where_in';
+ // if group name was used we do one more join with groups
+ if(!empty($group_names))
+ {
+ $this->db->join($this->tables['groups'], $this->tables['users_groups'] . '.' . $this->join['groups'] . ' = ' . $this->tables['groups'] . '.id', 'inner');
+ $this->db->where_in($this->tables['groups'] . '.name', $group_names);
+ }
+ if(!empty($group_ids))
+ {
+ $this->db->{$or_where_in}($this->tables['users_groups'].'.'.$this->join['groups'], $group_ids);
+ }
+ }
+
+ $this->trigger_events('extra_where');
+
+ // run each where that was passed
+ if (isset($this->_ion_where) && !empty($this->_ion_where))
+ {
+ foreach ($this->_ion_where as $where)
+ {
+ $this->db->where($where);
+ }
+
+ $this->_ion_where = array();
+ }
+
+ if (isset($this->_ion_like) && !empty($this->_ion_like))
+ {
+ foreach ($this->_ion_like as $like)
+ {
+ $this->db->or_like($like);
+ }
+
+ $this->_ion_like = array();
+ }
+
+ if (isset($this->_ion_limit) && isset($this->_ion_offset))
+ {
+ $this->db->limit($this->_ion_limit, $this->_ion_offset);
+
+ $this->_ion_limit = NULL;
+ $this->_ion_offset = NULL;
+ }
+ else if (isset($this->_ion_limit))
+ {
+ $this->db->limit($this->_ion_limit);
+
+ $this->_ion_limit = NULL;
+ }
+
+ // set the order
+ if (isset($this->_ion_order_by) && isset($this->_ion_order))
+ {
+ $this->db->order_by($this->_ion_order_by, $this->_ion_order);
+
+ $this->_ion_order = NULL;
+ $this->_ion_order_by = NULL;
+ }
+
+ $this->response = $this->db->get($this->tables['users']);
+
+ return $this;
+ }
+
+ /**
+ * user
+ *
+ * @return object
+ * @author Ben Edmunds
+ **/
+ public function user($id = NULL)
+ {
+ $this->trigger_events('user');
+
+ // if no id was passed use the current users id
+ $id = isset($id) ? $id : $this->session->userdata('user_id');
+
+ $this->limit(1);
+ $this->order_by($this->tables['users'].'.id', 'desc');
+ $this->where($this->tables['users'].'.id', $id);
+
+ $this->users();
+
+ return $this;
+ }
+
+ /**
+ * get_users_groups
+ *
+ * @return array
+ * @author Ben Edmunds
+ **/
+ public function get_users_groups($id=FALSE)
+ {
+ $this->trigger_events('get_users_group');
+
+ // if no id was passed use the current users id
+ $id || $id = $this->session->userdata('user_id');
+
+ return $this->db->select($this->tables['users_groups'].'.'.$this->join['groups'].' as id, '.$this->tables['groups'].'.name, '.$this->tables['groups'].'.description')
+ ->where($this->tables['users_groups'].'.'.$this->join['users'], $id)
+ ->join($this->tables['groups'], $this->tables['users_groups'].'.'.$this->join['groups'].'='.$this->tables['groups'].'.id')
+ ->get($this->tables['users_groups']);
+ }
+
+ /**
+ * add_to_group
+ *
+ * @return bool
+ * @author Ben Edmunds
+ **/
+ public function add_to_group($group_ids, $user_id=false)
+ {
+ $this->trigger_events('add_to_group');
+
+ // if no id was passed use the current users id
+ $user_id || $user_id = $this->session->userdata('user_id');
+
+ if(!is_array($group_ids))
+ {
+ $group_ids = array($group_ids);
+ }
+
+ $return = 0;
+
+ // Then insert each into the database
+ foreach ($group_ids as $group_id)
+ {
+ if ($this->db->insert($this->tables['users_groups'], array( $this->join['groups'] => (float)$group_id, $this->join['users'] => (float)$user_id)))
+ {
+ if (isset($this->_cache_groups[$group_id])) {
+ $group_name = $this->_cache_groups[$group_id];
+ }
+ else {
+ $group = $this->group($group_id)->result();
+ $group_name = $group[0]->name;
+ $this->_cache_groups[$group_id] = $group_name;
+ }
+ $this->_cache_user_in_group[$user_id][$group_id] = $group_name;
+
+ // Return the number of groups added
+ $return += 1;
+ }
+ }
+
+ return $return;
+ }
+
+ /**
+ * remove_from_group
+ *
+ * @return bool
+ * @author Ben Edmunds
+ **/
+ public function remove_from_group($group_ids=false, $user_id=false)
+ {
+ $this->trigger_events('remove_from_group');
+
+ // user id is required
+ if(empty($user_id))
+ {
+ return FALSE;
+ }
+
+ // if group id(s) are passed remove user from the group(s)
+ if( ! empty($group_ids))
+ {
+ if(!is_array($group_ids))
+ {
+ $group_ids = array($group_ids);
+ }
+
+ foreach($group_ids as $group_id)
+ {
+ $this->db->delete($this->tables['users_groups'], array($this->join['groups'] => (float)$group_id, $this->join['users'] => (float)$user_id));
+ if (isset($this->_cache_user_in_group[$user_id]) && isset($this->_cache_user_in_group[$user_id][$group_id]))
+ {
+ unset($this->_cache_user_in_group[$user_id][$group_id]);
+ }
+ }
+
+ $return = TRUE;
+ }
+ // otherwise remove user from all groups
+ else
+ {
+ if ($return = $this->db->delete($this->tables['users_groups'], array($this->join['users'] => (float)$user_id))) {
+ $this->_cache_user_in_group[$user_id] = array();
+ }
+ }
+ return $return;
+ }
+
+ /**
+ * groups
+ *
+ * @return object
+ * @author Ben Edmunds
+ **/
+ public function groups()
+ {
+ $this->trigger_events('groups');
+
+ // run each where that was passed
+ if (isset($this->_ion_where) && !empty($this->_ion_where))
+ {
+ foreach ($this->_ion_where as $where)
+ {
+ $this->db->where($where);
+ }
+ $this->_ion_where = array();
+ }
+
+ if (isset($this->_ion_limit) && isset($this->_ion_offset))
+ {
+ $this->db->limit($this->_ion_limit, $this->_ion_offset);
+
+ $this->_ion_limit = NULL;
+ $this->_ion_offset = NULL;
+ }
+ else if (isset($this->_ion_limit))
+ {
+ $this->db->limit($this->_ion_limit);
+
+ $this->_ion_limit = NULL;
+ }
+
+ // set the order
+ if (isset($this->_ion_order_by) && isset($this->_ion_order))
+ {
+ $this->db->order_by($this->_ion_order_by, $this->_ion_order);
+ }
+
+ $this->response = $this->db->get($this->tables['groups']);
+
+ return $this;
+ }
+
+ /**
+ * group
+ *
+ * @return object
+ * @author Ben Edmunds
+ **/
+ public function group($id = NULL)
+ {
+ $this->trigger_events('group');
+
+ if (isset($id))
+ {
+ $this->where($this->tables['groups'].'.id', $id);
+ }
+
+ $this->limit(1);
+ $this->order_by('id', 'desc');
+
+ return $this->groups();
+ }
+
+ /**
+ * update
+ *
+ * @return bool
+ * @author Phil Sturgeon
+ **/
+ public function update($id, array $data)
+ {
+ $this->trigger_events('pre_update_user');
+
+ $user = $this->user($id)->row();
+
+ $this->db->trans_begin();
+
+ if (array_key_exists($this->identity_column, $data) && $this->identity_check($data[$this->identity_column]) && $user->{$this->identity_column} !== $data[$this->identity_column])
+ {
+ $this->db->trans_rollback();
+ $this->set_error('account_creation_duplicate_identity');
+
+ $this->trigger_events(array('post_update_user', 'post_update_user_unsuccessful'));
+ $this->set_error('update_unsuccessful');
+
+ return FALSE;
+ }
+
+ // Filter the data passed
+ $data = $this->_filter_data($this->tables['users'], $data);
+
+ if (array_key_exists($this->identity_column, $data) || array_key_exists('password', $data) || array_key_exists('email', $data))
+ {
+ if (array_key_exists('password', $data))
+ {
+ if( ! empty($data['password']))
+ {
+ $data['password'] = $this->hash_password($data['password'], $user->salt);
+ }
+ else
+ {
+ // unset password so it doesn't effect database entry if no password passed
+ unset($data['password']);
+ }
+ }
+ }
+
+ $this->trigger_events('extra_where');
+ $this->db->update($this->tables['users'], $data, array('id' => $user->id));
+
+ if ($this->db->trans_status() === FALSE)
+ {
+ $this->db->trans_rollback();
+
+ $this->trigger_events(array('post_update_user', 'post_update_user_unsuccessful'));
+ $this->set_error('update_unsuccessful');
+ return FALSE;
+ }
+
+ $this->db->trans_commit();
+
+ $this->trigger_events(array('post_update_user', 'post_update_user_successful'));
+ $this->set_message('update_successful');
+ return TRUE;
+ }
+
+ /**
+ * delete_user
+ *
+ * @return bool
+ * @author Phil Sturgeon
+ **/
+ public function delete_user($id)
+ {
+ $this->trigger_events('pre_delete_user');
+
+ $this->db->trans_begin();
+
+ // remove user from groups
+ $this->remove_from_group(NULL, $id);
+
+ // delete user from users table should be placed after remove from group
+ $this->db->delete($this->tables['users'], array('id' => $id));
+
+ // if user does not exist in database then it returns FALSE else removes the user from groups
+ if ($this->db->affected_rows() == 0)
+ {
+ return FALSE;
+ }
+
+ if ($this->db->trans_status() === FALSE)
+ {
+ $this->db->trans_rollback();
+ $this->trigger_events(array('post_delete_user', 'post_delete_user_unsuccessful'));
+ $this->set_error('delete_unsuccessful');
+ return FALSE;
+ }
+
+ $this->db->trans_commit();
+
+ $this->trigger_events(array('post_delete_user', 'post_delete_user_successful'));
+ $this->set_message('delete_successful');
+ return TRUE;
+ }
+
+ /**
+ * update_last_login
+ *
+ * @return bool
+ * @author Ben Edmunds
+ **/
+ public function update_last_login($id)
+ {
+ $this->trigger_events('update_last_login');
+
+ $this->load->helper('date');
+
+ $this->trigger_events('extra_where');
+
+ $this->db->update($this->tables['users'], array('last_login' => time()), array('id' => $id));
+
+ return $this->db->affected_rows() == 1;
+ }
+
+ /**
+ * set_lang
+ *
+ * @return bool
+ * @author Ben Edmunds
+ **/
+ public function set_lang($lang = 'en')
+ {
+ $this->trigger_events('set_lang');
+
+ // if the user_expire is set to zero we'll set the expiration two years from now.
+ if($this->config->item('user_expire', 'ion_auth') === 0)
+ {
+ $expire = (60*60*24*365*2);
+ }
+ // otherwise use what is set
+ else
+ {
+ $expire = $this->config->item('user_expire', 'ion_auth');
+ }
+
+ set_cookie(array(
+ 'name' => 'lang_code',
+ 'value' => $lang,
+ 'expire' => $expire
+ ));
+
+ return TRUE;
+ }
+
+ /**
+ * set_session
+ *
+ * @return bool
+ * @author jrmadsen67
+ **/
+ public function set_session($user)
+ {
+
+ $this->trigger_events('pre_set_session');
+
+ $session_data = array(
+ 'identity' => $user->{$this->identity_column},
+ $this->identity_column => $user->{$this->identity_column},
+ 'email' => $user->email,
+ 'user_id' => $user->id, //everyone likes to overwrite id so we'll use user_id
+ 'old_last_login' => $user->last_login
+ );
+
+ $this->session->set_userdata($session_data);
+
+ $this->trigger_events('post_set_session');
+
+ return TRUE;
+ }
+
+ /**
+ * remember_user
+ *
+ * @return bool
+ * @author Ben Edmunds
+ **/
+ public function remember_user($id)
+ {
+ $this->trigger_events('pre_remember_user');
+
+ if (!$id)
+ {
+ return FALSE;
+ }
+
+ $user = $this->user($id)->row();
+
+ $salt = $this->salt();
+
+ $this->db->update($this->tables['users'], array('remember_code' => $salt), array('id' => $id));
+
+ if ($this->db->affected_rows() > -1)
+ {
+ // if the user_expire is set to zero we'll set the expiration two years from now.
+ if($this->config->item('user_expire', 'ion_auth') === 0)
+ {
+ $expire = (60*60*24*365*2);
+ }
+ // otherwise use what is set
+ else
+ {
+ $expire = $this->config->item('user_expire', 'ion_auth');
+ }
+
+ set_cookie(array(
+ 'name' => $this->config->item('identity_cookie_name', 'ion_auth'),
+ 'value' => $user->{$this->identity_column},
+ 'expire' => $expire
+ ));
+
+ set_cookie(array(
+ 'name' => $this->config->item('remember_cookie_name', 'ion_auth'),
+ 'value' => $salt,
+ 'expire' => $expire
+ ));
+
+ $this->trigger_events(array('post_remember_user', 'remember_user_successful'));
+ return TRUE;
+ }
+
+ $this->trigger_events(array('post_remember_user', 'remember_user_unsuccessful'));
+ return FALSE;
+ }
+
+ /**
+ * login_remembed_user
+ *
+ * @return bool
+ * @author Ben Edmunds
+ **/
+ public function login_remembered_user()
+ {
+ $this->trigger_events('pre_login_remembered_user');
+
+ // check for valid data
+ if (!get_cookie($this->config->item('identity_cookie_name', 'ion_auth'))
+ || !get_cookie($this->config->item('remember_cookie_name', 'ion_auth'))
+ || !$this->identity_check(get_cookie($this->config->item('identity_cookie_name', 'ion_auth'))))
+ {
+ $this->trigger_events(array('post_login_remembered_user', 'post_login_remembered_user_unsuccessful'));
+ return FALSE;
+ }
+
+ // get the user
+ $this->trigger_events('extra_where');
+ $query = $this->db->select($this->identity_column.', id, email, last_login')
+ ->where($this->identity_column, get_cookie($this->config->item('identity_cookie_name', 'ion_auth')))
+ ->where('remember_code', get_cookie($this->config->item('remember_cookie_name', 'ion_auth')))
+ ->limit(1)
+ ->order_by('id', 'desc')
+ ->get($this->tables['users']);
+
+ // if the user was found, sign them in
+ if ($query->num_rows() == 1)
+ {
+ $user = $query->row();
+
+ $this->update_last_login($user->id);
+
+ $this->set_session($user);
+
+ // extend the users cookies if the option is enabled
+ if ($this->config->item('user_extend_on_login', 'ion_auth'))
+ {
+ $this->remember_user($user->id);
+ }
+
+ $this->trigger_events(array('post_login_remembered_user', 'post_login_remembered_user_successful'));
+ return TRUE;
+ }
+
+ $this->trigger_events(array('post_login_remembered_user', 'post_login_remembered_user_unsuccessful'));
+ return FALSE;
+ }
+
+
+ /**
+ * create_group
+ *
+ * @author aditya menon
+ */
+ public function create_group($group_name = FALSE, $group_description = '', $additional_data = array())
+ {
+ // bail if the group name was not passed
+ if(!$group_name)
+ {
+ $this->set_error('group_name_required');
+ return FALSE;
+ }
+
+ // bail if the group name already exists
+ $existing_group = $this->db->get_where($this->tables['groups'], array('name' => $group_name))->num_rows();
+ if($existing_group !== 0)
+ {
+ $this->set_error('group_already_exists');
+ return FALSE;
+ }
+
+ $data = array('name'=>$group_name,'description'=>$group_description);
+
+ // filter out any data passed that doesnt have a matching column in the groups table
+ // and merge the set group data and the additional data
+ if (!empty($additional_data)) $data = array_merge($this->_filter_data($this->tables['groups'], $additional_data), $data);
+
+ $this->trigger_events('extra_group_set');
+
+ // insert the new group
+ $this->db->insert($this->tables['groups'], $data);
+ $group_id = $this->db->insert_id();
+
+ // report success
+ $this->set_message('group_creation_successful');
+ // return the brand new group id
+ return $group_id;
+ }
+
+ /**
+ * update_group
+ *
+ * @return bool
+ * @author aditya menon
+ **/
+ public function update_group($group_id = FALSE, $group_name = FALSE, $additional_data = array())
+ {
+ if (empty($group_id)) return FALSE;
+
+ $data = array();
+
+ if (!empty($group_name))
+ {
+ // we are changing the name, so do some checks
+
+ // bail if the group name already exists
+ $existing_group = $this->db->get_where($this->tables['groups'], array('name' => $group_name))->row();
+ if(isset($existing_group->id) && $existing_group->id != $group_id)
+ {
+ $this->set_error('group_already_exists');
+ return FALSE;
+ }
+
+ $data['name'] = $group_name;
+ }
+
+ // restrict change of name of the admin group
+ $group = $this->db->get_where($this->tables['groups'], array('id' => $group_id))->row();
+ if($this->config->item('admin_group', 'ion_auth') === $group->name && $group_name !== $group->name)
+ {
+ $this->set_error('group_name_admin_not_alter');
+ return FALSE;
+ }
+
+
+ // IMPORTANT!! Third parameter was string type $description; this following code is to maintain backward compatibility
+ // New projects should work with 3rd param as array
+ if (is_string($additional_data)) $additional_data = array('description' => $additional_data);
+
+
+ // filter out any data passed that doesnt have a matching column in the groups table
+ // and merge the set group data and the additional data
+ if (!empty($additional_data)) $data = array_merge($this->_filter_data($this->tables['groups'], $additional_data), $data);
+
+
+ $this->db->update($this->tables['groups'], $data, array('id' => $group_id));
+
+ $this->set_message('group_update_successful');
+
+ return TRUE;
+ }
+
+ /**
+ * delete_group
+ *
+ * @return bool
+ * @author aditya menon
+ **/
+ public function delete_group($group_id = FALSE)
+ {
+ // bail if mandatory param not set
+ if(!$group_id || empty($group_id))
+ {
+ return FALSE;
+ }
+ $group = $this->group($group_id)->row();
+ if($group->name == $this->config->item('admin_group', 'ion_auth'))
+ {
+ $this->trigger_events(array('post_delete_group', 'post_delete_group_notallowed'));
+ $this->set_error('group_delete_notallowed');
+ return FALSE;
+ }
+
+ $this->trigger_events('pre_delete_group');
+
+ $this->db->trans_begin();
+
+ // remove all users from this group
+ $this->db->delete($this->tables['users_groups'], array($this->join['groups'] => $group_id));
+ // remove the group itself
+ $this->db->delete($this->tables['groups'], array('id' => $group_id));
+
+ if ($this->db->trans_status() === FALSE)
+ {
+ $this->db->trans_rollback();
+ $this->trigger_events(array('post_delete_group', 'post_delete_group_unsuccessful'));
+ $this->set_error('group_delete_unsuccessful');
+ return FALSE;
+ }
+
+ $this->db->trans_commit();
+
+ $this->trigger_events(array('post_delete_group', 'post_delete_group_successful'));
+ $this->set_message('group_delete_successful');
+ return TRUE;
+ }
+
+ public function set_hook($event, $name, $class, $method, $arguments)
+ {
+ $this->_ion_hooks->{$event}[$name] = new stdClass;
+ $this->_ion_hooks->{$event}[$name]->class = $class;
+ $this->_ion_hooks->{$event}[$name]->method = $method;
+ $this->_ion_hooks->{$event}[$name]->arguments = $arguments;
+ }
+
+ public function remove_hook($event, $name)
+ {
+ if (isset($this->_ion_hooks->{$event}[$name]))
+ {
+ unset($this->_ion_hooks->{$event}[$name]);
+ }
+ }
+
+ public function remove_hooks($event)
+ {
+ if (isset($this->_ion_hooks->$event))
+ {
+ unset($this->_ion_hooks->$event);
+ }
+ }
+
+ protected function _call_hook($event, $name)
+ {
+ if (isset($this->_ion_hooks->{$event}[$name]) && method_exists($this->_ion_hooks->{$event}[$name]->class, $this->_ion_hooks->{$event}[$name]->method))
+ {
+ $hook = $this->_ion_hooks->{$event}[$name];
+
+ return call_user_func_array(array($hook->class, $hook->method), $hook->arguments);
+ }
+
+ return FALSE;
+ }
+
+ public function trigger_events($events)
+ {
+ if (is_array($events) && !empty($events))
+ {
+ foreach ($events as $event)
+ {
+ $this->trigger_events($event);
+ }
+ }
+ else
+ {
+ if (isset($this->_ion_hooks->$events) && !empty($this->_ion_hooks->$events))
+ {
+ foreach ($this->_ion_hooks->$events as $name => $hook)
+ {
+ $this->_call_hook($events, $name);
+ }
+ }
+ }
+ }
+
+ /**
+ * set_message_delimiters
+ *
+ * Set the message delimiters
+ *
+ * @return void
+ * @author Ben Edmunds
+ **/
+ public function set_message_delimiters($start_delimiter, $end_delimiter)
+ {
+ $this->message_start_delimiter = $start_delimiter;
+ $this->message_end_delimiter = $end_delimiter;
+
+ return TRUE;
+ }
+
+ /**
+ * set_error_delimiters
+ *
+ * Set the error delimiters
+ *
+ * @return void
+ * @author Ben Edmunds
+ **/
+ public function set_error_delimiters($start_delimiter, $end_delimiter)
+ {
+ $this->error_start_delimiter = $start_delimiter;
+ $this->error_end_delimiter = $end_delimiter;
+
+ return TRUE;
+ }
+
+ /**
+ * set_message
+ *
+ * Set a message
+ *
+ * @return void
+ * @author Ben Edmunds
+ **/
+ public function set_message($message)
+ {
+ $this->messages[] = $message;
+
+ return $message;
+ }
+
+
+
+ /**
+ * messages
+ *
+ * Get the messages
+ *
+ * @return void
+ * @author Ben Edmunds
+ **/
+ public function messages()
+ {
+ $_output = '';
+ foreach ($this->messages as $message)
+ {
+ $messageLang = $this->lang->line($message) ? $this->lang->line($message) : '##' . $message . '##';
+ $_output .= $this->message_start_delimiter . $messageLang . $this->message_end_delimiter;
+ }
+
+ return $_output;
+ }
+
+ /**
+ * messages as array
+ *
+ * Get the messages as an array
+ *
+ * @return array
+ * @author Raul Baldner Junior
+ **/
+ public function messages_array($langify = TRUE)
+ {
+ if ($langify)
+ {
+ $_output = array();
+ foreach ($this->messages as $message)
+ {
+ $messageLang = $this->lang->line($message) ? $this->lang->line($message) : '##' . $message . '##';
+ $_output[] = $this->message_start_delimiter . $messageLang . $this->message_end_delimiter;
+ }
+ return $_output;
+ }
+ else
+ {
+ return $this->messages;
+ }
+ }
+
+
+ /**
+ * clear_messages
+ *
+ * Clear messages
+ *
+ * @return void
+ * @author Ben Edmunds
+ **/
+ public function clear_messages()
+ {
+ $this->messages = array();
+
+ return TRUE;
+ }
+
+
+ /**
+ * set_error
+ *
+ * Set an error message
+ *
+ * @return void
+ * @author Ben Edmunds
+ **/
+ public function set_error($error)
+ {
+ $this->errors[] = $error;
+
+ return $error;
+ }
+
+ /**
+ * errors
+ *
+ * Get the error message
+ *
+ * @return void
+ * @author Ben Edmunds
+ **/
+ public function errors()
+ {
+ $_output = '';
+ foreach ($this->errors as $error)
+ {
+ $errorLang = $this->lang->line($error) ? $this->lang->line($error) : '##' . $error . '##';
+ $_output .= $this->error_start_delimiter . $errorLang . $this->error_end_delimiter;
+ }
+
+ return $_output;
+ }
+
+ /**
+ * errors as array
+ *
+ * Get the error messages as an array
+ *
+ * @return array
+ * @author Raul Baldner Junior
+ **/
+ public function errors_array($langify = TRUE)
+ {
+ if ($langify)
+ {
+ $_output = array();
+ foreach ($this->errors as $error)
+ {
+ $errorLang = $this->lang->line($error) ? $this->lang->line($error) : '##' . $error . '##';
+ $_output[] = $this->error_start_delimiter . $errorLang . $this->error_end_delimiter;
+ }
+ return $_output;
+ }
+ else
+ {
+ return $this->errors;
+ }
+ }
+
+
+ /**
+ * clear_errors
+ *
+ * Clear Errors
+ *
+ * @return void
+ * @author Ben Edmunds
+ **/
+ public function clear_errors()
+ {
+ $this->errors = array();
+
+ return TRUE;
+ }
+
+
+
+ protected function _filter_data($table, $data)
+ {
+ $filtered_data = array();
+ $columns = $this->db->list_fields($table);
+
+ if (is_array($data))
+ {
+ foreach ($columns as $column)
+ {
+ if (array_key_exists($column, $data))
+ $filtered_data[$column] = $data[$column];
+ }
+ }
+
+ return $filtered_data;
+ }
+
+ protected function _prepare_ip($ip_address) {
+ // just return the string IP address now for better compatibility
+ return $ip_address;
+ }
+}
diff --git a/application/views/auth/change_password.php b/application/views/auth/change_password.php
new file mode 100644
index 00000000..f8ce60b6
--- /dev/null
+++ b/application/views/auth/change_password.php
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/application/views/auth/create_group.php b/application/views/auth/create_group.php
new file mode 100644
index 00000000..86b07e93
--- /dev/null
+++ b/application/views/auth/create_group.php
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/application/views/auth/create_user.php b/application/views/auth/create_user.php
new file mode 100644
index 00000000..b292d7b4
--- /dev/null
+++ b/application/views/auth/create_user.php
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ';
+ echo lang('create_user_identity_label', 'identity');
+ echo ' ';
+ echo form_error('identity');
+ echo form_input($identity);
+ echo '
';
+ }
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/application/views/auth/deactivate_user.php b/application/views/auth/deactivate_user.php
new file mode 100644
index 00000000..85e9c36d
--- /dev/null
+++ b/application/views/auth/deactivate_user.php
@@ -0,0 +1,18 @@
+
+username);?>
+
+id);?>
+
+
+
+
+
+
+
+
+
+ $user->id)); ?>
+
+
+
+
\ No newline at end of file
diff --git a/application/views/auth/edit_group.php b/application/views/auth/edit_group.php
new file mode 100644
index 00000000..080dad7a
--- /dev/null
+++ b/application/views/auth/edit_group.php
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/application/views/auth/edit_user.php b/application/views/auth/edit_user.php
new file mode 100644
index 00000000..46e4190f
--- /dev/null
+++ b/application/views/auth/edit_user.php
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ion_auth->is_admin()): ?>
+
+
+
+
+ id) {
+ $checked= ' checked="checked"';
+ break;
+ }
+ }
+ ?>
+ >
+
+
+
+
+
+
+ id);?>
+
+
+
+
+
diff --git a/application/views/auth/email/activate.tpl.php b/application/views/auth/email/activate.tpl.php
new file mode 100644
index 00000000..e2436cf7
--- /dev/null
+++ b/application/views/auth/email/activate.tpl.php
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/application/views/auth/email/forgot_password.tpl.php b/application/views/auth/email/forgot_password.tpl.php
new file mode 100644
index 00000000..2cc5b02f
--- /dev/null
+++ b/application/views/auth/email/forgot_password.tpl.php
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/application/views/auth/email/new_password.tpl.php b/application/views/auth/email/new_password.tpl.php
new file mode 100644
index 00000000..f2239860
--- /dev/null
+++ b/application/views/auth/email/new_password.tpl.php
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/application/views/auth/forgot_password.php b/application/views/auth/forgot_password.php
new file mode 100644
index 00000000..5e969e03
--- /dev/null
+++ b/application/views/auth/forgot_password.php
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/application/views/auth/index.php b/application/views/auth/index.php
new file mode 100644
index 00000000..d9576447
--- /dev/null
+++ b/application/views/auth/index.php
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ first_name,ENT_QUOTES,'UTF-8');?>
+ last_name,ENT_QUOTES,'UTF-8');?>
+ email,ENT_QUOTES,'UTF-8');?>
+
+ groups as $group):?>
+ id, htmlspecialchars($group->name,ENT_QUOTES,'UTF-8')) ;?>
+
+
+ active) ? anchor("auth/deactivate/".$user->id, lang('index_active_link')) : anchor("auth/activate/". $user->id, lang('index_inactive_link'));?>
+ id, 'Edit') ;?>
+
+
+
+
+ |
\ No newline at end of file
diff --git a/application/views/auth/login.php b/application/views/auth/login.php
new file mode 100644
index 00000000..a43b939a
--- /dev/null
+++ b/application/views/auth/login.php
@@ -0,0 +1,16 @@
+
+
+
+ messages(); ?>
+ bs3_text('Email', 'username', ENVIRONMENT==='development' ? 'mhamzasite@gmail.com' : ''); ?>
+ bs3_password('Password', 'password', ENVIRONMENT==='development' ? '3267559' : ''); ?>
+
+
+ bs3_submit('Sign In', 'btn btn-primary btn-block btn-flat'); ?>
+
+
+ close(); ?>
+
+
+
+
\ No newline at end of file
diff --git a/application/views/auth/reset_password.php b/application/views/auth/reset_password.php
new file mode 100644
index 00000000..71017048
--- /dev/null
+++ b/application/views/auth/reset_password.php
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
From ef1da925862210671a236b0fa55b83c3839a150e Mon Sep 17 00:00:00 2001
From: M Hamza Siddiqui
Date: Tue, 24 Apr 2018 16:56:16 +0500
Subject: [PATCH 2/3] Update Build Number
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index e95261fd..839a669f 100755
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
## CodeIgniter 3 Bootstrap
-**Latest Build: 2016-07-02**
+**Latest Build: 2018-04-24**
**Note: This project is still in progress, but welcome for any issues encountered**
From 2092877e5eb3687321a8427a1cc410d407427e42 Mon Sep 17 00:00:00 2001
From: M Hamza Siddiqui
Date: Tue, 24 Apr 2018 19:20:42 +0500
Subject: [PATCH 3/3] Login Form Fix
---
application/views/auth/login.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/application/views/auth/login.php b/application/views/auth/login.php
index a43b939a..28082d26 100644
--- a/application/views/auth/login.php
+++ b/application/views/auth/login.php
@@ -2,8 +2,8 @@
messages(); ?>
- bs3_text('Email', 'username', ENVIRONMENT==='development' ? 'mhamzasite@gmail.com' : ''); ?>
- bs3_password('Password', 'password', ENVIRONMENT==='development' ? '3267559' : ''); ?>
+ bs3_text('Email', 'username', ''); ?>
+ bs3_password('Password', 'password', ''); ?>
bs3_submit('Sign In', 'btn btn-primary btn-block btn-flat'); ?>