1<?php 2/** 3 * @package Habari 4 * 5 */ 6 7/** 8 * Access Control List class 9 * 10 * The default Habari ACL class implements groups, and group permissions 11 * Users are assigned to one or more groups. 12 * Groups are assigned one or more permissions. 13 * Membership in any group that grants a permission 14 * means you have that permission. Membership in any group that denies 15 * that permission denies the user that permission, even if another group 16 * grants that permission. 17 * 18 */ 19 20class ACL 21{ 22 /** 23 * How to handle a permission request for a permission that is not in the permission list. 24 * For example, if you request $user->can('some non-existent permission') then this value is returned. 25 */ 26 const ACCESS_NONEXISTENT_PERMISSION = 0; 27 const CACHE_NULL = -1; 28 29 public static $access_names = array( 'read', 'edit', 'delete', 'create' ); 30 private static $token_cache = null; 31 32 /** 33 * Check a permission bitmask for a particular access type. 34 * @param Bitmask $bitmask The permission bitmask 35 * @param mixed $access The name of the access to check against (read, write, full) 36 * @return bool Returns true if the given access meets exceeds the access to check against 37 */ 38 public static function access_check( $bitmask, $access ) 39 { 40 if ( $access instanceof Bitmask ) { 41 return ( $bitmask->value & $access->value ) == $access->value; 42 } 43 44 switch ( $access ) { 45 case 'full': 46 return $bitmask->value == $bitmask->full; 47 case 'any': 48 return $bitmask->value != 0; 49 case 'deny': 50 return $bitmask->value == 0; 51 default: 52 return $bitmask->$access; 53 } 54 } 55 56 /** 57 * Get a Bitmask object representing the supplied access integer 58 * 59 * @param integer $mask The access mask, usually stored in the database 60 * @return Bitmask An object representing the access value 61 */ 62 public static function get_bitmask( $mask ) 63 { 64 $bitmask = new Bitmask( self::$access_names, $mask ); 65 return $bitmask; 66 } 67 68 /** 69 * Create a new permission token, and save it to the permission tokens table 70 * @param string $name The name of the permission 71 * @param string $description The description of the permission 72 * @param string $group The token group for organizational purposes 73 * @param bool $crud Indicates if the token is a CRUD or boolean type token (default is boolean) 74 * @return mixed the ID of the newly created permission, or boolean false 75 */ 76 public static function create_token( $name, $description, $group, $crud = false ) 77 { 78 $name = self::normalize_token( $name ); 79 $crud = ( $crud ) ? 1 : 0; 80 // first, make sure this isn't a duplicate 81 if ( ACL::token_exists( $name ) ) { 82 return false; 83 } 84 $allow = true; 85 // Plugins have the opportunity to prevent adding this token 86 $allow = Plugins::filter( 'token_create_allow', $allow, $name, $description, $group, $crud ); 87 if ( ! $allow ) { 88 return false; 89 } 90 Plugins::act( 'token_create_before', $name, $description, $group, $crud ); 91 92 $result = DB::query( 'INSERT INTO {tokens} (name, description, token_group, token_type) VALUES (?, ?, ?, ?)', array( $name, $description, $group, $crud ) ); 93 94 if ( ! $result ) { 95 // if it didn't work, don't bother trying to log it 96 return false; 97 } 98 99 self::clear_caches(); 100 101 // Add the token to the admin group 102 $token = ACL::token_id( $name ); 103 $admin = UserGroup::get( 'admin' ); 104 if ( $admin ) { 105 ACL::grant_group( $admin->id, $token, 'full' ); 106 } 107 108 EventLog::log( 'New permission token created: ' . $name, 'info', 'default', 'habari' ); 109 Plugins::act( 'permission_create_after', $name, $description, $group, $crud ); 110 return $result; 111 } 112 113 /** 114 * Remove a permission token, and any assignments of it 115 * @param mixed $permission a permission ID or name 116 * @return bool whether the permission was deleted or not 117 */ 118 public static function destroy_token( $token ) 119 { 120 // make sure the permission exists, first 121 if ( ! self::token_exists( $token ) ) { 122 return false; 123 } 124 125 // grab token ID 126 $token_id = self::token_id( $token ); 127 128 $allow = true; 129 // plugins have the opportunity to prevent deletion 130 $allow = Plugins::filter( 'token_destroy_allow', $allow, $token_id ); 131 if ( ! $allow ) { 132 return false; 133 } 134 Plugins::act( 'token_destroy_before', $token_id ); 135 // capture the token name 136 $name = DB::get_value( 'SELECT name FROM {tokens} WHERE id=?', array( $token_id ) ); 137 // remove all references to this permissions 138 $result = DB::query( 'DELETE FROM {group_token_permissions} WHERE token_id=?', array( $token_id ) ); 139 $result = DB::query( 'DELETE FROM {user_token_permissions} WHERE token_id=?', array( $token_id ) ); 140 $result = DB::query( 'DELETE FROM {post_tokens} WHERE token_id=?', array( $token_id ) ); 141 ACL::clear_caches(); 142 // remove this token 143 $result = DB::query( 'DELETE FROM {tokens} WHERE id=?', array( $token_id ) ); 144 if ( ! $result ) { 145 // if it didn't work, don't bother trying to log it 146 return false; 147 } 148 EventLog::log( sprintf( _t( 'Permission token deleted: %s' ), $name ), 'info', 'default', 'habari' ); 149 Plugins::act( 'token_destroy_after', $token_id ); 150 return $result; 151 } 152 153 /** 154 * Get an array of QueryRecord objects containing all permission tokens 155 * @param string $order the order in which to sort the returning array 156 * @return array an array of QueryRecord objects containing all tokens 157 */ 158 public static function all_tokens( $order = 'id' ) 159 { 160 $order = strtolower( $order ); 161 if ( ( 'id' != $order ) && ( 'name' != $order ) && ( 'description' != $order ) ) { 162 $order = 'id'; 163 } 164 $tokens = DB::get_results( 'SELECT id, name, description, token_group, token_type FROM {tokens} ORDER BY ' . $order ); 165 return $tokens ? $tokens : array(); 166 } 167 168 /** 169 * Get a permission token's name by its ID 170 * @param int $id a token ID 171 * @return string the name of the permission, or boolean false 172 */ 173 public static function token_name( $id ) 174 { 175 if ( ! is_int( $id ) ) { 176 return false; 177 } 178 else { 179 $tokens = ACL::cache_tokens(); 180 return isset( $tokens[ $id ] ) ? $tokens[ $id ] : false; 181 } 182 } 183 184 /** 185 * Get an associative array of token ids and their name. 186 * 187 * @return array an array in the form id => name 188 */ 189 private static function cache_tokens() 190 { 191 if ( ACL::$token_cache == null ) { 192 ACL::$token_cache = DB::get_keyvalue( 'SELECT id, name FROM {tokens}' ); 193 } 194 return ACL::$token_cache; 195 } 196 197 /** 198 * Get a permission token's ID by its name 199 * @param string $name the name of the permission 200 * @return int the permission's ID 201 */ 202 public static function token_id( $name ) 203 { 204 if ( is_numeric( $name ) ) { 205 return intval( $name ); 206 } 207 $name = self::normalize_token( $name ); 208 if ( $token = array_search( $name, ACL::cache_tokens() ) ) { 209 return $token; 210 } 211 return false; 212 } 213 214 /** 215 * Fetch a permission token's description from the DB 216 * @param mixed $permission a permission name or ID 217 * @return string the description of the permission 218 */ 219 public static function token_description( $permission ) 220 { 221 if ( is_int( $permission ) ) { 222 $query = 'id'; 223 } 224 else { 225 $query = 'name'; 226 $permission = self::normalize_token( $permission ); 227 } 228 return DB::get_value( "SELECT description FROM {tokens} WHERE $query=?", array( $permission ) ); 229 } 230 231 /** 232 * Determine whether a permission token exists 233 * @param mixed $permission a permission name or ID 234 * @return bool whether the permission exists or not 235 */ 236 public static function token_exists( $permission ) 237 { 238 if ( is_numeric( $permission ) ) { 239 $query = 'id'; 240 } 241 else { 242 $query = 'name'; 243 $permission = self::normalize_token( $permission ); 244 } 245 return ( (int) DB::get_value( "SELECT COUNT(id) FROM {tokens} WHERE $query=?", array( $permission ) ) > 0 ); 246 } 247 248 /** 249 * Determine whether a group can perform a specific action 250 * @param mixed $group A group ID or name 251 * @param mixed $token_id A permission token ID or name 252 * @param string $access Check for 'create', 'read', 'update', 'delete', or 'full' access 253 * @return bool Whether the group can perform the action 254 */ 255 public static function group_can( $group, $token_id, $access = 'full' ) 256 { 257 $bitmask = self::get_group_token_access( $group, $token_id ); 258 259 if ( isset( $bitmask ) && self::access_check( $bitmask, $access ) ) { 260 // the permission has been granted to this group 261 return true; 262 } 263 // either the permission hasn't been granted, or it's been 264 // explicitly denied. 265 return false; 266 } 267 268 /** 269 * Determine whether a group is explicitly denied permission to perform a specific action 270 * This function does not return true if the group is merely not granted a permission 271 * @param mixed $user A group ID or a group name 272 * @param mixed $token_id A permission ID or name 273 * @return bool True if access to the token is denied to the group 274 */ 275 public static function group_cannot( $group, $token_id ) 276 { 277 278 $result = self::get_group_token_access( $group, $token_id ); 279 if ( isset( $result ) && self::access_check( $result, 'deny' ) ) { 280 return true; 281 } 282 283 // The permission has been granted, or it hasn't been explicitly denied. 284 return false; 285 } 286 287 /** 288 * Determine whether a user can perform a specific action 289 * @param mixed $user A user object, user ID or a username 290 * @param mixed $token_id A permission ID or name 291 * @param string $access Check for 'create', 'read', 'update', 'delete', or 'full' access 292 * @return bool Whether the user can perform the action 293 */ 294 public static function user_can( $user, $token_id, $access = 'full' ) 295 { 296 297 $result = self::get_user_token_access( $user, $token_id ); 298 299 if ( isset( $result ) && self::access_check( $result, $access ) ) { 300 return true; 301 } 302 303 $super_user_access = self::get_user_token_access( $user, 'super_user' ); 304 if ( isset( $super_user_access ) && self::access_check( $super_user_access, 'any' ) ) { 305 return true; 306 } 307 308 // either the permission hasn't been granted, or it's been 309 // explicitly denied. 310 return false; 311 } 312 313 /** 314 * Determine whether a user is explicitly denied permission to perform a specific action 315 * This function does not return true if the user is merely not granted a permission 316 * @param mixed $user A User object, user ID or a username 317 * @param mixed $token_id A permission ID or name 318 * @return bool True if access to the token is denied to the user 319 */ 320 public static function user_cannot( $user, $token_id ) 321 { 322 323 $result = self::get_user_token_access( $user, $token_id ); 324 if ( isset( $result ) && self::access_check( $result, 'deny' ) ) { 325 return true; 326 } 327 328 // The permission has been granted, or it hasn't been explicitly denied. 329 return false; 330 } 331 332 /** 333 * Return the access bitmask to a specific token for a specific user 334 * 335 * @param mixed $user A User object instance or user id 336 * @param mixed $token_id A permission token name or token ID 337 * @return integer An access bitmask 338 */ 339 public static function get_user_token_access( $user, $token ) 340 { 341 // Use only numeric ids internally 342 $token_id = self::token_id( $token ); 343 344 /** 345 * Do we allow perms that don't exist? 346 * When ACL is functional ACCESS_NONEXISTENT_PERMISSION should be false by default. 347 */ 348 if ( is_null( $token_id ) ) { 349 return self::get_bitmask( self::ACCESS_NONEXISTENT_PERMISSION ); 350 } 351 352 // if we were given a user ID, use that to fetch the group membership from the DB 353 if ( is_numeric( $user ) ) { 354 $user_id = $user; 355 } 356 else { 357 // otherwise, make sure we have a User object, and get 358 // the groups from that 359 if ( ! $user instanceof User ) { 360 $user = User::get( $user ); 361 } 362 $user_id = $user->id; 363 } 364 365 if ( defined( 'LOCKED_OUT_SUPER_USER' ) && $token == 'super_user' ) { 366 $su = User::get( LOCKED_OUT_SUPER_USER ); 367 if ( $su->id == $user_id ) { 368 return new Bitmask( self::$access_names, 'read'); 369 } 370 } 371 372 // check the cache first for the user's access_mask on the token 373 if ( isset( $_SESSION[ 'user_token_access' ][ $user_id ][ $token_id ] ) ) { 374// Utils::debug($token, $_SESSION['user_token_access'][$token_id]); 375 if ( $_SESSION[ 'user_token_access' ][ $user_id ][ $token_id ] == ACL::CACHE_NULL ) { 376 return null; 377 } 378 else { 379 return self::get_bitmask( $_SESSION[ 'user_token_access' ][ $user_id ][ $token_id ] ); 380 } 381 } 382 383 /** 384 * Jay Pipe's explanation of the following SQL 385 * 1) Look into user_permissions for the user and the token. 386 * If exists, use that permission flag for the check. If not, 387 * go to 2) 388 * 389 * 2) Look into the group_permissions joined to 390 * users_groups for the user and the token. Order the results 391 * by the access bitmask. The lower the mask value, the 392 * fewest permissions that group has. Use the first record's 393 * access mask to check the ACL. 394 * 395 * This gives the system very fine grained control and grabbing 396 * the permission flag and can be accomplished in a single SQL 397 * call. 398 */ 399 400 $exceptions = ''; 401 $default_groups = array(); 402 $default_groups = Plugins::filter( 'user_default_groups', $default_groups, $user_id ); 403 $default_groups = array_filter( array_map( 'intval', $default_groups ) ); 404 switch ( count( $default_groups ) ) { 405 case 0: // do nothing 406 break; 407 case 1: // single argument 408 $exceptions = 'OR ug.group_id = ' . reset( $default_groups ); 409 break; 410 default: // multiple arguments 411 $exceptions = 'OR ug.group_id IN (' . implode( ',', $default_groups ) . ')'; 412 break; 413 } 414 415 $sql = <<<SQL 416SELECT access_mask 417 FROM {user_token_permissions} 418 WHERE user_id = ? 419 AND token_id = ? 420UNION ALL 421SELECT gp.access_mask 422 FROM {users_groups} ug 423 INNER JOIN {group_token_permissions} gp 424 ON ((ug.group_id = gp.group_id 425 AND ug.user_id = ?) 426 {$exceptions}) 427 AND gp.token_id = ? 428 ORDER BY access_mask ASC 429SQL; 430 431 if ( $token_id == '' ) { $token_id = '0'; } 432 433 $accesses = DB::get_column( $sql, array( $user_id, $token_id, $user_id, $token_id ) ); 434 435 $accesses = Plugins::filter( 'user_token_access', $accesses, $user_id, $token_id ); 436 437 if ( count( $accesses ) == 0 ) { 438 $_SESSION[ 'user_token_access' ][ $user_id ][ $token_id ] = ACL::CACHE_NULL; 439 return null; 440 } 441 else { 442 $result = 0; 443 foreach ( (array) $accesses as $access ) { 444 if ( $access == 0 ) { 445 $result = 0; 446 break; 447 } 448 else { 449 $result |= $access; 450 } 451 } 452 453 $_SESSION[ 'user_token_access' ][ $user_id ][ $token_id ] = $result; 454 return self::get_bitmask( $result ); 455 } 456 } 457 458 /** 459 * Get all the tokens for a given user with a particular kind of access 460 * @param mixed $user A user object, user ID or a username 461 * @param string $access Check for 'create' or 'read', 'update', or 'delete' access 462 * @return array of token IDs 463 */ 464 public static function user_tokens( $user, $access = 'full', $posts_only = false ) 465 { 466 static $post_tokens = null; 467 468 $bitmask = new Bitmask ( self::$access_names ); 469 $tokens = array(); 470 471 // convert $user to an ID 472 if ( is_numeric( $user ) ) { 473 $user_id = $user; 474 } 475 else { 476 if ( ! $user instanceof User ) { 477 $user = User::get( $user ); 478 } 479 $user_id = $user->id; 480 } 481 482 // Implement cache RIGHT HERE 483 if ( isset( $_SESSION[ 'user_tokens' ][ $user_id ][ $access ] ) ) { 484 return $_SESSION[ 'user_tokens' ][ $user_id ][ $access ]; 485 } 486 487 $super_user_access = self::get_user_token_access( $user, 'super_user' ); 488 if ( isset( $super_user_access ) && self::access_check( $super_user_access, 'any' ) ) { 489 $token_ids = DB::get_column( 'SELECT id as token_id FROM {tokens}' ); 490 $result = array(); 491 foreach ( $token_ids as $id ) { 492 $result_row = new StdClass(); 493 $result_row->token_id = $id; 494 $result_row->access_mask = $bitmask->full; 495 $result[] = $result_row; 496 } 497 } 498 else { 499 500 $sql = <<<SQL 501SELECT token_id, access_mask 502 FROM {user_token_permissions} 503 WHERE user_id = :user_id 504UNION ALL 505SELECT gp.token_id, gp.access_mask 506 FROM {users_groups} ug 507 INNER JOIN {group_token_permissions} gp 508 ON ug.group_id = gp.group_id 509 AND ug.user_id = :user_id 510 ORDER BY token_id ASC 511SQL; 512 $result = DB::get_results( $sql, array( ':user_id' => $user_id ) ); 513 } 514 515 if ( $posts_only && !isset( $post_tokens ) ) { 516 $post_tokens = DB::get_column( 'SELECT token_id FROM {post_tokens} GROUP BY token_id' ); 517 } 518 519 foreach ( (array) $result as $token ) { 520 $bitmask->value = $token->access_mask; 521 if ( $access === 'deny' ) { 522 if ( $bitmask->value === 0 ) { 523 $tokens[] = $token->token_id; 524 } 525 } 526 elseif ( $bitmask->$access ) { 527 $tokens[] = $token->token_id; 528 } 529 } 530 531 if ( $posts_only ) { 532 $tokens = array_intersect( $tokens, $post_tokens ); 533 } 534 535 $_SESSION[ 'user_tokens' ][ $user_id ][ $access ] = $tokens; 536 return $tokens; 537 } 538 539 /** 540 * Get the access bitmask of a group for a specific permission token 541 * @param integer $group The group ID 542 * @param mixed $token_id A permission name or ID 543 * @return an access bitmask 544 */ 545 public static function get_group_token_access( $group, $token_id ) 546 { 547 // Use only numeric ids internally 548 $group = UserGroup::id( $group ); 549 $token_id = self::token_id( $token_id ); 550 $sql = 'SELECT access_mask FROM {group_token_permissions} WHERE 551 group_id=? AND token_id=?;'; 552 553 $result = DB::get_value( $sql, array( $group, $token_id ) ); 554 555 if ( isset( $result ) ) { 556 return self::get_bitmask( $result ); 557 } 558 return null; 559 } 560 561 /** 562 * Grant a permission to a group 563 * @param integer $group_id The group ID 564 * @param mixed $token_id The name or ID of the permission token to grant 565 * @param string $access The kind of access to assign the group 566 * @return Result of the DB query 567 */ 568 public static function grant_group( $group_id, $token_id, $access = 'full' ) 569 { 570 $token_id = self::token_id( $token_id ); 571 $results = DB::get_column( 'SELECT access_mask FROM {group_token_permissions} WHERE group_id=? AND token_id=?', array( $group_id, $token_id ) ); 572 $access_mask = 0; 573 $row_exists = false; 574 if ( $results ) { 575 $row_exists = true; 576 if ( in_array( 0, $results ) ) { 577 $access_mask = 0; 578 } 579 else { 580 $access_mask = Utils::array_or( $results ); 581 } 582 } 583 584 $bitmask = self::get_bitmask( $access_mask ); 585 $orig_value = $bitmask->value; 586 587 if ( $access instanceof Bitmask ) { 588 $bitmask->value = $access->value; 589 } 590 elseif ( $access == 'full' ) { 591 $bitmask->value = $bitmask->full; 592 } 593 elseif ( $access == 'deny' ) { 594 $bitmask->value = 0; 595 } 596 else { 597 $bitmask->$access = true; 598 } 599 600 // Only update if the value is changed 601 if ( $orig_value != $bitmask->value || ( $orig_value == 0 && !$row_exists && $bitmask->value == 0 ) ) { 602 // DB::update will insert if the token is not already in the group tokens table 603 $result = DB::update( 604 '{group_token_permissions}', 605 array( 'access_mask' => $bitmask->value ), 606 array( 'group_id' => $group_id, 'token_id' => $token_id ) 607 ); 608 ACL::clear_caches(); 609 610 $ug = UserGroup::get_by_id( $group_id ); 611 $ug->clear_permissions_cache(); 612 $msg = _t( 'Group %1$s: Access to %2$s changed to %3$s', array( $ug->name, ACL::token_name( $token_id ), $bitmask ) ); 613 EventLog::log( $msg, 'notice', 'user', 'habari' ); 614 } 615 else { 616 $result = true; 617 } 618 619 return $result; 620 } 621 622 /** 623 * Grant a permission to a user 624 * @param integer $user_id The user ID 625 * @param integer $token_id The name or ID of the permission token to grant 626 * @param string $access The kind of access to assign the group 627 * @return Result of the DB query 628 */ 629 public static function grant_user( $user_id, $token_id, $access = 'full' ) 630 { 631 $token_id = self::token_id( $token_id ); 632 $access_mask = DB::get_value( 'SELECT access_mask FROM {user_token_permissions} WHERE user_id=? AND token_id=?', 633 array( $user_id, $token_id ) ); 634 if ( $access_mask === false ) { 635 $permission_bit = 0; // default is 'deny' (bitmask 0) 636 } 637 638 $bitmask = self::get_bitmask( $access_mask ); 639 640 if ( $access == 'full' ) { 641 $bitmask->value= $bitmask->full; 642 } 643 elseif ( $access == 'deny' ) { 644 $bitmask->value = 0; 645 } 646 else { 647 $bitmask->$access = true; 648 } 649 650 $result = DB::update( 651 '{user_token_permissions}', 652 array( 'access_mask' => $bitmask->value ), 653 array( 'user_id' => $user_id, 'token_id' => $token_id ) 654 ); 655 656 ACL::clear_caches(); 657 658 return $result; 659 } 660 661 /** 662 * Deny permission to a group 663 * @param integer $group_id The group ID 664 * @param mixed $token_id The name or ID of the permission token 665 * @return Result of the DB query 666 */ 667 public static function deny_group( $group_id, $token_id ) 668 { 669 self::grant_group( $group_id, $token_id, 'deny' ); 670 } 671 672 /** 673 * Deny permission to a user 674 * @param integer $user_id The user ID 675 * @param mixed $token_id The name or ID of the permission token 676 * @return Result of the DB query 677 */ 678 public static function deny_user( $user_id, $token_id ) 679 { 680 self::grant_user( $group_id, $token_id, 'deny' ); 681 } 682 683 /** 684 * Remove a permission token from the group permissions table 685 * @param integer $group_id The group ID 686 * @param mixed $token_id The name or ID of the permission token 687 * @return the result of the DB query 688 */ 689 public static function revoke_group_token( $group_id, $token_id ) 690 { 691 $token_id = self::token_id( $token_id ); 692 $ug = UserGroup::get_by_id( $group_id ); 693 694 $access = self::get_group_token_access( $group_id, $token_id ); 695 696 if ( empty( $access ) ) { 697 $result = true; 698 } 699 else { 700 $result = DB::delete( '{group_token_permissions}', 701 array( 'group_id' => $group_id, 'token_id' => $token_id ) ); 702 EventLog::log( _t( 'Group %1$s: Permission to %2$s revoked.', array( $ug->name, ACL::token_name( $token_id ) ) ), 'notice', 'user', 'habari' ); 703 } 704 705 $ug->clear_permissions_cache(); 706 ACL::clear_caches(); 707 708 return $result; 709 } 710 711 /** 712 * Remove a permission token from the user permissions table 713 * @param integer $user_id The user ID 714 * @param mixed $token_id The name or ID of the permission token 715 * @return the result of the DB query 716 */ 717 public static function revoke_user_token( $user_id, $token_id ) 718 { 719 $token_id = self::token_id( $token_id ); 720 $result = DB::delete( '{user_token_permissions}', 721 array( 'user_id' => $user_id, 'token_id' => $token_id ) ); 722 723 ACL::clear_caches(); 724 725 return $result; 726 } 727 728 /** 729 * Convert a token name into a valid format 730 * 731 * @param string $name The name of a permission 732 * @return string The permission with spaces converted to underscores and all lowercase 733 */ 734 public static function normalize_token( $name ) 735 { 736 return strtolower( preg_replace( '/\s+/u', '_', trim( $name ) ) ); 737 } 738 739 /** 740 * Clears all caches used to hold permissions 741 * 742 */ 743 public static function clear_caches() 744 { 745 if ( isset( $_SESSION[ 'user_token_access' ] ) ) { 746 unset( $_SESSION[ 'user_token_access' ] ); 747 748 } 749 if ( isset( $_SESSION[ 'user_tokens' ] ) ) { 750 unset( $_SESSION[ 'user_tokens' ] ); 751 } 752 self::$token_cache = null; 753 } 754 755 /** 756 * Creates the default set of permissions. 757 */ 758 public static function create_default_tokens() 759 { 760 // super user token 761 self::create_token( 'super_user', 'Permissions for super users', 'Super User' ); 762 763 // admin tokens 764 self::create_token( 'manage_all_comments', _t( 'Manage comments on all posts' ), 'Administration' ); 765 self::create_token( 'manage_own_post_comments', _t( 'Manage comments on one\'s own posts' ), 'Administration' ); 766 self::create_token( 'manage_tags', _t( 'Manage tags' ), 'Administration' ); 767 self::create_token( 'manage_options', _t( 'Manage options' ), 'Administration' ); 768 self::create_token( 'manage_theme', _t( 'Change theme' ), 'Administration' ); 769 self::create_token( 'manage_theme_config', _t( 'Configure the active theme' ), 'Administration' ); 770 self::create_token( 'manage_plugins', _t( 'Activate/deactivate plugins' ), 'Administration' ); 771 self::create_token( 'manage_plugins_config', _t( 'Configure active plugins' ), 'Administration' ); 772 self::create_token( 'manage_import', _t( 'Use the importer' ), 'Administration' ); 773 self::create_token( 'manage_users', _t( 'Add, remove, and edit users' ), 'Administration' ); 774 self::create_token( 'manage_self', _t( 'Edit own profile' ), 'Administration' ); 775 self::create_token( 'manage_groups', _t( 'Manage groups and permissions' ), 'Administration' ); 776 self::create_token( 'manage_logs', _t( 'Manage logs' ), 'Administration' ); 777 self::create_token( 'manage_dash_modules', _t( 'Manage dashboard modules' ), 'Administration' ); 778 779 // content tokens 780 self::create_token( 'own_posts', _t( 'Permissions on one\'s own posts' ), _t( 'Content' ), true ); 781 self::create_token( 'post_any', _t( 'Permissions to all posts' ), _t( 'Content' ), true ); 782 self::create_token( 'post_unpublished', _t( "Permissions to other users' unpublished posts" ), _t( 'Content' ), true ); 783 foreach ( Post::list_active_post_types() as $name => $posttype ) { 784 self::create_token( 'post_' . Utils::slugify( $name ), _t( 'Permissions to posts of type "%s"', array( $name ) ), _t( 'Content' ), true ); 785 } 786 787 // comments tokens 788 self::create_token( 'comment', 'Make comments on any post', _t( 'Comments' ) ); 789 } 790 791 /** 792 * Reset premissions to their default state 793 */ 794 public static function rebuild_permissions( $user = null ) 795 { 796 // Clear out all permission-related values 797 DB::query( 'DELETE FROM {tokens}' ); 798 DB::query( 'DELETE FROM {group_token_permissions}' ); 799 //DB::query( 'DELETE FROM {groups}' ); 800 DB::query( 'DELETE FROM {post_tokens}' ); 801 DB::query( 'DELETE FROM {user_token_permissions}' ); 802 //DB::query('DELETE FROM {users_groups}'); 803 804 // Create initial groups if they don't already exist 805 $admin_group = UserGroup::get_by_name( _t( 'admin' ) ); 806 if ( ! $admin_group instanceof UserGroup ) { 807 $admin_group = UserGroup::create( array( 'name' => _t( 'admin' ) ) ); 808 } 809 810 $anonymous_group = UserGroup::get_by_name( _t( 'anonymous' ) ); 811 if ( ! $anonymous_group instanceof UserGroup ) { 812 $anonymous_group = UserGroup::create( array( 'name' => _t( 'anonymous' ) ) ); 813 } 814 815 // Add all users or the passed user to the admin group 816 if ( empty($user) ) { 817 $users = Users::get_all(); 818 $ids = array(); 819 foreach ( $users as $user ) { 820 $ids[] = $user->id; 821 } 822 $admin_group->add( $ids ); 823 } 824 else { 825 $admin_group->add( $user ); 826 } 827 828 // create default permissions 829 self::create_default_tokens(); 830 // Make the admin group all superusers 831 $admin_group->grant( 'super_user' ); 832 // Add entry and page read access to the anonymous group 833 $anonymous_group->grant( 'post_entry', 'read' ); 834 $anonymous_group->grant( 'post_page', 'read' ); 835 $anonymous_group->grant( 'comment' ); 836 837 // Add the anonymous user to the anonymous group 838 $anonymous_group->add( 0 ); 839 840 // Create the default authenticated group 841 $authenticated_group = UserGroup::get_by_name( _t( 'authenticated' ) ); 842 if ( ! $authenticated_group instanceof UserGroup ) { 843 $authenticated_group = UserGroup::create( array( 'name' => _t( 'authenticated' ) ) ); 844 } 845 $authenticated_group->grant( 'post_entry', 'read' ); 846 $authenticated_group->grant( 'post_page', 'read' ); 847 $authenticated_group->grant( 'comment' ); 848 849 } 850 851 /** 852 * Dummy function to inject strings into the .pot 853 */ 854 private static function translations() { 855 // @locale The names of the CRUD group token permissions 856 _t( 'read' ); _t( 'edit' ); _t( 'delete' ); _t( 'create' ); 857 } 858 859} 860?> 861