Advertisement
Guest User

Library Tank Auth

a guest
Aug 16th, 2011
303
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 18.00 KB | None | 0 0
  1. <?php if (!defined('BASEPATH')) exit('No direct script access allowed');
  2.  
  3. require_once('phpass-0.1/PasswordHash.php');
  4.  
  5. define('STATUS_ACTIVATED', '1');
  6. define('STATUS_NOT_ACTIVATED', '0');
  7.  
  8. /**
  9.  * Tank_auth
  10.  *
  11.  * Authentication library for Code Igniter.
  12.  *
  13.  * @package     Tank_auth
  14.  * @author      Ilya Konyukhov (http://konyukhov.com/soft/)
  15.  * @version     1.0.9
  16.  * @based on    DX Auth by Dexcell (http://dexcell.shinsengumiteam.com/dx_auth)
  17.  * @license     MIT License Copyright (c) 2008 Erick Hartanto
  18.  */
  19. class Tank_auth
  20. {
  21.     private $error = array();
  22.  
  23.     function __construct()
  24.     {
  25.         $this->ci =& get_instance();
  26.  
  27.         $this->ci->load->config('tank_auth', TRUE);
  28.  
  29.         $this->ci->load->library('session');
  30.         $this->ci->load->database();
  31.         $this->ci->load->model('tank_auth/users');
  32.  
  33.         // Try to autologin
  34.         $this->autologin();
  35.     }
  36.  
  37.     /**
  38.      * Login user on the site. Return TRUE if login is successful
  39.      * (user exists and activated, password is correct), otherwise FALSE.
  40.      *
  41.      * @param   string  (username or email or both depending on settings in config file)
  42.      * @param   string
  43.      * @param   bool
  44.      * @return  bool
  45.      */
  46.     function login($login, $password, $remember, $login_by_username, $login_by_email)
  47.     {
  48.         if ((strlen($login) > 0) AND (strlen($password) > 0)) {
  49.  
  50.             // Which function to use to login (based on config)
  51.             if ($login_by_username AND $login_by_email) {
  52.                 $get_user_func = 'get_user_by_login';
  53.             } else if ($login_by_username) {
  54.                 $get_user_func = 'get_user_by_username';
  55.             } else {
  56.                 $get_user_func = 'get_user_by_email';
  57.             }
  58.  
  59.             if (!is_null($user = $this->ci->users->$get_user_func($login))) {   // login ok
  60.  
  61.                 // Does password match hash in database?
  62.                 $hasher = new PasswordHash(
  63.                         $this->ci->config->item('phpass_hash_strength', 'tank_auth'),
  64.                         $this->ci->config->item('phpass_hash_portable', 'tank_auth'));
  65.                 if ($hasher->CheckPassword($password, $user->password)) {       // password ok
  66.  
  67.                     if ($user->banned == 1) {                                   // fail - banned
  68.                         $this->error = array('banned' => $user->ban_reason);
  69.  
  70.                     } else {
  71.                         $this->ci->session->set_userdata(array(
  72.                                 'user_id'   => $user->id,
  73.                                 'username'  => $user->username,
  74.                                 'status'    => ($user->activated == 1) ? STATUS_ACTIVATED : STATUS_NOT_ACTIVATED,
  75.                         ));
  76.  
  77.                         if ($user->activated == 0) {                            // fail - not activated
  78.                             $this->error = array('not_activated' => '');
  79.  
  80.                         } else {                                                // success
  81.                             if ($remember) {
  82.                                 $this->create_autologin($user->id);
  83.                             }
  84.  
  85.                             $this->clear_login_attempts($login);
  86.  
  87.                             $this->ci->users->update_login_info(
  88.                                     $user->id,
  89.                                     $this->ci->config->item('login_record_ip', 'tank_auth'),
  90.                                     $this->ci->config->item('login_record_time', 'tank_auth'));
  91.                             return TRUE;
  92.                         }
  93.                     }
  94.                 } else {                                                        // fail - wrong password
  95.                     $this->increase_login_attempt($login);
  96.                     $this->error = array('password' => 'auth_incorrect_password');
  97.                 }
  98.             } else {                                                            // fail - wrong login
  99.                 $this->increase_login_attempt($login);
  100.                 $this->error = array('login' => 'auth_incorrect_login');
  101.             }
  102.         }
  103.         return FALSE;
  104.     }
  105.  
  106.     /**
  107.      * Logout user from the site
  108.      *
  109.      * @return  void
  110.      */
  111.     function logout()
  112.     {
  113.         $this->delete_autologin();
  114.  
  115.         // See http://codeigniter.com/forums/viewreply/662369/ as the reason for the next line
  116.         $this->ci->session->set_userdata(array('user_id' => '', 'username' => '', 'status' => ''));
  117.  
  118.         $this->ci->session->sess_destroy();
  119.     }
  120.  
  121.     /**
  122.      * Check if user logged in. Also test if user is activated or not.
  123.      *
  124.      * @param   bool
  125.      * @return  bool
  126.      */
  127.     function is_logged_in($activated = TRUE)
  128.     {
  129.         return $this->ci->session->userdata('status') === ($activated ? STATUS_ACTIVATED : STATUS_NOT_ACTIVATED);
  130.     }
  131.  
  132.     /**
  133.      * Get user_id
  134.      *
  135.      * @return  string
  136.      */
  137.     function get_user_id()
  138.     {
  139.         return $this->ci->session->userdata('user_id');
  140.     }
  141.  
  142.     /**
  143.      * Get username
  144.      *
  145.      * @return  string
  146.      */
  147.     function get_username()
  148.     {
  149.         return $this->ci->session->userdata('username');
  150.     }
  151.  
  152.     /**
  153.      * Create new user on the site and return some data about it:
  154.      * user_id, username, password, email, new_email_key (if any).
  155.      *
  156.      * @param   string
  157.      * @param   string
  158.      * @param   string
  159.      * @param   bool
  160.      * @return  array
  161.      */
  162.     function create_user($username, $email, $password, $email_activation, $userInfo)
  163.     {
  164.         if ((strlen($username) > 0) AND !$this->ci->users->is_username_available($username)) {
  165.             $this->error = array('username' => 'auth_username_in_use');
  166.  
  167.         } elseif (!$this->ci->users->is_email_available($email)) {
  168.             $this->error = array('email' => 'auth_email_in_use');
  169.  
  170.         } else {
  171.             // Hash password using phpass
  172.             $hasher = new PasswordHash(
  173.                     $this->ci->config->item('phpass_hash_strength', 'tank_auth'),
  174.                     $this->ci->config->item('phpass_hash_portable', 'tank_auth'));
  175.             $hashed_password = $hasher->HashPassword($password);
  176.  
  177.             $data = array(
  178.                 'username'  => $username,
  179.                 'password'  => $hashed_password,
  180.                 'email'     => $email,
  181.                 'last_ip'   => $this->ci->input->ip_address(),
  182.             );
  183.  
  184.             if ($email_activation) {
  185.                 $data['new_email_key'] = md5(rand().microtime());
  186.             }
  187.             if (!is_null($res = $this->ci->users->create_user($data, !$email_activation))) {
  188.                 $this->users->UpdateProfileInfo($userInfo["firstname"],$userInfo["lastname"]);
  189.                 $data['user_id'] = $res['user_id'];
  190.                 $data['password'] = $password;
  191.                 unset($data['last_ip']);
  192.                 return $data;
  193.             }
  194.         }
  195.         return NULL;
  196.     }
  197.  
  198.     /**
  199.      * Check if username available for registering.
  200.      * Can be called for instant form validation.
  201.      *
  202.      * @param   string
  203.      * @return  bool
  204.      */
  205.     function is_username_available($username)
  206.     {
  207.         return ((strlen($username) > 0) AND $this->ci->users->is_username_available($username));
  208.     }
  209.  
  210.     /**
  211.      * Check if email available for registering.
  212.      * Can be called for instant form validation.
  213.      *
  214.      * @param   string
  215.      * @return  bool
  216.      */
  217.     function is_email_available($email)
  218.     {
  219.         return ((strlen($email) > 0) AND $this->ci->users->is_email_available($email));
  220.     }
  221.  
  222.     /**
  223.      * Change email for activation and return some data about user:
  224.      * user_id, username, email, new_email_key.
  225.      * Can be called for not activated users only.
  226.      *
  227.      * @param   string
  228.      * @return  array
  229.      */
  230.     function change_email($email)
  231.     {
  232.         $user_id = $this->ci->session->userdata('user_id');
  233.  
  234.         if (!is_null($user = $this->ci->users->get_user_by_id($user_id, FALSE))) {
  235.  
  236.             $data = array(
  237.                 'user_id'   => $user_id,
  238.                 'username'  => $user->username,
  239.                 'email'     => $email,
  240.             );
  241.             if (strtolower($user->email) == strtolower($email)) {       // leave activation key as is
  242.                 $data['new_email_key'] = $user->new_email_key;
  243.                 return $data;
  244.  
  245.             } elseif ($this->ci->users->is_email_available($email)) {
  246.                 $data['new_email_key'] = md5(rand().microtime());
  247.                 $this->ci->users->set_new_email($user_id, $email, $data['new_email_key'], FALSE);
  248.                 return $data;
  249.  
  250.             } else {
  251.                 $this->error = array('email' => 'auth_email_in_use');
  252.             }
  253.         }
  254.         return NULL;
  255.     }
  256.  
  257.     /**
  258.      * Activate user using given key
  259.      *
  260.      * @param   string
  261.      * @param   string
  262.      * @param   bool
  263.      * @return  bool
  264.      */
  265.     function activate_user($user_id, $activation_key, $activate_by_email = TRUE)
  266.     {
  267.         $this->ci->users->purge_na($this->ci->config->item('email_activation_expire', 'tank_auth'));
  268.  
  269.         if ((strlen($user_id) > 0) AND (strlen($activation_key) > 0)) {
  270.             return $this->ci->users->activate_user($user_id, $activation_key, $activate_by_email);
  271.         }
  272.         return FALSE;
  273.     }
  274.  
  275.     /**
  276.      * Set new password key for user and return some data about user:
  277.      * user_id, username, email, new_pass_key.
  278.      * The password key can be used to verify user when resetting his/her password.
  279.      *
  280.      * @param   string
  281.      * @return  array
  282.      */
  283.     function forgot_password($login)
  284.     {
  285.         if (strlen($login) > 0) {
  286.             if (!is_null($user = $this->ci->users->get_user_by_login($login))) {
  287.  
  288.                 $data = array(
  289.                     'user_id'       => $user->id,
  290.                     'username'      => $user->username,
  291.                     'email'         => $user->email,
  292.                     'new_pass_key'  => md5(rand().microtime()),
  293.                 );
  294.  
  295.                 $this->ci->users->set_password_key($user->id, $data['new_pass_key']);
  296.                 return $data;
  297.  
  298.             } else {
  299.                 $this->error = array('login' => 'auth_incorrect_email_or_username');
  300.             }
  301.         }
  302.         return NULL;
  303.     }
  304.  
  305.     /**
  306.      * Check if given password key is valid and user is authenticated.
  307.      *
  308.      * @param   string
  309.      * @param   string
  310.      * @return  bool
  311.      */
  312.     function can_reset_password($user_id, $new_pass_key)
  313.     {
  314.         if ((strlen($user_id) > 0) AND (strlen($new_pass_key) > 0)) {
  315.             return $this->ci->users->can_reset_password(
  316.                 $user_id,
  317.                 $new_pass_key,
  318.                 $this->ci->config->item('forgot_password_expire', 'tank_auth'));
  319.         }
  320.         return FALSE;
  321.     }
  322.  
  323.     /**
  324.      * Replace user password (forgotten) with a new one (set by user)
  325.      * and return some data about it: user_id, username, new_password, email.
  326.      *
  327.      * @param   string
  328.      * @param   string
  329.      * @return  bool
  330.      */
  331.     function reset_password($user_id, $new_pass_key, $new_password)
  332.     {
  333.         if ((strlen($user_id) > 0) AND (strlen($new_pass_key) > 0) AND (strlen($new_password) > 0)) {
  334.  
  335.             if (!is_null($user = $this->ci->users->get_user_by_id($user_id, TRUE))) {
  336.  
  337.                 // Hash password using phpass
  338.                 $hasher = new PasswordHash(
  339.                         $this->ci->config->item('phpass_hash_strength', 'tank_auth'),
  340.                         $this->ci->config->item('phpass_hash_portable', 'tank_auth'));
  341.                 $hashed_password = $hasher->HashPassword($new_password);
  342.  
  343.                 if ($this->ci->users->reset_password(
  344.                         $user_id,
  345.                         $hashed_password,
  346.                         $new_pass_key,
  347.                         $this->ci->config->item('forgot_password_expire', 'tank_auth'))) {  // success
  348.  
  349.                     // Clear all user's autologins
  350.                     $this->ci->load->model('tank_auth/user_autologin');
  351.                     $this->ci->user_autologin->clear($user->id);
  352.  
  353.                     return array(
  354.                         'user_id'       => $user_id,
  355.                         'username'      => $user->username,
  356.                         'email'         => $user->email,
  357.                         'new_password'  => $new_password,
  358.                     );
  359.                 }
  360.             }
  361.         }
  362.         return NULL;
  363.     }
  364.  
  365.     /**
  366.      * Change user password (only when user is logged in)
  367.      *
  368.      * @param   string
  369.      * @param   string
  370.      * @return  bool
  371.      */
  372.     function change_password($old_pass, $new_pass)
  373.     {
  374.         $user_id = $this->ci->session->userdata('user_id');
  375.  
  376.         if (!is_null($user = $this->ci->users->get_user_by_id($user_id, TRUE))) {
  377.  
  378.             // Check if old password correct
  379.             $hasher = new PasswordHash(
  380.                     $this->ci->config->item('phpass_hash_strength', 'tank_auth'),
  381.                     $this->ci->config->item('phpass_hash_portable', 'tank_auth'));
  382.             if ($hasher->CheckPassword($old_pass, $user->password)) {           // success
  383.  
  384.                 // Hash new password using phpass
  385.                 $hashed_password = $hasher->HashPassword($new_pass);
  386.  
  387.                 // Replace old password with new one
  388.                 $this->ci->users->change_password($user_id, $hashed_password);
  389.                 return TRUE;
  390.  
  391.             } else {                                                            // fail
  392.                 $this->error = array('old_password' => 'auth_incorrect_password');
  393.             }
  394.         }
  395.         return FALSE;
  396.     }
  397.  
  398.     /**
  399.      * Change user email (only when user is logged in) and return some data about user:
  400.      * user_id, username, new_email, new_email_key.
  401.      * The new email cannot be used for login or notification before it is activated.
  402.      *
  403.      * @param   string
  404.      * @param   string
  405.      * @return  array
  406.      */
  407.     function set_new_email($new_email, $password)
  408.     {
  409.         $user_id = $this->ci->session->userdata('user_id');
  410.  
  411.         if (!is_null($user = $this->ci->users->get_user_by_id($user_id, TRUE))) {
  412.  
  413.             // Check if password correct
  414.             $hasher = new PasswordHash(
  415.                     $this->ci->config->item('phpass_hash_strength', 'tank_auth'),
  416.                     $this->ci->config->item('phpass_hash_portable', 'tank_auth'));
  417.             if ($hasher->CheckPassword($password, $user->password)) {           // success
  418.  
  419.                 $data = array(
  420.                     'user_id'   => $user_id,
  421.                     'username'  => $user->username,
  422.                     'new_email' => $new_email,
  423.                 );
  424.  
  425.                 if ($user->email == $new_email) {
  426.                     $this->error = array('email' => 'auth_current_email');
  427.  
  428.                 } elseif ($user->new_email == $new_email) {     // leave email key as is
  429.                     $data['new_email_key'] = $user->new_email_key;
  430.                     return $data;
  431.  
  432.                 } elseif ($this->ci->users->is_email_available($new_email)) {
  433.                     $data['new_email_key'] = md5(rand().microtime());
  434.                     $this->ci->users->set_new_email($user_id, $new_email, $data['new_email_key'], TRUE);
  435.                     return $data;
  436.  
  437.                 } else {
  438.                     $this->error = array('email' => 'auth_email_in_use');
  439.                 }
  440.             } else {                                                            // fail
  441.                 $this->error = array('password' => 'auth_incorrect_password');
  442.             }
  443.         }
  444.         return NULL;
  445.     }
  446.  
  447.     /**
  448.      * Activate new email, if email activation key is valid.
  449.      *
  450.      * @param   string
  451.      * @param   string
  452.      * @return  bool
  453.      */
  454.     function activate_new_email($user_id, $new_email_key)
  455.     {
  456.         if ((strlen($user_id) > 0) AND (strlen($new_email_key) > 0)) {
  457.             return $this->ci->users->activate_new_email(
  458.                     $user_id,
  459.                     $new_email_key);
  460.         }
  461.         return FALSE;
  462.     }
  463.  
  464.     /**
  465.      * Delete user from the site (only when user is logged in)
  466.      *
  467.      * @param   string
  468.      * @return  bool
  469.      */
  470.     function delete_user($password)
  471.     {
  472.         $user_id = $this->ci->session->userdata('user_id');
  473.  
  474.         if (!is_null($user = $this->ci->users->get_user_by_id($user_id, TRUE))) {
  475.  
  476.             // Check if password correct
  477.             $hasher = new PasswordHash(
  478.                     $this->ci->config->item('phpass_hash_strength', 'tank_auth'),
  479.                     $this->ci->config->item('phpass_hash_portable', 'tank_auth'));
  480.             if ($hasher->CheckPassword($password, $user->password)) {           // success
  481.  
  482.                 $this->ci->users->delete_user($user_id);
  483.                 $this->logout();
  484.                 return TRUE;
  485.  
  486.             } else {                                                            // fail
  487.                 $this->error = array('password' => 'auth_incorrect_password');
  488.             }
  489.         }
  490.         return FALSE;
  491.     }
  492.  
  493.     /**
  494.      * Get error message.
  495.      * Can be invoked after any failed operation such as login or register.
  496.      *
  497.      * @return  string
  498.      */
  499.     function get_error_message()
  500.     {
  501.         return $this->error;
  502.     }
  503.  
  504.     /**
  505.      * Save data for user's autologin
  506.      *
  507.      * @param   int
  508.      * @return  bool
  509.      */
  510.     private function create_autologin($user_id)
  511.     {
  512.         $this->ci->load->helper('cookie');
  513.         $key = substr(md5(uniqid(rand().get_cookie($this->ci->config->item('sess_cookie_name')))), 0, 16);
  514.  
  515.         $this->ci->load->model('tank_auth/user_autologin');
  516.         $this->ci->user_autologin->purge($user_id);
  517.  
  518.         if ($this->ci->user_autologin->set($user_id, md5($key))) {
  519.             set_cookie(array(
  520.                     'name'      => $this->ci->config->item('autologin_cookie_name', 'tank_auth'),
  521.                     'value'     => serialize(array('user_id' => $user_id, 'key' => $key)),
  522.                     'expire'    => $this->ci->config->item('autologin_cookie_life', 'tank_auth'),
  523.             ));
  524.             return TRUE;
  525.         }
  526.         return FALSE;
  527.     }
  528.  
  529.     /**
  530.      * Clear user's autologin data
  531.      *
  532.      * @return  void
  533.      */
  534.     private function delete_autologin()
  535.     {
  536.         $this->ci->load->helper('cookie');
  537.         if ($cookie = get_cookie($this->ci->config->item('autologin_cookie_name', 'tank_auth'), TRUE)) {
  538.  
  539.             $data = unserialize($cookie);
  540.  
  541.             $this->ci->load->model('tank_auth/user_autologin');
  542.             $this->ci->user_autologin->delete($data['user_id'], md5($data['key']));
  543.  
  544.             delete_cookie($this->ci->config->item('autologin_cookie_name', 'tank_auth'));
  545.         }
  546.     }
  547.  
  548.     /**
  549.      * Login user automatically if he/she provides correct autologin verification
  550.      *
  551.      * @return  void
  552.      */
  553.     private function autologin()
  554.     {
  555.         if (!$this->is_logged_in() AND !$this->is_logged_in(FALSE)) {           // not logged in (as any user)
  556.  
  557.             $this->ci->load->helper('cookie');
  558.             if ($cookie = get_cookie($this->ci->config->item('autologin_cookie_name', 'tank_auth'), TRUE)) {
  559.  
  560.                 $data = unserialize($cookie);
  561.  
  562.                 if (isset($data['key']) AND isset($data['user_id'])) {
  563.  
  564.                     $this->ci->load->model('tank_auth/user_autologin');
  565.                     if (!is_null($user = $this->ci->user_autologin->get($data['user_id'], md5($data['key'])))) {
  566.  
  567.                         // Login user
  568.                         $this->ci->session->set_userdata(array(
  569.                                 'user_id'   => $user->id,
  570.                                 'username'  => $user->username,
  571.                                 'status'    => STATUS_ACTIVATED,
  572.                         ));
  573.  
  574.                         // Renew users cookie to prevent it from expiring
  575.                         set_cookie(array(
  576.                                 'name'      => $this->ci->config->item('autologin_cookie_name', 'tank_auth'),
  577.                                 'value'     => $cookie,
  578.                                 'expire'    => $this->ci->config->item('autologin_cookie_life', 'tank_auth'),
  579.                         ));
  580.  
  581.                         $this->ci->users->update_login_info(
  582.                                 $user->id,
  583.                                 $this->ci->config->item('login_record_ip', 'tank_auth'),
  584.                                 $this->ci->config->item('login_record_time', 'tank_auth'));
  585.                         return TRUE;
  586.                     }
  587.                 }
  588.             }
  589.         }
  590.         return FALSE;
  591.     }
  592.  
  593.     /**
  594.      * Check if login attempts exceeded max login attempts (specified in config)
  595.      *
  596.      * @param   string
  597.      * @return  bool
  598.      */
  599.     function is_max_login_attempts_exceeded($login)
  600.     {
  601.         if ($this->ci->config->item('login_count_attempts', 'tank_auth')) {
  602.             $this->ci->load->model('tank_auth/login_attempts');
  603.             return $this->ci->login_attempts->get_attempts_num($this->ci->input->ip_address(), $login)
  604.                     >= $this->ci->config->item('login_max_attempts', 'tank_auth');
  605.         }
  606.         return FALSE;
  607.     }
  608.  
  609.     /**
  610.      * Increase number of attempts for given IP-address and login
  611.      * (if attempts to login is being counted)
  612.      *
  613.      * @param   string
  614.      * @return  void
  615.      */
  616.     private function increase_login_attempt($login)
  617.     {
  618.         if ($this->ci->config->item('login_count_attempts', 'tank_auth')) {
  619.             if (!$this->is_max_login_attempts_exceeded($login)) {
  620.                 $this->ci->load->model('tank_auth/login_attempts');
  621.                 $this->ci->login_attempts->increase_attempt($this->ci->input->ip_address(), $login);
  622.             }
  623.         }
  624.     }
  625.  
  626.     /**
  627.      * Clear all attempt records for given IP-address and login
  628.      * (if attempts to login is being counted)
  629.      *
  630.      * @param   string
  631.      * @return  void
  632.      */
  633.     private function clear_login_attempts($login)
  634.     {
  635.         if ($this->ci->config->item('login_count_attempts', 'tank_auth')) {
  636.             $this->ci->load->model('tank_auth/login_attempts');
  637.             $this->ci->login_attempts->clear_attempts(
  638.                     $this->ci->input->ip_address(),
  639.                     $login,
  640.                     $this->ci->config->item('login_attempt_expire', 'tank_auth'));
  641.         }
  642.     }
  643. }
  644.  
  645. /* End of file Tank_auth.php */
  646. /* Location: ./application/libraries/Tank_auth.php */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement