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