application/libraries/DX_Auth.php
<?php
if (!defined('BASEPATH')) {
exit('No direct script access allowed');
}
/**
* DX Auth Class
*
* Authentication library for Code Igniter.
*
* @author Dexcell
* @version 1.0.4
* @based on CL Auth by Jason Ashdown (http://http://www.jasonashdown.co.uk/)
* @link http://dexcell.shinsengumiteam.com/dx_auth
* @license MIT License Copyright (c) 2008 Erick Hartanto
* @credits http://dexcell.shinsengumiteam.com/dx_auth/general/credits.html
*/
class DX_Auth
{
// Private
var $_banned;
var $_ban_reason;
var $_auth_error; // Contain user error when login
var $_captcha_image;
public function __construct() {
$this->ci = &get_instance();
log_message('debug', 'DX Auth Initialized');
// Load required library
//$this->ci->load->library('Session');
//$this->ci->load->database();
// Load DX Auth config
$this->ci->load->config('auth');
// Load DX Auth language
// $this->ci->lang->load('dx_auth');
// Load DX Auth event
$this->ci->load->library('DX_Auth_Event');
// Initialize
$this->_init();
}
/* Private function */
public function _init() {
// When we load this library, auto Login any returning users
$this->autologin();
// Init helper config variable
$this->email_activation = $this->ci->config->item('DX_email_activation');
$this->allow_registration = $this->ci->config->item('DX_allow_registration');
$this->captcha_registration = $this->ci->config->item('DX_captcha_registration');
$this->captcha_login = $this->ci->config->item('DX_captcha_login');
//Use recaptcha
$this->use_recaptcha = $this->ci->config->item('DX_use_recaptcha');
$this->use_audio_recaptcha = $this->ci->config->item('DX_use_audio_recaptcha');
// URIs
$this->banned_uri = $this->ci->config->item('DX_banned_uri');
$this->deny_uri = $this->ci->config->item('DX_deny_uri');
$this->login_uri = $this->ci->config->item('DX_login_uri');
$this->logout_uri = $this->ci->config->item('DX_logout_uri');
$this->register_uri = $this->ci->config->item('DX_register_uri');
$this->activate_uri = $this->ci->config->item('DX_activate_uri');
$this->forgot_password_uri = $this->ci->config->item('DX_forgot_password_uri');
$this->reset_password_uri = $this->ci->config->item('DX_reset_password_uri');
$this->change_password_uri = $this->ci->config->item('DX_change_password_uri');
$this->cancel_account_uri = $this->ci->config->item('DX_cancel_account_uri');
// Forms view
$this->login_view = $this->ci->config->item('DX_login_view');
$this->register_view = $this->ci->config->item('DX_register_view');
$this->forgot_password_view = $this->ci->config->item('DX_forgot_password_view');
$this->change_password_view = $this->ci->config->item('DX_change_password_view');
$this->cancel_account_view = $this->ci->config->item('DX_cancel_account_view');
// Pages view
$this->deny_view = $this->ci->config->item('DX_deny_view');
$this->banned_view = $this->ci->config->item('DX_banned_view');
$this->logged_in_view = $this->ci->config->item('DX_logged_in_view');
$this->logout_view = $this->ci->config->item('DX_logout_view');
$this->register_success_view = $this->ci->config->item('DX_register_success_view');
$this->activate_success_view = $this->ci->config->item('DX_activate_success_view');
$this->forgot_password_success_view = $this->ci->config->item('DX_forgot_password_success_view');
$this->reset_password_success_view = $this->ci->config->item('DX_reset_password_success_view');
$this->change_password_success_view = $this->ci->config->item('DX_change_password_success_view');
$this->register_disabled_view = $this->ci->config->item('DX_register_disabled_view');
$this->activate_failed_view = $this->ci->config->item('DX_activate_failed_view');
$this->reset_password_failed_view = $this->ci->config->item('DX_reset_password_failed_view');
}
public function _gen_pass($len = 8) {
// No Zero (for user clarity);
$pool = '123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$str = '';
for ($i = 0; $i < $len; $i++) {
$str .= substr($pool, mt_rand(0, strlen($pool) - 1), 1);
}
return $str;
}
/*
* Function: _encode
* Modified for DX_Auth
* Original Author: FreakAuth_light 1.1
*/
public function _encode($password) {
$majorsalt = '';
// if you set your encryption key let's use it
if ($this->ci->config->item('encryption_key') != '') {
// concatenates the encryption key and the password
$_password = $this->ci->config->item('encryption_key') . $password;
} else {
$_password = $password;
}
// if PHP5
if (function_exists('str_split')) {
$_pass = str_split($_password);
} // if PHP4
else {
$_pass = [];
if (is_string($_password)) {
for ($i = 0; $i < strlen($_password); $i++) {
array_push($_pass, $_password[$i]);
}
}
}
// encrypts every single letter of the password
foreach ($_pass as $_hashpass) {
$majorsalt .= md5($_hashpass);
}
// encrypts the string combinations of every single encrypted letter
// and finally returns the encrypted password
return md5($majorsalt);
}
public function _array_in_array($needle, $haystack) {
//Make sure $needle is an array for foreach
if (!is_array($needle)) {
$needle = [$needle];
}
//For each value in $needle, return TRUE if in $haystack
foreach ($needle as $pin) {
if (in_array($pin, $haystack)) {
return TRUE;
}
}
//Return FALSE if none of the values from $needle are found in $haystack
return FALSE;
}
public function _email($to, $from, $subject, $message) {
$this->ci->load->library('Email');
$email = $this->ci->email;
$email->from($from);
$email->to($to);
$email->subject($subject);
$email->message($message);
return $email->send();
}
// Set last ip and last login function when user login
public function _set_last_ip_and_last_login($user_id) {
$data = [];
if ($this->ci->config->item('DX_login_record_ip')) {
$data['last_ip'] = $this->ci->input->ip_address();
}
if ($this->ci->config->item('DX_login_record_time')) {
$data['last_login'] = date('Y-m-d H:i:s', time());
}
if (!empty($data)) {
// Load model
$this->ci->load->model('dx_auth/users', 'users');
// Update record
$this->ci->users->set_user($user_id, $data);
}
}
// Increase login attempt
public function _increase_login_attempt() {
if ($this->ci->config->item('DX_count_login_attempts') AND ! $this->is_max_login_attempts_exceeded()) {
// Load model
$this->ci->load->model('dx_auth/login_attempts', 'login_attempts');
// Increase login attempts for current IP
$this->ci->login_attempts->increase_attempt($this->ci->input->ip_address());
}
}
// Clear login attempts
public function _clear_login_attempts() {
if ($this->ci->config->item('DX_count_login_attempts')) {
// Load model
$this->ci->load->model('dx_auth/login_attempts', 'login_attempts');
// Clear login attempts for current IP
$this->ci->login_attempts->clear_attempts($this->ci->input->ip_address());
}
}
// Get role data from database by id, used in _set_session() function
// $parent_roles_id, $parent_roles_name is an array.
public function _get_role_data($role_id) {
// Load models
$this->ci->load->model('dx_auth/roles', 'roles');
$this->ci->load->model('dx_auth/permissions', 'permissions');
// Clear return value
$role_name = '';
$parent_roles_id = [];
$parent_roles_name = [];
$permission = [];
$parent_permissions = [];
/* Get role_name, parent_roles_id and parent_roles_name */
// Get role query from role id
$query = $this->ci->roles->get_role_by_id($role_id);
// Check if role exist
if ($query->num_rows() > 0) {
// Get row
$role = $query->row();
// Get role name
$role_name = $role->name;
/*
Code below will search if user role_id have parent_id > 0 (which mean role_id have parent role_id)
and do it recursively until parent_id reach 0 (no parent) or parent_id not found.
If anyone have better approach than this code, please let me know.
*/
// Check if role has parent id
if (isset($role->parent_id) && $role->parent_id > 0) {
// Add to result array
$parent_roles_id[] = $role->parent_id;
// Set variable used in looping
$finished = FALSE;
$parent_id = $role->parent_id;
// Get all parent id
while ($finished == FALSE) {
$i_query = $this->ci->roles->get_role_by_id($parent_id);
// If role exist
if ($i_query->num_rows() > 0) {
// Get row
$i_role = $i_query->row();
// Check if role doesn't have parent
if ($i_role->parent_id == 0) {
// Get latest parent name
$parent_roles_name[] = $i_role->name;
// Stop looping
$finished = TRUE;
} else {
// Change parent id for next looping
$parent_id = $i_role->parent_id;
// Add to result array
$parent_roles_id[] = $parent_id;
$parent_roles_name[] = $i_role->name;
}
} else {
// Remove latest parent_roles_id since parent_id not found
array_pop($parent_roles_id);
// Stop looping
$finished = TRUE;
}
}
}
}
/* End of Get role_name, parent_roles_id and parent_roles_name */
/* Get user and parents permission */
// Get user role permission
$permission = $this->ci->permissions->get_permission_data($role_id);
// Get user role parent permissions
if (!empty($parent_roles_id)) {
$parent_permissions = $this->ci->permissions->get_permissions_data($parent_roles_id);
}
/* End of Get user and parents permission */
if ($role_id) {
$data['role_name'] = Permitions::checkControlPanelAccess($role_id);
}
// Set return value
//$data['role_name'] = $role_name;
$data['parent_roles_id'] = $parent_roles_id;
$data['parent_roles_name'] = $parent_roles_name;
$data['permission'] = $permission;
$data['parent_permissions'] = $parent_permissions;
return $data;
}
/* Autologin related function */
public function _create_autologin($user_id) {
$result = FALSE;
// User wants to be remembered
$user = [
'key_id' => substr(md5(uniqid(rand() . $this->ci->input->cookie($this->ci->config->item('sess_cookie_name')))), 0, 16),
'user_id' => $user_id,
];
// Load Models
$this->ci->load->model('dx_auth/user_autologin', 'user_autologin');
// Prune keys
$this->ci->user_autologin->prune_keys($user['user_id']);
if ($this->ci->user_autologin->store_key($user['key_id'], $user['user_id'])) {
// Set Users AutoLogin cookie
$this->_auto_cookie($user);
$result = TRUE;
}
return $result;
}
public function autologin() {
$result = FALSE;
//if ($auto = $this->ci->input->cookie($this->ci->config->item('DX_autologin_cookie_name')) AND ! $this->ci->session->userdata('DX_logged_in'))
if ($auto = $this->ci->input->cookie($this->ci->config->item('DX_autologin_cookie_name'))) {
// Extract data
$auto = unserialize($auto);
if (isset($auto['key_id']) AND $auto['key_id'] AND $auto['user_id']) {
// Load Models
$this->ci->load->model('dx_auth/user_autologin', 'user_autologin');
// Get key
$query = $this->ci->user_autologin->get_key($auto['key_id'], $auto['user_id']);
if ($result = $query->row()) {
// User verified, log them in
$this->_set_session($result);
// Renew users cookie to prevent it from expiring
$this->_auto_cookie($auto);
// Set last ip and last login
$this->_set_last_ip_and_last_login($auto['user_id']);
$result = TRUE;
}
}
}
return $result;
}
public function _delete_autologin() {
if ($auto = $this->ci->input->cookie($this->ci->config->item('DX_autologin_cookie_name'))) {
// Load Cookie Helper
$this->ci->load->helper('cookie');
// Load Models
$this->ci->load->model('dx_auth/user_autologin', 'user_autologin');
// Extract data
$auto = unserialize($auto);
// Delete db entry
$this->ci->user_autologin->delete_key($auto['key_id'], $auto['user_id']);
// Make cookie expired
set_cookie($this->ci->config->item('DX_autologin_cookie_name'), '', -1);
}
}
public function _set_session($data) {
// Get role data
$role_data = $this->_get_role_data($data->role_id);
// Set session data array
$user = [
'DX_user_id' => $data->id,
'DX_username' => $data->username,
'DX_role_id' => $data->role_id,
'DX_role_name' => $role_data['role_name'],
'DX_parent_roles_id' => $role_data['parent_roles_id'], // Array of parent role_id
'DX_parent_roles_name' => $role_data['parent_roles_name'], // Array of parent role_name
'DX_permission' => $role_data['permission'],
'DX_parent_permissions' => $role_data['parent_permissions'],
'DX_logged_in' => TRUE,
];
$this->ci->session->set_userdata($user);
}
public function _auto_cookie($data) {
// Load Cookie Helper
$this->ci->load->helper('cookie');
$cookie = [
'name' => $this->ci->config->item('DX_autologin_cookie_name'),
'value' => serialize($data),
'expire' => $this->ci->config->item('DX_autologin_cookie_life'),
];
set_cookie($cookie);
}
/* End of Auto login related function */
/* Helper function */
public function check_uri_permissions() {
// First check if user already logged in or not
if ($this->is_logged_in()) {
// If user is not admin
if (!$this->is_admin()) {
// Get variable from current URI
$controller = '/' . $this->ci->uri->rsegment(1) . '/';
if ($this->ci->uri->rsegment(2) != '') {
$action = $controller . $this->ci->uri->rsegment(2) . '/';
} else {
$action = $controller . 'index/';
}
// Get URI permissions from role and all parents
// Note: URI permissions is saved in 'uri' key
$roles_allowed_uris = $this->get_permissions_value('uri');
// Variable to determine if URI found
$found = FALSE;
// Loop each roles URI permissions
foreach ($roles_allowed_uris as $allowed_uris) {
// Check if user allowed to access URI
if ($this->_array_in_array(['/', $controller, $action], $allowed_uris)) {
$found = TRUE;
// Stop loop
break;
}
}
// Trigger event
$this->ci->dx_auth_event->checked_uri_permissions($this->get_user_id(), $found);
if (!$found) {
// User didn't have previlege to access current URI, so we show user 403 forbidden access
$this->deny_access();
}
}
} else {
// User haven't logged in, so just redirect user to login page
$this->deny_access('login');
}
}
/*
Obsolete in 1.0.2 and above, do not use this function.
Use check_uri_permisisons() instead
public function check_role_uri()
{
}
*/
/*
Get permission value from specified key.
Call this function only when user is logged in already.
$key is permission array key (Note: permissions is saved as array in table).
If $check_parent is TRUE means if permission value not found in user role, it will try to get permission value from parent role.
Returning value if permission found, otherwise returning NULL
*/
public function get_permission_value($key, $check_parent = TRUE) {
// Default return value
$result = NULL;
// Get current user permission
$permission = $this->ci->session->userdata('DX_permission');
// Check if key is in user permission array
if (array_key_exists($key, $permission)) {
$result = $permission[$key];
} // Key not found
else {
if ($check_parent) {
// Get current user parent permissions
$parent_permissions = $this->ci->session->userdata('DX_parent_permissions');
// Check parent permissions array
foreach ($parent_permissions as $permission) {
if (array_key_exists($key, $permission)) {
$result = $permission[$key];
break;
}
}
}
}
// Trigger event
$this->ci->dx_auth_event->got_permission_value($this->get_user_id(), $key);
return $result;
}
/*
Get permissions value from specified key.
Call this function only when user is logged in already.
This will get user permission, and it's parents permissions.
$array_key = 'default'. Array ordered using 0, 1, 2 as array key.
$array_key = 'role_id'. Array ordered using role_id as array key.
$array_key = 'role_name'. Array ordered using role_name as array key.
Returning array of value if permission found, otherwise returning NULL.
*/
/**
* @param string $key
*/
public function get_permissions_value($key, $array_key = 'default') {
$result = [];
$role_id = $this->ci->session->userdata('DX_role_id');
$role_name = $this->ci->session->userdata('DX_role_name');
$parent_roles_id = $this->ci->session->userdata('DX_parent_roles_id');
$parent_roles_name = $this->ci->session->userdata('DX_parent_roles_name');
// Get current user permission
$value = $this->get_permission_value($key, FALSE);
if ($array_key == 'role_id') {
$result[$role_id] = $value;
} elseif ($array_key == 'role_name') {
$result[$role_name] = $value;
} else {
array_push($result, $value);
}
// Get current user parent permissions
$parent_permissions = $this->ci->session->userdata('DX_parent_permissions');
$i = 0;
foreach ($parent_permissions as $permission) {
if (array_key_exists($key, $permission)) {
$value = $permission[$key];
}
if ($array_key == 'role_id') {
// It's safe to use $parents_roles_id[$i] because array order is same with permission array
$result[$parent_roles_id[$i]] = $value;
} elseif ($array_key == 'role_name') {
// It's safe to use $parents_roles_name[$i] because array order is same with permission array
$result[$parent_roles_name[$i]] = $value;
} else {
array_push($result, $value);
}
$i++;
}
// Trigger event
$this->ci->dx_auth_event->got_permissions_value($this->get_user_id(), $key);
return $result;
}
public function deny_access($uri = 'deny') {
$this->ci->load->helper('url');
if ($uri == 'login') {
redirect($this->ci->config->item('DX_login_uri'), 'location');
} else if ($uri == 'banned') {
redirect($this->ci->config->item('DX_banned_uri'), 'location');
} else {
redirect($this->ci->config->item('DX_deny_uri'), 'location');
}
exit;
}
// Get user id
public function get_user_id() {
return $this->ci->session->userdata('DX_user_id');
}
// Get username string
public function get_username() {
return $this->ci->session->userdata('DX_username');
}
// Get useremail string
public function get_user_email() {
$user = $this->ci->db
->where('id', $this->get_user_id())
->get('users');
if ($user) {
$user = $user->row_array();
return $user['email'];
} else {
return '';
}
}
// Get user role id
public function get_role_id() {
return $this->ci->session->userdata('DX_role_id');
}
// Get user role name
public function get_role_name() {
return $this->ci->session->userdata('DX_role_name');
}
// Check is user is has admin privilege
public function is_admin() {
if (PHP_SAPI == 'cli') {
return true;
}
return strtolower($this->ci->session->userdata('DX_role_name')) == 'admin';
}
// Check if user has $roles privilege
// If $use_role_name TRUE then $roles is name such as 'admin', 'editor', 'etc'
// else $roles is role_id such as 0, 1, 2
// If $check_parent is TRUE means if roles not found in user role, it will check if user role parent has that roles
public function is_role($roles = [], $use_role_name = TRUE, $check_parent = TRUE) {
// Default return value
$result = FALSE;
// Build checking array
$check_array = [];
if ($check_parent) {
// Add parent roles into check array
if ($use_role_name) {
$check_array = $this->ci->session->userdata('DX_parent_roles_name');
} else {
$check_array = $this->ci->session->userdata('DX_parent_roles_id');
}
}
// Add current role into check array
if ($use_role_name) {
array_push($check_array, $this->ci->session->userdata('DX_role_name'));
} else {
array_push($check_array, $this->ci->session->userdata('DX_role_id'));
}
// If $roles not array then we add it into an array
if (!is_array($roles)) {
$roles = [$roles];
}
if ($use_role_name) {
// Convert check array into lowercase since we want case insensitive checking
for ($i = 0; $i < count($check_array); $i++) {
$check_array[$i] = strtolower($check_array[$i]);
}
// Convert roles into lowercase since we want insensitive checking
for ($i = 0; $i < count($roles); $i++) {
$roles[$i] = strtolower($roles[$i]);
}
}
// Check if roles exist in check_array
if ($this->_array_in_array($roles, $check_array)) {
$result = TRUE;
}
return $result;
}
// Check if user is logged in
public function is_logged_in() {
return $this->ci->session->userdata('DX_logged_in');
}
// Check if user is a banned user, call this only after calling login() and returning FALSE
public function is_banned() {
return $this->_banned;
}
// Get ban reason, call this only after calling login() and returning FALSE
public function get_ban_reason() {
return $this->_ban_reason;
}
// Check if username is available to use, by making sure there is no same username in the database
public function is_username_available($username) {
// Load Models
$this->ci->load->model('dx_auth/users', 'users');
$this->ci->load->model('dx_auth/user_temp', 'user_temp');
$users = $this->ci->users->check_username($username);
$temp = $this->ci->user_temp->check_username($username);
return $users->num_rows() + $temp->num_rows() == 0;
}
// Check if email is available to use, by making sure there is no same email in the database
public function is_email_available($email) {
// Load Models
$this->ci->load->model('dx_auth/users', 'users');
$this->ci->load->model('dx_auth/user_temp', 'user_temp');
$users = $this->ci->users->check_email($email);
$temp = $this->ci->user_temp->check_email($email);
return $users->num_rows() + $temp->num_rows() == 0;
}
// Check if login attempts bigger than max login attempts specified in config
public function is_max_login_attempts_exceeded() {
$this->ci->load->model('dx_auth/login_attempts', 'login_attempts');
return ($this->ci->login_attempts->check_attempts($this->ci->input->ip_address())->num_rows() >= $this->ci->config->item('DX_max_login_attempts'));
}
public function get_auth_error() {
return $this->_auth_error;
}
/* End of Helper function */
/* Main function */
// $login is username or email or both depending on setting in config file
public function login($login, $password, $remember = TRUE) {
// Load Models
$this->ci->load->model('dx_auth/users', 'users');
$this->ci->load->model('dx_auth/user_temp', 'user_temp');
$this->ci->load->model('dx_auth/login_attempts', 'login_attempts');
// Default return value
$result = FALSE;
if (!empty($login) AND ! empty($password)) {
// Get which function to use based on config
if ($this->ci->config->item('DX_login_using_username') AND $this->ci->config->item('DX_login_using_email')) {
$get_user_function = 'get_login';
} else if ($this->ci->config->item('DX_login_using_email')) {
$get_user_function = 'get_user_by_email';
} else {
$get_user_function = 'get_user_by_username';
}
// Get user query
if ($query = $this->ci->users->$get_user_function($login) AND $query->num_rows() == 1) {
// Get user record
$row = $query->row();
// Check if user is banned or not
if ($row->banned > 0) {
// Set user as banned
$this->_banned = TRUE;
// Set ban reason
$this->_ban_reason = $row->ban_reason;
} else {
// If it's not a banned user then try to login
$password = $this->_encode($password);
$stored_hash = $row->password;
// Is password matched with hash in database ?
if (crypt($password, $stored_hash) === $stored_hash) {
// Log in user
$this->_set_session($row);
if ($row->newpass) {
// Clear any Reset Passwords
$this->ci->users->clear_newpass($row->id);
}
if ($remember) {
// Create auto login if user want to be remembered
$this->_create_autologin($row->id);
}
// Set last ip and last login
$this->_set_last_ip_and_last_login($row->id);
// Clear login attempts
$this->_clear_login_attempts();
// Trigger event
$this->ci->dx_auth_event->user_logged_in($row->id);
// Set return value
$result = TRUE;
} else {
// Increase login attempts
$this->_increase_login_attempt();
// Set error message
$this->_auth_error = lang('auth login incorrect password');
}
}
} elseif ($query = $this->ci->user_temp->$get_user_function($login) AND $query->num_rows() == 1) {
// Check if login is still not activated
// Set error message
$this->_auth_error = lang('auth not activated');
} else {
// Increase login attempts
$this->_increase_login_attempt();
// Set error message
$this->_auth_error = lang('auth login username not exist');
}
}
return $result;
}
public function logout() {
// Trigger event
$this->ci->dx_auth_event->user_logging_out($this->ci->session->userdata('DX_user_id'));
// Delete auto login
if ($this->ci->input->cookie($this->ci->config->item('DX_autologin_cookie_name'))) {
$this->_delete_autologin();
}
// Destroy session
$this->ci->session->sess_destroy();
}
public function register($username, $password, $email, $address = '', $key, $phone = '', $login_user = TRUE) {
// Load Models
$this->ci->load->model('dx_auth/users', 'users');
$this->ci->load->model('dx_auth/user_temp', 'user_temp');
$this->ci->load->helper('url');
// Default return value
$result = FALSE;
$siteSettings = $this->ci->cms_base->get_settings();
$new_user = [
'username' => $username,
'password' => crypt($this->_encode($password)),
'address' => $address,
'email' => $email,
'key' => $key,
'phone' => $phone,
'last_ip' => $this->ci->input->ip_address(),
'role_id' => $siteSettings['users_registration_role_id'] ?: 0,
];
// Do we need to send email to activate user
if ($this->ci->config->item('DX_email_activation')) {
// Add activation key to user array
$new_user['activation_key'] = md5(rand() . microtime());
// Create temporary user in database which means the user still unactivated.
$insert = $this->ci->user_temp->create_temp($new_user);
$from = $this->ci->config->item('DX_webmaster_email');
$subject = sprintf(lang('auth activate subject'), $this->ci->config->item('DX_website_name'));
// Activation Link
$new_user['activate_url'] = site_url($this->ci->config->item('DX_activate_uri') . "{$new_user['email']}/{$new_user['activation_key']}");
// Trigger event and get email content
$this->ci->dx_auth_event->sending_activation_email($new_user, $message);
// Send email with activation link
// $this->_email($email, $from, $subject, $message);
} else {
// Create user
$insert = $this->ci->users->create_user($new_user);
$last_user_id = $this->ci->db->insert_id();
foreach ($this->ci->input->post('custom_field') as $k => $custom_fields) {
$this->ci->db->insert(
'custom_fields_data',
[
'field_id' => $k,
'entity_id' => $last_user_id,
'field_data' => $custom_fields,
'locale' => \MY_Controller::defaultLocale(),
]
);
}
// Trigger event
$this->ci->dx_auth_event->user_activated($last_user_id);
}
if ($insert) {
// Replace password with plain for email
$new_user['password'] = $password;
$new_user['id_user'] = $last_user_id;
$result = $new_user;
// Send email based on config
// Check if user need to activate it's account using email
if ($this->ci->config->item('DX_email_activation')) {
// Create email
$from = $this->ci->config->item('DX_webmaster_email');
$subject = sprintf(lang('auth activate subject'), $this->ci->config->item('DX_website_name'));
// Activation Link
$new_user['activate_url'] = site_url();
// Trigger event and get email content
$this->ci->dx_auth_event->sending_account_email($new_user, $message);
// Send email with activation link
// $this->_email($email, $from, $subject, $message);
} else {
// Check if need to email account details
if ($this->ci->config->item('DX_email_account_details')) {
// Create email
$from = $this->ci->config->item('DX_webmaster_email');
$subject = sprintf(lang('auth account subject'), $this->ci->config->item('DX_website_name'));
// Trigger event and get email content
$this->ci->dx_auth_event->sending_account_email($new_user, $message);
// Send email with account details
// $this->_email($email, $from, $subject, $message);
}
$user_variables = [
'user_name' => $username,
'user_password' => $password,
'user_address' => $address,
'user_email' => $email,
'user_phone' => $phone,
];
\cmsemail\email::getInstance()->sendEmail($email, 'create_user', $user_variables);
if ($login_user) {
if ($this->login($email, $password)) {
if (class_exists('ShopCore')) {
ShopCore::app()->SCart->transferCartData();
}
if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) != 'xmlhttprequest') {
redirect('', 'location');
}
// if ($_SERVER['HTTP_X_REQUESTED_WITH'] != 'XMLHttpRequest') {
}
}
}
}
return $result;
}
public function forgot_password($login) {
// Default return value
$result = FALSE;
if ($login) {
// Load Model
$this->ci->load->model('dx_auth/users', 'users');
// Load Helper
$this->ci->load->helper('url');
// Get login and check if it's exist
if ($query = $this->ci->users->get_login($login) AND $query->num_rows() == 1) {
// Get User data
$row = $query->row();
// Check if there is already new password created but waiting to be activated for this login
if (strtotime($row->newpass_time) < time()) {
// Appearantly there is no password created yet for this login, so we create new password
$data['password'] = $this->_gen_pass();
// Encode & Crypt password
$encode = crypt($this->_encode($data['password']));
// Create key
$data['key'] = md5(rand() . microtime());
// Create new password (but it haven't activated yet)
$this->ci->users->newpass($row->id, $encode, $data['key']);
// Create reset password link to be included in email
$data['reset_password_uri'] = site_url($this->ci->config->item('DX_reset_password_uri') . "{$row->email}/{$data['key']}");
// Trigger event and get email content
// $this->ci->dx_auth_event->sending_forgot_password_email($data, $message);
$settings = $this->ci->cms_base->get_settings();
$replaceData = [
'webSiteName' => $settings['site_title'] ? $settings['site_title'] : $this->ci->config->item('DX_website_name'),
'resetPasswordUri' => $data['reset_password_uri'],
'password' => $data['password'],
'key' => $data['key'],
'webMasterEmail' => $this->ci->config->item('DX_webmaster_email'),
];
\cmsemail\email::getInstance()->sendEmail($row->email, 'forgot_password', $replaceData);
// Send instruction email
//$this->_email($row->email, $from, $subject, $message);
$result = TRUE;
} else {
// There is already new password waiting to be activated
$this->_auth_error = lang('auth request sent');
}
} else {
$this->_auth_error = lang('auth username or email not exist');
}
}
return $result;
}
public function reset_password($email, $key = '') {
// Load Models
$this->ci->load->model('dx_auth/users', 'users');
$this->ci->load->model('dx_auth/user_autologin', 'user_autologin');
// Default return value
$result = FALSE;
// Default user_id set to none
$user_id = 0;
// Get user id
if ($query = $this->ci->users->get_user_by_email($email) AND $query->num_rows() == 1) {
$user_id = $query->row()->id;
// Try to activate new password
if (!empty($email) AND ! empty($key) AND $this->ci->users->activate_newpass($user_id, $key) AND $this->ci->db->affected_rows() > 0) {
// Clear previously setup new password and keys
$this->ci->user_autologin->clear_keys($user_id);
$result = TRUE;
}
}
return $result;
}
public function activate($email, $key = '') {
// Load Models
$this->ci->load->model('dx_auth/users', 'users');
$this->ci->load->model('dx_auth/user_temp', 'user_temp');
// Default return value
$result = FALSE;
if ($this->ci->config->item('DX_email_activation')) {
// Delete user whose account expired (not activated until expired time)
$this->ci->user_temp->prune_temp();
}
// Activate user
if ($query = $this->ci->user_temp->activate_user($email, $key) AND $query->num_rows() > 0) {
// Get user
$row = $query->row_array();
$del = $row['id'];
// Unset any unwanted fields
unset($row['id']); // We don't want to copy the id across
unset($row['activation_key']);
// Create user
if ($this->ci->users->create_user($row)) {
// Trigger event
$this->ci->dx_auth_event->user_activated($this->ci->db->insert_id());
// Delete user from temp
$this->ci->user_temp->delete_user($del);
$result = TRUE;
}
}
return $result;
}
public function change_password($old_pass, $new_pass) {
// Load Models
$this->ci->load->model('dx_auth/users', 'users');
// Default return value
$result = FAlSE;
// Search current logged in user in database
if ($query = $this->ci->users->get_user_by_id($this->ci->session->userdata('DX_user_id')) AND $query->num_rows() > 0) {
// Get current logged in user
$row = $query->row();
$pass = $this->_encode($old_pass);
// Check if old password correct
if (crypt($pass, $row->password) === $row->password) {
// Crypt and encode new password
$new_pass_for_user = $new_pass;
$new_pass = crypt($this->_encode($new_pass));
// Replace old password with new password
$this->ci->users->change_password($this->ci->session->userdata('DX_user_id'), $new_pass);
// Trigger event
$this->ci->dx_auth_event->user_changed_password($this->ci->session->userdata('DX_user_id'), $new_pass);
$replaceData = [
'user_name' => $row->username,
'password' => $new_pass_for_user,
];
\cmsemail\email::getInstance()->sendEmail($row->email, 'change_password', $replaceData);
$result = TRUE;
} else {
$this->_auth_error = lang('auth incorrect old password');
}
}
return $result;
}
public function cancel_account($password) {
// Load Models
$this->ci->load->model('dx_auth/users', 'users');
// Default return value
$result = FAlSE;
// Search current logged in user in database
if ($query = $this->ci->users->get_user_by_id($this->ci->session->userdata('DX_user_id')) AND $query->num_rows() > 0) {
// Get current logged in user
$row = $query->row();
$pass = $this->_encode($password);
// Check if password correct
if (crypt($pass, $row->password) === $row->password) {
// Trigger event
$this->ci->dx_auth_event->user_canceling_account($this->ci->session->userdata('DX_user_id'));
// Delete user
$result = $this->ci->users->delete_user($this->ci->session->userdata('DX_user_id'));
// Force logout
$this->logout();
} else {
$this->_auth_error = lang('auth incorrect password');
}
}
return $result;
}
/* End of main function */
/* Captcha related function */
public function captcha() {
$this->ci->load->helper('dx_captcha');
// Load library SESSION
$vals = [
'img_path' => $this->ci->config->item('DX_captcha_path'),
'img_url' => media_url() . 'captcha/',
'font_path' => $this->ci->config->item('DX_captcha_fonts_path'),
'font_size' => $this->ci->config->item('DX_captcha_font_size'),
'img_width' => $this->ci->config->item('DX_captcha_width'),
'img_height' => $this->ci->config->item('DX_captcha_height'),
'show_grid' => $this->ci->config->item('DX_captcha_grid'),
'expiration' => $this->ci->config->item('DX_captcha_expire'),
];
$cap = create_captcha($vals);
$store = [
'captcha_word' => $cap['word'],
'captcha_time' => $cap['time'],
];
// Plain, simple but effective
$this->ci->session->set_flashdata($store);
// Set our captcha
$this->_captcha_image = $cap['image'];
}
public function get_captcha_image() {
if ($this->use_recaptcha) {
return $this->_get_recaptcha_data();
} else {
return $this->_captcha_image;
}
}
// Check if captcha already expired
// Use this in callback function in your form validation
public function is_captcha_expired() {
// Captcha Expired
list($usec, $sec) = explode(' ', microtime());
$now = ((float) $usec + (float) $sec);
// Check if captcha already expired
return (($this->ci->session->flashdata('captcha_time') + $this->ci->config->item('DX_captcha_expire')) < $now);
}
// Check is captcha match with code
// Use this in callback function in your form validation
public function is_captcha_match($code) {
// Just check if code is the same value with flash data captcha_word which created in captcha() function
if ($this->ci->config->item('DX_captcha_case_sensetive')) {
return ($code == $this->ci->session->flashdata('captcha_word'));
} else {
return (strtolower($code) == strtolower($this->ci->session->flashdata('captcha_word')));
}
}
/* End of captcha related function */
public function captcha_check($code) {
$CI = get_instance();
$result = TRUE;
if ($this->use_recaptcha) {
$result = $this->is_recaptcha_match();
if (!$result) {
$CI->form_validation->set_message('captcha_check', lang('Improper protection code'));
}
} else {
if ($this->is_captcha_expired()) {
// Will replace this error msg with $lang
$CI->form_validation->set_message('captcha_check', lang('Improper protection code'));
$result = FALSE;
} elseif (!$this->is_captcha_match($code)) {
$CI->form_validation->set_message('captcha_check', lang('Improper protection code'));
$result = FALSE;
}
}
return $result;
}
/* Recaptcha function */
public function get_recaptcha_reload_link($text = 'Get another CAPTCHA') {
return '<a href="javascript:Recaptcha.reload()">' . $text . '</a>';
}
public function get_recaptcha_switch_image_audio_link($switch_image_text = 'Get an image CAPTCHA', $switch_audio_text = 'Get an audio CAPTCHA') {
return '<div class="recaptcha_only_if_image"><a href="javascript:Recaptcha.switch_type(\'audio\')">' . $switch_audio_text . '</a></div>
<div class="recaptcha_only_if_audio"><a href="javascript:Recaptcha.switch_type(\'image\')">' . $switch_image_text . '</a></div>';
}
public function get_recaptcha_label($image_text = 'Enter the words above', $audio_text = 'Enter the numbers you hear') {
return '<span class="recaptcha_only_if_image">' . $image_text . '</span>
<span class="recaptcha_only_if_audio">' . $audio_text . '</span>';
}
// Get captcha image
public function get_recaptcha_image() {
return '<div id="recaptcha_image"></div>';
}
// Get captcha input box
// IMPORTANT: You should at least use this function when showing captcha even for testing, otherwise reCAPTCHA image won't show up
// because reCAPTCHA javascript will try to find input type with id="recaptcha_response_field" and name="recaptcha_response_field"
public function get_recaptcha_input() {
return '<input type="text" id="recaptcha_response_field" name="recaptcha_response_field" />';
}
// Get recaptcha javascript and non javasript html
// IMPORTANT: you should put call this function the last, after you are using some of get_recaptcha_xxx function above.
public function get_recaptcha_html() {
// Load reCAPTCHA helper function
$this->ci->load->helper('recaptcha');
// Add custom theme so we can get only image
$options = "<script>
var RecaptchaOptions = {
theme: 'clean',
custom_theme_widget: 'recaptcha_widget'
};
</script>";
// Get reCAPTCHA javascript and non javascript HTML
$html = recaptcha_get_html($this->ci->config->item('DX_recaptcha_public_key'));
return $options . $html;
}
// Check if entered captcha code match with the image.
// Use this in callback function in your form validation
public function is_recaptcha_match() {
$this->ci->load->helper('recaptcha');
$resp = recaptcha_check_answer($this->ci->config->item('DX_recaptcha_private_key'), $_SERVER['REMOTE_ADDR'], $_POST['recaptcha_challenge_field'], $_POST['recaptcha_response_field']);
return $resp->is_valid;
}
private function _get_recaptcha_data() {
return $this->get_recaptcha_html();
}
/* End of Recaptcha function */
}