├── README.md ├── application ├── config │ └── bitauth.php ├── controllers │ └── example.php ├── language │ └── english │ │ └── bitauth_lang.php ├── libraries │ ├── Bitauth.php │ ├── MY_Form_validation.php │ └── phpass.php └── views │ └── example │ ├── activation_failed.php │ ├── activation_successful.php │ ├── add_group.php │ ├── add_user.php │ ├── edit_group.php │ ├── edit_user.php │ ├── groups.php │ ├── login.php │ ├── no_access.php │ └── users.php ├── bitauth.sql └── user_guide ├── general ├── config.html ├── notes.html ├── utility.html └── validation.html ├── groups ├── adding.html ├── assigning.html ├── editing.html └── fetching.html ├── images ├── arrow.gif ├── nav_bg_darker.jpg ├── nav_separator_darker.jpg ├── nav_toggle_darker.jpg └── transparent.gif ├── index.html ├── nav ├── hacks.txt ├── moo.fx.js ├── nav.js ├── prototype.lite.js └── user_guide_menu.js ├── roles ├── checking.html ├── creating.html └── setting.html ├── toc.html ├── userguide.css └── users ├── adding.html ├── assigning.html ├── customizing.html ├── editing.html ├── fetching.html └── logging_in.html /README.md: -------------------------------------------------------------------------------- 1 | #BitAuth 2 | 3 | * [Website](http://www.dmontgomery.net/bitauth) - http://www.dmontgomery.net/bitauth 4 | * [Github](https://github.com/danmontgomery/codeigniter-bitauth) - https://github.com/danmontgomery/codeigniter-bitauth 5 | * [Issues](https://github.com/danmontgomery/codeigniter-bitauth/issues) - https://github.com/danmontgomery/codeigniter-bitauth/issues 6 | 7 | ##Requirements 8 | * PHP 5.1.6+, 5.3+ recommended 9 | * CodeIgniter 2.0+ 10 | * MySQL 11 | * ~~php-gmp~~ 12 | 13 | ##Features 14 | * Phpass Integration: BitAuth uses [phpass](http://www.openwall.com/phpass/) to handle password hashing 15 | * Password complexity rules: Along with minimum and maximum length, specify the required number of: 16 | * Uppercase Characters 17 | * Numbers 18 | * Special Characters 19 | * Spaces 20 | * ... Or, add your own 21 | * Password aging: Require your users to change their passwords at a set interval 22 | * Completely custom userdata: Easily customize BitAuth to include any custom you want. Full name, Nickname, Phone number, Favorite color... You name it! 23 | * Groups and Roles: Create groups, and assign users to your groups. Your roles are set on a group, not a user, so changing roles, whether the scale is large or small, is fast and painless. 24 | * Text-based roles: Simply list your roles in the configuration file, then check against them in your code. BitAuth handles everything in between. 25 | 26 | ##Download 27 | [https://github.com/danmontgomery/codeigniter-bitauth/tarball/v0.2.1](https://github.com/danmontgomery/codeigniter-bitauth/tarball/v0.2.1) 28 | 29 | ##Installation 30 | Copy the included files to their appropriate locations in the application/ folder. Import bitauth.sql into your database. **If you would like to change the names of the tables BitAuth uses, you can change them in this .sql file, and must also change them in config/bitauth.php**. 31 | 32 | ##Updating 33 | If updating from v0.1.x, there is a convert() function in the Example controller. This will modify the structure of your groups table, as well as convert any roles you have stored to the new format. This function uses base_convert(), which means results may vary depending on the machine you're running this on. After upgrading, be sure to check the roles in your groups for accuracy. 34 | 35 | ##Notes 36 | As of v0.2.0, php-gmp is no longer used. The structure of the bitauth_groups table has changed, as well. 37 | 38 | The default login is **admin**/**admin**. 39 | 40 | I **highly** recommend you not use the default cookie session... [Try my driver replacement](http://getsparks.org/packages/session-driver/show) for CI's session library (end of shameless self promotion). 41 | 42 | Currently, only MySQL is supported. This may change in the future. Or not. We'll see. -------------------------------------------------------------------------------- /application/config/bitauth.php: -------------------------------------------------------------------------------- 1 | 1, 68 | 'number' => 1, 69 | 'special' => 0, 70 | 'spaces' => 0, 71 | ); 72 | 73 | /** 74 | * Which characters are included in each complexity check. Must be in 75 | * regex-friendly format. Using the Posix Collating Sequences should make these 76 | * language-independent, but are here in case you want to change them. 77 | */ 78 | $config['pwd_complexity_chars'] = array( 79 | 'uppercase' => '[[:upper:]]', 80 | 'number' => '[[:digit:]]', 81 | 'special' => '[[:punct:]]', 82 | 'spaces' => '\s' 83 | ); 84 | 85 | /** 86 | * Number of seconds a "forgot password" code is valid for 87 | * Default: 3600 88 | */ 89 | $config['forgot_valid_for'] = 3600; 90 | 91 | /** 92 | * Whether or not to log login attemps. If set to FALSE, users can no longer 93 | * be locked out by invalid login attempts. 94 | * Default: TRUE 95 | */ 96 | $config['log_logins'] = TRUE; 97 | 98 | /** 99 | * Number of invalid logins before account is locked. 100 | * Set this to 0 to disable this functionality. 101 | * Default: 3 102 | */ 103 | $config['invalid_logins'] = 3; 104 | 105 | /** 106 | * Number of minutes between invalid login attemps where a user will be locked 107 | * out 108 | * Default: 5 109 | */ 110 | $config['mins_login_attempts'] = 5; 111 | 112 | /** 113 | * Number of minutes before a locked account is unlocked. 114 | * Default: 10 115 | */ 116 | $config['mins_locked_out'] = 10; 117 | 118 | /** 119 | * Tables used by BitAuth 120 | */ 121 | $config['table'] = array( 122 | 'users' => 'bitauth_users', // Required user information (username, password, etc) 123 | 'data' => 'bitauth_userdata', // Optional user information (profile) 124 | 'groups' => 'bitauth_groups', // Groups 125 | 'assoc' => 'bitauth_assoc', // Users -> Groups associations 126 | 'logins' => 'bitauth_logins' // Record of all logins 127 | ); 128 | 129 | /** 130 | * Base-2 logarithm of the iteration count used for password stretching by 131 | * Phpass 132 | * See: http://en.wikipedia.org/wiki/Key_strengthening 133 | * Default: 8 134 | */ 135 | $config['phpass_iterations'] = 8; 136 | 137 | /** 138 | * Require the hashes to be portable to older systems? 139 | * From: http://www.openwall.com/articles/PHP-Users-Passwords 140 | * Unless you force the use of "portable" hashes, phpass' preferred hashing 141 | * method is CRYPT_BLOWFISH, with a fallback to CRYPT_EXT_DES, and then a final 142 | * fallback to the "portable" hashes. 143 | * Default: FALSE 144 | */ 145 | $config['phpass_portable'] = FALSE; 146 | 147 | /** 148 | * What format BitAuth stores the date as. By default, BitAuth uses DATETIME 149 | * fields. If you want to store date as a unix timestamp, you just need to 150 | * change the columns in the database, and change this line: 151 | * $config['date_format'] = 'U'; 152 | * See: http://php.net/manual/en/function.date.php 153 | */ 154 | $config['date_format'] = 'Y-m-d H:i:s'; 155 | 156 | /** 157 | * Your roles. These are how you call permissions checks in your code. 158 | * eg: if($this->bitauth->has_role('example_role')) 159 | * DO NOT reorder these once they have been assigned. 160 | */ 161 | $config['roles'] = array( 162 | 163 | /** 164 | * THE FIRST ROLE IS ALWAYS THE ADMINISTRATOR ROLE 165 | * ANY USERS IN GROUPS GIVEN THIS ROLE WILL HAVE FULL ACCESS 166 | */ 167 | 'admin' => 'User is an Administrator', 168 | /** 169 | * Add as many roles here as you like. 170 | * Follow the format: 171 | * 'role_slug' => 'Role Description', 172 | */ 173 | 174 | ); -------------------------------------------------------------------------------- /application/controllers/example.php: -------------------------------------------------------------------------------- 1 | load->library('bitauth'); 15 | 16 | $this->load->helper('form'); 17 | $this->load->helper('url'); 18 | 19 | $this->load->library('form_validation'); 20 | $this->form_validation->set_error_delimiters('
', '
'); 21 | } 22 | 23 | /** 24 | * Example::convert() 25 | * 26 | */ 27 | public function convert() 28 | { 29 | $this->load->dbforge(); 30 | $this->dbforge->modify_column($this->bitauth->_table['groups'], array( 31 | 'roles' => array( 32 | 'name' => 'roles', 33 | 'type' => 'text' 34 | ) 35 | )); 36 | 37 | $query = $this->db->select('group_id, roles')->get($this->bitauth->_table['groups']); 38 | if($query && $query->num_rows()) 39 | { 40 | foreach($query->result() as $row) 41 | { 42 | $this->db->where('group_id', $row->group_id)->set('roles', $this->bitauth->convert($row->roles))->update($this->bitauth->_table['groups']); 43 | } 44 | } 45 | 46 | echo 'Update complete.'; 47 | } 48 | 49 | /** 50 | * Example::login() 51 | * 52 | */ 53 | public function login() 54 | { 55 | $data = array(); 56 | 57 | if($this->input->post()) 58 | { 59 | $this->form_validation->set_rules('username', 'Username', 'trim|required'); 60 | $this->form_validation->set_rules('password', 'Password', 'required'); 61 | $this->form_validation->set_rules('remember_me','Remember Me',''); 62 | 63 | if($this->form_validation->run() == TRUE) 64 | { 65 | // Login 66 | if($this->bitauth->login($this->input->post('username'), $this->input->post('password'), $this->input->post('remember_me'))) 67 | { 68 | // Redirect 69 | if($redir = $this->session->userdata('redir')) 70 | { 71 | $this->session->unset_userdata('redir'); 72 | } 73 | 74 | redirect($redir ? $redir : 'example'); 75 | } 76 | else 77 | { 78 | $data['error'] = $this->bitauth->get_error(); 79 | } 80 | } 81 | else 82 | { 83 | $data['error'] = validation_errors(); 84 | } 85 | } 86 | 87 | $this->load->view('example/login', $data); 88 | } 89 | 90 | /** 91 | * Example::index() 92 | * 93 | */ 94 | public function index() 95 | { 96 | if( ! $this->bitauth->logged_in()) 97 | { 98 | $this->session->set_userdata('redir', current_url()); 99 | redirect('example/login'); 100 | } 101 | 102 | $this->load->view('example/users', array('bitauth' => $this->bitauth, 'users' => $this->bitauth->get_users())); 103 | } 104 | 105 | /** 106 | * Example::register() 107 | * 108 | */ 109 | public function register() 110 | { 111 | if($this->input->post()) 112 | { 113 | $this->form_validation->set_rules('username', 'Username', 'trim|required|bitauth_unique_username'); 114 | $this->form_validation->set_rules('fullname', 'Fullname', ''); 115 | $this->form_validation->set_rules('email', 'Email', 'trim|required|valid_email'); 116 | $this->form_validation->set_rules('password', 'Password', 'required|bitauth_valid_password'); 117 | $this->form_validation->set_rules('password_conf', 'Password Confirmation', 'required|matches[password]'); 118 | 119 | if($this->form_validation->run() == TRUE) 120 | { 121 | unset($_POST['submit'], $_POST['password_conf']); 122 | $this->bitauth->add_user($this->input->post()); 123 | redirect('example/login'); 124 | } 125 | 126 | } 127 | 128 | $this->load->view('example/add_user', array('title' => 'Register')); 129 | } 130 | 131 | /** 132 | * Example::add_user() 133 | * 134 | */ 135 | public function add_user() 136 | { 137 | if( ! $this->bitauth->logged_in()) 138 | { 139 | $this->session->set_userdata('redir', current_url()); 140 | redirect('example/login'); 141 | } 142 | 143 | if ( ! $this->bitauth->has_role('admin')) 144 | { 145 | $this->load->view('example/no_access'); 146 | return; 147 | } 148 | 149 | if($this->input->post()) 150 | { 151 | $this->form_validation->set_rules('username', 'Username', 'trim|required|bitauth_unique_username'); 152 | $this->form_validation->set_rules('fullname', 'Fullname', ''); 153 | $this->form_validation->set_rules('email', 'Email', 'trim|required|valid_email'); 154 | $this->form_validation->set_rules('password', 'Password', 'required|bitauth_valid_password'); 155 | $this->form_validation->set_rules('password_conf', 'Password Confirmation', 'required|matches[password]'); 156 | 157 | if($this->form_validation->run() == TRUE) 158 | { 159 | unset($_POST['submit'], $_POST['password_conf']); 160 | $this->bitauth->add_user($this->input->post()); 161 | redirect('example'); 162 | } 163 | 164 | } 165 | 166 | $this->load->view('example/add_user', array('title' => 'Add User', 'bitauth' => $this->bitauth)); 167 | } 168 | 169 | 170 | /** 171 | * Example::edit_user() 172 | * 173 | */ 174 | public function edit_user($user_id) 175 | { 176 | if( ! $this->bitauth->logged_in()) 177 | { 178 | $this->session->set_userdata('redir', current_url()); 179 | redirect('example/login'); 180 | } 181 | 182 | if ( ! $this->bitauth->has_role('admin')) 183 | { 184 | $this->load->view('example/no_access'); 185 | return; 186 | } 187 | 188 | if($this->input->post()) 189 | { 190 | $this->form_validation->set_rules('username', 'Username', 'trim|required|bitauth_unique_username['.$user_id.']'); 191 | $this->form_validation->set_rules('fullname', 'Fullname', ''); 192 | $this->form_validation->set_rules('email', 'Email', 'trim|required|valid_email'); 193 | $this->form_validation->set_rules('active', 'Active', ''); 194 | $this->form_validation->set_rules('enabled', 'Enabled', ''); 195 | $this->form_validation->set_rules('password_never_expires', 'Password Never Expires', ''); 196 | $this->form_validation->set_rules('groups[]', 'Groups', ''); 197 | 198 | if($this->input->post('password')) 199 | { 200 | $this->form_validation->set_rules('password', 'Password', 'bitauth_valid_password'); 201 | $this->form_validation->set_rules('password_conf', 'Password Confirmation', 'required|matches[password]'); 202 | } 203 | 204 | if($this->form_validation->run() == TRUE) 205 | { 206 | unset($_POST['submit'], $_POST['password_conf']); 207 | $this->bitauth->update_user($user_id, $this->input->post()); 208 | redirect('example'); 209 | } 210 | 211 | } 212 | 213 | $groups = array(); 214 | foreach($this->bitauth->get_groups() as $_group) 215 | { 216 | $groups[$_group->group_id] = $_group->name; 217 | } 218 | 219 | 220 | $this->load->view('example/edit_user', array('bitauth' => $this->bitauth, 'groups' => $groups, 'user' => $this->bitauth->get_user_by_id($user_id))); 221 | } 222 | 223 | /** 224 | * Example::groups() 225 | * 226 | */ 227 | public function groups() 228 | { 229 | if( ! $this->bitauth->logged_in()) 230 | { 231 | $this->session->set_userdata('redir', current_url()); 232 | redirect('example/login'); 233 | } 234 | 235 | $this->load->view('example/groups', array('bitauth' => $this->bitauth, 'groups' => $this->bitauth->get_groups())); 236 | } 237 | 238 | /** 239 | * Example::add_group() 240 | * 241 | */ 242 | public function add_group() 243 | { 244 | if( ! $this->bitauth->logged_in()) 245 | { 246 | $this->session->set_userdata('redir', current_url()); 247 | redirect('example/login'); 248 | } 249 | 250 | if ( ! $this->bitauth->has_role('admin')) 251 | { 252 | $this->load->view('example/no_access'); 253 | return; 254 | } 255 | 256 | if($this->input->post()) 257 | { 258 | $this->form_validation->set_rules('name', 'Group Name', 'trim|required|bitauth_unique_group'); 259 | $this->form_validation->set_rules('description', 'Description', ''); 260 | $this->form_validation->set_rules('members[]', 'Members', ''); 261 | $this->form_validation->set_rules('roles[]', 'Roles', ''); 262 | 263 | if($this->form_validation->run() == TRUE) 264 | { 265 | unset($_POST['submit']); 266 | $this->bitauth->add_group($this->input->post()); 267 | redirect('example/groups'); 268 | } 269 | 270 | } 271 | 272 | $users = array(); 273 | foreach($this->bitauth->get_users() as $_user) 274 | { 275 | $users[$_user->user_id] = $_user->fullname; 276 | } 277 | 278 | $this->load->view('example/add_group', array('bitauth' => $this->bitauth, 'roles' => $this->bitauth->get_roles(), 'users' => $users)); 279 | } 280 | 281 | /** 282 | * Example:edit_group() 283 | * 284 | */ 285 | public function edit_group($group_id) 286 | { 287 | if( ! $this->bitauth->logged_in()) 288 | { 289 | $this->session->set_userdata('redir', current_url()); 290 | redirect('example/login'); 291 | } 292 | 293 | if ( ! $this->bitauth->has_role('admin')) 294 | { 295 | $this->load->view('example/no_access'); 296 | return; 297 | } 298 | 299 | if($this->input->post()) 300 | { 301 | $this->form_validation->set_rules('name', 'Group Name', 'trim|required|bitauth_unique_group['.$group_id.']'); 302 | $this->form_validation->set_rules('description', 'Description', ''); 303 | $this->form_validation->set_rules('members[]', 'Members', ''); 304 | $this->form_validation->set_rules('roles[]', 'Roles', ''); 305 | 306 | if($this->form_validation->run() == TRUE) 307 | { 308 | unset($_POST['submit']); 309 | $this->bitauth->update_group($group_id, $this->input->post()); 310 | redirect('example/groups'); 311 | } 312 | 313 | } 314 | 315 | $users = array(); 316 | foreach($this->bitauth->get_users() as $_user) 317 | { 318 | $users[$_user->user_id] = $_user->fullname; 319 | } 320 | 321 | $group = $this->bitauth->get_group_by_id($group_id); 322 | 323 | $role_list = array(); 324 | $roles = $this->bitauth->get_roles(); 325 | foreach($roles as $_slug => $_desc) 326 | { 327 | if($this->bitauth->has_role($_slug, $group->roles)) 328 | { 329 | $role_list[] = $_slug; 330 | } 331 | } 332 | 333 | $this->load->view('example/edit_group', array('bitauth' => $this->bitauth, 'roles' => $roles, 'group' => $group, 'group_roles' => $role_list, 'users' => $users)); 334 | } 335 | 336 | /** 337 | * Example::activate() 338 | * 339 | */ 340 | public function activate($activation_code) 341 | { 342 | if($this->bitauth->activate($activation_code)) 343 | { 344 | $this->load->view('example/activation_successful'); 345 | return; 346 | } 347 | 348 | $this->load->view('example/activation_failed'); 349 | } 350 | 351 | /** 352 | * Example::logout() 353 | * 354 | */ 355 | public function logout() 356 | { 357 | $this->bitauth->logout(); 358 | redirect('example'); 359 | } 360 | 361 | } -------------------------------------------------------------------------------- /application/language/english/bitauth_lang.php: -------------------------------------------------------------------------------- 1 | 9 | * @license DBAD 10 | * @link https://github.com/danmontgomery/codeigniter-bitauth 11 | * @link http://dmontgomery.net/bitauth 12 | * @todo Get all users with specific role 13 | */ 14 | class Bitauth 15 | { 16 | 17 | public $_table; 18 | public $_default_group_id; 19 | public $_admin_role; 20 | public $_remember_token_name; 21 | public $_remember_token_expires; 22 | public $_remember_token_updates; 23 | public $_require_user_activation; 24 | public $_pwd_max_age; 25 | public $_pwd_min_length; 26 | public $_pwd_max_length; 27 | public $_pwd_complexity; 28 | public $_pwd_complexity_chars; 29 | public $_error_delim_prefix = '

