PageRenderTime 32ms CodeModel.GetById 4ms RepoModel.GetById 0ms app.codeStats 0ms

/fuel/category_tool/fuel/packages/auth/classes/auth/login/simpleauth.php

https://github.com/connvoi/dev
PHP | 540 lines | 341 code | 65 blank | 134 comment | 38 complexity | 64fa7bf072df13f0a403429a77f06e2a MD5 | raw file
Possible License(s): MIT, BSD-3-Clause
  1. <?php
  2. /**
  3. * Fuel is a fast, lightweight, community driven PHP5 framework.
  4. *
  5. * @package Fuel
  6. * @version 1.0
  7. * @author Fuel Development Team
  8. * @license MIT License
  9. * @copyright 2010 - 2011 Fuel Development Team
  10. * @link http://fuelphp.com
  11. */
  12. namespace Auth;
  13. class SimpleUserUpdateException extends \FuelException {}
  14. class SimpleUserWrongPassword extends \FuelException {}
  15. /**
  16. * SimpleAuth basic login driver
  17. *
  18. * @package Fuel
  19. * @subpackage Auth
  20. */
  21. class Auth_Login_SimpleAuth extends \Auth_Login_Driver
  22. {
  23. public static function _init()
  24. {
  25. \Config::load('simpleauth', true, true, true);
  26. }
  27. /**
  28. * @var Database_Result when login succeeded
  29. */
  30. protected $user = null;
  31. /**
  32. * @var array value for guest login
  33. */
  34. protected static $guest_login = array(
  35. 'id' => 0,
  36. 'username' => 'guest',
  37. 'group' => '0',
  38. 'login_hash' => false,
  39. 'email' => false
  40. );
  41. /**
  42. * @var array SimpleAuth class config
  43. */
  44. protected $config = array(
  45. 'drivers' => array('group' => array('SimpleGroup')),
  46. 'additional_fields' => array('profile_fields'),
  47. );
  48. /**
  49. * Check for login
  50. *
  51. * @return bool
  52. */
  53. protected function perform_check()
  54. {
  55. $username = \Session::get('username');
  56. $login_hash = \Session::get('login_hash');
  57. // only worth checking if there's both a username and login-hash
  58. if ( ! empty($username) and ! empty($login_hash))
  59. {
  60. if (is_null($this->user) or ($this->user['username'] != $username and $this->user != static::$guest_login))
  61. {
  62. $this->user = \DB::select_array(\Config::get('simpleauth.table_columns', array('*')))
  63. ->where('username', '=', $username)
  64. ->from(\Config::get('simpleauth.table_name'))
  65. ->execute(\Config::get('simpleauth.db_connection'))->current();
  66. }
  67. // return true when login was verified
  68. if ($this->user and $this->user['login_hash'] === $login_hash)
  69. {
  70. return true;
  71. }
  72. }
  73. // no valid login when still here, ensure empty session and optionally set guest_login
  74. $this->user = \Config::get('simpleauth.guest_login', true) ? static::$guest_login : false;
  75. \Session::delete('username');
  76. \Session::delete('login_hash');
  77. return false;
  78. }
  79. /**
  80. * Check the user exists before logging in
  81. *
  82. * @return bool
  83. */
  84. public function validate_user($username_or_email = '', $password = '')
  85. {
  86. $username_or_email = trim($username_or_email) ?: trim(\Input::post(\Config::get('simpleauth.username_post_key', 'username')));
  87. $password = trim($password) ?: trim(\Input::post(\Config::get('simpleauth.password_post_key', 'password')));
  88. if (empty($username_or_email) or empty($password))
  89. {
  90. return false;
  91. }
  92. $password = $this->hash_password($password);
  93. $this->user = \DB::select_array(\Config::get('simpleauth.table_columns', array('*')))
  94. ->where_open()
  95. ->where('username', '=', $username_or_email)
  96. ->or_where('email', '=', $username_or_email)
  97. ->where_close()
  98. ->where('password', '=', $password)
  99. ->from(\Config::get('simpleauth.table_name'))
  100. ->execute(\Config::get('simpleauth.db_connection'))->current();
  101. return $this->user ?: false;
  102. }
  103. /**
  104. * Login user
  105. *
  106. * @param string
  107. * @param string
  108. * @return bool
  109. */
  110. public function login($username_or_email = '', $password = '')
  111. {
  112. if ( ! ($this->user = $this->validate_user($username_or_email, $password)))
  113. {
  114. $this->user = \Config::get('simpleauth.guest_login', true) ? static::$guest_login : false;
  115. \Session::delete('username');
  116. \Session::delete('login_hash');
  117. return false;
  118. }
  119. \Session::set('username', $this->user['username']);
  120. \Session::set('login_hash', $this->create_login_hash());
  121. \Session::instance()->rotate();
  122. return true;
  123. }
  124. /**
  125. * Force login user
  126. *
  127. * @param string
  128. * @return bool
  129. */
  130. public function force_login($user_id = '')
  131. {
  132. if (empty($user_id))
  133. {
  134. return false;
  135. }
  136. $this->user = \DB::select_array(\Config::get('simpleauth.table_columns', array('*')))
  137. ->where_open()
  138. ->where('id', '=', $user_id)
  139. ->where_close()
  140. ->from(\Config::get('simpleauth.table_name'))
  141. ->execute(\Config::get('simpleauth.db_connection'))
  142. ->current();
  143. if ($this->user == false)
  144. {
  145. $this->user = \Config::get('simpleauth.guest_login', true) ? static::$guest_login : false;
  146. \Session::delete('username');
  147. \Session::delete('login_hash');
  148. return false;
  149. }
  150. \Session::set('username', $this->user['username']);
  151. \Session::set('login_hash', $this->create_login_hash());
  152. return true;
  153. }
  154. /**
  155. * Logout user
  156. *
  157. * @return bool
  158. */
  159. public function logout()
  160. {
  161. $this->user = \Config::get('simpleauth.guest_login', true) ? static::$guest_login : false;
  162. \Session::delete('username');
  163. \Session::delete('login_hash');
  164. return true;
  165. }
  166. /**
  167. * Create new user
  168. *
  169. * @param string
  170. * @param string
  171. * @param string must contain valid email address
  172. * @param int group id
  173. * @param Array
  174. * @return bool
  175. */
  176. public function create_user($username, $password, $email, $group = 1, Array $profile_fields = array())
  177. {
  178. $password = trim($password);
  179. $email = filter_var(trim($email), FILTER_VALIDATE_EMAIL);
  180. if (empty($username) or empty($password) or empty($email))
  181. {
  182. throw new \SimpleUserUpdateException('Username, password and email address can\'t be empty.', 1);
  183. }
  184. $same_users = \DB::select_array(\Config::get('simpleauth.table_columns', array('*')))
  185. ->where('username', '=', $username)
  186. ->or_where('email', '=', $email)
  187. ->from(\Config::get('simpleauth.table_name'))
  188. ->execute(\Config::get('simpleauth.db_connection'));
  189. if ($same_users->count() > 0)
  190. {
  191. if (in_array(strtolower($email), array_map('strtolower', $same_users->current())))
  192. {
  193. throw new \SimpleUserUpdateException('Email address already exists', 2);
  194. }
  195. else
  196. {
  197. throw new \SimpleUserUpdateException('Username already exists', 3);
  198. }
  199. }
  200. $user = array(
  201. 'username' => (string) $username,
  202. 'password' => $this->hash_password((string) $password),
  203. 'email' => $email,
  204. 'group' => (int) $group,
  205. 'profile_fields' => serialize($profile_fields),
  206. 'created_at' => \Date::forge()->get_timestamp()
  207. );
  208. $result = \DB::insert(\Config::get('simpleauth.table_name'))
  209. ->set($user)
  210. ->execute(\Config::get('simpleauth.db_connection'));
  211. return ($result[1] > 0) ? $result[0] : false;
  212. }
  213. /**
  214. * Update a user's properties
  215. * Note: Username cannot be updated, to update password the old password must be passed as old_password
  216. *
  217. * @param Array properties to be updated including profile fields
  218. * @param string
  219. * @return bool
  220. */
  221. public function update_user($values, $username = null)
  222. {
  223. $username = $username ?: $this->user['username'];
  224. $current_values = \DB::select_array(\Config::get('simpleauth.table_columns', array('*')))
  225. ->where('username', '=', $username)
  226. ->from(\Config::get('simpleauth.table_name'))
  227. ->execute(\Config::get('simpleauth.db_connection'));
  228. if (empty($current_values))
  229. {
  230. throw new \SimpleUserUpdateException('Username not found', 4);
  231. }
  232. $update = array();
  233. if (array_key_exists('username', $values))
  234. {
  235. throw new \SimpleUserUpdateException('Username cannot be changed.', 5);
  236. }
  237. if (array_key_exists('password', $values))
  238. {
  239. if (empty($values['old_password'])
  240. or $current_values->get('password') != $this->hash_password(trim($values['old_password'])))
  241. {
  242. throw new \SimpleUserWrongPassword('Old password is invalid');
  243. }
  244. $password = trim(strval($values['password']));
  245. if ($password === '')
  246. {
  247. throw new \SimpleUserUpdateException('Password can\'t be empty.', 6);
  248. }
  249. $update['password'] = $this->hash_password($password);
  250. unset($values['password']);
  251. }
  252. if (array_key_exists('old_password', $values))
  253. {
  254. unset($values['old_password']);
  255. }
  256. if (array_key_exists('email', $values))
  257. {
  258. $email = filter_var(trim($values['email']), FILTER_VALIDATE_EMAIL);
  259. if ( ! $email)
  260. {
  261. throw new \SimpleUserUpdateException('Email address is not valid', 7);
  262. }
  263. $update['email'] = $email;
  264. unset($values['email']);
  265. }
  266. if (array_key_exists('group', $values))
  267. {
  268. if (is_numeric($values['group']))
  269. {
  270. $update['group'] = (int) $values['group'];
  271. }
  272. unset($values['group']);
  273. }
  274. if ( ! empty($values))
  275. {
  276. $profile_fields = @unserialize($current_values->get('profile_fields')) ?: array();
  277. foreach ($values as $key => $val)
  278. {
  279. if ($val === null)
  280. {
  281. unset($profile_fields[$key]);
  282. }
  283. else
  284. {
  285. $profile_fields[$key] = $val;
  286. }
  287. }
  288. $update['profile_fields'] = serialize($profile_fields);
  289. }
  290. $affected_rows = \DB::update(\Config::get('simpleauth.table_name'))
  291. ->set($update)
  292. ->where('username', '=', $username)
  293. ->execute(\Config::get('simpleauth.db_connection'));
  294. // Refresh user
  295. if ($this->user['username'] == $username)
  296. {
  297. $this->user = \DB::select_array(\Config::get('simpleauth.table_columns', array('*')))
  298. ->where('username', '=', $username)
  299. ->from(\Config::get('simpleauth.table_name'))
  300. ->execute(\Config::get('simpleauth.db_connection'))->current();
  301. }
  302. return $affected_rows > 0;
  303. }
  304. /**
  305. * Change a user's password
  306. *
  307. * @param string
  308. * @param string
  309. * @param string username or null for current user
  310. * @return bool
  311. */
  312. public function change_password($old_password, $new_password, $username = null)
  313. {
  314. try
  315. {
  316. return (bool) $this->update_user(array('old_password' => $old_password, 'password' => $new_password), $username);
  317. }
  318. // Only catch the wrong password exception
  319. catch (SimpleUserWrongPassword $e)
  320. {
  321. return false;
  322. }
  323. }
  324. /**
  325. * Generates new random password, sets it for the given username and returns the new password.
  326. * To be used for resetting a user's forgotten password, should be emailed afterwards.
  327. *
  328. * @param string $username
  329. * @return string
  330. */
  331. public function reset_password($username)
  332. {
  333. $new_password = \Str::random('alnum', 8);
  334. $password_hash = $this->hash_password($new_password);
  335. $affected_rows = \DB::update(\Config::get('simpleauth.table_name'))
  336. ->set(array('password' => $password_hash))
  337. ->where('username', '=', $username)
  338. ->execute(\Config::get('simpleauth.db_connection'));
  339. if ( ! $affected_rows)
  340. {
  341. throw new \SimpleUserUpdateException('Failed to reset password, user was invalid.', 8);
  342. }
  343. return $new_password;
  344. }
  345. /**
  346. * Deletes a given user
  347. *
  348. * @param string
  349. * @return bool
  350. */
  351. public function delete_user($username)
  352. {
  353. if (empty($username))
  354. {
  355. throw new \SimpleUserUpdateException('Cannot delete user with empty username', 9);
  356. }
  357. $affected_rows = \DB::delete(\Config::get('simpleauth.table_name'))
  358. ->where('username', '=', $username)
  359. ->execute(\Config::get('simpleauth.db_connection'));
  360. return $affected_rows > 0;
  361. }
  362. /**
  363. * Creates a temporary hash that will validate the current login
  364. *
  365. * @return string
  366. */
  367. public function create_login_hash()
  368. {
  369. if (empty($this->user))
  370. {
  371. throw new \SimpleUserUpdateException('User not logged in, can\'t create login hash.', 10);
  372. }
  373. $last_login = \Date::forge()->get_timestamp();
  374. $login_hash = sha1(\Config::get('simpleauth.login_hash_salt').$this->user['username'].$last_login);
  375. \DB::update(\Config::get('simpleauth.table_name'))
  376. ->set(array('last_login' => $last_login, 'login_hash' => $login_hash))
  377. ->where('username', '=', $this->user['username'])
  378. ->execute(\Config::get('simpleauth.db_connection'));
  379. $this->user['login_hash'] = $login_hash;
  380. return $login_hash;
  381. }
  382. /**
  383. * Get the user's ID
  384. *
  385. * @return Array containing this driver's ID & the user's ID
  386. */
  387. public function get_user_id()
  388. {
  389. if (empty($this->user))
  390. {
  391. return false;
  392. }
  393. return array($this->id, (int) $this->user['id']);
  394. }
  395. /**
  396. * Get the user's groups
  397. *
  398. * @return Array containing the group driver ID & the user's group ID
  399. */
  400. public function get_groups()
  401. {
  402. if (empty($this->user))
  403. {
  404. return false;
  405. }
  406. return array(array('SimpleGroup', $this->user['group']));
  407. }
  408. /**
  409. * Get the user's emailaddress
  410. *
  411. * @return string
  412. */
  413. public function get_email()
  414. {
  415. if (empty($this->user))
  416. {
  417. return false;
  418. }
  419. return $this->user['email'];
  420. }
  421. /**
  422. * Get the user's screen name
  423. *
  424. * @return string
  425. */
  426. public function get_screen_name()
  427. {
  428. if (empty($this->user))
  429. {
  430. return false;
  431. }
  432. return $this->user['username'];
  433. }
  434. /**
  435. * Get the user's profile fields
  436. *
  437. * @return Array
  438. */
  439. public function get_profile_fields()
  440. {
  441. if (empty($this->user))
  442. {
  443. return false;
  444. }
  445. if (isset($this->user['profile_fields']))
  446. {
  447. is_array($this->user['profile_fields']) or $this->user['profile_fields'] = @unserialize($this->user['profile_fields']);
  448. }
  449. else
  450. {
  451. $this->user['profile_fields'] = array();
  452. }
  453. return $this->user['profile_fields'];
  454. }
  455. /**
  456. * Extension of base driver method to default to user group instead of user id
  457. */
  458. public function has_access($condition, $driver = null, $user = null)
  459. {
  460. if (is_null($user))
  461. {
  462. $groups = $this->get_groups();
  463. $user = reset($groups);
  464. }
  465. return parent::has_access($condition, $driver, $user);
  466. }
  467. /**
  468. * Extension of base driver because this supports a guest login when switched on
  469. */
  470. public function guest_login()
  471. {
  472. return \Config::get('simpleauth.guest_login', true);
  473. }
  474. }
  475. // end of file simpleauth.php