Changeset 3730:5c45a5df9a59 for inc/core/class.dc.auth.php
- Timestamp:
- 03/08/18 17:58:39 (8 years ago)
- Branch:
- default
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
inc/core/class.dc.auth.php
r3627 r3730 10 10 # 11 11 # -- END LICENSE BLOCK ----------------------------------------- 12 if (!defined('DC_RC_PATH')) { return;}12 if (!defined('DC_RC_PATH')) {return;} 13 13 14 14 /** 15 * @ingroup DC_CORE16 * @nosubgrouping17 * @brief Authentication and user credentials management18 *19 * dcAuth is a class used to handle everything related to user authentication20 * and credentials. Object is provided by dcCore $auth property.21 */15 * @ingroup DC_CORE 16 * @nosubgrouping 17 * @brief Authentication and user credentials management 18 * 19 * dcAuth is a class used to handle everything related to user authentication 20 * and credentials. Object is provided by dcCore $auth property. 21 */ 22 22 class dcAuth 23 23 { 24 /** @var dcCore dcCore instance */ 25 protected $core; 26 /** @var connection Database connection object */ 27 protected $con; 28 29 /** @var string User table name */ 30 protected $user_table; 31 /** @var string Perm table name */ 32 protected $perm_table; 33 34 /** @var string Current user ID */ 35 protected $user_id; 36 /** @var array Array with user information */ 37 protected $user_info = array(); 38 /** @var array Array with user options */ 39 protected $user_options = array(); 40 /** @var boolean User must change his password after login */ 41 protected $user_change_pwd; 42 /** @var boolean User is super admin */ 43 protected $user_admin; 44 /** @var array Permissions for each blog */ 45 protected $permissions = array(); 46 /** @var boolean User can change its password */ 47 protected $allow_pass_change = true; 48 /** @var array List of blogs on which the user has permissions */ 49 protected $blogs = array(); 50 /** @var integer Count of user blogs */ 51 public $blog_count = null; 52 53 /** @var array Permission types */ 54 protected $perm_types; 55 56 /** @var dcPrefs dcPrefs object */ 57 public $user_prefs; 58 59 /** 60 * Class constructor. Takes dcCore object as single argument. 61 * 62 * @param dcCore $core dcCore object 63 */ 64 public function __construct($core) 65 { 66 $this->core =& $core; 67 $this->con =& $core->con; 68 $this->blog_table = $core->prefix.'blog'; 69 $this->user_table = $core->prefix.'user'; 70 $this->perm_table = $core->prefix.'permissions'; 71 72 $this->perm_types = array( 73 'admin' => __('administrator'), 74 'usage' => __('manage their own entries and comments'), 75 'publish' => __('publish entries and comments'), 76 'delete' => __('delete entries and comments'), 77 'contentadmin' => __('manage all entries and comments'), 78 'categories' => __('manage categories'), 79 'media' => __('manage their own media items'), 80 'media_admin' => __('manage all media items') 81 ); 82 } 83 84 /// @name Credentials and user permissions 85 //@{ 86 /** 87 * Checks if user exists and can log in. <var>$pwd</var> argument is optionnal 88 * while you may need to check user without password. This method will create 89 * credentials and populate all needed object properties. 90 * 91 * @param string $user_id User ID 92 * @param string $pwd User password 93 * @param string $user_key User key check 94 * @param boolean $check_blog checks if user is associated to a blog or not. 95 * @return boolean 96 */ 97 public function checkUser($user_id, $pwd=null, $user_key=null, $check_blog=true) 98 { 99 # Check user and password 100 $strReq = 'SELECT user_id, user_super, user_pwd, user_change_pwd, '. 101 'user_name, user_firstname, user_displayname, user_email, '. 102 'user_url, user_default_blog, user_options, '. 103 'user_lang, user_tz, user_post_status, user_creadt, user_upddt '. 104 'FROM '.$this->con->escapeSystem($this->user_table).' '. 105 "WHERE user_id = '".$this->con->escape($user_id)."' "; 106 107 try { 108 $rs = $this->con->select($strReq); 109 } catch (Exception $e) { 110 $err = $e->getMessage(); 111 return false; 112 } 113 114 if ($rs->isEmpty()) { 115 sleep(rand(2,5)); 116 return false; 117 } 118 119 $rs->extend('rsExtUser'); 120 121 if ($pwd != '') 122 { 123 $rehash = false; 124 if (password_verify($pwd,$rs->user_pwd)) { 125 // User password ok 126 if (password_needs_rehash($rs->user_pwd,PASSWORD_DEFAULT)) { 127 $rs->user_pwd = $this->crypt($pwd); 128 $rehash = true; 129 } 130 } else { 131 // Check if pwd still stored in old fashion way 132 $ret = password_get_info($rs->user_pwd); 133 if (is_array($ret) && isset($ret['algo']) && $ret['algo'] == 0) { 134 // hash not done with password_hash() function, check by old fashion way 135 if (crypt::hmac(DC_MASTER_KEY,$pwd,DC_CRYPT_ALGO) == $rs->user_pwd) { 136 // Password Ok, need to store it in new fashion way 137 $rs->user_pwd = $this->crypt($pwd); 138 $rehash = true; 139 } else { 140 // Password KO 141 sleep(rand(2,5)); 142 return false; 143 } 144 } else { 145 // Password KO 146 sleep(rand(2,5)); 147 return false; 148 } 149 } 150 if ($rehash) { 151 // Store new hash in DB 152 $cur = $this->con->openCursor($this->user_table); 153 $cur->user_pwd = (string) $rs->user_pwd; 154 $cur->update("WHERE user_id = '".$rs->user_id."'"); 155 } 156 } 157 elseif ($user_key != '') 158 { 159 if (http::browserUID(DC_MASTER_KEY.$rs->user_id.$this->cryptLegacy($rs->user_id)) != $user_key) { 160 return false; 161 } 162 } 163 164 $this->user_id = $rs->user_id; 165 $this->user_change_pwd = (boolean) $rs->user_change_pwd; 166 $this->user_admin = (boolean) $rs->user_super; 167 168 $this->user_info['user_pwd'] = $rs->user_pwd; 169 $this->user_info['user_name'] = $rs->user_name; 170 $this->user_info['user_firstname'] = $rs->user_firstname; 171 $this->user_info['user_displayname'] = $rs->user_displayname; 172 $this->user_info['user_email'] = $rs->user_email; 173 $this->user_info['user_url'] = $rs->user_url; 174 $this->user_info['user_default_blog'] = $rs->user_default_blog; 175 $this->user_info['user_lang'] = $rs->user_lang; 176 $this->user_info['user_tz'] = $rs->user_tz; 177 $this->user_info['user_post_status'] = $rs->user_post_status; 178 $this->user_info['user_creadt'] = $rs->user_creadt; 179 $this->user_info['user_upddt'] = $rs->user_upddt; 180 181 $this->user_info['user_cn'] = dcUtils::getUserCN($rs->user_id, $rs->user_name, 182 $rs->user_firstname, $rs->user_displayname); 183 184 $this->user_options = array_merge($this->core->userDefaults(),$rs->options()); 185 186 $this->user_prefs = new dcPrefs($this->core,$this->user_id); 187 188 # Get permissions on blogs 189 if ($check_blog && ($this->findUserBlog() === false)) { 190 return false; 191 } 192 return true; 193 } 194 195 /** 196 * This method crypt given string (password, session_id, …). 197 * 198 * @param string $pwd string to be crypted 199 * @return string crypted value 200 */ 201 public function crypt($pwd) 202 { 203 return password_hash($pwd,PASSWORD_DEFAULT); 204 } 205 206 /** 207 * This method crypt given string (password, session_id, …). 208 * 209 * @param string $pwd string to be crypted 210 * @return string crypted value 211 */ 212 public function cryptLegacy($pwd) 213 { 214 return crypt::hmac(DC_MASTER_KEY,$pwd,DC_CRYPT_ALGO); 215 } 216 217 /** 218 * This method only check current user password. 219 * 220 * @param string $pwd User password 221 * @return boolean 222 */ 223 public function checkPassword($pwd) 224 { 225 if (!empty($this->user_info['user_pwd'])) { 226 return password_verify($pwd,$this->user_info['user_pwd']); 227 } 228 229 return false; 230 } 231 232 /** 233 * This method checks if user session cookie exists 234 * 235 * @return boolean 236 */ 237 public function sessionExists() 238 { 239 return isset($_COOKIE[DC_SESSION_NAME]); 240 } 241 242 /** 243 * This method checks user session validity. 244 * 245 * @return boolean 246 */ 247 public function checkSession($uid=null) 248 { 249 $this->core->session->start(); 250 251 # If session does not exist, logout. 252 if (!isset($_SESSION['sess_user_id'])) { 253 $this->core->session->destroy(); 254 return false; 255 } 256 257 # Check here for user and IP address 258 $this->checkUser($_SESSION['sess_user_id']); 259 $uid = $uid ?: http::browserUID(DC_MASTER_KEY); 260 261 $user_can_log = $this->userID() !== null && $uid == $_SESSION['sess_browser_uid']; 262 263 if (!$user_can_log) { 264 $this->core->session->destroy(); 265 return false; 266 } 267 268 return true; 269 } 270 271 /** 272 * Checks if user must change his password in order to login. 273 * 274 * @return boolean 275 */ 276 public function mustChangePassword() 277 { 278 return $this->user_change_pwd; 279 } 280 281 /** 282 * Checks if user is super admin 283 * 284 * @return boolean 285 */ 286 public function isSuperAdmin() 287 { 288 return $this->user_admin; 289 } 290 291 /** 292 * Checks if user has permissions given in <var>$permissions</var> for blog 293 * <var>$blog_id</var>. <var>$permissions</var> is a coma separated list of 294 * permissions. 295 * 296 * @param string $permissions Permissions list 297 * @param string $blog_id Blog ID 298 * @return boolean 299 */ 300 public function check($permissions,$blog_id) 301 { 302 if ($this->user_admin) { 303 return true; 304 } 305 306 $p = array_map('trim',explode(',',$permissions)); 307 $b = $this->getPermissions($blog_id); 308 309 if ($b != false) 310 { 311 if (isset($b['admin'])) { 312 return true; 313 } 314 315 foreach ($p as $v) 316 { 317 if (isset($b[$v])) { 318 return true; 319 } 320 } 321 } 322 323 return false; 324 } 325 326 /** 327 * Returns true if user is allowed to change its password. 328 * 329 * @return boolean 330 */ 331 public function allowPassChange() 332 { 333 return $this->allow_pass_change; 334 } 335 //@} 336 337 /// @name User code handlers 338 //@{ 339 public function getUserCode() 340 { 341 $code = 342 pack('a32',$this->userID()). 343 pack('H*',$this->crypt($this->getInfo('user_pwd'))); 344 return bin2hex($code); 345 } 346 347 public function checkUserCode($code) 348 { 349 $code = @pack('H*',$code); 350 351 $user_id = trim(@pack('a32',substr($code,0,32))); 352 $pwd = @unpack('H*hex',substr($code,32)); 353 354 if ($user_id === false || $pwd === false) { 355 return false; 356 } 357 358 $pwd = $pwd['hex']; 359 360 $strReq = 'SELECT user_id, user_pwd '. 361 'FROM '.$this->user_table.' '. 362 "WHERE user_id = '".$this->con->escape($user_id)."' "; 363 364 $rs = $this->con->select($strReq); 365 366 if ($rs->isEmpty()) { 367 return false; 368 } 369 370 if ($this->crypt($rs->user_pwd) != $pwd) { 371 return false; 372 } 373 374 return $rs->user_id; 375 } 376 //@} 377 378 379 /// @name Sudo 380 //@{ 381 /** 382 * Calls $f function with super admin rights. 383 * Returns the function result. 384 * 385 * @param callback $f Callback function 386 * @return mixed 387 */ 388 public function sudo($f) 389 { 390 if (!is_callable($f)) { 391 throw new Exception($f.' function doest not exist'); 392 } 393 394 $args = func_get_args(); 395 array_shift($args); 396 397 if ($this->user_admin) { 398 $res = call_user_func_array($f,$args); 399 } else { 400 $this->user_admin = true; 401 try { 402 $res = call_user_func_array($f,$args); 403 $this->user_admin = false; 404 } catch (Exception $e) { 405 $this->user_admin = false; 406 throw $e; 407 } 408 } 409 410 return $res; 411 } 412 //@} 413 414 /// @name User information and options 415 //@{ 416 /** 417 * Returns user permissions for a blog as an array which looks like: 418 * 419 * - [blog_id] 420 * - [permission] => true 421 * - ... 422 * 423 * @param string $blog_id Blog ID 424 * @return array 425 */ 426 public function getPermissions($blog_id) 427 { 428 if (isset($this->blogs[$blog_id])) { 429 return $this->blogs[$blog_id]; 430 } 431 432 if ($this->user_admin) { 433 $strReq = 'SELECT blog_id '. 434 'from '.$this->blog_table.' '. 435 "WHERE blog_id = '".$this->con->escape($blog_id)."' "; 436 $rs = $this->con->select($strReq); 437 438 $this->blogs[$blog_id] = $rs->isEmpty() ? false : array('admin' => true); 439 440 return $this->blogs[$blog_id]; 441 } 442 443 $strReq = 'SELECT permissions '. 444 'FROM '.$this->perm_table.' '. 445 "WHERE user_id = '".$this->con->escape($this->user_id)."' ". 446 "AND blog_id = '".$this->con->escape($blog_id)."' ". 447 "AND (permissions LIKE '%|usage|%' OR permissions LIKE '%|admin|%' OR permissions LIKE '%|contentadmin|%') "; 448 $rs = $this->con->select($strReq); 449 450 $this->blogs[$blog_id] = $rs->isEmpty() ? false : $this->parsePermissions($rs->permissions); 451 452 return $this->blogs[$blog_id]; 453 } 454 455 public function getBlogCount() { 456 if ($this->blog_count === null) { 457 $this->blog_count = $this->core->getBlogs(array(),true)->f(0); 458 } 24 /** @var dcCore dcCore instance */ 25 protected $core; 26 /** @var connection Database connection object */ 27 protected $con; 28 29 /** @var string User table name */ 30 protected $user_table; 31 /** @var string Perm table name */ 32 protected $perm_table; 33 34 /** @var string Current user ID */ 35 protected $user_id; 36 /** @var array Array with user information */ 37 protected $user_info = array(); 38 /** @var array Array with user options */ 39 protected $user_options = array(); 40 /** @var boolean User must change his password after login */ 41 protected $user_change_pwd; 42 /** @var boolean User is super admin */ 43 protected $user_admin; 44 /** @var array Permissions for each blog */ 45 protected $permissions = array(); 46 /** @var boolean User can change its password */ 47 protected $allow_pass_change = true; 48 /** @var array List of blogs on which the user has permissions */ 49 protected $blogs = array(); 50 /** @var integer Count of user blogs */ 51 public $blog_count = null; 52 53 /** @var array Permission types */ 54 protected $perm_types; 55 56 /** @var dcPrefs dcPrefs object */ 57 public $user_prefs; 58 59 /** 60 * Class constructor. Takes dcCore object as single argument. 61 * 62 * @param dcCore $core dcCore object 63 */ 64 public function __construct($core) 65 { 66 $this->core = &$core; 67 $this->con = &$core->con; 68 $this->blog_table = $core->prefix . 'blog'; 69 $this->user_table = $core->prefix . 'user'; 70 $this->perm_table = $core->prefix . 'permissions'; 71 72 $this->perm_types = array( 73 'admin' => __('administrator'), 74 'usage' => __('manage their own entries and comments'), 75 'publish' => __('publish entries and comments'), 76 'delete' => __('delete entries and comments'), 77 'contentadmin' => __('manage all entries and comments'), 78 'categories' => __('manage categories'), 79 'media' => __('manage their own media items'), 80 'media_admin' => __('manage all media items') 81 ); 82 } 83 84 /// @name Credentials and user permissions 85 //@{ 86 /** 87 * Checks if user exists and can log in. <var>$pwd</var> argument is optionnal 88 * while you may need to check user without password. This method will create 89 * credentials and populate all needed object properties. 90 * 91 * @param string $user_id User ID 92 * @param string $pwd User password 93 * @param string $user_key User key check 94 * @param boolean $check_blog checks if user is associated to a blog or not. 95 * @return boolean 96 */ 97 public function checkUser($user_id, $pwd = null, $user_key = null, $check_blog = true) 98 { 99 # Check user and password 100 $strReq = 'SELECT user_id, user_super, user_pwd, user_change_pwd, ' . 101 'user_name, user_firstname, user_displayname, user_email, ' . 102 'user_url, user_default_blog, user_options, ' . 103 'user_lang, user_tz, user_post_status, user_creadt, user_upddt ' . 104 'FROM ' . $this->con->escapeSystem($this->user_table) . ' ' . 105 "WHERE user_id = '" . $this->con->escape($user_id) . "' "; 106 107 try { 108 $rs = $this->con->select($strReq); 109 } catch (Exception $e) { 110 $err = $e->getMessage(); 111 return false; 112 } 113 114 if ($rs->isEmpty()) { 115 sleep(rand(2, 5)); 116 return false; 117 } 118 119 $rs->extend('rsExtUser'); 120 121 if ($pwd != '') { 122 $rehash = false; 123 if (password_verify($pwd, $rs->user_pwd)) { 124 // User password ok 125 if (password_needs_rehash($rs->user_pwd, PASSWORD_DEFAULT)) { 126 $rs->user_pwd = $this->crypt($pwd); 127 $rehash = true; 128 } 129 } else { 130 // Check if pwd still stored in old fashion way 131 $ret = password_get_info($rs->user_pwd); 132 if (is_array($ret) && isset($ret['algo']) && $ret['algo'] == 0) { 133 // hash not done with password_hash() function, check by old fashion way 134 if (crypt::hmac(DC_MASTER_KEY, $pwd, DC_CRYPT_ALGO) == $rs->user_pwd) { 135 // Password Ok, need to store it in new fashion way 136 $rs->user_pwd = $this->crypt($pwd); 137 $rehash = true; 138 } else { 139 // Password KO 140 sleep(rand(2, 5)); 141 return false; 142 } 143 } else { 144 // Password KO 145 sleep(rand(2, 5)); 146 return false; 147 } 148 } 149 if ($rehash) { 150 // Store new hash in DB 151 $cur = $this->con->openCursor($this->user_table); 152 $cur->user_pwd = (string) $rs->user_pwd; 153 $cur->update("WHERE user_id = '" . $rs->user_id . "'"); 154 } 155 } elseif ($user_key != '') { 156 if (http::browserUID(DC_MASTER_KEY . $rs->user_id . $this->cryptLegacy($rs->user_id)) != $user_key) { 157 return false; 158 } 159 } 160 161 $this->user_id = $rs->user_id; 162 $this->user_change_pwd = (boolean) $rs->user_change_pwd; 163 $this->user_admin = (boolean) $rs->user_super; 164 165 $this->user_info['user_pwd'] = $rs->user_pwd; 166 $this->user_info['user_name'] = $rs->user_name; 167 $this->user_info['user_firstname'] = $rs->user_firstname; 168 $this->user_info['user_displayname'] = $rs->user_displayname; 169 $this->user_info['user_email'] = $rs->user_email; 170 $this->user_info['user_url'] = $rs->user_url; 171 $this->user_info['user_default_blog'] = $rs->user_default_blog; 172 $this->user_info['user_lang'] = $rs->user_lang; 173 $this->user_info['user_tz'] = $rs->user_tz; 174 $this->user_info['user_post_status'] = $rs->user_post_status; 175 $this->user_info['user_creadt'] = $rs->user_creadt; 176 $this->user_info['user_upddt'] = $rs->user_upddt; 177 178 $this->user_info['user_cn'] = dcUtils::getUserCN($rs->user_id, $rs->user_name, 179 $rs->user_firstname, $rs->user_displayname); 180 181 $this->user_options = array_merge($this->core->userDefaults(), $rs->options()); 182 183 $this->user_prefs = new dcPrefs($this->core, $this->user_id); 184 185 # Get permissions on blogs 186 if ($check_blog && ($this->findUserBlog() === false)) { 187 return false; 188 } 189 return true; 190 } 191 192 /** 193 * This method crypt given string (password, session_id, …). 194 * 195 * @param string $pwd string to be crypted 196 * @return string crypted value 197 */ 198 public function crypt($pwd) 199 { 200 return password_hash($pwd, PASSWORD_DEFAULT); 201 } 202 203 /** 204 * This method crypt given string (password, session_id, …). 205 * 206 * @param string $pwd string to be crypted 207 * @return string crypted value 208 */ 209 public function cryptLegacy($pwd) 210 { 211 return crypt::hmac(DC_MASTER_KEY, $pwd, DC_CRYPT_ALGO); 212 } 213 214 /** 215 * This method only check current user password. 216 * 217 * @param string $pwd User password 218 * @return boolean 219 */ 220 public function checkPassword($pwd) 221 { 222 if (!empty($this->user_info['user_pwd'])) { 223 return password_verify($pwd, $this->user_info['user_pwd']); 224 } 225 226 return false; 227 } 228 229 /** 230 * This method checks if user session cookie exists 231 * 232 * @return boolean 233 */ 234 public function sessionExists() 235 { 236 return isset($_COOKIE[DC_SESSION_NAME]); 237 } 238 239 /** 240 * This method checks user session validity. 241 * 242 * @return boolean 243 */ 244 public function checkSession($uid = null) 245 { 246 $this->core->session->start(); 247 248 # If session does not exist, logout. 249 if (!isset($_SESSION['sess_user_id'])) { 250 $this->core->session->destroy(); 251 return false; 252 } 253 254 # Check here for user and IP address 255 $this->checkUser($_SESSION['sess_user_id']); 256 $uid = $uid ?: http::browserUID(DC_MASTER_KEY); 257 258 $user_can_log = $this->userID() !== null && $uid == $_SESSION['sess_browser_uid']; 259 260 if (!$user_can_log) { 261 $this->core->session->destroy(); 262 return false; 263 } 264 265 return true; 266 } 267 268 /** 269 * Checks if user must change his password in order to login. 270 * 271 * @return boolean 272 */ 273 public function mustChangePassword() 274 { 275 return $this->user_change_pwd; 276 } 277 278 /** 279 * Checks if user is super admin 280 * 281 * @return boolean 282 */ 283 public function isSuperAdmin() 284 { 285 return $this->user_admin; 286 } 287 288 /** 289 * Checks if user has permissions given in <var>$permissions</var> for blog 290 * <var>$blog_id</var>. <var>$permissions</var> is a coma separated list of 291 * permissions. 292 * 293 * @param string $permissions Permissions list 294 * @param string $blog_id Blog ID 295 * @return boolean 296 */ 297 public function check($permissions, $blog_id) 298 { 299 if ($this->user_admin) { 300 return true; 301 } 302 303 $p = array_map('trim', explode(',', $permissions)); 304 $b = $this->getPermissions($blog_id); 305 306 if ($b != false) { 307 if (isset($b['admin'])) { 308 return true; 309 } 310 311 foreach ($p as $v) { 312 if (isset($b[$v])) { 313 return true; 314 } 315 } 316 } 317 318 return false; 319 } 320 321 /** 322 * Returns true if user is allowed to change its password. 323 * 324 * @return boolean 325 */ 326 public function allowPassChange() 327 { 328 return $this->allow_pass_change; 329 } 330 //@} 331 332 /// @name User code handlers 333 //@{ 334 public function getUserCode() 335 { 336 $code = 337 pack('a32', $this->userID()) . 338 pack('H*', $this->crypt($this->getInfo('user_pwd'))); 339 return bin2hex($code); 340 } 341 342 public function checkUserCode($code) 343 { 344 $code = @pack('H*', $code); 345 346 $user_id = trim(@pack('a32', substr($code, 0, 32))); 347 $pwd = @unpack('H*hex', substr($code, 32)); 348 349 if ($user_id === false || $pwd === false) { 350 return false; 351 } 352 353 $pwd = $pwd['hex']; 354 355 $strReq = 'SELECT user_id, user_pwd ' . 356 'FROM ' . $this->user_table . ' ' . 357 "WHERE user_id = '" . $this->con->escape($user_id) . "' "; 358 359 $rs = $this->con->select($strReq); 360 361 if ($rs->isEmpty()) { 362 return false; 363 } 364 365 if ($this->crypt($rs->user_pwd) != $pwd) { 366 return false; 367 } 368 369 return $rs->user_id; 370 } 371 //@} 372 373 /// @name Sudo 374 //@{ 375 /** 376 * Calls $f function with super admin rights. 377 * Returns the function result. 378 * 379 * @param callback $f Callback function 380 * @return mixed 381 */ 382 public function sudo($f) 383 { 384 if (!is_callable($f)) { 385 throw new Exception($f . ' function doest not exist'); 386 } 387 388 $args = func_get_args(); 389 array_shift($args); 390 391 if ($this->user_admin) { 392 $res = call_user_func_array($f, $args); 393 } else { 394 $this->user_admin = true; 395 try { 396 $res = call_user_func_array($f, $args); 397 $this->user_admin = false; 398 } catch (Exception $e) { 399 $this->user_admin = false; 400 throw $e; 401 } 402 } 403 404 return $res; 405 } 406 //@} 407 408 /// @name User information and options 409 //@{ 410 /** 411 * Returns user permissions for a blog as an array which looks like: 412 * 413 * - [blog_id] 414 * - [permission] => true 415 * - ... 416 * 417 * @param string $blog_id Blog ID 418 * @return array 419 */ 420 public function getPermissions($blog_id) 421 { 422 if (isset($this->blogs[$blog_id])) { 423 return $this->blogs[$blog_id]; 424 } 425 426 if ($this->user_admin) { 427 $strReq = 'SELECT blog_id ' . 428 'from ' . $this->blog_table . ' ' . 429 "WHERE blog_id = '" . $this->con->escape($blog_id) . "' "; 430 $rs = $this->con->select($strReq); 431 432 $this->blogs[$blog_id] = $rs->isEmpty() ? false : array('admin' => true); 433 434 return $this->blogs[$blog_id]; 435 } 436 437 $strReq = 'SELECT permissions ' . 438 'FROM ' . $this->perm_table . ' ' . 439 "WHERE user_id = '" . $this->con->escape($this->user_id) . "' " . 440 "AND blog_id = '" . $this->con->escape($blog_id) . "' " . 441 "AND (permissions LIKE '%|usage|%' OR permissions LIKE '%|admin|%' OR permissions LIKE '%|contentadmin|%') "; 442 $rs = $this->con->select($strReq); 443 444 $this->blogs[$blog_id] = $rs->isEmpty() ? false : $this->parsePermissions($rs->permissions); 445 446 return $this->blogs[$blog_id]; 447 } 448 449 public function getBlogCount() 450 { 451 if ($this->blog_count === null) { 452 $this->blog_count = $this->core->getBlogs(array(), true)->f(0); 453 } 459 454 460 455 return $this->blog_count; 461 456 } 462 457 463 public function findUserBlog($blog_id=null) 464 { 465 if ($blog_id && $this->getPermissions($blog_id) !== false) 466 { 467 return $blog_id; 468 } 469 else 470 { 471 if ($this->user_admin) 472 { 473 $strReq = 'SELECT blog_id '. 474 'FROM '.$this->blog_table.' '. 475 'ORDER BY blog_id ASC '. 476 $this->con->limit(1); 477 } 478 else 479 { 480 $strReq = 'SELECT P.blog_id '. 481 'FROM '.$this->perm_table.' P, '.$this->blog_table.' B '. 482 "WHERE user_id = '".$this->con->escape($this->user_id)."' ". 483 "AND P.blog_id = B.blog_id ". 484 "AND (permissions LIKE '%|usage|%' OR permissions LIKE '%|admin|%' OR permissions LIKE '%|contentadmin|%') ". 485 "AND blog_status >= 0 ". 486 'ORDER BY P.blog_id ASC '. 487 $this->con->limit(1); 488 } 489 490 $rs = $this->con->select($strReq); 491 if (!$rs->isEmpty()) { 492 return $rs->blog_id; 493 } 494 } 495 496 return false; 497 } 498 499 /** 500 * Returns current user ID 501 * 502 * @return string 503 */ 504 public function userID() 505 { 506 return $this->user_id; 507 } 508 509 /** 510 * Returns information about a user . 511 * 512 * @param string $n Information name 513 * @return string 514 */ 515 public function getInfo($n) 516 { 517 if (isset($this->user_info[$n])) { 518 return $this->user_info[$n]; 519 } 520 521 return null; 522 } 523 524 /** 525 * Returns a specific user option 526 * 527 * @param string $n Option name 528 * @return string 529 */ 530 public function getOption($n) 531 { 532 if (isset($this->user_options[$n])) { 533 return $this->user_options[$n]; 534 } 535 return null; 536 } 537 538 /** 539 * Returns all user options in an associative array. 540 * 541 * @return array 542 */ 543 public function getOptions() 544 { 545 return $this->user_options; 546 } 547 //@} 548 549 /// @name Permissions 550 //@{ 551 /** 552 * Returns an array with permissions parsed from the string <var>$level</var> 553 * 554 * @param string $level Permissions string 555 * @return array 556 */ 557 public function parsePermissions($level) 558 { 559 $level = preg_replace('/^\|/','',$level); 560 $level = preg_replace('/\|$/','',$level); 561 562 $res = array(); 563 foreach (explode('|',$level) as $v) { 564 $res[$v] = true; 565 } 566 return $res; 567 } 568 569 /** 570 * Returns <var>perm_types</var> property content. 571 * 572 * @return array 573 */ 574 public function getPermissionsTypes() 575 { 576 return $this->perm_types; 577 } 578 579 /** 580 * Adds a new permission type. 581 * 582 * @param string $name Permission name 583 * @param string $title Permission title 584 */ 585 public function setPermissionType($name,$title) 586 { 587 $this->perm_types[$name] = $title; 588 } 589 //@} 590 591 /// @name Password recovery 592 //@{ 593 /** 594 * Add a recover key to a specific user identified by its email and 595 * password. 596 * 597 * @param string $user_id User ID 598 * @param string $user_email User Email 599 * @return string 600 */ 601 public function setRecoverKey($user_id,$user_email) 602 { 603 $strReq = 'SELECT user_id '. 604 'FROM '.$this->user_table.' '. 605 "WHERE user_id = '".$this->con->escape($user_id)."' ". 606 "AND user_email = '".$this->con->escape($user_email)."' "; 607 608 $rs = $this->con->select($strReq); 609 610 if ($rs->isEmpty()) { 611 throw new Exception(__('That user does not exist in the database.')); 612 } 613 614 $key = md5(uniqid('',true)); 615 616 $cur = $this->con->openCursor($this->user_table); 617 $cur->user_recover_key = $key; 618 619 $cur->update("WHERE user_id = '".$this->con->escape($user_id)."'"); 620 621 return $key; 622 } 623 624 /** 625 * Creates a new user password using recovery key. Returns an array: 626 * 627 * - user_email 628 * - user_id 629 * - new_pass 630 * 631 * @param string $recover_key Recovery key 632 * @return array 633 */ 634 public function recoverUserPassword($recover_key) 635 { 636 $strReq = 'SELECT user_id, user_email '. 637 'FROM '.$this->user_table.' '. 638 "WHERE user_recover_key = '".$this->con->escape($recover_key)."' "; 639 640 $rs = $this->con->select($strReq); 641 642 if ($rs->isEmpty()) { 643 throw new Exception(__('That key does not exist in the database.')); 644 } 645 646 $new_pass = crypt::createPassword(); 647 648 $cur = $this->con->openCursor($this->user_table); 649 $cur->user_pwd = $this->crypt($new_pass); 650 $cur->user_recover_key = null; 651 $cur->user_change_pwd = 1; // User will have to change this temporary password at next login 652 653 $cur->update("WHERE user_recover_key = '".$this->con->escape($recover_key)."'"); 654 655 return array('user_email' => $rs->user_email, 'user_id' => $rs->user_id, 'new_pass' => $new_pass); 656 } 657 //@} 658 659 /** @name User management callbacks 660 This 3 functions only matter if you extend this class and use 661 DC_AUTH_CLASS constant. 662 These are called after core user management functions. 663 Could be useful if you need to add/update/remove stuff in your 664 LDAP directory or other third party authentication database. 665 */ 666 //@{ 667 668 /** 669 * Called after core->addUser 670 * @see dcCore::addUser 671 * @param cursor $cur User cursor 672 */ 673 public function afterAddUser($cur) {} 674 675 /** 676 * Called after core->updUser 677 * @see dcCore::updUser 678 * @param string $id User ID 679 * @param cursor $cur User cursor 680 */ 681 public function afterUpdUser($id,$cur) {} 682 683 /** 684 * Called after core->delUser 685 * @see dcCore::delUser 686 * @param string $id User ID 687 */ 688 public function afterDelUser($id) {} 689 //@} 458 public function findUserBlog($blog_id = null) 459 { 460 if ($blog_id && $this->getPermissions($blog_id) !== false) { 461 return $blog_id; 462 } else { 463 if ($this->user_admin) { 464 $strReq = 'SELECT blog_id ' . 465 'FROM ' . $this->blog_table . ' ' . 466 'ORDER BY blog_id ASC ' . 467 $this->con->limit(1); 468 } else { 469 $strReq = 'SELECT P.blog_id ' . 470 'FROM ' . $this->perm_table . ' P, ' . $this->blog_table . ' B ' . 471 "WHERE user_id = '" . $this->con->escape($this->user_id) . "' " . 472 "AND P.blog_id = B.blog_id " . 473 "AND (permissions LIKE '%|usage|%' OR permissions LIKE '%|admin|%' OR permissions LIKE '%|contentadmin|%') " . 474 "AND blog_status >= 0 " . 475 'ORDER BY P.blog_id ASC ' . 476 $this->con->limit(1); 477 } 478 479 $rs = $this->con->select($strReq); 480 if (!$rs->isEmpty()) { 481 return $rs->blog_id; 482 } 483 } 484 485 return false; 486 } 487 488 /** 489 * Returns current user ID 490 * 491 * @return string 492 */ 493 public function userID() 494 { 495 return $this->user_id; 496 } 497 498 /** 499 * Returns information about a user . 500 * 501 * @param string $n Information name 502 * @return string 503 */ 504 public function getInfo($n) 505 { 506 if (isset($this->user_info[$n])) { 507 return $this->user_info[$n]; 508 } 509 510 return; 511 } 512 513 /** 514 * Returns a specific user option 515 * 516 * @param string $n Option name 517 * @return string 518 */ 519 public function getOption($n) 520 { 521 if (isset($this->user_options[$n])) { 522 return $this->user_options[$n]; 523 } 524 return; 525 } 526 527 /** 528 * Returns all user options in an associative array. 529 * 530 * @return array 531 */ 532 public function getOptions() 533 { 534 return $this->user_options; 535 } 536 //@} 537 538 /// @name Permissions 539 //@{ 540 /** 541 * Returns an array with permissions parsed from the string <var>$level</var> 542 * 543 * @param string $level Permissions string 544 * @return array 545 */ 546 public function parsePermissions($level) 547 { 548 $level = preg_replace('/^\|/', '', $level); 549 $level = preg_replace('/\|$/', '', $level); 550 551 $res = array(); 552 foreach (explode('|', $level) as $v) { 553 $res[$v] = true; 554 } 555 return $res; 556 } 557 558 /** 559 * Returns <var>perm_types</var> property content. 560 * 561 * @return array 562 */ 563 public function getPermissionsTypes() 564 { 565 return $this->perm_types; 566 } 567 568 /** 569 * Adds a new permission type. 570 * 571 * @param string $name Permission name 572 * @param string $title Permission title 573 */ 574 public function setPermissionType($name, $title) 575 { 576 $this->perm_types[$name] = $title; 577 } 578 //@} 579 580 /// @name Password recovery 581 //@{ 582 /** 583 * Add a recover key to a specific user identified by its email and 584 * password. 585 * 586 * @param string $user_id User ID 587 * @param string $user_email User Email 588 * @return string 589 */ 590 public function setRecoverKey($user_id, $user_email) 591 { 592 $strReq = 'SELECT user_id ' . 593 'FROM ' . $this->user_table . ' ' . 594 "WHERE user_id = '" . $this->con->escape($user_id) . "' " . 595 "AND user_email = '" . $this->con->escape($user_email) . "' "; 596 597 $rs = $this->con->select($strReq); 598 599 if ($rs->isEmpty()) { 600 throw new Exception(__('That user does not exist in the database.')); 601 } 602 603 $key = md5(uniqid('', true)); 604 605 $cur = $this->con->openCursor($this->user_table); 606 $cur->user_recover_key = $key; 607 608 $cur->update("WHERE user_id = '" . $this->con->escape($user_id) . "'"); 609 610 return $key; 611 } 612 613 /** 614 * Creates a new user password using recovery key. Returns an array: 615 * 616 * - user_email 617 * - user_id 618 * - new_pass 619 * 620 * @param string $recover_key Recovery key 621 * @return array 622 */ 623 public function recoverUserPassword($recover_key) 624 { 625 $strReq = 'SELECT user_id, user_email ' . 626 'FROM ' . $this->user_table . ' ' . 627 "WHERE user_recover_key = '" . $this->con->escape($recover_key) . "' "; 628 629 $rs = $this->con->select($strReq); 630 631 if ($rs->isEmpty()) { 632 throw new Exception(__('That key does not exist in the database.')); 633 } 634 635 $new_pass = crypt::createPassword(); 636 637 $cur = $this->con->openCursor($this->user_table); 638 $cur->user_pwd = $this->crypt($new_pass); 639 $cur->user_recover_key = null; 640 $cur->user_change_pwd = 1; // User will have to change this temporary password at next login 641 642 $cur->update("WHERE user_recover_key = '" . $this->con->escape($recover_key) . "'"); 643 644 return array('user_email' => $rs->user_email, 'user_id' => $rs->user_id, 'new_pass' => $new_pass); 645 } 646 //@} 647 648 /** @name User management callbacks 649 This 3 functions only matter if you extend this class and use 650 DC_AUTH_CLASS constant. 651 These are called after core user management functions. 652 Could be useful if you need to add/update/remove stuff in your 653 LDAP directory or other third party authentication database. 654 */ 655 //@{ 656 657 /** 658 * Called after core->addUser 659 * @see dcCore::addUser 660 * @param cursor $cur User cursor 661 */ 662 public function afterAddUser($cur) 663 {} 664 665 /** 666 * Called after core->updUser 667 * @see dcCore::updUser 668 * @param string $id User ID 669 * @param cursor $cur User cursor 670 */ 671 public function afterUpdUser($id, $cur) 672 {} 673 674 /** 675 * Called after core->delUser 676 * @see dcCore::delUser 677 * @param string $id User ID 678 */ 679 public function afterDelUser($id) 680 {} 681 //@} 690 682 }
Note: See TracChangeset
for help on using the changeset viewer.