'; 30 | public $_error_delim_suffix = '

'; 31 | public $_forgot_valid_for; 32 | public $_log_logins; 33 | public $_invalid_logins; 34 | public $_mins_login_attempts; 35 | public $_mins_locked_out; 36 | public $_date_format; 37 | public $_cookie_elem_prefix = 'ba_'; 38 | 39 | private $_all_roles; 40 | private $_error; 41 | 42 | // IF YOU CHANGE THE STRUCTURE OF THE `users` TABLE, THAT CHANGE MUST BE REFLECTED HERE 43 | private $_data_fields = array( 44 | 'username','password','password_last_set','password_never_expires','remember_me', 'activation_code', 45 | 'active','forgot_code','forgot_generated','enabled','last_login','last_login_ip' 46 | ); 47 | 48 | public function __construct() 49 | { 50 | $this->_assign_libraries(); 51 | 52 | $this->_table = $this->config->item('table', 'bitauth'); 53 | $this->_default_group_id = $this->config->item('default_group_id', 'bitauth'); 54 | $this->_remember_token_name = $this->config->item('remember_token_name', 'bitauth'); 55 | $this->_remember_token_expires = $this->config->item('remember_token_expires', 'bitauth'); 56 | $this->_remember_token_updates = $this->config->item('remember_token_updates', 'bitauth'); 57 | $this->_require_user_activation = $this->config->item('require_user_activation', 'bitauth'); 58 | $this->_pwd_max_age = $this->config->item('pwd_max_age', 'bitauth'); 59 | $this->_pwd_age_notification = $this->config->item('pwd_age_notification', 'bitauth'); 60 | $this->_pwd_min_length = $this->config->item('pwd_min_length', 'bitauth'); 61 | $this->_pwd_max_length = $this->config->item('pwd_max_length', 'bitauth'); 62 | $this->_pwd_complexity = $this->config->item('pwd_complexity', 'bitauth'); 63 | $this->_pwd_complexity_chars = $this->config->item('pwd_complexity_chars', 'bitauth'); 64 | $this->_forgot_valid_for = $this->config->item('forgot_valid_for', 'bitauth'); 65 | $this->_log_logins = $this->config->item('log_logins', 'bitauth'); 66 | $this->_invalid_logins = $this->config->item('invalid_logins', 'bitauth'); 67 | $this->_mins_login_attempts = $this->config->item('mins_login_attempts', 'bitauth'); 68 | $this->_mins_locked_out = $this->config->item('mins_locked_out', 'bitauth'); 69 | $this->_date_format = $this->config->item('date_format', 'bitauth'); 70 | 71 | $this->_all_roles = $this->config->item('roles', 'bitauth'); 72 | 73 | // Grab the first role on the list as the administrator role 74 | $slugs = array_keys($this->_all_roles); 75 | $this->_admin_role = $slugs[0]; 76 | 77 | // Specify any extra login fields 78 | $this->_login_fields = array(); 79 | 80 | // If we're logged in, grab session values. If not, check for a "remember me" cookie 81 | if($this->logged_in()) 82 | { 83 | $this->get_session_values(); 84 | } 85 | else if($this->input->cookie($this->config->item('cookie_prefix').$this->_remember_token_name)) 86 | { 87 | $this->login_from_token(); 88 | } 89 | 90 | $this->set_error($this->session->flashdata('bitauth_error'), FALSE); 91 | unset($slugs); 92 | } 93 | 94 | /** 95 | * Bitauth::login() 96 | * 97 | * Process a login, either from username/password (+ extra fields) or a "remember me" cookie 98 | */ 99 | public function login($username, $password, $remember = FALSE, $extra = array(), $token = NULL) 100 | { 101 | if(empty($username)) 102 | { 103 | $this->set_error($this->lang->line('bitauth_username_required')); 104 | return FALSE; 105 | } 106 | 107 | if($this->locked_out()) 108 | { 109 | $this->set_error(sprintf($this->lang->line('bitauth_user_locked_out'), $this->_mins_locked_out)); 110 | return FALSE; 111 | } 112 | 113 | $user = $this->get_user_by_username($username); 114 | 115 | if($user !== FALSE) 116 | { 117 | if($this->phpass->CheckPassword($password, $user->password) || ($password === NULL && $user->remember_me == $token)) 118 | { 119 | if( ! empty($this->_login_fields) && ! $this->check_login_fields($user, $extra)) 120 | { 121 | $this->log_attempt($user->user_id, FALSE); 122 | return FALSE; 123 | } 124 | 125 | // Inactive 126 | if( ! $user->active) 127 | { 128 | $this->log_attempt($user->user_id, FALSE); 129 | $this->set_error($this->lang->line('bitauth_user_inactive')); 130 | return FALSE; 131 | } 132 | 133 | // Expired password 134 | if($this->password_is_expired($user)) 135 | { 136 | $this->log_attempt($user->user_id, FALSE); 137 | $this->set_error($this->lang->line('bitauth_pwd_expired')); 138 | return FALSE; 139 | } 140 | 141 | $this->set_session_values($user); 142 | 143 | if($remember != FALSE) 144 | { 145 | $this->update_remember_token($user->username, $user->user_id); 146 | } 147 | 148 | $data = array( 149 | 'last_login' => $this->timestamp(), 150 | 'last_login_ip' => ip2long($_SERVER['REMOTE_ADDR']) 151 | ); 152 | 153 | // If user logged in, they must have remembered their password. 154 | if( ! empty($user->forgot_code)) 155 | { 156 | $data['forgot_code'] = ''; 157 | } 158 | 159 | // Update last login timestamp and IP 160 | $this->update_user($user->user_id, $data); 161 | 162 | $this->log_attempt($user->user_id, TRUE); 163 | return TRUE; 164 | } 165 | 166 | $this->log_attempt($user->user_id, FALSE); 167 | } 168 | else 169 | { 170 | $this->log_attempt(FALSE, FALSE); 171 | } 172 | 173 | $this->set_error(sprintf($this->lang->line('bitauth_login_failed'), $this->lang->line('bitauth_username'))); 174 | return FALSE; 175 | } 176 | 177 | /** 178 | * Bitauth::login_from_token() 179 | * 180 | * Tries to login from a "remember me" cookie 181 | */ 182 | public function login_from_token() 183 | { 184 | if(($token = $this->input->cookie($this->config->item('cookie_prefix').$this->_remember_token_name))) 185 | { 186 | $token = explode("\n", $token); 187 | $username = $token[0]; 188 | 189 | if($this->login($username, NULL, (bool)$this->_remember_token_updates, FALSE, $token[1])) 190 | { 191 | return TRUE; 192 | } 193 | } 194 | 195 | $this->logout(); 196 | return FALSE; 197 | } 198 | 199 | /** 200 | * Bitauth::logout() 201 | * 202 | * Logs out, destroys session, etc 203 | */ 204 | public function logout() 205 | { 206 | $session_data = $this->session->all_userdata(); 207 | foreach($session_data as $_key => $_value) 208 | { 209 | if(substr($_key, 0, strlen($this->_cookie_elem_prefix)) == $this->_cookie_elem_prefix) 210 | { 211 | $this->session->unset_userdata($_key); 212 | } 213 | } 214 | 215 | unset($this->username); 216 | $this->delete_remember_token(); 217 | 218 | return; 219 | } 220 | 221 | /** 222 | * Bitauth::check_login_fields() 223 | * 224 | * Processes any extra login fields that were specified 225 | */ 226 | public function check_login_fields($user, $data) 227 | { 228 | if(empty($this->_login_fields)) 229 | { 230 | return TRUE; 231 | } 232 | 233 | foreach($this->_login_fields as $_field) 234 | { 235 | if( ! isset($user->{$_field}) || $user->{$_field} != $data[$_field]) 236 | { 237 | if($this->lang->line('bitauth_invalid_'.$_field)) 238 | { 239 | $this->set_error($this->lang->line('bitauth_invalid_'.$_field)); 240 | } 241 | else 242 | { 243 | $this->set_error(sprintf($this->lang->line('bitauth_lang_not_found'), 'bitauth_invalid_'.$_field)); 244 | } 245 | return FALSE; 246 | } 247 | } 248 | 249 | return TRUE; 250 | } 251 | 252 | /** 253 | * Bitauth::add_login_field() 254 | * 255 | * Declare an extra login field that must be checked on login 256 | */ 257 | public function add_login_field($field) 258 | { 259 | if(is_array($field)) 260 | { 261 | foreach($field as $_field) 262 | { 263 | $_field = trim($_field); 264 | if(strlen($_field)) 265 | { 266 | $this->add_login_field($_field); 267 | } 268 | } 269 | 270 | return; 271 | } 272 | 273 | $field = trim($field); 274 | if(strlen($field)) 275 | { 276 | $this->_login_fields[] = trim($field); 277 | } 278 | return; 279 | } 280 | 281 | /** 282 | * Bitauth::locked_out() 283 | * 284 | * Checks bad logins against invalid_logins and mins_login_attempts (config) 285 | */ 286 | public function locked_out() 287 | { 288 | // If invalid_logins is disabled, can't be locked out 289 | if($this->_invalid_logins < 1) 290 | { 291 | return FALSE; 292 | } 293 | 294 | $query = $this->db 295 | ->where('ip_address', ip2long($_SERVER['REMOTE_ADDR'])) 296 | ->where('success', 0) 297 | ->limit($this->_invalid_logins) 298 | ->order_by('time', 'DESC') 299 | ->get($this->_table['logins']); 300 | 301 | if($query && $query->num_rows() == $this->_invalid_logins) 302 | { 303 | $first = $query->row(0); 304 | $last = $query->row($this->_invalid_logins - 1); 305 | 306 | if($this->timestamp(strtotime($last->time), 'U') - $this->timestamp(strtotime($first->time), 'U') <= ($this->_mins_login_attempts * 60) 307 | && $this->timestamp(strtotime($last->time), 'U') >= $this->timestamp(strtotime($this->_mins_login_attempts.' minutes ago'), 'U')) 308 | { 309 | return TRUE; 310 | } 311 | } 312 | 313 | return FALSE; 314 | } 315 | 316 | /** 317 | * Bitauth::log_attempt() 318 | * 319 | * Logs a login attempt 320 | */ 321 | public function log_attempt($user_id, $success = FALSE) 322 | { 323 | if($this->_log_logins == TRUE) 324 | { 325 | 326 | $data = array( 327 | 'ip_address' => ip2long($_SERVER['REMOTE_ADDR']), 328 | 'user_id' => (empty($user_id) ? 0 : $user_id), 329 | 'success' => (int)$success, 330 | 'time' => $this->timestamp() 331 | ); 332 | 333 | return $this->db->insert($this->_table['logins'], $data); 334 | } 335 | 336 | return TRUE; 337 | } 338 | 339 | /** 340 | * Bitauth::set_session_values() 341 | * 342 | * Set values to be saved in the session (should be coming from get_user_by_x) 343 | */ 344 | public function set_session_values($values) 345 | { 346 | $session_data = array(); 347 | foreach($values as $_key => $_value) 348 | { 349 | if($_key !== 'password') 350 | { 351 | $this->$_key = $_value; 352 | 353 | if($_key == 'roles') 354 | { 355 | $_value = $this->encrypt->encode($_value); 356 | } 357 | 358 | $session_data[$this->_cookie_elem_prefix.$_key] = $_value; 359 | } 360 | } 361 | 362 | $this->session->set_userdata($session_data); 363 | } 364 | 365 | /** 366 | * Bitauth::get_session_values() 367 | * 368 | * Retrieves session values and assigns them to the object 369 | */ 370 | public function get_session_values() 371 | { 372 | $session_data = $this->session->all_userdata(); 373 | foreach($session_data as $_key => $_value) 374 | { 375 | if(substr($_key, 0, strlen($this->_cookie_elem_prefix)) !== $this->_cookie_elem_prefix) 376 | { 377 | continue; 378 | } 379 | 380 | $_key = substr($_key, strlen($this->_cookie_elem_prefix)); 381 | 382 | if( ! isset($this->$_key)) 383 | { 384 | if($_key == 'roles') 385 | { 386 | $_value = $this->encrypt->decode($_value); 387 | } 388 | 389 | $this->$_key = $_value; 390 | } 391 | else 392 | { 393 | log_message('error', sprintf($this->lang->line('bitauth_data_error'),$_key)); 394 | show_error(sprintf($this->lang->line('bitauth_data_error'),$_key)); 395 | } 396 | } 397 | } 398 | 399 | /** 400 | * Bitauth::update_remember_token() 401 | * 402 | * Sets or Updates the "remember me" cookie 403 | */ 404 | public function update_remember_token($username = NULL, $user_id = NULL) 405 | { 406 | if( ! $this->logged_in()) 407 | { 408 | return; 409 | } 410 | 411 | if($username === NULL) 412 | { 413 | $username = $this->username; 414 | } 415 | if($user_id === NULL) 416 | { 417 | $user_id = $this->user_id; 418 | } 419 | 420 | $session_id = sha1(mt_rand(0, PHP_INT_MAX).time()); 421 | 422 | $cookie = array( 423 | 'name' => $this->_remember_token_name, 424 | 'value' => $username."\n".$session_id, 425 | 'expire' => $this->_remember_token_expires, 426 | 'domain' => $this->config->item('cookie_domain'), 427 | 'path' => $this->config->item('cookie_path'), 428 | 'secure' => $this->config->item('cookie_secure') 429 | ); 430 | 431 | $this->input->set_cookie($cookie); 432 | 433 | return $this->update_user($user_id, array('remember_me' => $session_id)); 434 | } 435 | 436 | /** 437 | * Bitauth::delete_remember_token() 438 | * 439 | * Deletes the "remember me" cookie (called on logout) 440 | */ 441 | public function delete_remember_token() 442 | { 443 | if($this->input->cookie($this->config->item('cookie_prefix').$this->_remember_token_name)) 444 | { 445 | $cookie = array( 446 | 'name' => $this->_remember_token_name, 447 | 'value' => '', 448 | 'expire' => -86400 449 | ); 450 | 451 | if($token = $this->input->cookie($this->config->item('cookie_prefix').$this->_remember_token_name)) 452 | { 453 | $token = explode("\n", $token); 454 | $this->db 455 | ->set('remember_me', '') 456 | ->where('username', $token[0]) 457 | ->where('remember_me', $token[1]) 458 | ->update($this->_table['users']); 459 | } 460 | 461 | $this->input->set_cookie($cookie); 462 | } 463 | } 464 | 465 | /** 466 | * Bitauth::add_user() 467 | * 468 | * Add a user 469 | */ 470 | public function add_user($data, $require_activation = NULL) 471 | { 472 | if( ! is_array($data) && ! is_object($data)) 473 | { 474 | $this->set_error($this->lang->line('bitauth_add_user_datatype')); 475 | return FALSE; 476 | } 477 | 478 | if($require_activation === NULL) 479 | { 480 | $require_activation = $this->_require_user_activation; 481 | } 482 | 483 | $data = (array)$data; 484 | 485 | if(empty($data['username'])) 486 | { 487 | $this->set_error(sprintf($this->lang->line('bitauth_username_required'), $this->lang->line('bitauth_username'))); 488 | return FALSE; 489 | } 490 | 491 | if(empty($data['password'])) 492 | { 493 | $this->set_error($this->lang->line('bitauth_password_required')); 494 | return FALSE; 495 | } 496 | 497 | $data['active'] = ! (bool)$require_activation; 498 | if($require_activation) 499 | { 500 | $data['activation_code'] = $this->generate_code(); 501 | } 502 | 503 | // Just in case 504 | if( ! empty($data['user_id'])) 505 | { 506 | unset($data['user_id']); 507 | } 508 | 509 | if(isset($data['groups'])) 510 | { 511 | $groups = $data['groups']; 512 | unset($data['groups']); 513 | } 514 | 515 | $userdata = array(); 516 | foreach($data as $_key => $_val) 517 | { 518 | if( ! in_array($_key, $this->_data_fields)) 519 | { 520 | $userdata[$_key] = $_val; 521 | unset($data[$_key]); 522 | } 523 | } 524 | 525 | $data['password'] = $this->hash_password($data['password']); 526 | $data['password_last_set'] = $this->timestamp(); 527 | 528 | $this->db->trans_begin(); 529 | 530 | $this->db->insert($this->_table['users'], $data); 531 | 532 | $user_id = $this->db->insert_id(); 533 | $userdata['user_id'] = $user_id; 534 | 535 | $this->db->insert($this->_table['data'], $userdata); 536 | 537 | if(empty($groups)) 538 | { 539 | $this->db->insert($this->_table['assoc'], array('user_id' => $user_id, 'group_id' => $this->_default_group_id)); 540 | } 541 | else 542 | { 543 | $new_groups = array(); 544 | foreach($groups as $group_id) 545 | { 546 | $new_groups[] = array( 547 | 'user_id' => $user_id, 548 | 'group_id' => (int)$group_id 549 | ); 550 | } 551 | 552 | $this->db->insert_batch($this->_table['assoc'], $new_groups); 553 | } 554 | 555 | if($this->db->trans_status() === FALSE) 556 | { 557 | $this->set_error($this->lang->line('bitauth_add_user_failed')); 558 | $this->db->trans_rollback(); 559 | 560 | return FALSE; 561 | } 562 | 563 | $this->db->trans_commit(); 564 | return $this->get_user_by_id($user_id); 565 | } 566 | 567 | /** 568 | * Bitauth::add_group() 569 | * 570 | * Add a group 571 | */ 572 | public function add_group($data) 573 | { 574 | if( ! is_array($data) && ! is_object($data)) 575 | { 576 | $this->set_error($this->lang->line('bitauth_add_group_datatype')); 577 | return FALSE; 578 | } 579 | 580 | $data = (array)$data; 581 | 582 | if(empty($data['name'])) 583 | { 584 | $this->set_error($this->lang->line('bitauth_groupname_required')); 585 | return FALSE; 586 | } 587 | 588 | // Just in case 589 | if( ! empty($data['group_id'])) 590 | { 591 | unset($data['group_id']); 592 | } 593 | 594 | if(isset($data['members'])) 595 | { 596 | $members = $data['members']; 597 | unset($data['members']); 598 | } 599 | 600 | $roles = 0; 601 | if(isset($data['roles']) && is_array($data['roles'])) 602 | { 603 | foreach($data['roles'] as $slug) 604 | { 605 | if(($index = $this->get_role($slug)) !== FALSE) 606 | { 607 | $this->_set_bit($roles, $index); 608 | } 609 | } 610 | } 611 | 612 | $data['roles'] = $roles; 613 | 614 | $this->db->trans_start(); 615 | 616 | $this->db->insert($this->_table['groups'], $data); 617 | 618 | $group_id = $this->db->insert_id(); 619 | 620 | // If we were given an array of user id's, set them as the group members 621 | if( ! empty($members)) 622 | { 623 | $new_members = array(); 624 | foreach(array_unique($members) as $user_id) 625 | { 626 | $new_members[] = array( 627 | 'group_id' => $group_id, 628 | 'user_id' => (int)$user_id 629 | ); 630 | } 631 | 632 | $this->db->insert_batch($this->_table['assoc'], $new_members); 633 | } 634 | 635 | if($this->db->trans_status() === FALSE) 636 | { 637 | $this->set_error($this->lang->line('bitauth_add_group_failed')); 638 | $this->db->trans_rollback(); 639 | 640 | return FALSE; 641 | } 642 | 643 | $this->db->trans_commit(); 644 | return $this->get_group_by_id($group_id); 645 | } 646 | 647 | /** 648 | * Bitauth::activate() 649 | * 650 | * Activate a user 651 | */ 652 | public function activate($activation_code) 653 | { 654 | if($user = $this->get_user_by_activation_code($activation_code)) 655 | { 656 | return $this->update_user($user->user_id, array('active' => 1, 'activation_code' => '')); 657 | } 658 | 659 | $this->set_error($this->lang->line('bitauth_activate_failed')); 660 | return FALSE; 661 | } 662 | 663 | /** 664 | * Bitauth::update_user() 665 | * 666 | * Update a user 667 | */ 668 | public function update_user($id, $data) 669 | { 670 | if( ! is_array($data) && ! is_object($data)) 671 | { 672 | $this->set_error($this->lang->line('bitauth_edit_user_datatype')); 673 | return FALSE; 674 | } 675 | 676 | $data = (array)$data; 677 | 678 | if(isset($data['username']) && ! strlen($data['username'])) 679 | { 680 | $this->set_error(sprintf($this->lang->line('bitauth_username_required'), $this->lang->line('bitauth_username'))); 681 | return FALSE; 682 | } 683 | 684 | // Just in case 685 | unset($data['user_id'], $data['roles'], $data['id']); 686 | 687 | if(isset($data['groups'])) 688 | { 689 | $groups = $data['groups']; 690 | unset($data['groups']); 691 | } 692 | 693 | $userdata = array(); 694 | foreach($data as $_key => $_val) 695 | { 696 | if( ! in_array($_key, $this->_data_fields)) 697 | { 698 | $userdata[$_key] = $_val; 699 | unset($data[$_key]); 700 | } 701 | } 702 | 703 | if( ! empty($data['password'])) 704 | { 705 | $new_password = $this->hash_password($data['password']); 706 | 707 | $data['password'] = $new_password; 708 | $data['password_last_set'] = $this->timestamp(); 709 | } 710 | else 711 | { 712 | // Will always be set, but empty, if passing POST directly 713 | unset($data['password']); 714 | } 715 | 716 | $this->db->trans_start(); 717 | 718 | if( ! empty($data)) 719 | { 720 | $this->db->set($data)->where('user_id', $id)->update($this->_table['users']); 721 | } 722 | 723 | if( ! empty($userdata)) 724 | { 725 | $this->db->set($userdata)->where('user_id', $id)->update($this->_table['data']); 726 | } 727 | 728 | 729 | if(isset($groups)) 730 | { 731 | $this->db->where('user_id', $id)->delete($this->_table['assoc']); 732 | $new_groups = array(); 733 | if( ! empty($groups)) 734 | { 735 | foreach($groups as $group_id) 736 | { 737 | $new_groups[] = array( 738 | 'user_id' => $id, 739 | 'group_id' => (int)$group_id 740 | ); 741 | } 742 | 743 | $this->db->insert_batch($this->_table['assoc'], $new_groups); 744 | } 745 | } 746 | 747 | if($this->db->trans_status() === FALSE) 748 | { 749 | $this->set_error($this->lang->line('bitauth_edit_user_failed')); 750 | $this->db->trans_rollback(); 751 | 752 | return FALSE; 753 | } 754 | 755 | if( ! empty($this->user_id) && $this->user_id == $id) 756 | { 757 | $user = $this->get_user_by_id($id); 758 | $this->set_session_values($user); 759 | } 760 | 761 | $this->db->trans_commit(); 762 | return TRUE; 763 | } 764 | 765 | /** 766 | * Bitauth::enable() 767 | * 768 | * Enable a user 769 | */ 770 | public function enable($user_id) 771 | { 772 | return $this->disable($user_id, 1); 773 | } 774 | 775 | /** 776 | * Bitauth::disable() 777 | * 778 | * Disable a user 779 | */ 780 | public function disable($user_id, $enabled = 0) 781 | { 782 | if($user = $this->get_user_by_id($user_id, $enabled)) 783 | { 784 | return $this->update_user($user_id, array('enabled' => $enabled)); 785 | } 786 | 787 | $this->set_error(sprintf($this->lang->line('bitauth_user_not_found'), $user_id)); 788 | return FALSE; 789 | } 790 | 791 | /** 792 | * Bitauth::delete() 793 | * 794 | * "Delete" a user (remove from groups, disable, and delete userdata) 795 | */ 796 | public function delete($user_id) 797 | { 798 | if($user = $this->get_user_by_id($user_id)) 799 | { 800 | $this->db->trans_start(); 801 | 802 | $this->update_user($user_id, array('enabled' => 0, 'groups' => array())); 803 | 804 | // Delete userdata and recreate with no data 805 | $this->db->where('user_id', $user_id)->delete($this->_table['data']); 806 | $this->db->insert($this->_table['data'], array('user_id' => $user_id)); 807 | 808 | if($this->db->trans_status() == FALSE) 809 | { 810 | $this->set_error($this->lang->line('bitauth_del_user_failed')); 811 | $this->db->trans_rollback(); 812 | return FALSE; 813 | } 814 | 815 | $this->db->trans_commit(); 816 | return TRUE; 817 | } 818 | 819 | $this->set_error(sprintf($this->lang->line('bitauth_user_not_found'), $user_id)); 820 | return FALSE; 821 | } 822 | 823 | /** 824 | * Bitauth::forgot_password() 825 | * 826 | * Generate and store a "forgot password code" 827 | */ 828 | public function forgot_password($user_id) 829 | { 830 | if($user = $this->get_user_by_id($user_id)) 831 | { 832 | $forgot_code = $this->generate_code(); 833 | 834 | if($this->update_user($user_id, array('forgot_code' => $forgot_code, 'forgot_generated' => $this->timestamp()))) 835 | { 836 | return $forgot_code; 837 | } 838 | } 839 | 840 | return FALSE; 841 | } 842 | 843 | /** 844 | * Bitauth::set_password() 845 | * 846 | * Sets a new password (should already be hashed) 847 | */ 848 | public function set_password($user_id, $new_password) 849 | { 850 | if($this->update_user($user_id, array('password' => $new_password))) 851 | { 852 | return TRUE; 853 | } 854 | 855 | $this->set_error($this->lang->line('bitauth_set_pw_failed')); 856 | return FALSE; 857 | } 858 | 859 | /** 860 | * Bitauth::update_group() 861 | * 862 | * Update a group 863 | */ 864 | public function update_group($id, $data) 865 | { 866 | if( ! is_array($data) && ! is_object($data)) 867 | { 868 | $this->set_error($this->lang->line('bitauth_edit_group_datatype')); 869 | return FALSE; 870 | } 871 | 872 | $data = (array)$data; 873 | 874 | // Just in case 875 | unset($data['group_id'], $data['id']); 876 | 877 | // If this array was returned by get_groups(), don't try to update a non-existent column 878 | if(isset($data['members'])) 879 | { 880 | $members = $data['members']; 881 | unset($data['members']); 882 | } 883 | 884 | $roles = 0; 885 | if(isset($data['roles'])) 886 | { 887 | if(is_array($data['roles'])) 888 | { 889 | foreach($data['roles'] as $slug) 890 | { 891 | if(($index = $this->get_role($slug)) !== FALSE) 892 | { 893 | $this->_set_bit($roles, $index); 894 | } 895 | } 896 | } 897 | else if(is_numeric($data['roles'])) 898 | { 899 | $roles = $data['roles']; 900 | } 901 | } 902 | 903 | $data['roles'] = $roles; 904 | 905 | $this->db->trans_start(); 906 | 907 | $this->db->set($data)->where('group_id', $id)->update($this->_table['groups']); 908 | 909 | // If we were given an array of user id's, set them as the group members 910 | if(isset($members)) 911 | { 912 | $this->db->where('group_id', $id)->delete($this->_table['assoc']); 913 | 914 | $new_members = array(); 915 | if( ! empty($members)) 916 | { 917 | foreach(array_unique($members) as $user_id) 918 | { 919 | $new_members[] = array( 920 | 'group_id' => $id, 921 | 'user_id' => (int)$user_id 922 | ); 923 | } 924 | 925 | $this->db->insert_batch($this->_table['assoc'], $new_members); 926 | } 927 | } 928 | 929 | if($this->db->trans_status() === FALSE) 930 | { 931 | $this->set_error($this->lang->line('bitauth_edit_group_failed')); 932 | $this->db->trans_rollback(); 933 | 934 | return FALSE; 935 | } 936 | 937 | $this->db->trans_commit(); 938 | return TRUE; 939 | 940 | } 941 | 942 | /** 943 | * Bitauth::delete_group() 944 | * 945 | * Delete a group, remove all members 946 | */ 947 | public function delete_group($group_id) 948 | { 949 | $this->db->trans_start(); 950 | 951 | $this->db->where('group_id', $group_id)->delete($this->_table['groups']); 952 | $this->db->where('group_id', $group_id)->delete($this->_table['assoc']); 953 | 954 | if($this->db->trans_status() == FALSE) 955 | { 956 | $this->set_error($this->lang->line('bitauth_del_group_failed')); 957 | $this->db->trans_rollback(); 958 | return FALSE; 959 | } 960 | 961 | $this->db->trans_commit(); 962 | return TRUE; 963 | } 964 | 965 | /** 966 | * Bitauth::has_role() 967 | * 968 | * Check if a user or group has a role 969 | */ 970 | public function has_role($slug, $mask = NULL) 971 | { 972 | if($mask === NULL) 973 | { 974 | $mask = $this->roles; 975 | } 976 | 977 | // No point checking, user doesn't have permission 978 | if($mask == 0) 979 | { 980 | return FALSE; 981 | } 982 | 983 | // Make sure it's a valid slug, otherwise don't give permission, even to administrators 984 | if(($index = $this->get_role($slug)) !== FALSE) 985 | { 986 | if($slug != $this->_admin_role && $this->has_role($this->_admin_role, $mask)) 987 | { 988 | return TRUE; 989 | } 990 | 991 | return $this->_check_bit($mask, $index); 992 | } 993 | 994 | return FALSE; 995 | } 996 | 997 | /** 998 | * Bitauth::is_admin() 999 | * 1000 | * Check if a user or group has the administrator role 1001 | */ 1002 | public function is_admin($mask = NULL) 1003 | { 1004 | return $this->has_role($this->_admin_role, $mask); 1005 | } 1006 | 1007 | /** 1008 | * Bitauth::get_role() 1009 | * 1010 | * Return index of a role by it's slug 1011 | */ 1012 | public function get_role($slug) 1013 | { 1014 | return array_search($slug, array_keys($this->get_roles())); 1015 | } 1016 | 1017 | /** 1018 | * Bitauth::get_roles() 1019 | * 1020 | * Get all roles 1021 | */ 1022 | public function get_roles() 1023 | { 1024 | return $this->_all_roles; 1025 | } 1026 | 1027 | /** 1028 | * Bitauth::username_is_unique() 1029 | * 1030 | * Checks if username is unique 1031 | */ 1032 | public function username_is_unique($username, $exclude_user = FALSE) 1033 | { 1034 | if($exclude_user != FALSE) 1035 | { 1036 | $this->db->where('user_id !=', (int)$exclude_user); 1037 | } 1038 | 1039 | $query = $this->db->where('LOWER(`username`)', strtolower($username))->get($this->_table['users']); 1040 | if($query && $query->num_rows()) 1041 | { 1042 | $this->set_error($this->lang->line('bitauth_unique_username')); 1043 | return FALSE; 1044 | } 1045 | 1046 | return TRUE; 1047 | } 1048 | 1049 | /** 1050 | * Bitauth::group_is_unique() 1051 | * 1052 | * Checks if group name is unique 1053 | */ 1054 | public function group_is_unique($group_name, $exclude_group = FALSE) 1055 | { 1056 | if($exclude_group != FALSE) 1057 | { 1058 | $this->db->where('group_id !=', (int)$exclude_group); 1059 | } 1060 | 1061 | $query = $this->db->where('LOWER(`name`)', strtolower($group_name))->get($this->_table['groups']); 1062 | if($query && $query->num_rows()) 1063 | { 1064 | $this->set_error($this->lang->line('bitauth_unique_group')); 1065 | return FALSE; 1066 | } 1067 | 1068 | return TRUE; 1069 | } 1070 | 1071 | /** 1072 | * Bitauth::password_is_valid() 1073 | * 1074 | * Checks if password meets complexity requirements 1075 | */ 1076 | public function password_is_valid($password) 1077 | { 1078 | if($this->_pwd_min_length > 0 && strlen($password) < $this->_pwd_min_length) 1079 | { 1080 | $this->set_error(sprintf($this->lang->line('bitauth_passwd_min_length'), $this->_pwd_min_length)); 1081 | return FALSE; 1082 | } 1083 | 1084 | if($this->_pwd_max_length > 0 && strlen($password) > $this->_pwd_max_length) 1085 | { 1086 | $this->set_error(sprintf($this->lang->line('bitauth_passwd_max_length'), $this->_pwd_max_length)); 1087 | return FALSE; 1088 | } 1089 | 1090 | foreach($this->_pwd_complexity_chars as $_label => $_rule) 1091 | { 1092 | if(preg_match('/'.$_rule.'/', $password) < $this->_pwd_complexity[$_label]) 1093 | { 1094 | $this->set_error(sprintf($this->lang->line('bitauth_passwd_complexity'), $this->complexity_requirements())); 1095 | return FALSE; 1096 | } 1097 | } 1098 | 1099 | return TRUE; 1100 | } 1101 | 1102 | /** 1103 | * Bitauth::password_almost_expired() 1104 | * 1105 | * Checks if password expiration is within pwd_age_notification days 1106 | */ 1107 | public function password_almost_expired($user = NULL) 1108 | { 1109 | if($user === NULL) 1110 | { 1111 | $user = $this; 1112 | } 1113 | 1114 | if( ! is_array($user) && ! is_object($user)) 1115 | { 1116 | $this->set_error($this->lang->line('bitauth_expired_datatype')); 1117 | return TRUE; 1118 | } 1119 | 1120 | $user = (object)$user; 1121 | 1122 | if($this->_pwd_max_age == 0 || $user->password_never_expires == 1) 1123 | { 1124 | return FALSE; 1125 | } 1126 | 1127 | return (bool)$this->timestamp(time(), 'U') > ( strtotime($user->password_last_set) + (($this->_pwd_max_age - $this->_pwd_age_notification) * 86400)); 1128 | } 1129 | 1130 | /** 1131 | * Bitauth::password_is_expired() 1132 | * 1133 | * Checks if password has expired 1134 | */ 1135 | public function password_is_expired($user = NULL) 1136 | { 1137 | if($user === NULL) 1138 | { 1139 | $user = $this; 1140 | } 1141 | 1142 | if( ! is_array($user) && ! is_object($user)) 1143 | { 1144 | $this->set_error($this->lang->line('bitauth_expiring_datatype')); 1145 | return TRUE; 1146 | } 1147 | 1148 | $user = (object)$user; 1149 | 1150 | if($this->_pwd_max_age == 0 || $user->password_never_expires == 1) 1151 | { 1152 | return FALSE; 1153 | } 1154 | 1155 | return (bool)$this->timestamp(time(), 'U') > ( strtotime($user->password_last_set) + ($this->_pwd_max_age * 86400) ); 1156 | } 1157 | 1158 | /** 1159 | * Bitauth::get_users() 1160 | * 1161 | * Get all users 1162 | */ 1163 | public function get_users($include_disabled = FALSE) 1164 | { 1165 | if( ! $include_disabled) 1166 | { 1167 | $this->db->where('users.enabled', 1); 1168 | } 1169 | 1170 | $query = $this->db 1171 | ->select('users.*') 1172 | ->select('userdata.*') 1173 | ->select('GROUP_CONCAT(assoc.group_id SEPARATOR "|") AS groups') 1174 | ->select('GROUP_CONCAT(groups.roles SEPARATOR "|") AS roles') 1175 | ->join($this->_table['data'].' userdata', 'userdata.user_id = users.user_id', 'left') 1176 | ->join($this->_table['assoc'].' assoc', 'assoc.user_id = users.user_id', 'left') 1177 | ->join($this->_table['groups'].' groups', 'groups.group_id = assoc.group_id', 'left') 1178 | ->group_by('users.user_id') 1179 | ->get($this->_table['users'].' '.$this->db->dbprefix.'users'); 1180 | 1181 | if($query && $query->num_rows()) 1182 | { 1183 | $ret = array(); 1184 | $result = $query->result(); 1185 | foreach($result as $row) 1186 | { 1187 | $roles = 0; 1188 | $row->groups = explode('|', $row->groups); 1189 | if( ! empty($row->roles)) 1190 | { 1191 | $this->_or_bits($roles, explode('|', $row->roles)); 1192 | } 1193 | $row->roles = $roles; 1194 | $row->last_login_ip = long2ip($row->last_login_ip); 1195 | 1196 | $ret[] = $row; 1197 | } 1198 | 1199 | return $ret; 1200 | } 1201 | 1202 | return FALSE; 1203 | } 1204 | 1205 | /** 1206 | * Bitauth::get_user_by_username() 1207 | * 1208 | * Get a user by unique username 1209 | */ 1210 | public function get_user_by_username($username, $include_disabled = FALSE) 1211 | { 1212 | $this->db->where('users.username', $username); 1213 | $users = $this->get_users($include_disabled); 1214 | 1215 | if(is_array($users) && ! empty($users)) 1216 | { 1217 | return $users[0]; 1218 | } 1219 | 1220 | return FALSE; 1221 | } 1222 | 1223 | /** 1224 | * Bitauth::get_user_by_id() 1225 | * 1226 | * Get a user by unique ID 1227 | */ 1228 | public function get_user_by_id($id, $include_disabled = TRUE) 1229 | { 1230 | $this->db->where('users.user_id', $id); 1231 | $users = $this->get_users($include_disabled); 1232 | 1233 | if(is_array($users) && ! empty($users)) 1234 | { 1235 | return $users[0]; 1236 | } 1237 | 1238 | return FALSE; 1239 | } 1240 | 1241 | /** 1242 | * Bitauth::get_user_by_activation_code() 1243 | * 1244 | * Get a user by activation code 1245 | */ 1246 | public function get_user_by_activation_code($activation_code) 1247 | { 1248 | $this->db->where('activation_code', $activation_code); 1249 | $users = $this->get_users(); 1250 | 1251 | if(is_array($users) && ! empty($users)) 1252 | { 1253 | return $users[0]; 1254 | } 1255 | 1256 | return FALSE; 1257 | } 1258 | 1259 | /** 1260 | * Bitauth::get_user_by_forgot_code() 1261 | * 1262 | * Get a user by forgot code 1263 | */ 1264 | public function get_user_by_forgot_code($forgot_code) 1265 | { 1266 | $this->db->where('forgot_code', $forgot_code); 1267 | $users = $this->get_users(); 1268 | 1269 | if(is_array($users) && ! empty($users)) 1270 | { 1271 | $user = $users[0]; 1272 | 1273 | // If forgot code has expired, remove it and return false 1274 | if($user->forgot_generated < $this->timestamp($this->timestamp(time(), 'U') - $this->_forgot_valid_for)) 1275 | { 1276 | $this->update_user($user->user_id, array('forgot_code' => '')); 1277 | return FALSE; 1278 | } 1279 | 1280 | return $user; 1281 | } 1282 | 1283 | return FALSE; 1284 | } 1285 | 1286 | /** 1287 | * Bitauth::get_groups() 1288 | * 1289 | * Get all groups 1290 | */ 1291 | public function get_groups() 1292 | { 1293 | $query = $this->db 1294 | ->select('groups.*, GROUP_CONCAT(assoc.user_id SEPARATOR "|") AS members') 1295 | ->join($this->_table['assoc'].' assoc', 'assoc.group_id = groups.group_id', 'left') 1296 | ->group_by('groups.group_id') 1297 | ->get($this->_table['groups'].' '.$this->db->dbprefix.'groups'); 1298 | 1299 | if($query && $query->num_rows()) 1300 | { 1301 | $ret = array(); 1302 | $result = $query->result(); 1303 | foreach($result as $row) 1304 | { 1305 | $row->members = explode('|', $row->members); 1306 | $ret[] = $row; 1307 | } 1308 | 1309 | return $ret; 1310 | } 1311 | 1312 | return FALSE; 1313 | } 1314 | 1315 | /** 1316 | * Bitauth::get_group_by_name() 1317 | * 1318 | * Get a group by unique group name 1319 | */ 1320 | public function get_group_by_name($group_name) 1321 | { 1322 | $this->db->where('LOWER(groups.name)', strtolower($group_name)); 1323 | $groups = $this->get_groups(); 1324 | 1325 | if(is_array($groups) && ! empty($groups)) 1326 | { 1327 | return $groups[0]; 1328 | } 1329 | 1330 | return FALSE; 1331 | } 1332 | 1333 | /** 1334 | * Bitauth::get_group_by_id() 1335 | * 1336 | * Get a group by unique ID 1337 | */ 1338 | public function get_group_by_id($id) 1339 | { 1340 | $this->db->where('groups.group_id', $id); 1341 | $groups = $this->get_groups(); 1342 | 1343 | if(is_array($groups) && ! empty($groups)) 1344 | { 1345 | return $groups[0]; 1346 | } 1347 | 1348 | return FALSE; 1349 | } 1350 | 1351 | /** 1352 | * Bitauth::set_error() 1353 | * 1354 | * Sets an error message 1355 | */ 1356 | public function set_error($str, $update_session = TRUE) 1357 | { 1358 | $this->_error = $str; 1359 | 1360 | if($update_session == TRUE) 1361 | { 1362 | $this->session->set_flashdata('bitauth_error', $this->_error); 1363 | } 1364 | } 1365 | 1366 | /** 1367 | * Bitauth::get_error() 1368 | * 1369 | * Get the error message 1370 | */ 1371 | public function get_error($incl_delim = TRUE) 1372 | { 1373 | if($incl_delim) 1374 | { 1375 | return $this->_error_delim_prefix.$this->_error.$this->_error_delim_suffix; 1376 | } 1377 | 1378 | return $this->_error; 1379 | } 1380 | 1381 | /** 1382 | * Bitauth::set_error_delimiters() 1383 | * 1384 | * Set what get_error() is wrapped with 1385 | */ 1386 | public function set_error_delimiters($prefix, $suffix) 1387 | { 1388 | $this->_error_delim_prefix = $prefix; 1389 | $this->_error_delim_suffix = $suffix; 1390 | } 1391 | 1392 | /** 1393 | * Bitauth::hash_password() 1394 | * 1395 | * Hash a cleartext password 1396 | */ 1397 | public function hash_password($str) 1398 | { 1399 | return $this->phpass->HashPassword($str); 1400 | } 1401 | 1402 | /** 1403 | * Bitauth::generate_code() 1404 | * 1405 | * Generate a random code (for activation and forgot password) 1406 | */ 1407 | public function generate_code() 1408 | { 1409 | return sha1(uniqid().time()); 1410 | } 1411 | 1412 | /** 1413 | * Bitauth::logged_in() 1414 | * 1415 | * User is logged in? 1416 | */ 1417 | public function logged_in() 1418 | { 1419 | return (bool)$this->session->userdata($this->_cookie_elem_prefix.'username'); 1420 | } 1421 | 1422 | /** 1423 | * Bitauth::complexity_requirements() 1424 | * 1425 | * Outputs password complexity rules 1426 | */ 1427 | public function complexity_requirements($separator = ', ') 1428 | { 1429 | $ret = array(); 1430 | 1431 | foreach($this->_pwd_complexity as $_label => $_count) 1432 | { 1433 | if($_count > 0) 1434 | { 1435 | $ret[] = $this->lang->line('bitauth_pwd_'.$_label).': '.$_count; 1436 | } 1437 | } 1438 | 1439 | return implode($separator, $ret); 1440 | } 1441 | 1442 | /** 1443 | * Bitauth::timestamp() 1444 | * 1445 | * Return a timestamp based on config settings 1446 | */ 1447 | public function timestamp($time = NULL, $format = NULL) 1448 | { 1449 | if($time === NULL) 1450 | { 1451 | $time = time(); 1452 | } 1453 | if($format === NULL) 1454 | { 1455 | $format = $this->_date_format; 1456 | } 1457 | 1458 | if($this->config->item('time_reference') == 'local') 1459 | { 1460 | return date($format, $time); 1461 | } 1462 | 1463 | return gmdate($format, $time); 1464 | } 1465 | 1466 | /** 1467 | * Bitauth::_or_bits() 1468 | * 1469 | */ 1470 | protected function _or_bits(&$mask, $set) 1471 | { 1472 | if(is_array($set)) 1473 | { 1474 | foreach($set as $_set) 1475 | { 1476 | $this->_or_bits($mask, $_set); 1477 | } 1478 | 1479 | return TRUE; 1480 | } 1481 | 1482 | $bits = $this->_find_bits(trim($set)); 1483 | foreach($bits as $_offset) 1484 | { 1485 | $this->_set_bit($mask, $_offset); 1486 | } 1487 | 1488 | return TRUE; 1489 | } 1490 | 1491 | /** 1492 | * Bitauth::_set_bit() 1493 | * 1494 | */ 1495 | protected function _set_bit(&$mask, $idx) 1496 | { 1497 | if(is_array($idx)) 1498 | { 1499 | foreach($idx as $_idx) 1500 | { 1501 | $this->_set_bit($mask, $_idx); 1502 | } 1503 | 1504 | return TRUE; 1505 | } 1506 | 1507 | $idx++; 1508 | 1509 | if(strlen($mask) < $idx) 1510 | { 1511 | $mask = str_pad($mask, $idx, '0', STR_PAD_LEFT); 1512 | } 1513 | 1514 | $mask = substr_replace($mask, '1', '-'.$idx, 1); 1515 | } 1516 | 1517 | /** 1518 | * Bitauth::_check_bit() 1519 | * 1520 | */ 1521 | protected function _check_bit($mask, $idx) 1522 | { 1523 | return strlen($mask) > $idx && (substr($mask, '-'.++$idx, 1) === '1'); 1524 | } 1525 | 1526 | /** 1527 | * Bitauth::_find_bits() 1528 | * 1529 | */ 1530 | protected function _find_bits($string, $find = '1') 1531 | { 1532 | $ret = array(); 1533 | $string = strrev($string); 1534 | 1535 | for($i = 0; $i < strlen($string); $i++) 1536 | { 1537 | if(substr($string, $i, 1) === '1') 1538 | { 1539 | $ret[] = $i; 1540 | } 1541 | } 1542 | 1543 | return $ret; 1544 | } 1545 | 1546 | /** 1547 | * Bitauth::convert() 1548 | * 1549 | */ 1550 | public function convert($old) 1551 | { 1552 | return base_convert($old, 10, 2); 1553 | } 1554 | 1555 | /** 1556 | * Bitauth::_assign_libraries() 1557 | * 1558 | * Grab everything from the CI superobject that we need 1559 | */ 1560 | public function _assign_libraries() 1561 | { 1562 | if($CI =& get_instance()) 1563 | { 1564 | $this->input = $CI->input; 1565 | $this->load = $CI->load; 1566 | $this->config = $CI->config; 1567 | $this->lang = $CI->lang; 1568 | 1569 | $CI->load->library('session'); 1570 | $this->session = $CI->session; 1571 | 1572 | $CI->load->library('encrypt'); 1573 | $this->encrypt = $CI->encrypt; 1574 | 1575 | $this->load->database(); 1576 | $this->db = $CI->db; 1577 | 1578 | $this->lang->load('bitauth'); 1579 | $this->load->config('bitauth', TRUE); 1580 | 1581 | // Load Phpass library 1582 | $CI->load->library('phpass', array( 1583 | 'iteration_count_log2' => $this->config->item('phpass_iterations', 'bitauth'), 1584 | 'portable_hashes' => $this->config->item('phpass_portable', 'bitauth') 1585 | )); 1586 | $this->phpass = $CI->phpass; 1587 | 1588 | return; 1589 | } 1590 | 1591 | log_message('error', $this->lang->line('bitauth_instance_na')); 1592 | show_error($this->lang->line('bitauth_instance_na')); 1593 | 1594 | } 1595 | 1596 | } -------------------------------------------------------------------------------- /application/libraries/MY_Form_validation.php: -------------------------------------------------------------------------------- 1 | CI->bitauth->username_is_unique($username, $exclude_id)) 13 | { 14 | $this->set_message('bitauth_unique_username', $this->CI->bitauth->get_error(FALSE)); 15 | return FALSE; 16 | } 17 | 18 | return TRUE; 19 | } 20 | 21 | /** 22 | * My_Form_validation::bitauth_unique_group() 23 | * 24 | */ 25 | public function bitauth_unique_group($group_name, $exclude_id = FALSE) 26 | { 27 | if( ! $this->CI->bitauth->group_is_unique($group_name, $exclude_id)) 28 | { 29 | $this->set_message('bitauth_unique_group', $this->CI->bitauth->get_error(FALSE)); 30 | return FALSE; 31 | } 32 | 33 | return TRUE; 34 | } 35 | 36 | /** 37 | * MY_Form_validation::bitauth_valid_password() 38 | * 39 | */ 40 | public function bitauth_valid_password($password) 41 | { 42 | if( ! $this->CI->bitauth->password_is_valid($password)) 43 | { 44 | $this->set_message('bitauth_valid_password', $this->CI->bitauth->get_error(FALSE)); 45 | return FALSE; 46 | } 47 | 48 | return TRUE; 49 | } 50 | } -------------------------------------------------------------------------------- /application/libraries/phpass.php: -------------------------------------------------------------------------------- 1 | in 2004-2006 and placed in 8 | # the public domain. Revised in subsequent years, still public domain. 9 | # 10 | # There's absolutely no warranty. 11 | # 12 | # The homepage URL for this framework is: 13 | # 14 | # http://www.openwall.com/phpass/ 15 | # 16 | # Please be sure to update the Version line if you edit this file in any way. 17 | # It is suggested that you leave the main version number intact, but indicate 18 | # your project name (after the slash) and add your own revision information. 19 | # 20 | # Please do not change the "private" password hashing method implemented in 21 | # here, thereby making your hashes incompatible. However, if you must, please 22 | # change the hash type identifier (the "$P$") to something different. 23 | # 24 | # Obviously, since this code is in the public domain, the above are not 25 | # requirements (there can be none), but merely suggestions. 26 | # 27 | # DEM - 28 | # Changed this filename and class name, and modified the constructor so this class 29 | # will function as a library in CodeIgniter for BitAuth. 30 | # 31 | class Phpass { 32 | var $itoa64; 33 | var $iteration_count_log2; 34 | var $portable_hashes; 35 | var $random_state; 36 | 37 | function __construct($params) 38 | { 39 | $iteration_count_log2 = $params['iteration_count_log2']; 40 | $portable_hashes = $params['portable_hashes']; 41 | 42 | $this->itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; 43 | 44 | if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31) 45 | $iteration_count_log2 = 8; 46 | $this->iteration_count_log2 = $iteration_count_log2; 47 | 48 | $this->portable_hashes = $portable_hashes; 49 | 50 | $this->random_state = microtime(); 51 | if (function_exists('getmypid')) 52 | $this->random_state .= getmypid(); 53 | } 54 | 55 | function get_random_bytes($count) 56 | { 57 | $output = ''; 58 | if (is_readable('/dev/urandom') && 59 | ($fh = @fopen('/dev/urandom', 'rb'))) { 60 | $output = fread($fh, $count); 61 | fclose($fh); 62 | } 63 | 64 | if (strlen($output) < $count) { 65 | $output = ''; 66 | for ($i = 0; $i < $count; $i += 16) { 67 | $this->random_state = 68 | md5(microtime() . $this->random_state); 69 | $output .= 70 | pack('H*', md5($this->random_state)); 71 | } 72 | $output = substr($output, 0, $count); 73 | } 74 | 75 | return $output; 76 | } 77 | 78 | function encode64($input, $count) 79 | { 80 | $output = ''; 81 | $i = 0; 82 | do { 83 | $value = ord($input[$i++]); 84 | $output .= $this->itoa64[$value & 0x3f]; 85 | if ($i < $count) 86 | $value |= ord($input[$i]) << 8; 87 | $output .= $this->itoa64[($value >> 6) & 0x3f]; 88 | if ($i++ >= $count) 89 | break; 90 | if ($i < $count) 91 | $value |= ord($input[$i]) << 16; 92 | $output .= $this->itoa64[($value >> 12) & 0x3f]; 93 | if ($i++ >= $count) 94 | break; 95 | $output .= $this->itoa64[($value >> 18) & 0x3f]; 96 | } while ($i < $count); 97 | 98 | return $output; 99 | } 100 | 101 | function gensalt_private($input) 102 | { 103 | $output = '$P$'; 104 | $output .= $this->itoa64[min($this->iteration_count_log2 + 105 | ((PHP_VERSION >= '5') ? 5 : 3), 30)]; 106 | $output .= $this->encode64($input, 6); 107 | 108 | return $output; 109 | } 110 | 111 | function crypt_private($password, $setting) 112 | { 113 | $output = '*0'; 114 | if (substr($setting, 0, 2) == $output) 115 | $output = '*1'; 116 | 117 | $id = substr($setting, 0, 3); 118 | # We use "$P$", phpBB3 uses "$H$" for the same thing 119 | if ($id != '$P$' && $id != '$H$') 120 | return $output; 121 | 122 | $count_log2 = strpos($this->itoa64, $setting[3]); 123 | if ($count_log2 < 7 || $count_log2 > 30) 124 | return $output; 125 | 126 | $count = 1 << $count_log2; 127 | 128 | $salt = substr($setting, 4, 8); 129 | if (strlen($salt) != 8) 130 | return $output; 131 | 132 | # We're kind of forced to use MD5 here since it's the only 133 | # cryptographic primitive available in all versions of PHP 134 | # currently in use. To implement our own low-level crypto 135 | # in PHP would result in much worse performance and 136 | # consequently in lower iteration counts and hashes that are 137 | # quicker to crack (by non-PHP code). 138 | if (PHP_VERSION >= '5') { 139 | $hash = md5($salt . $password, TRUE); 140 | do { 141 | $hash = md5($hash . $password, TRUE); 142 | } while (--$count); 143 | } else { 144 | $hash = pack('H*', md5($salt . $password)); 145 | do { 146 | $hash = pack('H*', md5($hash . $password)); 147 | } while (--$count); 148 | } 149 | 150 | $output = substr($setting, 0, 12); 151 | $output .= $this->encode64($hash, 16); 152 | 153 | return $output; 154 | } 155 | 156 | function gensalt_extended($input) 157 | { 158 | $count_log2 = min($this->iteration_count_log2 + 8, 24); 159 | # This should be odd to not reveal weak DES keys, and the 160 | # maximum valid value is (2**24 - 1) which is odd anyway. 161 | $count = (1 << $count_log2) - 1; 162 | 163 | $output = '_'; 164 | $output .= $this->itoa64[$count & 0x3f]; 165 | $output .= $this->itoa64[($count >> 6) & 0x3f]; 166 | $output .= $this->itoa64[($count >> 12) & 0x3f]; 167 | $output .= $this->itoa64[($count >> 18) & 0x3f]; 168 | 169 | $output .= $this->encode64($input, 3); 170 | 171 | return $output; 172 | } 173 | 174 | function gensalt_blowfish($input) 175 | { 176 | # This one needs to use a different order of characters and a 177 | # different encoding scheme from the one in encode64() above. 178 | # We care because the last character in our encoded string will 179 | # only represent 2 bits. While two known implementations of 180 | # bcrypt will happily accept and correct a salt string which 181 | # has the 4 unused bits set to non-zero, we do not want to take 182 | # chances and we also do not want to waste an additional byte 183 | # of entropy. 184 | $itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; 185 | 186 | $output = '$2a$'; 187 | $output .= chr(ord('0') + $this->iteration_count_log2 / 10); 188 | $output .= chr(ord('0') + $this->iteration_count_log2 % 10); 189 | $output .= '$'; 190 | 191 | $i = 0; 192 | do { 193 | $c1 = ord($input[$i++]); 194 | $output .= $itoa64[$c1 >> 2]; 195 | $c1 = ($c1 & 0x03) << 4; 196 | if ($i >= 16) { 197 | $output .= $itoa64[$c1]; 198 | break; 199 | } 200 | 201 | $c2 = ord($input[$i++]); 202 | $c1 |= $c2 >> 4; 203 | $output .= $itoa64[$c1]; 204 | $c1 = ($c2 & 0x0f) << 2; 205 | 206 | $c2 = ord($input[$i++]); 207 | $c1 |= $c2 >> 6; 208 | $output .= $itoa64[$c1]; 209 | $output .= $itoa64[$c2 & 0x3f]; 210 | } while (1); 211 | 212 | return $output; 213 | } 214 | 215 | function HashPassword($password) 216 | { 217 | $random = ''; 218 | 219 | if (CRYPT_BLOWFISH == 1 && !$this->portable_hashes) { 220 | $random = $this->get_random_bytes(16); 221 | $hash = 222 | crypt($password, $this->gensalt_blowfish($random)); 223 | if (strlen($hash) == 60) 224 | return $hash; 225 | } 226 | 227 | if (CRYPT_EXT_DES == 1 && !$this->portable_hashes) { 228 | if (strlen($random) < 3) 229 | $random = $this->get_random_bytes(3); 230 | $hash = 231 | crypt($password, $this->gensalt_extended($random)); 232 | if (strlen($hash) == 20) 233 | return $hash; 234 | } 235 | 236 | if (strlen($random) < 6) 237 | $random = $this->get_random_bytes(6); 238 | $hash = 239 | $this->crypt_private($password, 240 | $this->gensalt_private($random)); 241 | if (strlen($hash) == 34) 242 | return $hash; 243 | 244 | # Returning '*' on error is safe here, but would _not_ be safe 245 | # in a crypt(3)-like function used _both_ for generating new 246 | # hashes and for validating passwords against existing hashes. 247 | return '*'; 248 | } 249 | 250 | function CheckPassword($password, $stored_hash) 251 | { 252 | $hash = $this->crypt_private($password, $stored_hash); 253 | if ($hash[0] == '*') 254 | $hash = crypt($password, $stored_hash); 255 | 256 | return $hash == $stored_hash; 257 | } 258 | } 259 | 260 | ?> 261 | -------------------------------------------------------------------------------- /application/views/example/activation_failed.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | BitAuth: Activation Failed 13 | 14 | 15 | '; 17 | echo 'BitAuth Example: Activation Failed!'; 18 | echo ''.anchor('example', 'Continue').''; 19 | echo ''; 20 | ?> 21 | 22 | -------------------------------------------------------------------------------- /application/views/example/activation_successful.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | BitAuth: Activation Successful 13 | 14 | 15 | '; 17 | echo ''; 18 | echo ''; 19 | echo '
BitAuth Example: Activation Successful
'.anchor('example', 'Continue').'
'; 20 | ?> 21 | 22 | -------------------------------------------------------------------------------- /application/views/example/add_group.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | 16 | BitAuth: Add Group 17 | 18 | 19 | '; 23 | echo ''; 24 | 25 | echo ''; 26 | echo ''; 27 | echo ''; 28 | echo ''; 29 | if(validation_errors()) 30 | { 31 | echo ''; 32 | } 33 | 34 | echo ''; 35 | echo '
BitAuth Example: Add Group
Group Name'.form_input('name', set_value('name')).'
Description'.form_textarea('description', set_value('description')).'
Roles'.form_multiselect('roles[]', $roles, set_value('roles[]')).'
Members'.form_multiselect('members[]', $users, set_value('members[]')).'
'.validation_errors().'
'.form_submit('submit','Add Group').'
'; 36 | echo form_close(); 37 | 38 | echo '
'; 39 | if(isset($bitauth) && $bitauth->logged_in()) 40 | { 41 | echo anchor('example/logout', 'Logout', 'style="float: right;"'); 42 | } 43 | else 44 | { 45 | echo anchor('example/login', 'Login', 'style="float: right;"'); 46 | } 47 | echo '
'; 48 | 49 | ?> 50 | 51 | 52 | -------------------------------------------------------------------------------- /application/views/example/add_user.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | BitAuth: <?php echo $title; ?> 16 | 17 | 18 | '; 22 | echo 'BitAuth Example: '.$title.''; 23 | echo 'Username'.form_input('username', set_value('username')).''; 24 | echo 'Full Name'.form_input('fullname', set_value('fullname')).''; 25 | echo 'Email'.form_input('email', set_value('email')).''; 26 | echo 'Password'.form_password('password').''; 27 | echo 'Confirm Password'.form_password('password_conf').''; 28 | 29 | if(validation_errors()) 30 | { 31 | echo ''.validation_errors().''; 32 | } 33 | 34 | echo ''.form_submit('submit',$title).''; 35 | echo ''; 36 | echo form_close(); 37 | 38 | echo '
'; 39 | if(isset($bitauth) && $bitauth->logged_in()) 40 | { 41 | echo anchor('example/logout', 'Logout', 'style="float: right;"'); 42 | } 43 | else 44 | { 45 | echo anchor('example/login', 'Login', 'style="float: right;"'); 46 | } 47 | echo '
'; 48 | 49 | ?> 50 | 51 | 52 | -------------------------------------------------------------------------------- /application/views/example/edit_group.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | BitAuth: Edit Group 16 | 17 | 18 | '; 24 | echo 'BitAuth Example: Edit Group'; 25 | 26 | if( ! empty($group)) 27 | { 28 | echo 'Group Name'.form_input('name', set_value('name', $group->name)).''; 29 | echo 'Description'.form_textarea('description', set_value('description', $group->description)).''; 30 | echo 'Roles'.form_multiselect('roles[]', $roles, set_value('roles[]', $group_roles)).''; 31 | echo 'Members'.form_multiselect('members[]', $users, set_value('members[]', $group->members)).''; 32 | 33 | if(validation_errors()) 34 | { 35 | echo ''.validation_errors().''; 36 | } 37 | 38 | echo ''.anchor('example/groups', 'Cancel').' '.form_submit('submit','Update').''; 39 | } else { 40 | echo '

Group Not Found

'.anchor('example/groups', 'Go Back').'

'; 41 | } 42 | 43 | echo ''; 44 | echo form_close(); 45 | 46 | echo '
'; 47 | echo anchor('example/logout', 'Logout', 'style="float: right;"'); 48 | echo '
'; 49 | 50 | ?> 51 | 52 | 53 | -------------------------------------------------------------------------------- /application/views/example/edit_user.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | BitAuth: Edit User 16 | 17 | 18 | '; 24 | echo 'BitAuth Example: Edit User'; 25 | 26 | if( ! empty($user)) 27 | { 28 | echo 'Username'.form_input('username', set_value('username', $user->username)).''; 29 | echo 'Full Name'.form_input('fullname', set_value('fullname', $user->fullname)).''; 30 | echo 'Email'.form_input('email', set_value('email', $user->email)).''; 31 | echo 'Active'.form_dropdown('active', $yesno, set_value('active', $user->active)).''; 32 | echo 'Enabled'.form_dropdown('enabled', $yesno, set_value('enabled', $user->enabled)).''; 33 | echo 'Password Never Expires'.form_dropdown('password_never_expires', $yesno, set_value('password_never_expires', $user->password_never_expires)).''; 34 | echo 'Groups'.form_multiselect('groups[]', $groups, set_value('groups[]', $user->groups)).''; 35 | echo 'Only enter a password if you would like to set a new one'; 36 | echo 'New Password'.form_password('password').''; 37 | echo 'Confirm New Password'.form_password('password_conf').''; 38 | 39 | if(validation_errors()) 40 | { 41 | echo ''.validation_errors().''; 42 | } 43 | 44 | echo ''.anchor('example', 'Cancel').' '.form_submit('submit','Update').''; 45 | } else { 46 | echo '

User Not Found

'.anchor('example', 'Go Back').'

'; 47 | } 48 | 49 | echo ''; 50 | echo form_close(); 51 | 52 | echo '
'; 53 | echo anchor('example/logout', 'Logout', 'style="float: right;"'); 54 | echo '
'; 55 | 56 | ?> 57 | 58 | 59 | -------------------------------------------------------------------------------- /application/views/example/groups.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | BitAuth: Groups 13 | 14 | 15 | '; 17 | echo 'BitAuth Example: Groups'; 18 | echo 'IDNameDescriptionActions'; 19 | foreach($groups as $_group) 20 | { 21 | $actions = ''; 22 | if($bitauth->has_role('admin')) 23 | { 24 | $actions = anchor('example/edit_group/'.$_group->group_id, 'Edit Group'); 25 | } 26 | 27 | echo ''. 28 | ''.$_group->group_id.''. 29 | ''.$_group->name.''. 30 | ''.$_group->description.''. 31 | ''.$actions.''. 32 | ''; 33 | } 34 | echo ''; 35 | echo '
'; 36 | echo anchor('example/logout', 'Logout', 'style="float: right;"'); 37 | echo anchor('example', 'View Users'); 38 | if($bitauth->is_admin()) 39 | { 40 | echo '
'.anchor('example/add_group', 'Add Group'); 41 | } 42 | echo '
'; 43 | ?> 44 | 45 | 46 | -------------------------------------------------------------------------------- /application/views/example/login.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 14 | BitAuth: Login 15 | 16 | 17 | BitAuth Example: Login'; 19 | 20 | echo form_open(current_url()); 21 | echo form_label('Username','username'); 22 | echo form_input('username'); 23 | echo form_label('Password','password'); 24 | echo form_password('password'); 25 | echo form_label(form_checkbox('remember_me', 1).' Remember Me', 'remember_me'); 26 | echo form_submit('login','Login'); 27 | echo ( ! empty($error) ? $error : '' ); 28 | echo form_close(); 29 | 30 | echo '
'; 31 | echo ''.anchor('example/register', 'Register').''; 32 | echo 'Username: admin
Password: admin'; 33 | echo '
'; 34 | 35 | ?> 36 | 37 | 38 | -------------------------------------------------------------------------------- /application/views/example/no_access.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | BitAuth: Access Denied 13 | 14 | 15 | '; 17 | echo 'BitAuth Example: Access Denied'; 18 | echo 'Nope.
'.anchor('example', 'Continue').''; 19 | echo ''; 20 | ?> 21 | 22 | -------------------------------------------------------------------------------- /application/views/example/users.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | BitAuth: Users 13 | 14 | 15 | '; 18 | echo ''; 19 | echo ''; 20 | if( ! empty($users)) 21 | { 22 | foreach($users as $_user) 23 | { 24 | $actions = ''; 25 | if($bitauth->has_role('admin')) 26 | { 27 | $actions = anchor('example/edit_user/'.$_user->user_id, 'Edit User'); 28 | if( ! $_user->active) 29 | { 30 | $actions .= '
'.anchor('example/activate/'.$_user->activation_code, 'Activate User'); 31 | } 32 | 33 | } 34 | 35 | echo ''. 36 | ''. 37 | ''. 38 | ''. 39 | ''. 40 | ''; 41 | } 42 | } 43 | echo '
BitAuth Example: Users
IDUsernameFull NameActions
'.$_user->user_id.''.$_user->username.''.$_user->fullname.''.$actions.'
'; 44 | 45 | echo '
'; 46 | echo anchor('example/logout', 'Logout', 'style="float: right;"'); 47 | echo anchor('example/groups', 'View Groups'); 48 | if($bitauth->is_admin()) 49 | { 50 | echo '
'.anchor('example/add_user', 'Add User'); 51 | } 52 | echo '
'; 53 | 54 | ?> 55 | 56 | 57 | -------------------------------------------------------------------------------- /bitauth.sql: -------------------------------------------------------------------------------- 1 | -- phpMyAdmin SQL Dump 2 | -- version 3.3.9 3 | -- http://www.phpmyadmin.net 4 | -- 5 | -- Host: localhost 6 | -- Generation Time: Aug 20, 2011 at 03:19 PM 7 | -- Server version: 5.1.53 8 | -- PHP Version: 5.3.4 9 | 10 | SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"; 11 | 12 | 13 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 14 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; 15 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; 16 | /*!40101 SET NAMES utf8 */; 17 | 18 | -- 19 | -- Database: `bitauth` 20 | -- 21 | 22 | -- -------------------------------------------------------- 23 | 24 | -- 25 | -- Table structure for table `bitauth_assoc` 26 | -- 27 | 28 | CREATE TABLE IF NOT EXISTS `bitauth_assoc` ( 29 | `assoc_id` int(10) unsigned NOT NULL AUTO_INCREMENT, 30 | `user_id` int(10) unsigned NOT NULL, 31 | `group_id` int(10) unsigned NOT NULL, 32 | PRIMARY KEY (`assoc_id`), 33 | KEY `user_id` (`user_id`,`group_id`) 34 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ; 35 | 36 | -- 37 | -- Dumping data for table `bitauth_assoc` 38 | -- 39 | 40 | INSERT INTO `bitauth_assoc` (`assoc_id`, `user_id`, `group_id`) VALUES 41 | (1, 1, 1); 42 | 43 | -- -------------------------------------------------------- 44 | 45 | -- 46 | -- Table structure for table `bitauth_groups` 47 | -- 48 | 49 | CREATE TABLE IF NOT EXISTS `bitauth_groups` ( 50 | `group_id` int(10) unsigned NOT NULL AUTO_INCREMENT, 51 | `name` varchar(48) NOT NULL, 52 | `description` text NOT NULL, 53 | `roles` text NOT NULL, 54 | PRIMARY KEY (`group_id`) 55 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ; 56 | 57 | -- 58 | -- Dumping data for table `bitauth_groups` 59 | -- 60 | 61 | INSERT INTO `bitauth_groups` (`group_id`, `name`, `description`, `roles`) VALUES 62 | (1, 'Administrators', 'Administrators (Full Access)', 1), 63 | (2, 'Users', 'Default User Group', 0); 64 | 65 | -- -------------------------------------------------------- 66 | 67 | -- 68 | -- Table structure for table `bitauth_logins` 69 | -- 70 | 71 | CREATE TABLE IF NOT EXISTS `bitauth_logins` ( 72 | `login_id` int(10) unsigned NOT NULL AUTO_INCREMENT, 73 | `ip_address` int(10) unsigned NOT NULL, 74 | `user_id` int(10) unsigned NOT NULL, 75 | `time` datetime NOT NULL, 76 | `success` tinyint(1) NOT NULL DEFAULT '0', 77 | PRIMARY KEY (`login_id`), 78 | KEY `user_id` (`user_id`) 79 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; 80 | 81 | -- 82 | -- Dumping data for table `bitauth_logins` 83 | -- 84 | 85 | 86 | -- -------------------------------------------------------- 87 | 88 | -- 89 | -- Table structure for table `bitauth_userdata` 90 | -- 91 | 92 | CREATE TABLE IF NOT EXISTS `bitauth_userdata` ( 93 | `userdata_id` int(10) unsigned NOT NULL AUTO_INCREMENT, 94 | `user_id` int(10) unsigned NOT NULL, 95 | `fullname` varchar(40) NOT NULL, 96 | `email` varchar(254) NOT NULL, 97 | PRIMARY KEY (`userdata_id`), 98 | KEY `user_id` (`user_id`) 99 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ; 100 | 101 | -- 102 | -- Dumping data for table `bitauth_userdata` 103 | -- 104 | 105 | INSERT INTO `bitauth_userdata` (`userdata_id`, `user_id`, `fullname`, `email`) VALUES 106 | (1, 1, 'Administrator', 'admin@admin.com'); 107 | 108 | -- -------------------------------------------------------- 109 | 110 | -- 111 | -- Table structure for table `bitauth_users` 112 | -- 113 | 114 | CREATE TABLE IF NOT EXISTS `bitauth_users` ( 115 | `user_id` int(11) unsigned NOT NULL AUTO_INCREMENT, 116 | `username` varchar(32) NOT NULL, 117 | `password` varchar(60) NOT NULL, 118 | `password_last_set` datetime NOT NULL, 119 | `password_never_expires` tinyint(1) NOT NULL DEFAULT '0', 120 | `remember_me` varchar(40) NOT NULL, 121 | `activation_code` varchar(40) NOT NULL, 122 | `active` tinyint(1) NOT NULL DEFAULT '0', 123 | `forgot_code` varchar(40) NOT NULL, 124 | `forgot_generated` datetime NOT NULL, 125 | `enabled` tinyint(1) NOT NULL DEFAULT '1', 126 | `last_login` datetime NOT NULL, 127 | `last_login_ip` int(10) NOT NULL, 128 | PRIMARY KEY (`user_id`) 129 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ; 130 | 131 | -- 132 | -- Dumping data for table `bitauth_users` 133 | -- 134 | 135 | INSERT INTO `bitauth_users` (`user_id`, `username`, `password`, `password_last_set`, `password_never_expires`, `remember_me`, `activation_code`, `active`, `forgot_code`, `forgot_generated`, `enabled`, `last_login`, `last_login_ip`) VALUES 136 | (1, 'admin', '$2a$08$560JEYl2Np/7/6RLc/mq/ecnumuBXig3e.pHh1lnH1pgpk94sTZhu', now(), 0, '', '', 1, '', '0000-00-00 00:00:00', 1, '0000-00-00 00:00:00', 0); 137 | -------------------------------------------------------------------------------- /user_guide/general/config.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | BitAuth User Guide : Configuration 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 |

BitAuth User Guide Version 1.0

36 |
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 49 | 50 |
51 | 52 | 53 |
54 | 55 | 56 |
57 |

Configuration

58 | 59 |

BitAuth has the following configuration options available:

60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 199 | 200 | 201 | 202 |
ConfigDefault ValueOptionsDescription
require_user_activationTRUETRUE, FALSE

If set to TRUE, users must be activated before they are able to login.

default_group_id2Any Existing Group ID

The group_id of the default group users will be added to when they register. NOTE: This group's roles will not be inherited by the user until they are activated.

remember_token_namerememberme 

Name of the cookie where the "Remember Me" token is stored. This value is prefixed with cookie_prefix value in config.php, if one is set.

remember_token_expires604800 (7 days) 

Number of seconds that the "Remember Me" token lasts before expiring. Once this time has passed, the user will need to login again the next time they visit.

remember_token_updatesTRUETRUE, FALSE

If set to TRUE, the timer on the "Remember Me" token will reset every time this user revisits the site.

pwd_max_age90 

Number of days a password is valid for. Once this time has passed, a user cannot login, and must have their password reset by an administrator or through the "Forgot Password" page. To disable, set to FALSE.

pwd_age_notification7 

Number of days before password expiration that a user is notified. Once inside this number of days, the user will be directed to a form to change their password every time they login automatically. To disable, set to FALSE.

pwd_min_length8 

Minimum required length of passwords. To disable, set to FALSE.

pwd_max_length20 

Maximum allowable length of passwords. To disable, set to FALSE.

pwd_complexityUppercase: 1
Numbers: 1
Special Chars: 0
 

Minimum number of each type of character required for a password to valid. To disable requirements for any type of character, set that value to 0.

pwd_complexity_charsUppercase: [[:upper:]]
Numbers: [[:digit:]]
Special Chars: [[:punct:]]
Spaces: \s
 

The regular expression for each type of character. The default values should be language independent, so you should not need to change them.

log_loginsTRUETRUE,FALSE

Whether or not to log login attemps. Setting this to FALSE effectively disables locking out users from invalid login attemps.

invalid_logins3 

How many invalid logins a user gets before they are locked out.

mins_login_attempts5 

Number of minutes between invalid login attemps where a user will be locked out.

mins_locked_out10 

Number of minutes before a locked account is unlocked.

tableUsers: bitauth_users
Data: bitauth_userdata
Groups: bitauth_groups
Assoc: bitauth_assoc
Logins: bitauth_logins
  163 |

The tables used by BitAuth. If you have changed these in your database, you should change them here.

164 |
    165 |
  • users: Where user information required by BitAuth is stored.
  • 166 |
  • data: Where all optional user data is stored. Any custom fields you add go here.
  • 167 |
  • groups: Where all group information is stored.
  • 168 |
  • assoc: Where the relationships between users and groups are stored.
  • 169 |
  • logins: Where login attempts are logged
  • 170 |
171 |
phpass_iterations8 

Base-2 logarithm of the iteration count used for password stretching by Phpass. See: http://en.wikipedia.org/wiki/Key_strengthening.

phpass_portableFALSE 

Require the hashes to be portable to older systems. If FALSE, phpass' preferred hashing method is CRYPT_BLOWFISH, with a fallback to CRYPT_EXT_DES, and then a final fallback to the "portable" hashes. See: http://www.openwall.com/articles/PHP-Users-Passwords.

date_formatY-m-d H:i:s 

What format BitAuth stores timestamps in. Defaults to the MySQL DATETIME format. To use unix timestamps, change this value to 'U' (in addition to changing your DB structure).

roles   196 |

This is where all of your roles are stored. There is only one role required by BitAuth, admin. This should always be the first listed.

197 |

You can read more about roles at Creating Roles.

198 |
203 |
204 | 205 | 206 | 207 | 210 | 211 | 212 | 213 | -------------------------------------------------------------------------------- /user_guide/general/notes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | BitAuth User Guide : Notes 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 |

BitAuth User Guide Version 1.0

36 |
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 49 | 50 | 51 |
52 | 53 | 54 |
55 | 56 | 57 |
58 |

Notes

59 |

BitAuth stores roles in the session (encrypted), which means if you are using CodeIgniter's default session settings, roles are stored in a cookie. I can't advise against this strongly enough. You should, at a bare minimum be encrypting the session cookie by enabling sess_encrypt_cookie in config.php. Even better, you should be using database sessions so the information is stored server-side.

60 |

Why PHP 5.3+?

61 |

As of 5.3.0, crypt_blowfish is integrated into the PHP interpreter, which means PHPass will never fall back to CRYPT_EXT_DES or md5.

62 | 63 |

Limitations

64 |

Currently, you are limited to 64 roles. This is due to MySQL's limitation of 64 bits when working with bit operations. No more limitations on the number of roles!

65 |

What is NOT included?

66 | 70 |
71 | 72 | 73 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /user_guide/general/utility.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | BitAuth User Guide : Utility Functions 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 |

BitAuth User Guide Version 1.0

36 |
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 49 | 50 | 51 |
52 | 53 | 54 |
55 | 56 | 57 |
58 |

Utility Functions

59 |

$this->bitauth->activate($activation_code)

60 |

This will activate a user based on the activation_code generated by add_user() if $require_activation is TRUE.

61 | 62 |

$this->bitauth->set_password($user_id, $new_password)

63 |

This will hash the plain text password passed to $new_password, and update the user along with the value for password_last_set.

64 | 65 |

$this->bitauth->get_role($slug)

66 |

This will return the bit offset for a role based on the slug that is passed. This is a utility function used internally in BitAuth.

67 | 68 |

$this->bitauth->get_roles()

69 |

This returns an array of all roles defined in the configuration. The array is exactly as it's defined, in the format:

70 |
array( 'slug' => 'description' );
71 | 72 |

$this->bitauth->set_login_field($field)

73 |

Declares a field that must be matched on login. There is no processing done before or after this check, an exact match is required. So, for example, if you want a 74 | case-insensitive match, you should run strtolower() on the data before it's stored in the database, and also on the form data before it's checked.

75 |

More on this method can be found in Logging In/Logging Out.

76 | 77 |

$this->bitauth->check_login_fields($user, $data)

78 |

This is a utility function called by login() which checks any fields 79 | 80 |

$this->bitauth->set_error($str, $update_session = TRUE)

81 |

Stores an error message in BitAuth. Currently, BitAuth only stores one message at a time. By default, this message will be saved to the session, 82 | you can disable this by passing FALSE as the second parameter.

83 | 84 |

$this->bitauth->get_error($incl_delim = TRUE)

85 |

Retrieves the message stored by $this->bitauth->set_error(). The message is wrapped with $_error_delim_prefix and $_error_delim_suffix, unless passed FALSE as a parameter.

86 | 87 |

$this->bitauth->set_error_delimiters($prefix, $suffix)

88 |

Set the prefix and suffix error delimiters.

89 | 90 |

$this->bitauth->locked_out()

91 |

Returns TRUE if the current IP is locked out

92 | 93 |

$this->bitauth->log_attempt($user_id, $success = FALSE)

94 |

Logs a login attempt.

95 | 96 |

$this->bitauth->hash_password($str)

97 |

This function will hash the string it is given. This is a utility function used internally by BitAuth.

98 | 99 |

$this->bitauth->generate_code()

100 |

Generates a random sha1 hash used for things like activation, forgot password, etc. Length of the string returned is 40 characters.

101 | 102 |

$this->bitauth->complexity_requirements($separator = '<br/>')

103 |

This function returns a string explaining the complexity requirements you have defined in your configuration. 104 | Called by the bitauth_valid_password form_validation rule. 105 | 106 |

107 | 108 | 109 | 110 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /user_guide/general/validation.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | BitAuth User Guide : Form Validation 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 |

BitAuth User Guide Version 1.0

36 |
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 49 | 50 | 51 |
52 | 53 | 54 |
55 | 56 | 57 |
58 |

Form Validation

59 |

BitAuth comes with an extended Form Validation library with methods to help validate input for users and groups.

60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 84 | 85 | 86 |
RuleParameterDescriptionExample
bitauth_unique_usernameYesReturns FALSE if the username is not unique. Pass a user_id as an optional parameter to exclude that user from the check.bitauth_unique_username
bitauth_unique_username[2]
bitauth_unique_groupYesReturns FALSE if the group name is not unique. Pass a group_id as an optional parameter to exclude that group from the check. bitauth_unique_group
bitauth_unique_group[2]
bitauth_valid_passwordNoReturns FALSE if the password does not meet the complexity requirements you have specified in the configuration. This rule 83 | also checks the pwd_min_length and pwd_max_length you have specified, so separate use of those rules is unnecessary.
87 |
88 | 89 | 90 | 91 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /user_guide/groups/adding.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | BitAuth User Guide : Adding Groups 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 |

BitAuth User Guide Version 1.0

36 |
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 49 | 50 | 51 |
52 | 53 | 54 |
55 | 56 | 57 |
58 |

Adding Groups

59 |

When adding a group, there is only one required field: name. However, you do have a few other options.

60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 |
AttributeExampleDescription
nameExample GroupName of the group.
descriptionThis is an example groupDescription of the group.
rolesarray('example_role_1', 'example_role_2')Array of roles slugs to be given to this group.
membersarray(1, 4, 15)Array of user_ids for users who are members of this group.
88 | 89 |

$this->bitauth->add_group($data)

90 |
$group = array(
 91 |     'name' => 'Example Group',
 92 |     'description' => 'This is an example group.',
 93 |     'roles' => array('example_role_1', 'example_role_2'),
 94 |     'members' => array(1, 4, 15)
 95 | );
 96 | 
 97 | $this->bitauth->add_group($group);
98 | 99 |

For information on assigning roles, see Setting Roles.

100 |

For information on adding users to a group, see Adding Members.

101 | 102 |
103 | 104 | 105 | 106 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /user_guide/groups/assigning.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | BitAuth User Guide : Adding Members 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 |

BitAuth User Guide Version 1.0

36 |
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 49 | 50 | 51 |
52 | 53 | 54 |
55 | 56 | 57 |
58 |

Adding Members

59 |

Just like when assigning groups to the user, adding users to the group is done by passing an array of user_ids to the group 60 | object in the members attribute.

61 |

When Adding a Group

62 |

There are no default members when creating a group, so if you don't specify any the group will be empty. Specifying members, however, is quite simple.

63 |
$group = array(
64 |     'name' => 'Test Group',
65 |     'description' => 'This is a test group.',
66 |     'members' => array(1,5,15)
67 | );
68 | 
69 | $this->bitauth->add_group($group);
70 | 71 |

When Updating a Group

72 |

When updating a group, adding a user to a group is done exactly the same way.

73 |
$group = $this->bitauth->get_group_by_id(2);
74 | 
75 | // Add user_id 3 to members
76 | $group->members[] = 3;
77 | 
78 | $this->bitauth->update_group(2, $group);
79 |
80 | 81 | 82 | 83 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /user_guide/groups/editing.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | BitAuth User Guide : Editing Groups 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 |

BitAuth User Guide Version 1.0

36 |
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 49 | 50 | 51 |
52 | 53 | 54 |
55 | 56 | 57 |
58 |

Editing Groups

59 |

Editing Groups works exactly like Editing Users.

60 |

$this->bitauth->update_group($group_id, $data)

61 |
$group = $this->bitauth->get_group_by_name('Test Group');
62 | 
63 | // Remove all users from a group
64 | $group->members = array();
65 | $this->bitauth->update_group($group->group_id, $group);
66 |

For a list of all group fields, see Adding Groups.

67 | 68 |

Deleting Groups

69 |

$this->bitauth->delete_group($group_id)

70 |

Deletes a group:

71 |
$this->bitauth->delete_group(2);
72 |
73 | 74 | 75 | 76 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /user_guide/groups/fetching.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | BitAuth User Guide : Fetching Groups 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 |

BitAuth User Guide Version 1.0

36 |
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 49 | 50 | 51 |
52 | 53 | 54 |
55 | 56 | 57 |
58 |

Fetching Groups

59 |

$this->bitauth->get_groups()

60 |

Returns all groups. Each group object contains the following information:

61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 |
AttributeExampleDescription
group_id1Unique ID of this group.
nameExample GroupName of the group.
descriptionThis is an example groupDescription of the group.
roles4Numeric representation of the group's roles.
membersarray(1, 4, 15)Array of user_ids for users who are members of this group.
94 | 95 |

get_groups() returns an array of objects containing this information. You might iterate through all groups like:

96 |
$all_groups = $this->bitauth->get_groups();
 97 | 
 98 | foreach($all_groups as $group)
 99 | {
100 |     echo $group->name.'<br/>';
101 | }
102 | 103 |

For information on checking a group's roles, see Checking Roles.

104 | 105 |

$this->bitauth->get_group_by_id($group_id)

106 |

Returns an object with the same information as get_groups() for one group, by group_id. Returns FALSE on failure.

107 |
$group = $this->bitauth->get_group_by_id(1);
108 | 
109 | if($group == FALSE)
110 | {
111 |     echo 'Group Not Found';
112 | }
113 | else
114 | {
115 |     echo 'Group Name: '.$group->name;
116 | }
117 |

$this->bitauth->get_group_by_name($group_name)

118 |

Returns an object with the same information as get_groups() for one group, by name. $group_name is case-insensitive. Returns FALSE on failure.

119 | 120 |
121 | 122 | 123 | 124 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /user_guide/images/arrow.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danmontgomery/codeigniter-bitauth/97c3a0e4844e085ddd6c1eae78800fc0c8fc3734/user_guide/images/arrow.gif -------------------------------------------------------------------------------- /user_guide/images/nav_bg_darker.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danmontgomery/codeigniter-bitauth/97c3a0e4844e085ddd6c1eae78800fc0c8fc3734/user_guide/images/nav_bg_darker.jpg -------------------------------------------------------------------------------- /user_guide/images/nav_separator_darker.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danmontgomery/codeigniter-bitauth/97c3a0e4844e085ddd6c1eae78800fc0c8fc3734/user_guide/images/nav_separator_darker.jpg -------------------------------------------------------------------------------- /user_guide/images/nav_toggle_darker.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danmontgomery/codeigniter-bitauth/97c3a0e4844e085ddd6c1eae78800fc0c8fc3734/user_guide/images/nav_toggle_darker.jpg -------------------------------------------------------------------------------- /user_guide/images/transparent.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danmontgomery/codeigniter-bitauth/97c3a0e4844e085ddd6c1eae78800fc0c8fc3734/user_guide/images/transparent.gif -------------------------------------------------------------------------------- /user_guide/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | BitAuth User Guide 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 |

BitAuth User Guide Version 1.0

36 |
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 48 | 49 | 50 |
51 | 52 | 53 | 54 |
55 | 56 |

Requirements

57 | 63 | 64 |

Features

65 | 81 | 82 |

Download

83 |

BitAuth is available on GitHub at http://www.github.com/danmontgomery/codeigniter-bitauth.

84 | 85 |
86 | 87 | 88 | 89 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /user_guide/nav/hacks.txt: -------------------------------------------------------------------------------- 1 | I did the following hack in moo.fx.js: 2 | 3 | At line 79 in the toggle: function() function, I added: 4 | 5 | document.getElementById('nav').style.display = 'block'; 6 | 7 | -- Rick Ellis 8 | 9 | 10 | Also removed fx.Opacity and fx.Height from moo.fx.js -- Pascal -------------------------------------------------------------------------------- /user_guide/nav/moo.fx.js: -------------------------------------------------------------------------------- 1 | /* 2 | moo.fx, simple effects library built with prototype.js (http://prototype.conio.net). 3 | by Valerio Proietti (http://mad4milk.net) MIT-style LICENSE. 4 | for more info (http://moofx.mad4milk.net). 5 | 10/24/2005 6 | v(1.0.2) 7 | */ 8 | 9 | //base 10 | var fx = new Object(); 11 | fx.Base = function(){}; 12 | fx.Base.prototype = { 13 | setOptions: function(options) { 14 | this.options = { 15 | duration: 500, 16 | onComplete: '' 17 | } 18 | Object.extend(this.options, options || {}); 19 | }, 20 | 21 | go: function() { 22 | this.duration = this.options.duration; 23 | this.startTime = (new Date).getTime(); 24 | this.timer = setInterval (this.step.bind(this), 13); 25 | }, 26 | 27 | step: function() { 28 | var time = (new Date).getTime(); 29 | var Tpos = (time - this.startTime) / (this.duration); 30 | if (time >= this.duration+this.startTime) { 31 | this.now = this.to; 32 | clearInterval (this.timer); 33 | this.timer = null; 34 | if (this.options.onComplete) setTimeout(this.options.onComplete.bind(this), 10); 35 | } 36 | else { 37 | this.now = ((-Math.cos(Tpos*Math.PI)/2) + 0.5) * (this.to-this.from) + this.from; 38 | //this time-position, sinoidal transition thing is from script.aculo.us 39 | } 40 | this.increase(); 41 | }, 42 | 43 | custom: function(from, to) { 44 | if (this.timer != null) return; 45 | this.from = from; 46 | this.to = to; 47 | this.go(); 48 | }, 49 | 50 | hide: function() { 51 | this.now = 0; 52 | this.increase(); 53 | }, 54 | 55 | clearTimer: function() { 56 | clearInterval(this.timer); 57 | this.timer = null; 58 | } 59 | } 60 | 61 | //stretchers 62 | fx.Layout = Class.create(); 63 | fx.Layout.prototype = Object.extend(new fx.Base(), { 64 | initialize: function(el, options) { 65 | this.el = $(el); 66 | this.el.style.overflow = "hidden"; 67 | this.el.iniWidth = this.el.offsetWidth; 68 | this.el.iniHeight = this.el.offsetHeight; 69 | this.setOptions(options); 70 | } 71 | }); 72 | 73 | fx.Height = Class.create(); 74 | Object.extend(Object.extend(fx.Height.prototype, fx.Layout.prototype), { 75 | increase: function() { 76 | this.el.style.height = this.now + "px"; 77 | }, 78 | 79 | toggle: function() { 80 | if (this.el.offsetHeight > 0) this.custom(this.el.offsetHeight, 0); 81 | else this.custom(0, this.el.scrollHeight); 82 | } 83 | }); 84 | -------------------------------------------------------------------------------- /user_guide/nav/nav.js: -------------------------------------------------------------------------------- 1 | function create_menu(basepath) 2 | { 3 | var base = (basepath == 'null') ? '' : basepath; 4 | 5 | document.write( 6 | '' + 7 | '
' + 8 | 9 | '

General

' + 10 | '' + 16 | 17 | '
' + 18 | '

Users

' + 19 | '' + 27 | '
' + 28 | '

Groups

' + 29 | '' + 35 | '
' + 36 | '

Roles

' + 37 | '' + 42 | 43 | '
'); 44 | } -------------------------------------------------------------------------------- /user_guide/nav/prototype.lite.js: -------------------------------------------------------------------------------- 1 | /* Prototype JavaScript framework 2 | * (c) 2005 Sam Stephenson 3 | * 4 | * Prototype is freely distributable under the terms of an MIT-style license. 5 | * 6 | * For details, see the Prototype web site: http://prototype.conio.net/ 7 | * 8 | /*--------------------------------------------------------------------------*/ 9 | 10 | 11 | //note: this is a stripped down version of prototype, to be used with moo.fx by mad4milk (http://moofx.mad4milk.net). 12 | 13 | var Class = { 14 | create: function() { 15 | return function() { 16 | this.initialize.apply(this, arguments); 17 | } 18 | } 19 | } 20 | 21 | Object.extend = function(destination, source) { 22 | for (property in source) { 23 | destination[property] = source[property]; 24 | } 25 | return destination; 26 | } 27 | 28 | Function.prototype.bind = function(object) { 29 | var __method = this; 30 | return function() { 31 | return __method.apply(object, arguments); 32 | } 33 | } 34 | 35 | function $() { 36 | var elements = new Array(); 37 | 38 | for (var i = 0; i < arguments.length; i++) { 39 | var element = arguments[i]; 40 | if (typeof element == 'string') 41 | element = document.getElementById(element); 42 | 43 | if (arguments.length == 1) 44 | return element; 45 | 46 | elements.push(element); 47 | } 48 | 49 | return elements; 50 | } 51 | 52 | //------------------------- 53 | 54 | document.getElementsByClassName = function(className) { 55 | var children = document.getElementsByTagName('*') || document.all; 56 | var elements = new Array(); 57 | 58 | for (var i = 0; i < children.length; i++) { 59 | var child = children[i]; 60 | var classNames = child.className.split(' '); 61 | for (var j = 0; j < classNames.length; j++) { 62 | if (classNames[j] == className) { 63 | elements.push(child); 64 | break; 65 | } 66 | } 67 | } 68 | 69 | return elements; 70 | } 71 | 72 | //------------------------- 73 | 74 | if (!window.Element) { 75 | var Element = new Object(); 76 | } 77 | 78 | Object.extend(Element, { 79 | remove: function(element) { 80 | element = $(element); 81 | element.parentNode.removeChild(element); 82 | }, 83 | 84 | hasClassName: function(element, className) { 85 | element = $(element); 86 | if (!element) 87 | return; 88 | var a = element.className.split(' '); 89 | for (var i = 0; i < a.length; i++) { 90 | if (a[i] == className) 91 | return true; 92 | } 93 | return false; 94 | }, 95 | 96 | addClassName: function(element, className) { 97 | element = $(element); 98 | Element.removeClassName(element, className); 99 | element.className += ' ' + className; 100 | }, 101 | 102 | removeClassName: function(element, className) { 103 | element = $(element); 104 | if (!element) 105 | return; 106 | var newClassName = ''; 107 | var a = element.className.split(' '); 108 | for (var i = 0; i < a.length; i++) { 109 | if (a[i] != className) { 110 | if (i > 0) 111 | newClassName += ' '; 112 | newClassName += a[i]; 113 | } 114 | } 115 | element.className = newClassName; 116 | }, 117 | 118 | // removes whitespace-only text node children 119 | cleanWhitespace: function(element) { 120 | element = $(element); 121 | for (var i = 0; i < element.childNodes.length; i++) { 122 | var node = element.childNodes[i]; 123 | if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) 124 | Element.remove(node); 125 | } 126 | } 127 | }); -------------------------------------------------------------------------------- /user_guide/nav/user_guide_menu.js: -------------------------------------------------------------------------------- 1 | window.onload = function() { 2 | myHeight = new fx.Height('nav', {duration: 400}); 3 | myHeight.hide(); 4 | } -------------------------------------------------------------------------------- /user_guide/roles/checking.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | BitAuth User Guide : Checking Roles 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 |

BitAuth User Guide Version 1.0

36 |
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 49 | 50 | 51 |
52 | 53 | 54 |
55 | 56 | 57 |
58 |

How does it work?

59 |

Users can be members of one or many groups. Roles are assigned to a group. When a user is a member of a group, he or she inherits all roles of that group. If a user is a member of multiple groups, he or she inherits all of the combined roles of those groups.

60 |

Checking Roles

61 | 62 |

$this->bitauth->has_role($slug, $mask = NULL)

63 |

Checks whether a user or group has a role. If $mask is NULL, the currently logged in user is assumed.

64 | 65 |

Checking the current user

66 |
if($this->bitauth->has_role('can_edit'))
 67 | {
 68 |     echo "Current user has 'can_edit' role.";
 69 | }
70 | 71 |

Checking another user

72 |
$user = $this->bitauth->get_user_by_username('testuser');
 73 | 
 74 | if($this->bitauth->has_role('can_edit', $user->roles))
 75 | {
 76 |     echo "User 'testuser' has the 'can_edit' role.";
 77 | }
78 | 79 |

Checking a group

80 |
$group = $this->bitauth->get_group_by_name('Test Group');
 81 | 
 82 | if($this->bitauth->has_role('can_edit', $group->roles))
 83 | {
 84 |     echo "Users in group 'Test Group' have the 'can_edit' role.";
 85 | }
86 | 87 |

$this->bitauth->is_admin($mask = NULL)

88 |

Check specifically for the administrator role. The $mask parameter of this function 89 | behaves exactly like it does in has_role().

90 |
if($this->bitauth->is_admin())
 91 | {
 92 |     echo 'Current user is an administrator.';
 93 | }
94 |
95 | 96 | 97 | 98 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /user_guide/roles/creating.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | BitAuth User Guide : Creating Roles 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 |

BitAuth User Guide Version 1.0

36 |
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 49 | 50 | 51 |
52 | 53 | 54 |
55 | 56 | 57 |
58 |

Creating Roles

59 |

Roles are created in the configuration file. What roles you choose are completely up to you, BitAuth only requires one: admin. 60 | The roles section of the configuration file looks like this:

61 |
/**
62 |  * Your roles. These are how you call permissions checks in your code.
63 |  * eg: if($this->bitauth->has_role('example_role'))
64 |  */
65 | $config['roles'] = array(
66 | 
67 | /**
68 |  * THE FIRST ROLE IS ALWAYS THE ADMINISTRATOR ROLE
69 |  * ANY USERS IN GROUPS GIVEN THIS ROLE WILL HAVE FULL ACCESS
70 |  */
71 | 	'admin'			=> 'User is an Administrator',
72 | /**
73 |  * Add as many roles here as you like.
74 |  * Follow the format:
75 |  * 'role_slug' => 'Role Description',
76 |  */
77 |  	
78 | );
79 | 80 |

Creating roles is as simple as adding new elements to this array:

81 |
'sample_role'  => 'This is a sample role',
82 | 83 |

The slug is how you check that role in your code. The description is how you describe that role in human-readable language.

84 | 85 |

You can add any number of roles you like in this format, as long as the first (admin) remains at the top of the list. You can change the slug and description of this role, the first on the list will always be treated as the administrator role. No matter what you change the slug to be, you can always check for this role with $this->bitauth->is_admin().

86 | 87 |
88 | 89 | 90 | 91 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /user_guide/roles/setting.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | BitAuth User Guide : Setting Roles 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 |

BitAuth User Guide Version 1.0

36 |
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 49 | 50 | 51 |
52 | 53 | 54 |
55 | 56 | 57 |
58 |

Setting Roles

59 |

Setting roles on a group is simple. All you need to do is set the roles attribute when adding or updating a group:

60 |

When Adding a Group

61 |
$group = array(
62 |     'name'        => 'Test Group',
63 |     'description' => 'This is a test group.',
64 |     'roles'       => array('new_role_1', 'new_role_2')
65 | );
66 | 
67 | $this->bitauth->add_group($group);
68 |

The example included in the BitAuth download gives an example of how to do this easily with an HTML form.

69 | 70 |

When Updating a Group

71 |
$group = $this->bitauth->get_group_by_name('Test Group');
72 | 
73 | $group->roles = array('new_role_1', 'new_role_2');
74 | $this->bitauth->update_group($group->group_id, $group);
75 | 76 |

Any changes you make to group roles are reflected in all members of that group the next time they log in.

77 |
78 | 79 | 80 | 81 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /user_guide/toc.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | BitAuth User Guide 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 | 32 | 33 | 34 |

BitAuth User Guide Version 1.0

35 |
36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 48 | 49 | 50 |
51 | 52 | 53 | 54 |
55 | 56 |

Table of Contents

57 | 58 | 59 | 70 | 83 | 93 | 103 | 104 |
60 | 61 |

General

62 | 68 | 69 |
71 | 72 |

Users

73 | 81 | 82 |
84 |

Groups

85 | 91 | 92 |
94 | 95 |

Roles

96 | 101 | 102 |
105 | 106 |
107 | 108 | 109 | 110 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /user_guide/userguide.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: Lucida Grande, Verdana, Geneva, Sans-serif; 5 | font-size: 14px; 6 | color: #333; 7 | background-color: #fff; 8 | } 9 | 10 | a { 11 | color: #0134c5; 12 | background-color: transparent; 13 | text-decoration: none; 14 | font-weight: normal; 15 | outline-style: none; 16 | } 17 | a:visited { 18 | color: #0134c5; 19 | background-color: transparent; 20 | text-decoration: none; 21 | outline-style: none; 22 | } 23 | a:hover { 24 | color: #000; 25 | text-decoration: none; 26 | background-color: transparent; 27 | outline-style: none; 28 | } 29 | 30 | #breadcrumb { 31 | float: left; 32 | background-color: transparent; 33 | margin: 10px 0 0 42px; 34 | padding: 0; 35 | font-size: 10px; 36 | color: #666; 37 | } 38 | #breadcrumb_right { 39 | float: right; 40 | width: 175px; 41 | background-color: transparent; 42 | padding: 8px 8px 3px 0; 43 | text-align: right; 44 | font-size: 10px; 45 | color: #666; 46 | } 47 | #nav { 48 | background-color: #494949; 49 | margin: 0; 50 | padding: 0; 51 | } 52 | #nav2 { 53 | background: #fff url(images/nav_bg_darker.jpg) repeat-x left top; 54 | padding: 0 310px 0 0; 55 | margin: 0; 56 | text-align: right; 57 | } 58 | #nav_inner { 59 | background-color: transparent; 60 | padding: 8px 12px 0 20px; 61 | margin: 0; 62 | font-family: Lucida Grande, Verdana, Geneva, Sans-serif; 63 | font-size: 11px; 64 | } 65 | 66 | #nav_inner h3 { 67 | font-size: 12px; 68 | color: #fff; 69 | margin: 0; 70 | padding: 0; 71 | } 72 | 73 | #nav_inner .td_sep { 74 | background: transparent url(images/nav_separator_darker.jpg) repeat-y left top; 75 | width: 25%; 76 | padding: 0 0 0 20px; 77 | } 78 | #nav_inner .td { 79 | width: 25%; 80 | } 81 | #nav_inner p { 82 | color: #eee; 83 | background-color: transparent; 84 | padding:0; 85 | margin: 0 0 10px 0; 86 | } 87 | #nav_inner ul { 88 | list-style-image: url(images/arrow.gif); 89 | padding: 0 0 0 18px; 90 | margin: 8px 0 12px 0; 91 | } 92 | #nav_inner li { 93 | padding: 0; 94 | margin: 0 0 4px 0; 95 | } 96 | 97 | #nav_inner a { 98 | color: #eee; 99 | background-color: transparent; 100 | text-decoration: none; 101 | font-weight: normal; 102 | outline-style: none; 103 | } 104 | 105 | #nav_inner a:visited { 106 | color: #eee; 107 | background-color: transparent; 108 | text-decoration: none; 109 | outline-style: none; 110 | } 111 | 112 | #nav_inner a:hover { 113 | color: #ccc; 114 | text-decoration: none; 115 | background-color: transparent; 116 | outline-style: none; 117 | } 118 | 119 | #masthead { 120 | margin: 0 40px 0 35px; 121 | padding: 0 0 0 6px; 122 | border-bottom: 1px solid #999; 123 | } 124 | 125 | #masthead h1 { 126 | background-color: transparent; 127 | color: #e13300; 128 | font-size: 18px; 129 | font-weight: normal; 130 | margin: 0; 131 | padding: 0 0 6px 0; 132 | } 133 | 134 | #searchbox { 135 | background-color: transparent; 136 | padding: 6px 40px 0 0; 137 | text-align: right; 138 | font-size: 10px; 139 | color: #666; 140 | } 141 | 142 | #img_welcome { 143 | border-bottom: 1px solid #D0D0D0; 144 | margin: 0 40px 0 40px; 145 | padding: 0; 146 | text-align: center; 147 | } 148 | 149 | #content { 150 | margin: 20px 40px 0 40px; 151 | padding: 0; 152 | } 153 | 154 | #content p { 155 | margin: 12px 20px 12px 0; 156 | } 157 | 158 | #content h1 { 159 | color: #e13300; 160 | border-bottom: 1px solid #666; 161 | background-color: transparent; 162 | font-weight: normal; 163 | font-size: 24px; 164 | margin: 0 0 20px 0; 165 | padding: 3px 0 7px 3px; 166 | } 167 | 168 | #content h2 { 169 | background-color: transparent; 170 | border-bottom: 1px solid #999; 171 | color: #000; 172 | font-size: 18px; 173 | font-weight: bold; 174 | margin: 28px 0 16px 0; 175 | padding: 5px 0 6px 0; 176 | } 177 | 178 | #content h3 { 179 | background-color: transparent; 180 | color: #333; 181 | font-size: 16px; 182 | font-weight: bold; 183 | margin: 16px 0 15px 0; 184 | padding: 0 0 0 0; 185 | } 186 | 187 | #content h4 { 188 | background-color: transparent; 189 | color: #444; 190 | font-size: 14px; 191 | font-weight: bold; 192 | margin: 22px 0 0 0; 193 | padding: 0 0 0 0; 194 | } 195 | 196 | #content img { 197 | margin: auto; 198 | padding: 0; 199 | } 200 | 201 | #content code { 202 | font-family: Monaco, Verdana, Sans-serif; 203 | font-size: 12px; 204 | background-color: #f9f9f9; 205 | border: 1px solid #D0D0D0; 206 | color: #002166; 207 | display: block; 208 | margin: 14px 0 14px 0; 209 | padding: 12px 10px 12px 10px; 210 | } 211 | 212 | #content pre { 213 | font-family: Consolas, "Courier New", monospace; 214 | font-size: 12px; 215 | background-color: #f9f9f9; 216 | border: 1px solid #D0D0D0; 217 | color: #002166; 218 | display: block; 219 | margin: 14px 0 14px 0; 220 | padding: 12px 10px 12px 10px; 221 | } 222 | 223 | #content .path { 224 | background-color: #EBF3EC; 225 | border: 1px solid #99BC99; 226 | color: #005702; 227 | text-align: center; 228 | margin: 0 0 14px 0; 229 | padding: 5px 10px 5px 8px; 230 | } 231 | 232 | #content dfn { 233 | font-family: Lucida Grande, Verdana, Geneva, Sans-serif; 234 | color: #00620C; 235 | font-weight: bold; 236 | font-style: normal; 237 | } 238 | #content var { 239 | font-family: Lucida Grande, Verdana, Geneva, Sans-serif; 240 | color: #8F5B00; 241 | font-weight: bold; 242 | font-style: normal; 243 | } 244 | #content samp { 245 | font-family: Lucida Grande, Verdana, Geneva, Sans-serif; 246 | color: #480091; 247 | font-weight: bold; 248 | font-style: normal; 249 | } 250 | #content kbd { 251 | font-family: Lucida Grande, Verdana, Geneva, Sans-serif; 252 | color: #A70000; 253 | font-weight: bold; 254 | font-style: normal; 255 | } 256 | 257 | #content ul { 258 | list-style-image: url(images/arrow.gif); 259 | margin: 10px 0 12px 0; 260 | } 261 | 262 | li.reactor { 263 | list-style-image: url(images/reactor-bullet.png); 264 | } 265 | #content li { 266 | margin-bottom: 9px; 267 | } 268 | 269 | #content li p { 270 | margin-left: 0; 271 | margin-right: 0; 272 | } 273 | 274 | #content .tableborder { 275 | border: 1px solid #999; 276 | } 277 | #content th { 278 | font-weight: bold; 279 | text-align: left; 280 | font-size: 12px; 281 | background-color: #666; 282 | color: #fff; 283 | padding: 4px; 284 | } 285 | 286 | #content .td { 287 | font-weight: normal; 288 | font-size: 12px; 289 | padding: 6px; 290 | background-color: #f3f3f3; 291 | } 292 | 293 | #content .tdpackage { 294 | font-weight: normal; 295 | font-size: 12px; 296 | } 297 | 298 | #content .important { 299 | background: #FBE6F2; 300 | border: 1px solid #D893A1; 301 | color: #333; 302 | margin: 10px 0 5px 0; 303 | padding: 10px; 304 | } 305 | 306 | #content .important p { 307 | margin: 6px 0 8px 0; 308 | padding: 0; 309 | } 310 | 311 | #content .important .leftpad { 312 | margin: 6px 0 8px 0; 313 | padding-left: 20px; 314 | } 315 | 316 | #content .critical { 317 | background: #FBE6F2; 318 | border: 1px solid #E68F8F; 319 | color: #333; 320 | margin: 10px 0 5px 0; 321 | padding: 10px; 322 | } 323 | 324 | #content .critical p { 325 | margin: 5px 0 6px 0; 326 | padding: 0; 327 | } 328 | 329 | 330 | #footer { 331 | background-color: transparent; 332 | font-size: 10px; 333 | padding: 16px 0 15px 0; 334 | margin: 20px 0 0 0; 335 | text-align: center; 336 | } 337 | 338 | #footer p { 339 | font-size: 10px; 340 | color: #999; 341 | text-align: center; 342 | } 343 | #footer address { 344 | font-style: normal; 345 | } 346 | 347 | .center { 348 | text-align: center; 349 | } 350 | 351 | img { 352 | padding:0; 353 | border: 0; 354 | margin: 0; 355 | } 356 | 357 | .nopad { 358 | padding:0; 359 | border: 0; 360 | margin: 0; 361 | } 362 | 363 | 364 | form { 365 | margin: 0; 366 | padding: 0; 367 | } 368 | 369 | .input { 370 | font-family: Lucida Grande, Verdana, Geneva, Sans-serif; 371 | font-size: 11px; 372 | color: #333; 373 | border: 1px solid #B3B4BD; 374 | width: 100%; 375 | font-size: 11px; 376 | height: 1.5em; 377 | padding: 0; 378 | margin: 0; 379 | } 380 | 381 | .textarea { 382 | font-family: Lucida Grande, Verdana, Geneva, Sans-serif; 383 | font-size: 14px; 384 | color: #143270; 385 | background-color: #f9f9f9; 386 | border: 1px solid #B3B4BD; 387 | width: 100%; 388 | padding: 6px; 389 | margin: 0; 390 | } 391 | 392 | .select { 393 | background-color: #fff; 394 | font-size: 11px; 395 | font-weight: normal; 396 | color: #333; 397 | padding: 0; 398 | margin: 0 0 3px 0; 399 | } 400 | 401 | .checkbox { 402 | background-color: transparent; 403 | padding: 0; 404 | border: 0; 405 | } 406 | 407 | .submit { 408 | background-color: #000; 409 | color: #fff; 410 | font-weight: normal; 411 | font-size: 10px; 412 | border: 1px solid #fff; 413 | margin: 0; 414 | padding: 1px 5px 2px 5px; 415 | } -------------------------------------------------------------------------------- /user_guide/users/adding.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | BitAuth User Guide : Adding Users 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 |

BitAuth User Guide Version 1.0

36 |
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 49 | 50 | 51 |
52 | 53 | 54 |
55 | 56 | 57 |
58 |

Adding Users

59 |

When adding a user, there are two required fields: username and password. The password must be given 60 | in clear text. BitAuth will handle the password hashing.

61 |

If you have customized user data, you only need to pass these fields to add_user() with all 62 | of the other data, BitAuth will put them in the appropriate table.

63 |

$this->bitauth->add_user($data, $require_activation = NULL)

64 |
$user = array(
 65 |     'username' => 'testuser',
 66 |     'password' => 'ABC123!'
 67 | );
 68 | 
 69 | $this->bitauth->add_user($user);
70 | 71 |

If you don't specify a groups attribute, the configuration value of default_group_id is used. 72 | For information about adding users to groups, see Assigning Groups or Adding Members.

73 |

$require_activation defaults to the configuration value of require_user_activation. 74 | How you handle user activation is completely up to you. If this value is TRUE, an activation code is generated and stored in the 75 | activation_code field.

76 |
$user = $this->bitauth->get_user_by_id(2);
 77 | 
 78 | if($user->active == FALSE)
 79 | {
 80 |     echo $user->activation_code;
 81 | }
82 | 83 |

Adding Password Complexity Rules

84 |

In order to add your own password complexity rules, you need to make 3 changes.

85 |

In config/bitauth.php, you need to add a line to both $config['pwd_complexity'] and $config['pwd_complexity_chars']. pwd_complexity contains the required number of characters, and pwd_complexity_chars contains the regular expression to check for those characters.

86 |
/**
 87 |  * Optional password complexity options. Set a number for each to
 88 |  * require that many characters, or set to 0 to disable
 89 |  * Default: 1, 1, 0, 0
 90 |  */
 91 | $config['pwd_complexity'] = array(
 92 | 	'uppercase' => 1,
 93 | 	'number' => 1,
 94 | 	'special' => 0,
 95 | 	'spaces' => 0,
 96 | 	'dash' => 1
 97 | );
 98 | 
 99 | /**
100 |  * Which characters are included in each complexity check. Must be in
101 |  * regex-friendly format. Using the Posix Collating Sequences should make these
102 |  * language-independent, but are here in case you want to change them.
103 |  */
104 | $config['pwd_complexity_chars'] = array(
105 | 	'uppercase' => '[[:upper:]]',
106 | 	'number' => '[[:digit:]]',
107 | 	'special' => '[[:punct:]]',
108 | 	'spaces' => '\s',
109 | 	'dash' => '-'
110 | );
111 | 112 |

Then, you just need to add a line to language/english/bitauth_lang.php, which contains the language line called when the rule fails validation.

113 |
/**
114 |  * Password Complexity Labels
115 |  */
116 | $lang['bitauth_pwd_uppercase']    = 'Uppercase Letters';
117 | $lang['bitauth_pwd_number']       = 'Numbers';
118 | $lang['bitauth_pwd_special']      = 'Special Characters';
119 | $lang['bitauth_pwd_spaces']       = 'Spaces';
120 | $lang['bitauth_pwd_dash']	  = 'Dashes';
121 | 
122 | 
123 | 124 | 125 | 126 | 129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /user_guide/users/assigning.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | BitAuth User Guide : Assigning Groups 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 |

BitAuth User Guide Version 1.0

36 |
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 49 | 50 | 51 |
52 | 53 | 54 |
55 | 56 | 57 |
58 |

Assigning Groups

59 |

Assigning a user to one or more groups is as simple as passing an array of group_ids to that user when adding or updating.

60 |

When Adding a User

61 |

When adding a user, you can pass an array of group_ids for that user to be added to. If you don't, the user will be added to 62 | whatever you have specified in the configuration file as default_group_id.

63 |
$user = array(
64 |     'username' => 'testuser',
65 |     'password' => 'ABC123!',
66 |     'groups'   => array(2,5,7)
67 | );
68 | 
69 | $this->bitauth->add_user($user);
70 |

When Updating a User

71 |

When updating a user, the same applies. What groups the user is a member of are passed as an array to update_user().

72 |
$user = $this->bitauth->get_user_by_username('testuser');
73 | 
74 | $user->groups = array(2,5,7);
75 | $this->bitauth->update_user($user->user_id, $user);
76 |
77 | 78 | 79 | 80 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /user_guide/users/customizing.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | BitAuth User Guide : Customizing User Data 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 |

BitAuth User Guide Version 1.0

36 |
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 49 | 50 | 51 |
52 | 53 | 54 |
55 | 56 | 57 |
58 |

Customizing User Data

59 |

BitAuth has a number of required fields, and they are all in the users table (default: bitauth_users). 60 | Anything in the data (default: bitauth_userdata) table is optional, and you can customize this table 61 | to include anything you like. This table will only be updated when data is passed to add_user() or update_user() 62 | that is not found in the users table.

63 |

To include custom user data in BitAuth, all you need to do is update the structure of bitauth_userdata with your new fields, 64 | then pass data for those new fields to add_user() and update_user(). That's it! BitAuth determines which table 65 | the data given to it belongs to, and it will insert or update the appropriate table. Also, just by being in the userdata table, your 66 | custom data will be included with the user object that is returned when fetching users.

67 |

For example, if you add the column mydata to the userdata table, you can access that attribute easily with:

68 |
$user = $this->bitauth->get_user_by_id(2);
69 | 
70 | echo $user->mydata;
71 |

You can also set that column when adding or updating just like any other column:

72 |
$user = array(
73 |     'username' => 'testuser',
74 |     'password' => 'ABC123!',
75 |     'groups'   => array(2,5,7),
76 |     'mydata'   => 'This is my data!'
77 | );
78 | 
79 | $this->bitauth->add_user($user);
80 |
81 | 82 | 83 | 84 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /user_guide/users/editing.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | BitAuth User Guide : Editing Users 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 |

BitAuth User Guide Version 1.0

36 |
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 49 | 50 | 51 |
52 | 53 | 54 |
55 | 56 | 57 |
58 |

Editing Users

59 |

Editing a user is as simple as passing a user_id and the user data to update_user(). $data may be an object or an array. 60 | Only the information you give is updated, and what information you do give overwrites what is currently stored. Just like with add_user(), 61 | BitAuth is able to determine whether the information you are updating is in the users table or the data table.

62 |

$this->bitauth->update_user($user_id, $data)

63 |

A good example of how this works is found in $this->bitauth->activate(): 64 |

/**
 65 |  * Bitauth::activate()
 66 |  *
 67 |  */
 68 | public function activate($activation_code)
 69 | {
 70 |     $query = $this->db->where('activation_code', $activation_code)->get($this->_table['users']);
 71 |     if($query && $query->num_rows())
 72 |     {
 73 |         $user = $query->row();
 74 |         return $this->update_user($user->user_id, array('active' => 1, 'activation_code' => ''));
 75 |     }
 76 | 
 77 |     return FALSE;
 78 | }
79 |

This can be combined with Fetching Users to quickly and easily update user information:

80 |
$user = $this->bitauth->get_user_by_username('testuser');
 81 | 
 82 | // Remove user from all groups
 83 | $user->groups = array();
 84 | $this->bitauth->update_user($user->user_id, $user);
85 |

For a list of all user fields, see Fetching Users.

86 |

Disabling/Deleting Users

87 |

Users who are disabled will not be able to login, are removed from all groups, and aren't returned by get_users() or get_groups() 88 | (see Fetching Users for information on overriding this).

89 |

Users who are deleted, in addition to being disabled, also have their corresponding row deleted in the data table (bitauth_userdata). 90 | Essential information (user_id and username) should be kept for posterity.

91 |

$this->bitauth->enable($user_id)

92 |

Enables a user:

93 |
$this->bitauth->enable(2);
94 | 95 |

$this->bitauth->disable($user_id)

96 |

Disables a user:

97 |
$this->bitauth->disable(2);
98 | 99 |

$this->bitauth->delete($user_id)

100 |

Deletes a user:

101 |
$this->bitauth->delete(2);
102 | 103 |
104 | 105 | 106 | 107 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /user_guide/users/fetching.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | BitAuth User Guide : Fetching Users 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 |

BitAuth User Guide Version 1.0

36 |
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 49 | 50 | 51 |
52 | 53 | 54 |
55 | 56 | 57 |
58 |

Fetching Users

59 |

User Fields

60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 |
FieldDescription
user_idUnique User ID
usernameUnique Username
passwordHashed password
password_last_setTimestamp of when the user's password was last set
password_never_expiresBoolean value, set to TRUE and the user's password will never expire.
remember_me"Remember Me" token, if the user has a currently active "remember me" login
activation_codeRandom hash for activation code, if this option is enabled in the configuration
activeWhether user is active or not
enabledWhether user is enabled or not. If FALSE, user will not show up by default in any queries for fetching users
last_loginTimestamp of when the user last logged in
last_login_ipIP the user last logged in from
groupsArray of group_ids the user is a member of
rolesNumeric representation of the user's inherited roles. You cannot set this value directly on the user.
118 |

Along with all of this information, any custom user data you may have is also returned. You can access and edit this information exactly as you would any other user information.

119 | 120 |

$this->bitauth->get_users($include_disabled = FALSE)

121 |

Returns all users. Each user object contains the information listed above. By default, any users with enabled = 0 will be excluded. 122 | Pass TRUE as the second parameter to override this. For information on disabled/deleted users see Disabling/Deleting Users.

123 | 124 |
$all_users = $this->bitauth->get_users();
125 | 
126 | foreach($all_users as $user)
127 | {
128 |     echo $user->username.'<br/>';
129 | }
130 | 131 |

For information on checking a user's roles, see Checking Roles.
132 | For information on customizing user data, see Customizing User Data.

133 | 134 |

$this->bitauth->get_user_by_id($user_id, $include_disabled = FALSE)

135 |

Returns an object with the same information as get_users() for one user, by user_id. Returns FALSE on failure.

136 |
$user = $this->bitauth->get_user_by_id(1);
137 | 
138 | if($user == FALSE)
139 | {
140 |     echo 'User Not Found';
141 | }
142 | else
143 | {
144 |     echo 'Username: '.$user->username;
145 | }
146 |

$this->bitauth->get_user_by_username($username, $include_disabled = FALSE)

147 |

Returns an object with the same information as get_users() for one user, by username. $username is case-insensitive. Returns FALSE on failure.

148 | 149 |

$this->bitauth->get_user_by_activation_code($activation_code)

150 |

Fetches a user by activation code, called by activate().

151 | 152 |

$this->bitauth->get_user_by_forgot_code($forgot_code)

153 |

Fetches a user by forgot password code. If the code has expired, it is removed and FALSE is returned.

154 |
155 | 156 | 157 | 158 | 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /user_guide/users/logging_in.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | BitAuth User Guide : Logging In/Logging Out 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 |

BitAuth User Guide Version 1.0

36 |
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 49 | 50 | 51 |
52 | 53 | 54 |
55 | 56 | 57 |
58 |

Logging In/Logging Out

59 |

$this->bitauth->logged_in()

60 |

Returns TRUE if a user is currently logged in, FALSE if not.

61 |
if( ! $this->bitauth->logged_in())
 62 | {
 63 |     // Save current URL for redirect after successful login
 64 |     $this->session->set_userdata('redir', current_url());
 65 | 
 66 |     // Redirect to login form
 67 |     redirect('path/to/login_form');
 68 | }
69 | 70 |

$this->bitauth->login($username, $password, $remember = FALSE, $extra = array())

71 |

Tries to authenticate the user, and sets the "Remember Me" token if appropriate. Returns FALSE and sets an error message retrieved with get_error() if authentication fails. The following code is from the example that comes with BitAuth:

72 |
$username = $this->input->post('username');
 73 | $password = $this->input->post('password');
 74 | $remember_me = $this->input->post('remember_me');
 75 | 
 76 | if($this->bitauth->login($username, $password, $remember_me))
 77 | {
 78 |     // Redirect
 79 |     if($redir = $this->session->userdata('redir'))
 80 |     {
 81 |         $this->session->unset_userdata('redir');
 82 |     }
 83 | 
 84 |     redirect($redir ? $redir : 'bitauth_example');
 85 | }
 86 | else
 87 | {
 88 |     $data['error'] = $this->bitauth->get_error();
 89 | }
90 |

Once logged in, all userdata for the user is assigned directly to the BitAuth object in the same manner as get_users(), 91 | with the exception of the password:

92 |
echo $this->bitauth->username;
93 |

For information on all of the available fields, see Fetching Users.

94 | 95 |

Requiring Additional Login Fields

96 |

Username is always required. You can, however, add any number of additional fields which will be checked at login. This is a 2-step process. First, you must tell BitAuth to expect the field(s):

97 |
$this->bitauth->add_login_field('email');
98 |

Once this is done, you simply have to pass the data to login() as an associative array. So, we would update our earlier example:

99 |
$username = $this->input->post('username');
100 | $password = $this->input->post('password');
101 | $remember_me = $this->input->post('remember_me');
102 | $extra = array('email' => $this->input->post('email'));
103 | 
104 | $this->bitauth->add_login_field('email');
105 | 
106 | if($this->bitauth->login($username, $password, $remember_me, $extra))
107 | {
108 |     // Redirect
109 |     if($redir = $this->session->userdata('redir'))
110 |     {
111 |         $this->session->unset_userdata('redir');
112 |     }
113 | 
114 |     redirect($redir ? $redir : 'bitauth_example');
115 | }
116 | else
117 | {
118 |     $data['error'] = $this->bitauth->get_error();
119 | }
120 |

In order to get an error message for these fields if they fail validation, you must add a line to the language file, bitauth_invalid_{field} (ie, bitauth_invalid_email).

121 |
$lang['bitauth_invalid_email'] = 'Email does not match this username';
122 |

This function also accepts an array for multiple fields:

123 |
$this->bitauth->add_login_field(array('email', 'pin'));
124 |

Logging in with something besides username

125 |

To login with something besides username; to use email as a username, for example, simply change the bitauth_username line in the language file to whatever label you like, 126 | and setup the form_validation for your login form appropriately.

127 | 128 |

$this->bitauth->login_from_token()

129 |

If a valid "Remember Me" token is found, but not an active login, BitAuth will try to login from that token. If the login is invalid, the token is destroyed. This can be seen in BitAuth's __construct():

130 |
if($this->logged_in())
131 | {
132 |     $this->get_session_values();
133 | }
134 | else if($this->input->cookie($this->_remember_token_name))
135 | {
136 |     $this->login_from_token();
137 | }
138 | 139 |

$this->bitauth->logout()

140 |

Destroys the session, deletes the "Remember Me" token if one exists, and updates the users table to clear the "remember me" token there as well.

141 | 142 |

$this->bitauth->delete_remember_token()

143 |

Called by $this->bitauth->logout(), deletes the "Remember Me" token and updates the users table as described above.

144 | 145 |

$this->bitauth->password_almost_expired($user = NULL)

146 |

Returns TRUE if the user is within pwd_max_age days of the maximum password age config setting. If no $user 147 | is given, the currently logged in user is assumed.

148 | 149 |

$this->bitauth->password_is_expired($user = NULL)

150 |

Returns TRUE if the user's password is expired. If no $user is given, the currently logged in user is assumed.

151 | 152 |
153 | 154 | 155 | 156 | 159 | 160 | 161 | 162 | --------------------------------------------------------------------------------