Advertisement
Guest User

Untitled

a guest
Jul 28th, 2016
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 53.23 KB | None | 0 0
  1. <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
  2.  
  3. class Ion_auth_model extends CI_Model
  4. {
  5. /**
  6. * Holds an array of tables used
  7. *
  8. * @var array
  9. **/
  10. public $tables = array();
  11.  
  12. /**
  13. * activation code
  14. *
  15. * @var string
  16. **/
  17. public $activation_code;
  18.  
  19. /**
  20. * forgotten password key
  21. *
  22. * @var string
  23. **/
  24. public $forgotten_password_code;
  25.  
  26. /**
  27. * new password
  28. *
  29. * @var string
  30. **/
  31. public $new_password;
  32.  
  33. /**
  34. * Identity
  35. *
  36. * @var string
  37. **/
  38. public $identity;
  39.  
  40. /**
  41. * Where
  42. *
  43. * @var array
  44. **/
  45. public $_ion_where = array();
  46.  
  47. /**
  48. * Select
  49. *
  50. * @var array
  51. **/
  52. public $_ion_select = array();
  53.  
  54. /**
  55. * Like
  56. *
  57. * @var array
  58. **/
  59. public $_ion_like = array();
  60.  
  61. /**
  62. * Limit
  63. *
  64. * @var string
  65. **/
  66. public $_ion_limit = NULL;
  67.  
  68. /**
  69. * Offset
  70. *
  71. * @var string
  72. **/
  73. public $_ion_offset = NULL;
  74.  
  75. /**
  76. * Order By
  77. *
  78. * @var string
  79. **/
  80. public $_ion_order_by = NULL;
  81.  
  82. /**
  83. * Order
  84. *
  85. * @var string
  86. **/
  87. public $_ion_order = NULL;
  88.  
  89. /**
  90. * Hooks
  91. *
  92. * @var object
  93. **/
  94. protected $_ion_hooks;
  95.  
  96. /**
  97. * Response
  98. *
  99. * @var string
  100. **/
  101. protected $response = NULL;
  102.  
  103. /**
  104. * message (uses lang file)
  105. *
  106. * @var string
  107. **/
  108. protected $messages;
  109.  
  110. /**
  111. * error message (uses lang file)
  112. *
  113. * @var string
  114. **/
  115. protected $errors;
  116.  
  117. /**
  118. * error start delimiter
  119. *
  120. * @var string
  121. **/
  122. protected $error_start_delimiter;
  123.  
  124. /**
  125. * error end delimiter
  126. *
  127. * @var string
  128. **/
  129. protected $error_end_delimiter;
  130.  
  131. /**
  132. * caching of users and their groups
  133. *
  134. * @var array
  135. **/
  136. public $_cache_user_in_group = array();
  137.  
  138. /**
  139. * caching of groups
  140. *
  141. * @var array
  142. **/
  143. protected $_cache_groups = array();
  144.  
  145. public function __construct()
  146. {
  147. parent::__construct();
  148. $this->load->database();
  149. $this->load->config('ion_auth', TRUE);
  150. $this->load->helper('cookie');
  151. $this->load->helper('date');
  152. $this->lang->load('ion_auth');
  153.  
  154. // initialize db tables data
  155. $this->tables = $this->config->item('tables', 'ion_auth');
  156.  
  157. //initialize data
  158. $this->identity_column = $this->config->item('identity', 'ion_auth');
  159. $this->store_salt = $this->config->item('store_salt', 'ion_auth');
  160. $this->salt_length = $this->config->item('salt_length', 'ion_auth');
  161. $this->join = $this->config->item('join', 'ion_auth');
  162.  
  163.  
  164. // initialize hash method options (Bcrypt)
  165. $this->hash_method = $this->config->item('hash_method', 'ion_auth');
  166. $this->default_rounds = $this->config->item('default_rounds', 'ion_auth');
  167. $this->random_rounds = $this->config->item('random_rounds', 'ion_auth');
  168. $this->min_rounds = $this->config->item('min_rounds', 'ion_auth');
  169. $this->max_rounds = $this->config->item('max_rounds', 'ion_auth');
  170.  
  171.  
  172. // initialize messages and error
  173. $this->messages = array();
  174. $this->errors = array();
  175. $delimiters_source = $this->config->item('delimiters_source', 'ion_auth');
  176.  
  177. // load the error delimeters either from the config file or use what's been supplied to form validation
  178. if ($delimiters_source === 'form_validation')
  179. {
  180. // load in delimiters from form_validation
  181. // to keep this simple we'll load the value using reflection since these properties are protected
  182. $this->load->library('form_validation');
  183. $form_validation_class = new ReflectionClass("CI_Form_validation");
  184.  
  185. $error_prefix = $form_validation_class->getProperty("_error_prefix");
  186. $error_prefix->setAccessible(TRUE);
  187. $this->error_start_delimiter = $error_prefix->getValue($this->form_validation);
  188. $this->message_start_delimiter = $this->error_start_delimiter;
  189.  
  190. $error_suffix = $form_validation_class->getProperty("_error_suffix");
  191. $error_suffix->setAccessible(TRUE);
  192. $this->error_end_delimiter = $error_suffix->getValue($this->form_validation);
  193. $this->message_end_delimiter = $this->error_end_delimiter;
  194. }
  195. else
  196. {
  197. // use delimiters from config
  198. $this->message_start_delimiter = $this->config->item('message_start_delimiter', 'ion_auth');
  199. $this->message_end_delimiter = $this->config->item('message_end_delimiter', 'ion_auth');
  200. $this->error_start_delimiter = $this->config->item('error_start_delimiter', 'ion_auth');
  201. $this->error_end_delimiter = $this->config->item('error_end_delimiter', 'ion_auth');
  202. }
  203.  
  204.  
  205. // initialize our hooks object
  206. $this->_ion_hooks = new stdClass;
  207.  
  208. // load the bcrypt class if needed
  209. if ($this->hash_method == 'bcrypt') {
  210. if ($this->random_rounds)
  211. {
  212. $rand = rand($this->min_rounds,$this->max_rounds);
  213. $params = array('rounds' => $rand);
  214. }
  215. else
  216. {
  217. $params = array('rounds' => $this->default_rounds);
  218. }
  219.  
  220. $params['salt_prefix'] = $this->config->item('salt_prefix', 'ion_auth');
  221. $this->load->library('bcrypt',$params);
  222. }
  223.  
  224. $this->trigger_events('model_constructor');
  225. }
  226.  
  227. /**
  228. * Misc functions
  229. *
  230. * Hash password : Hashes the password to be stored in the database.
  231. * Hash password db : This function takes a password and validates it
  232. * against an entry in the users table.
  233. * Salt : Generates a random salt value.
  234. *
  235. * @author Mathew
  236. */
  237.  
  238. /**
  239. * Hashes the password to be stored in the database.
  240. *
  241. * @return void
  242. * @author Mathew
  243. **/
  244. public function hash_password($password, $salt=false, $use_sha1_override=FALSE)
  245. {
  246. if (empty($password))
  247. {
  248. return FALSE;
  249. }
  250.  
  251. // bcrypt
  252. if ($use_sha1_override === FALSE && $this->hash_method == 'bcrypt')
  253. {
  254. return $this->bcrypt->hash($password);
  255. }
  256.  
  257.  
  258. if ($this->store_salt && $salt)
  259. {
  260. return sha1($password . $salt);
  261. }
  262. else
  263. {
  264. $salt = $this->salt();
  265. return $salt . substr(sha1($salt . $password), 0, -$this->salt_length);
  266. }
  267. }
  268.  
  269. /**
  270. * This function takes a password and validates it
  271. * against an entry in the users table.
  272. *
  273. * @return void
  274. * @author Mathew
  275. **/
  276. public function hash_password_db($id, $password, $use_sha1_override=FALSE)
  277. {
  278. if (empty($id) || empty($password))
  279. {
  280. return FALSE;
  281. }
  282.  
  283. $this->trigger_events('extra_where');
  284.  
  285. $query = $this->db->select('password, salt')
  286. ->where('id', $id)
  287. ->limit(1)
  288. ->order_by('id', 'desc')
  289. ->get($this->tables['users']);
  290.  
  291. $hash_password_db = $query->row();
  292.  
  293. if ($query->num_rows() !== 1)
  294. {
  295. return FALSE;
  296. }
  297.  
  298. // bcrypt
  299. if ($use_sha1_override === FALSE && $this->hash_method == 'bcrypt')
  300. {
  301. if ($this->bcrypt->verify($password,$hash_password_db->password))
  302. {
  303. return TRUE;
  304. }
  305.  
  306. return FALSE;
  307. }
  308.  
  309. // sha1
  310. if ($this->store_salt)
  311. {
  312. $db_password = sha1($password . $hash_password_db->salt);
  313. }
  314. else
  315. {
  316. $salt = substr($hash_password_db->password, 0, $this->salt_length);
  317.  
  318. $db_password = $salt . substr(sha1($salt . $password), 0, -$this->salt_length);
  319. }
  320.  
  321. if($db_password == $hash_password_db->password)
  322. {
  323. return TRUE;
  324. }
  325. else
  326. {
  327. return FALSE;
  328. }
  329. }
  330.  
  331. /**
  332. * Generates a random salt value for forgotten passwords or any other keys. Uses SHA1.
  333. *
  334. * @return void
  335. * @author Mathew
  336. **/
  337. public function hash_code($password)
  338. {
  339. return $this->hash_password($password, FALSE, TRUE);
  340. }
  341.  
  342. /**
  343. * Generates a random salt value.
  344. *
  345. * Salt generation code taken from https://github.com/ircmaxell/password_compat/blob/master/lib/password.php
  346. *
  347. * @return void
  348. * @author Anthony Ferrera
  349. **/
  350. public function salt()
  351. {
  352.  
  353. $raw_salt_len = 16;
  354.  
  355. $buffer = '';
  356. $buffer_valid = false;
  357.  
  358. if (function_exists('mcrypt_create_iv') && !defined('PHALANGER')) {
  359. $buffer = mcrypt_create_iv($raw_salt_len, MCRYPT_DEV_URANDOM);
  360. if ($buffer) {
  361. $buffer_valid = true;
  362. }
  363. }
  364.  
  365. if (!$buffer_valid && function_exists('openssl_random_pseudo_bytes')) {
  366. $buffer = openssl_random_pseudo_bytes($raw_salt_len);
  367. if ($buffer) {
  368. $buffer_valid = true;
  369. }
  370. }
  371.  
  372. if (!$buffer_valid && @is_readable('/dev/urandom')) {
  373. $f = fopen('/dev/urandom', 'r');
  374. $read = strlen($buffer);
  375. while ($read < $raw_salt_len) {
  376. $buffer .= fread($f, $raw_salt_len - $read);
  377. $read = strlen($buffer);
  378. }
  379. fclose($f);
  380. if ($read >= $raw_salt_len) {
  381. $buffer_valid = true;
  382. }
  383. }
  384.  
  385. if (!$buffer_valid || strlen($buffer) < $raw_salt_len) {
  386. $bl = strlen($buffer);
  387. for ($i = 0; $i < $raw_salt_len; $i++) {
  388. if ($i < $bl) {
  389. $buffer[$i] = $buffer[$i] ^ chr(mt_rand(0, 255));
  390. } else {
  391. $buffer .= chr(mt_rand(0, 255));
  392. }
  393. }
  394. }
  395.  
  396. $salt = $buffer;
  397.  
  398. // encode string with the Base64 variant used by crypt
  399. $base64_digits = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  400. $bcrypt64_digits = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  401. $base64_string = base64_encode($salt);
  402. $salt = strtr(rtrim($base64_string, '='), $base64_digits, $bcrypt64_digits);
  403.  
  404. $salt = substr($salt, 0, $this->salt_length);
  405.  
  406.  
  407. return $salt;
  408.  
  409. }
  410.  
  411. /**
  412. * Activation functions
  413. *
  414. * Activate : Validates and removes activation code.
  415. * Deactivate : Updates a users row with an activation code.
  416. *
  417. * @author Mathew
  418. */
  419.  
  420. /**
  421. * activate
  422. *
  423. * @return void
  424. * @author Mathew
  425. **/
  426. public function activate($id, $code = false)
  427. {
  428. $this->trigger_events('pre_activate');
  429.  
  430. if ($code !== FALSE)
  431. {
  432. $query = $this->db->select($this->identity_column)
  433. ->where('activation_code', $code)
  434. ->where('id', $id)
  435. ->limit(1)
  436. ->order_by('id', 'desc')
  437. ->get($this->tables['users']);
  438.  
  439. $result = $query->row();
  440.  
  441. if ($query->num_rows() !== 1)
  442. {
  443. $this->trigger_events(array('post_activate', 'post_activate_unsuccessful'));
  444. $this->set_error('activate_unsuccessful');
  445. return FALSE;
  446. }
  447.  
  448. $data = array(
  449. 'activation_code' => NULL,
  450. 'active' => 1
  451. );
  452.  
  453. $this->trigger_events('extra_where');
  454. $this->db->update($this->tables['users'], $data, array('id' => $id));
  455. }
  456. else
  457. {
  458. $data = array(
  459. 'activation_code' => NULL,
  460. 'active' => 1
  461. );
  462.  
  463.  
  464. $this->trigger_events('extra_where');
  465. $this->db->update($this->tables['users'], $data, array('id' => $id));
  466. }
  467.  
  468.  
  469. $return = $this->db->affected_rows() == 1;
  470. if ($return)
  471. {
  472. $this->trigger_events(array('post_activate', 'post_activate_successful'));
  473. $this->set_message('activate_successful');
  474. }
  475. else
  476. {
  477. $this->trigger_events(array('post_activate', 'post_activate_unsuccessful'));
  478. $this->set_error('activate_unsuccessful');
  479. }
  480.  
  481.  
  482. return $return;
  483. }
  484.  
  485.  
  486. /**
  487. * Deactivate
  488. *
  489. * @return void
  490. * @author Mathew
  491. **/
  492. public function deactivate($id = NULL)
  493. {
  494. $this->trigger_events('deactivate');
  495.  
  496. if (!isset($id))
  497. {
  498. $this->set_error('deactivate_unsuccessful');
  499. return FALSE;
  500. }
  501.  
  502. $activation_code = sha1(md5(microtime()));
  503. $this->activation_code = $activation_code;
  504.  
  505. $data = array(
  506. 'activation_code' => $activation_code,
  507. 'active' => 0
  508. );
  509.  
  510. $this->trigger_events('extra_where');
  511. $this->db->update($this->tables['users'], $data, array('id' => $id));
  512.  
  513. $return = $this->db->affected_rows() == 1;
  514. if ($return)
  515. $this->set_message('deactivate_successful');
  516. else
  517. $this->set_error('deactivate_unsuccessful');
  518.  
  519. return $return;
  520. }
  521.  
  522. public function clear_forgotten_password_code($code) {
  523.  
  524. if (empty($code))
  525. {
  526. return FALSE;
  527. }
  528.  
  529. $this->db->where('forgotten_password_code', $code);
  530.  
  531. if ($this->db->count_all_results($this->tables['users']) > 0)
  532. {
  533. $data = array(
  534. 'forgotten_password_code' => NULL,
  535. 'forgotten_password_time' => NULL
  536. );
  537.  
  538. $this->db->update($this->tables['users'], $data, array('forgotten_password_code' => $code));
  539.  
  540. return TRUE;
  541. }
  542.  
  543. return FALSE;
  544. }
  545.  
  546. /**
  547. * reset password
  548. *
  549. * @return bool
  550. * @author Mathew
  551. **/
  552. public function reset_password($identity, $new) {
  553. $this->trigger_events('pre_change_password');
  554.  
  555. if (!$this->identity_check($identity)) {
  556. $this->trigger_events(array('post_change_password', 'post_change_password_unsuccessful'));
  557. return FALSE;
  558. }
  559.  
  560. $this->trigger_events('extra_where');
  561.  
  562. $query = $this->db->select('id, password, salt')
  563. ->where($this->identity_column, $identity)
  564. ->limit(1)
  565. ->order_by('id', 'desc')
  566. ->get($this->tables['users']);
  567.  
  568. if ($query->num_rows() !== 1)
  569. {
  570. $this->trigger_events(array('post_change_password', 'post_change_password_unsuccessful'));
  571. $this->set_error('password_change_unsuccessful');
  572. return FALSE;
  573. }
  574.  
  575. $result = $query->row();
  576.  
  577. $new = $this->hash_password($new, $result->salt);
  578.  
  579. // store the new password and reset the remember code so all remembered instances have to re-login
  580. // also clear the forgotten password code
  581. $data = array(
  582. 'password' => $new,
  583. 'remember_code' => NULL,
  584. 'forgotten_password_code' => NULL,
  585. 'forgotten_password_time' => NULL,
  586. );
  587.  
  588. $this->trigger_events('extra_where');
  589. $this->db->update($this->tables['users'], $data, array($this->identity_column => $identity));
  590.  
  591. $return = $this->db->affected_rows() == 1;
  592. if ($return)
  593. {
  594. $this->trigger_events(array('post_change_password', 'post_change_password_successful'));
  595. $this->set_message('password_change_successful');
  596. }
  597. else
  598. {
  599. $this->trigger_events(array('post_change_password', 'post_change_password_unsuccessful'));
  600. $this->set_error('password_change_unsuccessful');
  601. }
  602.  
  603. return $return;
  604. }
  605.  
  606. /**
  607. * change password
  608. *
  609. * @return bool
  610. * @author Mathew
  611. **/
  612. public function change_password($identity, $old, $new)
  613. {
  614. $this->trigger_events('pre_change_password');
  615.  
  616. $this->trigger_events('extra_where');
  617.  
  618. $query = $this->db->select('id, password, salt')
  619. ->where($this->identity_column, $identity)
  620. ->limit(1)
  621. ->order_by('id', 'desc')
  622. ->get($this->tables['users']);
  623.  
  624. if ($query->num_rows() !== 1)
  625. {
  626. $this->trigger_events(array('post_change_password', 'post_change_password_unsuccessful'));
  627. $this->set_error('password_change_unsuccessful');
  628. return FALSE;
  629. }
  630.  
  631. $user = $query->row();
  632.  
  633. $old_password_matches = $this->hash_password_db($user->id, $old);
  634.  
  635. if ($old_password_matches === TRUE)
  636. {
  637. // store the new password and reset the remember code so all remembered instances have to re-login
  638. $hashed_new_password = $this->hash_password($new, $user->salt);
  639. $data = array(
  640. 'password' => $hashed_new_password,
  641. 'remember_code' => NULL,
  642. );
  643.  
  644. $this->trigger_events('extra_where');
  645.  
  646. $successfully_changed_password_in_db = $this->db->update($this->tables['users'], $data, array($this->identity_column => $identity));
  647. if ($successfully_changed_password_in_db)
  648. {
  649. $this->trigger_events(array('post_change_password', 'post_change_password_successful'));
  650. $this->set_message('password_change_successful');
  651. }
  652. else
  653. {
  654. $this->trigger_events(array('post_change_password', 'post_change_password_unsuccessful'));
  655. $this->set_error('password_change_unsuccessful');
  656. }
  657.  
  658. return $successfully_changed_password_in_db;
  659. }
  660.  
  661. $this->set_error('password_change_unsuccessful');
  662. return FALSE;
  663. }
  664.  
  665. /**
  666. * Checks username
  667. *
  668. * @return bool
  669. * @author Mathew
  670. **/
  671. public function username_check($username = '')
  672. {
  673. $this->trigger_events('username_check');
  674.  
  675. if (empty($username))
  676. {
  677. return FALSE;
  678. }
  679.  
  680. $this->trigger_events('extra_where');
  681.  
  682. return $this->db->where('username', $username)
  683. ->group_by("id")
  684. ->order_by("id", "ASC")
  685. ->limit(1)
  686. ->count_all_results($this->tables['users']) > 0;
  687. }
  688.  
  689. /**
  690. * Checks email
  691. *
  692. * @return bool
  693. * @author Mathew
  694. **/
  695. public function email_check($email = '')
  696. {
  697. $this->trigger_events('email_check');
  698.  
  699. if (empty($email))
  700. {
  701. return FALSE;
  702. }
  703.  
  704. $this->trigger_events('extra_where');
  705.  
  706. return $this->db->where('email', $email)
  707. ->group_by("id")
  708. ->order_by("id", "ASC")
  709. ->limit(1)
  710. ->count_all_results($this->tables['users']) > 0;
  711. }
  712.  
  713. /**
  714. * Identity check
  715. *
  716. * @return bool
  717. * @author Mathew
  718. **/
  719. public function identity_check($identity = '')
  720. {
  721. $this->trigger_events('identity_check');
  722.  
  723. if (empty($identity))
  724. {
  725. return FALSE;
  726. }
  727.  
  728. return $this->db->where($this->identity_column, $identity)
  729. ->count_all_results($this->tables['users']) > 0;
  730. }
  731.  
  732. /**
  733. * Insert a forgotten password key.
  734. *
  735. * @return bool
  736. * @author Mathew
  737. * @updated Ryan
  738. * @updated 52aa456eef8b60ad6754b31fbdcc77bb
  739. **/
  740. public function forgotten_password($identity)
  741. {
  742. if (empty($identity))
  743. {
  744. $this->trigger_events(array('post_forgotten_password', 'post_forgotten_password_unsuccessful'));
  745. return FALSE;
  746. }
  747.  
  748. // All some more randomness
  749. $activation_code_part = "";
  750. if(function_exists("openssl_random_pseudo_bytes")) {
  751. $activation_code_part = openssl_random_pseudo_bytes(128);
  752. }
  753.  
  754. for($i=0;$i<1024;$i++) {
  755. $activation_code_part = sha1($activation_code_part . mt_rand() . microtime());
  756. }
  757.  
  758. $key = $this->hash_code($activation_code_part.$identity);
  759.  
  760. // If enable query strings is set, then we need to replace any unsafe characters so that the code can still work
  761. if ($key != '' && $this->config->item('permitted_uri_chars') != '' && $this->config->item('enable_query_strings') == FALSE)
  762. {
  763. // preg_quote() in PHP 5.3 escapes -, so the str_replace() and addition of - to preg_quote() is to maintain backwards
  764. // compatibility as many are unaware of how characters in the permitted_uri_chars will be parsed as a regex pattern
  765. if ( ! preg_match("|^[".str_replace(array('\\-', '\-'), '-', preg_quote($this->config->item('permitted_uri_chars'), '-'))."]+$|i", $key))
  766. {
  767. $key = preg_replace("/[^".$this->config->item('permitted_uri_chars')."]+/i", "-", $key);
  768. }
  769. }
  770.  
  771. $this->forgotten_password_code = $key;
  772.  
  773. $this->trigger_events('extra_where');
  774.  
  775. $update = array(
  776. 'forgotten_password_code' => $key,
  777. 'forgotten_password_time' => time()
  778. );
  779.  
  780. $this->db->update($this->tables['users'], $update, array($this->identity_column => $identity));
  781.  
  782. $return = $this->db->affected_rows() == 1;
  783.  
  784. if ($return)
  785. $this->trigger_events(array('post_forgotten_password', 'post_forgotten_password_successful'));
  786. else
  787. $this->trigger_events(array('post_forgotten_password', 'post_forgotten_password_unsuccessful'));
  788.  
  789. return $return;
  790. }
  791.  
  792. /**
  793. * Forgotten Password Complete
  794. *
  795. * @return string
  796. * @author Mathew
  797. **/
  798. public function forgotten_password_complete($code, $salt=FALSE)
  799. {
  800. $this->trigger_events('pre_forgotten_password_complete');
  801.  
  802. if (empty($code))
  803. {
  804. $this->trigger_events(array('post_forgotten_password_complete', 'post_forgotten_password_complete_unsuccessful'));
  805. return FALSE;
  806. }
  807.  
  808. $profile = $this->where('forgotten_password_code', $code)->users()->row(); //pass the code to profile
  809.  
  810. if ($profile) {
  811.  
  812. if ($this->config->item('forgot_password_expiration', 'ion_auth') > 0) {
  813. //Make sure it isn't expired
  814. $expiration = $this->config->item('forgot_password_expiration', 'ion_auth');
  815. if (time() - $profile->forgotten_password_time > $expiration) {
  816. //it has expired
  817. $this->set_error('forgot_password_expired');
  818. $this->trigger_events(array('post_forgotten_password_complete', 'post_forgotten_password_complete_unsuccessful'));
  819. return FALSE;
  820. }
  821. }
  822.  
  823. $password = $this->salt();
  824.  
  825. $data = array(
  826. 'password' => $this->hash_password($password, $salt),
  827. 'forgotten_password_code' => NULL,
  828. 'active' => 1,
  829. );
  830.  
  831. $this->db->update($this->tables['users'], $data, array('forgotten_password_code' => $code));
  832.  
  833. $this->trigger_events(array('post_forgotten_password_complete', 'post_forgotten_password_complete_successful'));
  834. return $password;
  835. }
  836.  
  837. $this->trigger_events(array('post_forgotten_password_complete', 'post_forgotten_password_complete_unsuccessful'));
  838. return FALSE;
  839. }
  840.  
  841. /**
  842. * register
  843. *
  844. * @return bool
  845. * @author Mathew
  846. **/
  847. public function register($identity, $password, $email, $additional_data = array(), $groups = array())
  848. {
  849. $this->trigger_events('pre_register');
  850.  
  851. $manual_activation = $this->config->item('manual_activation', 'ion_auth');
  852.  
  853. if ($this->identity_check($identity))
  854. {
  855. $this->set_error('account_creation_duplicate_identity');
  856. return FALSE;
  857. }
  858. elseif ( !$this->config->item('default_group', 'ion_auth') && empty($groups) )
  859. {
  860. $this->set_error('account_creation_missing_default_group');
  861. return FALSE;
  862. }
  863.  
  864. // check if the default set in config exists in database
  865. $query = $this->db->get_where($this->tables['groups'],array('name' => $this->config->item('default_group', 'ion_auth')),1)->row();
  866. if( !isset($query->id) && empty($groups) )
  867. {
  868. $this->set_error('account_creation_invalid_default_group');
  869. return FALSE;
  870. }
  871.  
  872. // capture default group details
  873. $default_group = $query;
  874.  
  875. // IP Address
  876. $ip_address = $this->_prepare_ip($this->input->ip_address());
  877. $salt = $this->store_salt ? $this->salt() : FALSE;
  878. $password = $this->hash_password($password, $salt);
  879.  
  880. // Users table.
  881. $data = array(
  882. $this->identity_column => $identity,
  883. 'password' => $password,
  884. 'email' => $email,
  885. 'ip_address' => $ip_address,
  886. 'created_on' => time(),
  887. 'active' => ($manual_activation === false ? 1 : 0)
  888. );
  889.  
  890. if ($this->store_salt)
  891. {
  892. $data['salt'] = $salt;
  893. }
  894.  
  895. // filter out any data passed that doesnt have a matching column in the users table
  896. // and merge the set user data and the additional data
  897. $user_data = array_merge($this->_filter_data($this->tables['users'], $additional_data), $data);
  898.  
  899. $this->trigger_events('extra_set');
  900.  
  901. $this->db->insert($this->tables['users'], $user_data);
  902.  
  903. $id = $this->db->insert_id();
  904.  
  905. // add in groups array if it doesn't exists and stop adding into default group if default group ids are set
  906. if( isset($default_group->id) && empty($groups) )
  907. {
  908. $groups[] = $default_group->id;
  909. }
  910.  
  911. if (!empty($groups))
  912. {
  913. // add to groups
  914. foreach ($groups as $group)
  915. {
  916. $this->add_to_group($group, $id);
  917. }
  918. }
  919.  
  920. $this->trigger_events('post_register');
  921.  
  922. return (isset($id)) ? $id : FALSE;
  923. }
  924.  
  925. /**
  926. * login
  927. *
  928. * @return bool
  929. * @author Mathew
  930. **/
  931. public function login($identity, $password, $remember=FALSE)
  932. {
  933. $this->trigger_events('pre_login');
  934.  
  935. if (empty($identity) || empty($password))
  936. {
  937. $this->set_error('login_unsuccessful');
  938. return FALSE;
  939. }
  940.  
  941. $this->trigger_events('extra_where');
  942.  
  943. $query = $this->db->select($this->identity_column . ', email, id, password, active, last_login')
  944. ->where($this->identity_column, $identity)
  945. ->limit(1)
  946. ->order_by('id', 'desc')
  947. ->get($this->tables['users']);
  948.  
  949.  
  950.  
  951. if ($query->num_rows() === 1)
  952. {
  953. $user = $query->row();
  954.  
  955. $password = $this->hash_password_db($user->id, $password);
  956.  
  957. if ($password === TRUE)
  958. {
  959. if ($user->active == 0)
  960. {
  961. $this->trigger_events('post_login_unsuccessful');
  962. $this->set_error('login_unsuccessful_not_active');
  963.  
  964. return FALSE;
  965. }
  966.  
  967. $this->set_session($user);
  968.  
  969. $this->update_last_login($user->id);
  970.  
  971. $this->clear_login_attempts($identity);
  972.  
  973. if ($remember && $this->config->item('remember_users', 'ion_auth'))
  974. {
  975. $this->remember_user($user->id);
  976. }
  977.  
  978. $this->trigger_events(array('post_login', 'post_login_successful'));
  979. $this->set_message('login_successful');
  980.  
  981. return TRUE;
  982. }
  983. }
  984.  
  985. // Hash something anyway, just to take up time
  986. $this->hash_password($password);
  987.  
  988. $this->increase_login_attempts($identity);
  989.  
  990. $this->trigger_events('post_login_unsuccessful');
  991. $this->set_error('login_unsuccessful');
  992.  
  993. return FALSE;
  994. }
  995.  
  996.  
  997. /**
  998. * is_max_login_attempts_exceeded
  999. * Based on code from Tank Auth, by Ilya Konyukhov (https://github.com/ilkon/Tank-Auth)
  1000. *
  1001. * @param string $identity
  1002. * @return boolean
  1003. **/
  1004. public function is_max_login_attempts_exceeded($identity) {
  1005. $max_attempts = 3;
  1006. if ($max_attempts > 0) {
  1007. $attempts = $this->get_attempts_num($identity);
  1008. return $attempts >= $max_attempts;
  1009. }
  1010.  
  1011. return FALSE;
  1012. }
  1013.  
  1014. /**
  1015. * Get number of attempts to login occured from given IP-address or identity
  1016. *
  1017. * @param string $identity
  1018. * @return int
  1019. */
  1020. public function get_attempts_num($identity)
  1021. {
  1022.  
  1023. $ip_address = $this->_prepare_ip($this->input->ip_address());
  1024. $this->db->select('attempts');
  1025. $this->db->where('username', $identity);
  1026. $query = $this->db->get('users')->result();
  1027. $total = $this->db->count_all_results();
  1028.  
  1029. if($total > 0):
  1030. return $query[0]->attempts;
  1031. endif;
  1032. }
  1033.  
  1034. /**
  1035. * Get a boolean to determine if an account should be locked out due to
  1036. * exceeded login attempts within a given period
  1037. *
  1038. * @return boolean
  1039. */
  1040. public function is_time_locked_out($identity) {
  1041.  
  1042. return $this->is_max_login_attempts_exceeded($identity);
  1043. }
  1044.  
  1045. /**
  1046. * Get the time of the last time a login attempt occured from given IP-address or identity
  1047. *
  1048. * @param string $identity
  1049. * @return int
  1050. */
  1051. public function get_last_attempt_time($identity) {
  1052. if ($this->config->item('track_login_attempts', 'ion_auth')) {
  1053. $ip_address = $this->_prepare_ip($this->input->ip_address());
  1054.  
  1055. $this->db->select('time');
  1056. if ($this->config->item('track_login_ip_address', 'ion_auth')) $this->db->where('ip_address', $ip_address);
  1057. else if (strlen($identity) > 0) $this->db->or_where('login', $identity);
  1058. $this->db->order_by('id', 'desc');
  1059. $qres = $this->db->get($this->tables['login_attempts'], 1);
  1060.  
  1061. if($qres->num_rows() > 0) {
  1062. return $qres->row()->time;
  1063. }
  1064. }
  1065.  
  1066. return 0;
  1067. }
  1068.  
  1069. /**
  1070. * increase_login_attempts
  1071. *
  1072. * @param string $identity
  1073. **/
  1074. public function increase_login_attempts($identity) {
  1075. $this->db->where('username', $identity);
  1076. $this->db->set('attempts', 'attempts+1', FALSE);
  1077. $this->db->update('users');
  1078. return TRUE;
  1079. }
  1080.  
  1081. /**
  1082. * clear_login_attempts
  1083. * Based on code from Tank Auth, by Ilya Konyukhov (https://github.com/ilkon/Tank-Auth)
  1084. *
  1085. * @param string $identity
  1086. **/
  1087. public function clear_login_attempts($identity, $expire_period = 86400) {
  1088. $this->db->where('username', $identity);
  1089. $this->db->set('attempts', 0, FALSE);
  1090. $this->db->update('users');
  1091. }
  1092.  
  1093. public function limit($limit)
  1094. {
  1095. $this->trigger_events('limit');
  1096. $this->_ion_limit = $limit;
  1097.  
  1098. return $this;
  1099. }
  1100.  
  1101. public function offset($offset)
  1102. {
  1103. $this->trigger_events('offset');
  1104. $this->_ion_offset = $offset;
  1105.  
  1106. return $this;
  1107. }
  1108.  
  1109. public function where($where, $value = NULL)
  1110. {
  1111. $this->trigger_events('where');
  1112.  
  1113. if (!is_array($where))
  1114. {
  1115. $where = array($where => $value);
  1116. }
  1117.  
  1118. array_push($this->_ion_where, $where);
  1119.  
  1120. return $this;
  1121. }
  1122.  
  1123. public function like($like, $value = NULL, $position = 'both')
  1124. {
  1125. $this->trigger_events('like');
  1126.  
  1127. if (!is_array($like))
  1128. {
  1129. $like = array($like => array(
  1130. 'value' => $value,
  1131. 'position' => $position,
  1132. ));
  1133. }
  1134.  
  1135. array_push($this->_ion_like, $like);
  1136.  
  1137. return $this;
  1138. }
  1139.  
  1140. public function select($select)
  1141. {
  1142. $this->trigger_events('select');
  1143.  
  1144. $this->_ion_select[] = $select;
  1145.  
  1146. return $this;
  1147. }
  1148.  
  1149. public function order_by($by, $order='desc')
  1150. {
  1151. $this->trigger_events('order_by');
  1152.  
  1153. $this->_ion_order_by = $by;
  1154. $this->_ion_order = $order;
  1155.  
  1156. return $this;
  1157. }
  1158.  
  1159. public function row()
  1160. {
  1161. $this->trigger_events('row');
  1162.  
  1163. $row = $this->response->row();
  1164.  
  1165. return $row;
  1166. }
  1167.  
  1168. public function row_array()
  1169. {
  1170. $this->trigger_events(array('row', 'row_array'));
  1171.  
  1172. $row = $this->response->row_array();
  1173.  
  1174. return $row;
  1175. }
  1176.  
  1177. public function result()
  1178. {
  1179. $this->trigger_events('result');
  1180.  
  1181. $result = $this->response->result();
  1182.  
  1183. return $result;
  1184. }
  1185.  
  1186. public function result_array()
  1187. {
  1188. $this->trigger_events(array('result', 'result_array'));
  1189.  
  1190. $result = $this->response->result_array();
  1191.  
  1192. return $result;
  1193. }
  1194.  
  1195. public function num_rows()
  1196. {
  1197. $this->trigger_events(array('num_rows'));
  1198.  
  1199. $result = $this->response->num_rows();
  1200.  
  1201. return $result;
  1202. }
  1203.  
  1204. /**
  1205. * users
  1206. *
  1207. * @return object Users
  1208. * @author Ben Edmunds
  1209. **/
  1210. public function users($groups = NULL)
  1211. {
  1212. $this->trigger_events('users');
  1213.  
  1214. if (isset($this->_ion_select) && !empty($this->_ion_select))
  1215. {
  1216. foreach ($this->_ion_select as $select)
  1217. {
  1218. $this->db->select($select);
  1219. }
  1220.  
  1221. $this->_ion_select = array();
  1222. }
  1223. else
  1224. {
  1225. //default selects
  1226. $this->db->select(array(
  1227. $this->tables['users'].'.*',
  1228. $this->tables['users'].'.id as id',
  1229. $this->tables['users'].'.id as user_id'
  1230. ));
  1231. }
  1232.  
  1233. // filter by group id(s) if passed
  1234. if (isset($groups))
  1235. {
  1236. // build an array if only one group was passed
  1237. if (!is_array($groups))
  1238. {
  1239. $groups = Array($groups);
  1240. }
  1241.  
  1242. // join and then run a where_in against the group ids
  1243. if (isset($groups) && !empty($groups))
  1244. {
  1245. $this->db->distinct();
  1246. $this->db->join(
  1247. $this->tables['users_groups'],
  1248. $this->tables['users_groups'].'.'.$this->join['users'].'='.$this->tables['users'].'.id',
  1249. 'inner'
  1250. );
  1251. }
  1252.  
  1253. // verify if group name or group id was used and create and put elements in different arrays
  1254. $group_ids = array();
  1255. $group_names = array();
  1256. foreach($groups as $group)
  1257. {
  1258. if(is_numeric($group)) $group_ids[] = $group;
  1259. else $group_names[] = $group;
  1260. }
  1261. $or_where_in = (!empty($group_ids) && !empty($group_names)) ? 'or_where_in' : 'where_in';
  1262. // if group name was used we do one more join with groups
  1263. if(!empty($group_names))
  1264. {
  1265. $this->db->join($this->tables['groups'], $this->tables['users_groups'] . '.' . $this->join['groups'] . ' = ' . $this->tables['groups'] . '.id', 'inner');
  1266. $this->db->where_in($this->tables['groups'] . '.name', $group_names);
  1267. }
  1268. if(!empty($group_ids))
  1269. {
  1270. $this->db->{$or_where_in}($this->tables['users_groups'].'.'.$this->join['groups'], $group_ids);
  1271. }
  1272. }
  1273.  
  1274. $this->trigger_events('extra_where');
  1275.  
  1276. // run each where that was passed
  1277. if (isset($this->_ion_where) && !empty($this->_ion_where))
  1278. {
  1279. foreach ($this->_ion_where as $where)
  1280. {
  1281. $this->db->where($where);
  1282. }
  1283.  
  1284. $this->_ion_where = array();
  1285. }
  1286.  
  1287. if (isset($this->_ion_like) && !empty($this->_ion_like))
  1288. {
  1289. foreach ($this->_ion_like as $like)
  1290. {
  1291. $this->db->or_like($like);
  1292. }
  1293.  
  1294. $this->_ion_like = array();
  1295. }
  1296.  
  1297. if (isset($this->_ion_limit) && isset($this->_ion_offset))
  1298. {
  1299. $this->db->limit($this->_ion_limit, $this->_ion_offset);
  1300.  
  1301. $this->_ion_limit = NULL;
  1302. $this->_ion_offset = NULL;
  1303. }
  1304. else if (isset($this->_ion_limit))
  1305. {
  1306. $this->db->limit($this->_ion_limit);
  1307.  
  1308. $this->_ion_limit = NULL;
  1309. }
  1310.  
  1311. // set the order
  1312. if (isset($this->_ion_order_by) && isset($this->_ion_order))
  1313. {
  1314. $this->db->order_by($this->_ion_order_by, $this->_ion_order);
  1315.  
  1316. $this->_ion_order = NULL;
  1317. $this->_ion_order_by = NULL;
  1318. }
  1319.  
  1320. $this->response = $this->db->get($this->tables['users']);
  1321.  
  1322. return $this;
  1323. }
  1324.  
  1325. /**
  1326. * user
  1327. *
  1328. * @return object
  1329. * @author Ben Edmunds
  1330. **/
  1331. public function user($id = NULL)
  1332. {
  1333. $this->trigger_events('user');
  1334.  
  1335. // if no id was passed use the current users id
  1336. $id = isset($id) ? $id : $this->session->userdata('user_id');
  1337.  
  1338. $this->limit(1);
  1339. $this->order_by($this->tables['users'].'.id', 'desc');
  1340. $this->where($this->tables['users'].'.id', $id);
  1341.  
  1342. $this->users();
  1343.  
  1344. return $this;
  1345. }
  1346.  
  1347. /**
  1348. * get_users_groups
  1349. *
  1350. * @return array
  1351. * @author Ben Edmunds
  1352. **/
  1353. public function get_users_groups($id=FALSE)
  1354. {
  1355. $this->trigger_events('get_users_group');
  1356.  
  1357. // if no id was passed use the current users id
  1358. $id || $id = $this->session->userdata('user_id');
  1359.  
  1360. return $this->db->select($this->tables['users_groups'].'.'.$this->join['groups'].' as id, '.$this->tables['groups'].'.name, '.$this->tables['groups'].'.description')
  1361. ->where($this->tables['users_groups'].'.'.$this->join['users'], $id)
  1362. ->join($this->tables['groups'], $this->tables['users_groups'].'.'.$this->join['groups'].'='.$this->tables['groups'].'.id')
  1363. ->get($this->tables['users_groups']);
  1364. }
  1365.  
  1366. /**
  1367. * add_to_group
  1368. *
  1369. * @return bool
  1370. * @author Ben Edmunds
  1371. **/
  1372. public function add_to_group($group_ids, $user_id=false)
  1373. {
  1374. $this->trigger_events('add_to_group');
  1375.  
  1376. // if no id was passed use the current users id
  1377. $user_id || $user_id = $this->session->userdata('user_id');
  1378.  
  1379. if(!is_array($group_ids))
  1380. {
  1381. $group_ids = array($group_ids);
  1382. }
  1383.  
  1384. $return = 0;
  1385.  
  1386. // Then insert each into the database
  1387. foreach ($group_ids as $group_id)
  1388. {
  1389. if ($this->db->insert($this->tables['users_groups'], array( $this->join['groups'] => (float)$group_id, $this->join['users'] => (float)$user_id)))
  1390. {
  1391. if (isset($this->_cache_groups[$group_id])) {
  1392. $group_name = $this->_cache_groups[$group_id];
  1393. }
  1394. else {
  1395. $group = $this->group($group_id)->result();
  1396. $group_name = $group[0]->name;
  1397. $this->_cache_groups[$group_id] = $group_name;
  1398. }
  1399. $this->_cache_user_in_group[$user_id][$group_id] = $group_name;
  1400.  
  1401. // Return the number of groups added
  1402. $return += 1;
  1403. }
  1404. }
  1405.  
  1406. return $return;
  1407. }
  1408.  
  1409. /**
  1410. * remove_from_group
  1411. *
  1412. * @return bool
  1413. * @author Ben Edmunds
  1414. **/
  1415. public function remove_from_group($group_ids=false, $user_id=false)
  1416. {
  1417. $this->trigger_events('remove_from_group');
  1418.  
  1419. // user id is required
  1420. if(empty($user_id))
  1421. {
  1422. return FALSE;
  1423. }
  1424.  
  1425. // if group id(s) are passed remove user from the group(s)
  1426. if( ! empty($group_ids))
  1427. {
  1428. if(!is_array($group_ids))
  1429. {
  1430. $group_ids = array($group_ids);
  1431. }
  1432.  
  1433. foreach($group_ids as $group_id)
  1434. {
  1435. $this->db->delete($this->tables['users_groups'], array($this->join['groups'] => (float)$group_id, $this->join['users'] => (float)$user_id));
  1436. if (isset($this->_cache_user_in_group[$user_id]) && isset($this->_cache_user_in_group[$user_id][$group_id]))
  1437. {
  1438. unset($this->_cache_user_in_group[$user_id][$group_id]);
  1439. }
  1440. }
  1441.  
  1442. $return = TRUE;
  1443. }
  1444. // otherwise remove user from all groups
  1445. else
  1446. {
  1447. if ($return = $this->db->delete($this->tables['users_groups'], array($this->join['users'] => (float)$user_id))) {
  1448. $this->_cache_user_in_group[$user_id] = array();
  1449. }
  1450. }
  1451. return $return;
  1452. }
  1453.  
  1454. /**
  1455. * groups
  1456. *
  1457. * @return object
  1458. * @author Ben Edmunds
  1459. **/
  1460. public function groups()
  1461. {
  1462. $this->trigger_events('groups');
  1463.  
  1464. // run each where that was passed
  1465. if (isset($this->_ion_where) && !empty($this->_ion_where))
  1466. {
  1467. foreach ($this->_ion_where as $where)
  1468. {
  1469. $this->db->where($where);
  1470. }
  1471. $this->_ion_where = array();
  1472. }
  1473.  
  1474. if (isset($this->_ion_limit) && isset($this->_ion_offset))
  1475. {
  1476. $this->db->limit($this->_ion_limit, $this->_ion_offset);
  1477.  
  1478. $this->_ion_limit = NULL;
  1479. $this->_ion_offset = NULL;
  1480. }
  1481. else if (isset($this->_ion_limit))
  1482. {
  1483. $this->db->limit($this->_ion_limit);
  1484.  
  1485. $this->_ion_limit = NULL;
  1486. }
  1487.  
  1488. // set the order
  1489. if (isset($this->_ion_order_by) && isset($this->_ion_order))
  1490. {
  1491. $this->db->order_by($this->_ion_order_by, $this->_ion_order);
  1492. }
  1493.  
  1494. $this->response = $this->db->get($this->tables['groups']);
  1495.  
  1496. return $this;
  1497. }
  1498.  
  1499. /**
  1500. * group
  1501. *
  1502. * @return object
  1503. * @author Ben Edmunds
  1504. **/
  1505. public function group($id = NULL)
  1506. {
  1507. $this->trigger_events('group');
  1508.  
  1509. if (isset($id))
  1510. {
  1511. $this->where($this->tables['groups'].'.id', $id);
  1512. }
  1513.  
  1514. $this->limit(1);
  1515. $this->order_by('id', 'desc');
  1516.  
  1517. return $this->groups();
  1518. }
  1519.  
  1520. /**
  1521. * update
  1522. *
  1523. * @return bool
  1524. * @author Phil Sturgeon
  1525. **/
  1526. public function update($id, array $data)
  1527. {
  1528. $this->trigger_events('pre_update_user');
  1529.  
  1530. $user = $this->user($id)->row();
  1531.  
  1532. $this->db->trans_begin();
  1533.  
  1534. if (array_key_exists($this->identity_column, $data) && $this->identity_check($data[$this->identity_column]) && $user->{$this->identity_column} !== $data[$this->identity_column])
  1535. {
  1536. $this->db->trans_rollback();
  1537. $this->set_error('account_creation_duplicate_identity');
  1538.  
  1539. $this->trigger_events(array('post_update_user', 'post_update_user_unsuccessful'));
  1540. $this->set_error('update_unsuccessful');
  1541.  
  1542. return FALSE;
  1543. }
  1544.  
  1545. // Filter the data passed
  1546. $data = $this->_filter_data($this->tables['users'], $data);
  1547.  
  1548. if (array_key_exists($this->identity_column, $data) || array_key_exists('password', $data) || array_key_exists('email', $data))
  1549. {
  1550. if (array_key_exists('password', $data))
  1551. {
  1552. if( ! empty($data['password']))
  1553. {
  1554. $data['password'] = $this->hash_password($data['password'], $user->salt);
  1555. }
  1556. else
  1557. {
  1558. // unset password so it doesn't effect database entry if no password passed
  1559. unset($data['password']);
  1560. }
  1561. }
  1562. }
  1563.  
  1564. $this->trigger_events('extra_where');
  1565. $this->db->update($this->tables['users'], $data, array('id' => $user->id));
  1566.  
  1567. if ($this->db->trans_status() === FALSE)
  1568. {
  1569. $this->db->trans_rollback();
  1570.  
  1571. $this->trigger_events(array('post_update_user', 'post_update_user_unsuccessful'));
  1572. $this->set_error('update_unsuccessful');
  1573. return FALSE;
  1574. }
  1575.  
  1576. $this->db->trans_commit();
  1577.  
  1578. $this->trigger_events(array('post_update_user', 'post_update_user_successful'));
  1579. $this->set_message('update_successful');
  1580. return TRUE;
  1581. }
  1582.  
  1583. /**
  1584. * delete_user
  1585. *
  1586. * @return bool
  1587. * @author Phil Sturgeon
  1588. **/
  1589. public function delete_user($id)
  1590. {
  1591. $this->trigger_events('pre_delete_user');
  1592.  
  1593. $this->db->trans_begin();
  1594.  
  1595. // remove user from groups
  1596. $this->remove_from_group(NULL, $id);
  1597.  
  1598. // delete user from users table should be placed after remove from group
  1599. $this->db->delete($this->tables['users'], array('id' => $id));
  1600.  
  1601. // if user does not exist in database then it returns FALSE else removes the user from groups
  1602. if ($this->db->affected_rows() <= 0)
  1603. {
  1604. return FALSE;
  1605. }
  1606.  
  1607. if ($this->db->trans_status() === FALSE)
  1608. {
  1609. $this->db->trans_rollback();
  1610. $this->trigger_events(array('post_delete_user', 'post_delete_user_unsuccessful'));
  1611. $this->set_error('delete_unsuccessful');
  1612. return FALSE;
  1613. }
  1614.  
  1615. $this->db->trans_commit();
  1616.  
  1617. $this->trigger_events(array('post_delete_user', 'post_delete_user_successful'));
  1618. $this->set_message('delete_successful');
  1619. return TRUE;
  1620. }
  1621.  
  1622. /**
  1623. * update_last_login
  1624. *
  1625. * @return bool
  1626. * @author Ben Edmunds
  1627. **/
  1628. public function update_last_login($id)
  1629. {
  1630. $this->trigger_events('update_last_login');
  1631.  
  1632. $this->load->helper('date');
  1633.  
  1634. $this->trigger_events('extra_where');
  1635.  
  1636. $this->db->update($this->tables['users'], array('last_login' => time()), array('id' => $id));
  1637.  
  1638. return $this->db->affected_rows() == 1;
  1639. }
  1640.  
  1641. /**
  1642. * set_lang
  1643. *
  1644. * @return bool
  1645. * @author Ben Edmunds
  1646. **/
  1647. public function set_lang($lang = 'en')
  1648. {
  1649. $this->trigger_events('set_lang');
  1650.  
  1651. // if the user_expire is set to zero we'll set the expiration two years from now.
  1652. if($this->config->item('user_expire', 'ion_auth') === 0)
  1653. {
  1654. $expire = (60*60*24*365*2);
  1655. }
  1656. // otherwise use what is set
  1657. else
  1658. {
  1659. $expire = $this->config->item('user_expire', 'ion_auth');
  1660. }
  1661.  
  1662. set_cookie(array(
  1663. 'name' => 'lang_code',
  1664. 'value' => $lang,
  1665. 'expire' => $expire
  1666. ));
  1667.  
  1668. return TRUE;
  1669. }
  1670.  
  1671. /**
  1672. * set_session
  1673. *
  1674. * @return bool
  1675. * @author jrmadsen67
  1676. **/
  1677. public function set_session($user)
  1678. {
  1679.  
  1680. $this->trigger_events('pre_set_session');
  1681.  
  1682. $session_data = array(
  1683. 'identity' => $user->{$this->identity_column},
  1684. $this->identity_column => $user->{$this->identity_column},
  1685. 'email' => $user->email,
  1686. 'user_id' => $user->id, //everyone likes to overwrite id so we'll use user_id
  1687. 'old_last_login' => $user->last_login
  1688. );
  1689.  
  1690. $this->session->set_userdata($session_data);
  1691.  
  1692. $this->trigger_events('post_set_session');
  1693.  
  1694. return TRUE;
  1695. }
  1696.  
  1697. /**
  1698. * remember_user
  1699. *
  1700. * @return bool
  1701. * @author Ben Edmunds
  1702. **/
  1703. public function remember_user($id)
  1704. {
  1705. $this->trigger_events('pre_remember_user');
  1706.  
  1707. if (!$id)
  1708. {
  1709. return FALSE;
  1710. }
  1711.  
  1712. $user = $this->user($id)->row();
  1713.  
  1714. $salt = $this->salt();
  1715.  
  1716. $this->db->update($this->tables['users'], array('remember_code' => $salt), array('id' => $id));
  1717.  
  1718. if ($this->db->affected_rows() > -1)
  1719. {
  1720. // if the user_expire is set to zero we'll set the expiration two years from now.
  1721. if($this->config->item('user_expire', 'ion_auth') === 0)
  1722. {
  1723. $expire = (60*60*24*365*2);
  1724. }
  1725. // otherwise use what is set
  1726. else
  1727. {
  1728. $expire = $this->config->item('user_expire', 'ion_auth');
  1729. }
  1730.  
  1731. set_cookie(array(
  1732. 'name' => $this->config->item('identity_cookie_name', 'ion_auth'),
  1733. 'value' => $user->{$this->identity_column},
  1734. 'expire' => $expire
  1735. ));
  1736.  
  1737. set_cookie(array(
  1738. 'name' => $this->config->item('remember_cookie_name', 'ion_auth'),
  1739. 'value' => $salt,
  1740. 'expire' => $expire
  1741. ));
  1742.  
  1743. $this->trigger_events(array('post_remember_user', 'remember_user_successful'));
  1744. return TRUE;
  1745. }
  1746.  
  1747. $this->trigger_events(array('post_remember_user', 'remember_user_unsuccessful'));
  1748. return FALSE;
  1749. }
  1750.  
  1751. /**
  1752. * login_remembed_user
  1753. *
  1754. * @return bool
  1755. * @author Ben Edmunds
  1756. **/
  1757. public function login_remembered_user()
  1758. {
  1759. $this->trigger_events('pre_login_remembered_user');
  1760.  
  1761. // check for valid data
  1762. if (!get_cookie($this->config->item('identity_cookie_name', 'ion_auth'))
  1763. || !get_cookie($this->config->item('remember_cookie_name', 'ion_auth'))
  1764. || !$this->identity_check(get_cookie($this->config->item('identity_cookie_name', 'ion_auth'))))
  1765. {
  1766. $this->trigger_events(array('post_login_remembered_user', 'post_login_remembered_user_unsuccessful'));
  1767. return FALSE;
  1768. }
  1769.  
  1770. // get the user
  1771. $this->trigger_events('extra_where');
  1772. $query = $this->db->select($this->identity_column.', id, email, last_login')
  1773. ->where($this->identity_column, get_cookie($this->config->item('identity_cookie_name', 'ion_auth')))
  1774. ->where('remember_code', get_cookie($this->config->item('remember_cookie_name', 'ion_auth')))
  1775. ->limit(1)
  1776. ->order_by('id', 'desc')
  1777. ->get($this->tables['users']);
  1778.  
  1779. // if the user was found, sign them in
  1780. if ($query->num_rows() == 1)
  1781. {
  1782. $user = $query->row();
  1783.  
  1784. $this->update_last_login($user->id);
  1785.  
  1786. $this->set_session($user);
  1787.  
  1788. // extend the users cookies if the option is enabled
  1789. if ($this->config->item('user_extend_on_login', 'ion_auth'))
  1790. {
  1791. $this->remember_user($user->id);
  1792. }
  1793.  
  1794. $this->trigger_events(array('post_login_remembered_user', 'post_login_remembered_user_successful'));
  1795. return TRUE;
  1796. }
  1797.  
  1798. $this->trigger_events(array('post_login_remembered_user', 'post_login_remembered_user_unsuccessful'));
  1799. return FALSE;
  1800. }
  1801.  
  1802.  
  1803. /**
  1804. * create_group
  1805. *
  1806. * @author aditya menon
  1807. */
  1808. public function create_group($group_name = FALSE, $group_description = '', $additional_data = array())
  1809. {
  1810. // bail if the group name was not passed
  1811. if(!$group_name)
  1812. {
  1813. $this->set_error('group_name_required');
  1814. return FALSE;
  1815. }
  1816.  
  1817. // bail if the group name already exists
  1818. $existing_group = $this->db->get_where($this->tables['groups'], array('name' => $group_name))->num_rows();
  1819. if($existing_group !== 0)
  1820. {
  1821. $this->set_error('group_already_exists');
  1822. return FALSE;
  1823. }
  1824.  
  1825. $data = array('name'=>$group_name,'description'=>$group_description);
  1826.  
  1827. // filter out any data passed that doesnt have a matching column in the groups table
  1828. // and merge the set group data and the additional data
  1829. if (!empty($additional_data)) $data = array_merge($this->_filter_data($this->tables['groups'], $additional_data), $data);
  1830.  
  1831. $this->trigger_events('extra_group_set');
  1832.  
  1833. // insert the new group
  1834. $this->db->insert($this->tables['groups'], $data);
  1835. $group_id = $this->db->insert_id();
  1836.  
  1837. // report success
  1838. $this->set_message('group_creation_successful');
  1839. // return the brand new group id
  1840. return $group_id;
  1841. }
  1842.  
  1843. /**
  1844. * update_group
  1845. *
  1846. * @return bool
  1847. * @author aditya menon
  1848. **/
  1849. public function update_group($group_id = FALSE, $group_name = FALSE, $additional_data = array())
  1850. {
  1851. if (empty($group_id)) return FALSE;
  1852.  
  1853. $data = array();
  1854.  
  1855. if (!empty($group_name))
  1856. {
  1857. // we are changing the name, so do some checks
  1858.  
  1859. // bail if the group name already exists
  1860. $existing_group = $this->db->get_where($this->tables['groups'], array('name' => $group_name))->row();
  1861. if(isset($existing_group->id) && $existing_group->id != $group_id)
  1862. {
  1863. $this->set_error('group_already_exists');
  1864. return FALSE;
  1865. }
  1866.  
  1867. $data['name'] = $group_name;
  1868. }
  1869.  
  1870. // restrict change of name of the admin group
  1871. $group = $this->db->get_where($this->tables['groups'], array('id' => $group_id))->row();
  1872. if($this->config->item('admin_group', 'ion_auth') === $group->name && $group_name !== $group->name)
  1873. {
  1874. $this->set_error('group_name_admin_not_alter');
  1875. return FALSE;
  1876. }
  1877.  
  1878.  
  1879. // IMPORTANT!! Third parameter was string type $description; this following code is to maintain backward compatibility
  1880. // New projects should work with 3rd param as array
  1881. if (is_string($additional_data)) $additional_data = array('description' => $additional_data);
  1882.  
  1883.  
  1884. // filter out any data passed that doesnt have a matching column in the groups table
  1885. // and merge the set group data and the additional data
  1886. if (!empty($additional_data)) $data = array_merge($this->_filter_data($this->tables['groups'], $additional_data), $data);
  1887.  
  1888.  
  1889. $this->db->update($this->tables['groups'], $data, array('id' => $group_id));
  1890.  
  1891. $this->set_message('group_update_successful');
  1892.  
  1893. return TRUE;
  1894. }
  1895.  
  1896. /**
  1897. * delete_group
  1898. *
  1899. * @return bool
  1900. * @author aditya menon
  1901. **/
  1902. public function delete_group($group_id = FALSE)
  1903. {
  1904. // bail if mandatory param not set
  1905. if(!$group_id || empty($group_id))
  1906. {
  1907. return FALSE;
  1908. }
  1909. $group = $this->group($group_id)->row();
  1910. if($group->name == $this->config->item('admin_group', 'ion_auth'))
  1911. {
  1912. $this->trigger_events(array('post_delete_group', 'post_delete_group_notallowed'));
  1913. $this->set_error('group_delete_notallowed');
  1914. return FALSE;
  1915. }
  1916.  
  1917. $this->trigger_events('pre_delete_group');
  1918.  
  1919. $this->db->trans_begin();
  1920.  
  1921. // remove all users from this group
  1922. $this->db->delete($this->tables['users_groups'], array($this->join['groups'] => $group_id));
  1923. // remove the group itself
  1924. $this->db->delete($this->tables['groups'], array('id' => $group_id));
  1925.  
  1926. if ($this->db->trans_status() === FALSE)
  1927. {
  1928. $this->db->trans_rollback();
  1929. $this->trigger_events(array('post_delete_group', 'post_delete_group_unsuccessful'));
  1930. $this->set_error('group_delete_unsuccessful');
  1931. return FALSE;
  1932. }
  1933.  
  1934. $this->db->trans_commit();
  1935.  
  1936. $this->trigger_events(array('post_delete_group', 'post_delete_group_successful'));
  1937. $this->set_message('group_delete_successful');
  1938. return TRUE;
  1939. }
  1940.  
  1941. public function set_hook($event, $name, $class, $method, $arguments)
  1942. {
  1943. $this->_ion_hooks->{$event}[$name] = new stdClass;
  1944. $this->_ion_hooks->{$event}[$name]->class = $class;
  1945. $this->_ion_hooks->{$event}[$name]->method = $method;
  1946. $this->_ion_hooks->{$event}[$name]->arguments = $arguments;
  1947. }
  1948.  
  1949. public function remove_hook($event, $name)
  1950. {
  1951. if (isset($this->_ion_hooks->{$event}[$name]))
  1952. {
  1953. unset($this->_ion_hooks->{$event}[$name]);
  1954. }
  1955. }
  1956.  
  1957. public function remove_hooks($event)
  1958. {
  1959. if (isset($this->_ion_hooks->$event))
  1960. {
  1961. unset($this->_ion_hooks->$event);
  1962. }
  1963. }
  1964.  
  1965. protected function _call_hook($event, $name)
  1966. {
  1967. if (isset($this->_ion_hooks->{$event}[$name]) && method_exists($this->_ion_hooks->{$event}[$name]->class, $this->_ion_hooks->{$event}[$name]->method))
  1968. {
  1969. $hook = $this->_ion_hooks->{$event}[$name];
  1970.  
  1971. return call_user_func_array(array($hook->class, $hook->method), $hook->arguments);
  1972. }
  1973.  
  1974. return FALSE;
  1975. }
  1976.  
  1977. public function trigger_events($events)
  1978. {
  1979. if (is_array($events) && !empty($events))
  1980. {
  1981. foreach ($events as $event)
  1982. {
  1983. $this->trigger_events($event);
  1984. }
  1985. }
  1986. else
  1987. {
  1988. if (isset($this->_ion_hooks->$events) && !empty($this->_ion_hooks->$events))
  1989. {
  1990. foreach ($this->_ion_hooks->$events as $name => $hook)
  1991. {
  1992. $this->_call_hook($events, $name);
  1993. }
  1994. }
  1995. }
  1996. }
  1997.  
  1998. /**
  1999. * set_message_delimiters
  2000. *
  2001. * Set the message delimiters
  2002. *
  2003. * @return void
  2004. * @author Ben Edmunds
  2005. **/
  2006. public function set_message_delimiters($start_delimiter, $end_delimiter)
  2007. {
  2008. $this->message_start_delimiter = $start_delimiter;
  2009. $this->message_end_delimiter = $end_delimiter;
  2010.  
  2011. return TRUE;
  2012. }
  2013.  
  2014. /**
  2015. * set_error_delimiters
  2016. *
  2017. * Set the error delimiters
  2018. *
  2019. * @return void
  2020. * @author Ben Edmunds
  2021. **/
  2022. public function set_error_delimiters($start_delimiter, $end_delimiter)
  2023. {
  2024. $this->error_start_delimiter = $start_delimiter;
  2025. $this->error_end_delimiter = $end_delimiter;
  2026.  
  2027. return TRUE;
  2028. }
  2029.  
  2030. /**
  2031. * set_message
  2032. *
  2033. * Set a message
  2034. *
  2035. * @return void
  2036. * @author Ben Edmunds
  2037. **/
  2038. public function set_message($message)
  2039. {
  2040. $this->messages[] = $message;
  2041.  
  2042. return $message;
  2043. }
  2044.  
  2045.  
  2046.  
  2047. /**
  2048. * messages
  2049. *
  2050. * Get the messages
  2051. *
  2052. * @return void
  2053. * @author Ben Edmunds
  2054. **/
  2055. public function messages()
  2056. {
  2057. $_output = '';
  2058. foreach ($this->messages as $message)
  2059. {
  2060. $messageLang = $this->lang->line($message) ? $this->lang->line($message) : '##' . $message . '##';
  2061. $_output .= $this->message_start_delimiter . $messageLang . $this->message_end_delimiter;
  2062. }
  2063.  
  2064. return $_output;
  2065. }
  2066.  
  2067. /**
  2068. * messages as array
  2069. *
  2070. * Get the messages as an array
  2071. *
  2072. * @return array
  2073. * @author Raul Baldner Junior
  2074. **/
  2075. public function messages_array($langify = TRUE)
  2076. {
  2077. if ($langify)
  2078. {
  2079. $_output = array();
  2080. foreach ($this->messages as $message)
  2081. {
  2082. $messageLang = $this->lang->line($message) ? $this->lang->line($message) : '##' . $message . '##';
  2083. $_output[] = $this->message_start_delimiter . $messageLang . $this->message_end_delimiter;
  2084. }
  2085. return $_output;
  2086. }
  2087. else
  2088. {
  2089. return $this->messages;
  2090. }
  2091. }
  2092.  
  2093.  
  2094. /**
  2095. * clear_messages
  2096. *
  2097. * Clear messages
  2098. *
  2099. * @return void
  2100. * @author Ben Edmunds
  2101. **/
  2102. public function clear_messages()
  2103. {
  2104. $this->messages = array();
  2105.  
  2106. return TRUE;
  2107. }
  2108.  
  2109.  
  2110. /**
  2111. * set_error
  2112. *
  2113. * Set an error message
  2114. *
  2115. * @return void
  2116. * @author Ben Edmunds
  2117. **/
  2118. public function set_error($error)
  2119. {
  2120. $this->errors[] = $error;
  2121.  
  2122. return $error;
  2123. }
  2124.  
  2125. /**
  2126. * errors
  2127. *
  2128. * Get the error message
  2129. *
  2130. * @return void
  2131. * @author Ben Edmunds
  2132. **/
  2133. public function errors()
  2134. {
  2135. $_output = '';
  2136. foreach ($this->errors as $error)
  2137. {
  2138. $errorLang = $this->lang->line($error) ? $this->lang->line($error) : '##' . $error . '##';
  2139. $_output .= $this->error_start_delimiter . $errorLang . $this->error_end_delimiter;
  2140. }
  2141.  
  2142. return $_output;
  2143. }
  2144.  
  2145. /**
  2146. * errors as array
  2147. *
  2148. * Get the error messages as an array
  2149. *
  2150. * @return array
  2151. * @author Raul Baldner Junior
  2152. **/
  2153. public function errors_array($langify = TRUE)
  2154. {
  2155. if ($langify)
  2156. {
  2157. $_output = array();
  2158. foreach ($this->errors as $error)
  2159. {
  2160. $errorLang = $this->lang->line($error) ? $this->lang->line($error) : '##' . $error . '##';
  2161. $_output[] = $this->error_start_delimiter . $errorLang . $this->error_end_delimiter;
  2162. }
  2163. return $_output;
  2164. }
  2165. else
  2166. {
  2167. return $this->errors;
  2168. }
  2169. }
  2170.  
  2171.  
  2172. /**
  2173. * clear_errors
  2174. *
  2175. * Clear Errors
  2176. *
  2177. * @return void
  2178. * @author Ben Edmunds
  2179. **/
  2180. public function clear_errors()
  2181. {
  2182. $this->errors = array();
  2183.  
  2184. return TRUE;
  2185. }
  2186.  
  2187.  
  2188. protected function _filter_data($table, $data)
  2189. {
  2190. $filtered_data = array();
  2191. $columns = $this->db->list_fields($table);
  2192.  
  2193. if (is_array($data))
  2194. {
  2195. foreach ($columns as $column)
  2196. {
  2197. if (array_key_exists($column, $data))
  2198. $filtered_data[$column] = $data[$column];
  2199. }
  2200. }
  2201.  
  2202. return $filtered_data;
  2203. }
  2204.  
  2205. protected function _prepare_ip($ip_address) {
  2206. // just return the string IP address now for better compatibility
  2207. return $ip_address;
  2208. }
  2209. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement