ocPortal Developer's Guide: The Permissions system
» Return to Contents
Permissions are drawn off usergroup membership, and access control is defined on usergroup level. Preferably a forum would allow multiple usergroups per member, in order to allow overlapping (not just plain stacked) permissions - but most unfortunately are rather simplistic, which is just as limiting to the forum as well as to ocPortal. OCF supports advanced multiple usergroup membership features.
The permission architecture in ocPortal is particularly rich, giving the user a high degree of control over their site, without the need for additional complexity (because permissions are overrided on a per-page and per-category basis, but otherwise apply globally).
The term 'module' in the permissions sense is not exactly the same as a 'module' in the usual ocPortal sense. A permissions module is usually the same name as the main module for viewing the content in question, but it may not be if the main module supports multiple types of content: for example, the catalogues module has support for both catalogue-permissions and category-permissions, so the permission modules are 'catalogues_catalogue' and 'catalogues_category'.
When specific permissions are overrided by pages, the pages that the overriding is defined for is usually the content management page; for example, if add_midrange_content is overridden for the download system as a whole, it would be overridden with the page name 'cms_downloads'. It could also be overridden on a per-download-category basis, in which case the permissions module would be 'downloads'.
A third point of confusion is that of SEO modules: these define yet another set of 'module' names: these are however totally unrelated to permissions.
sources/permissions.php
Global_functions_permissions.php
Function summary
|
void
|
init__permissions ()
|
|
void
|
handle_permission_check_logging (MEMBER member, ID_TEXT op, array params, boolean result)
|
|
void
|
access_denied (ID_TEXT class, string param, boolean force_login)
|
|
boolean
|
has_zone_access (MEMBER member, ID_TEXT zone)
|
|
boolean
|
has_actual_page_access (?MEMBER member, ?ID_TEXT page, ?ID_TEXT zone, ?array cats, ?mixed sp)
|
|
void
|
load_up_all_self_page_permissions (MEMBER member)
|
|
boolean
|
has_page_access (MEMBER member, ID_TEXT page, ID_TEXT zone, boolean at_now)
|
|
void
|
load_up_all_module_category_permissions (MEMBER member, ?ID_TEXT module)
|
|
boolean
|
has_category_access (MEMBER member, ID_TEXT module, ID_TEXT category)
|
|
?string
|
_get_where_clause_groups (MEMBER member)
|
|
void
|
enforce_personal_access (MEMBER member_id, ?ID_TEXT permission, ?ID_TEXT permission2, ?MEMBER member_viewing)
|
|
void
|
check_specific_permission (ID_TEXT permission, ?array cats, ?MEMBER member_id)
|
|
boolean
|
has_some_cat_specific_permission (MEMBER member, ID_TEXT permission, ?ID_TEXT page, ID_TEXT permission_module)
|
|
boolean
|
has_specific_permission (MEMBER member, ID_TEXT permission, ?ID_TEXT page, ?array cats)
|
|
void
|
check_submit_permission (string range, ?array cats, ?ID_TEXT page)
|
|
boolean
|
has_submit_permission (string range, MEMBER member, IP ip, ?ID_TEXT page, ?array cats)
|
|
void
|
check_some_edit_permission (string range, ?array cats)
|
|
void
|
check_edit_permission (string range, ?MEMBER resource_owner, ?array cats, ?ID_TEXT page)
|
|
boolean
|
has_edit_permission (string range, MEMBER member, ?MEMBER resource_owner, ?ID_TEXT page, ?array cats)
|
|
void
|
check_delete_permission (string range, ?MEMBER resource_owner, ?array cats, ?ID_TEXT page)
|
|
boolean
|
has_delete_permission (string range, MEMBER member, ?MEMBER resource_owner, ?ID_TEXT page, ?array cats)
|
void init__permissions()
Standard code module initialisation function.
Parameters…
(No return value)
function init__permissions()
{
global $SPECIFIC_PERMISSION_CACHE;
$SPECIFIC_PERMISSION_CACHE=array();
global $GROUP_SPECIFIC_PERMISSION_CACHE;
$GROUP_SPECIFIC_PERMISSION_CACHE=array();
global $ZONE_ACCESS_CACHE;
$ZONE_ACCESS_CACHE=array();
global $PAGE_ACCESS_CACHE;
$PAGE_ACCESS_CACHE=array();
global $CATEGORY_ACCESS_CACHE,$LOADED_ALL_CATEGORY_PERMISSIONS_FOR;
$CATEGORY_ACCESS_CACHE=array();
$LOADED_ALL_CATEGORY_PERMISSIONS_FOR=array();
global $SUBMIT_PERMISSION_CACHE;
$SUBMIT_PERMISSION_CACHE=array();
global $TOTAL_PP_CACHE;
$TOTAL_PP_CACHE=array();
global $PERMISSION_CHECK_LOGGER,$PERMISSIONS_ALREADY_LOGGED;
$PERMISSION_CHECK_LOGGER=NULL;
$PERMISSIONS_ALREADY_LOGGED=array();
}
void handle_permission_check_logging(MEMBER member, ID_TEXT op, array params, boolean result)
Log permission checks to the permission_checks.log file, if it exists.
Parameters…
| Name |
member |
| Description |
The user checking against |
| Type |
MEMBER |
| Name |
op |
| Description |
The function that was called to check a permission |
| Type |
ID_TEXT |
| Name |
params |
| Description |
Parameters to this permission-checking function |
| Type |
array |
| Name |
result |
| Description |
Whether the permission was held |
| Type |
boolean |
(No return value)
function handle_permission_check_logging($member,$op,$params,$result)
{
global $PERMISSION_CHECK_LOGGER,$PERMISSIONS_ALREADY_LOGGED,$SITE_INFO;
if ($PERMISSION_CHECK_LOGGER===NULL)
{
$file_path=get_custom_file_base().'/data_custom/permissioncheckslog.php';
if (((!isset($SITE_INFO['no_extra_logs'])) || ($SITE_INFO['no_extra_logs']=='0')) && (is_file($file_path)) && (is_writable_wrap($file_path)))
{
$PERMISSION_CHECK_LOGGER=fopen($file_path,'at');
if (!function_exists('get_self_url')) require_code('urls');
$self_url=get_self_url(true);
if (!is_string($self_url)) $self_url=get_self_url_easy(); // A weirdness can happen here. If some kind of fatal error happens then output buffers can malfunction making it impossible to use Tempcode as above. So we fall back to this. (This function may be called in a fatal error due to the 'display_php_errors' permissions).
fwrite($PERMISSION_CHECK_LOGGER,chr(10).chr(10).date('Y/m/d h:m:i').' -- '.$self_url.' -- '.$GLOBALS['FORUM_DRIVER']->get_username(get_member()).chr(10));
} else $PERMISSION_CHECK_LOGGER=false;
}
static $fbe=NULL;
if ($fbe===NULL) $fbe=function_exists('fb');
if (($PERMISSION_CHECK_LOGGER===false) && ((!$fbe) || (get_param_integer('keep_firephp',0)==0))) return;
$sz=serialize(array($member,$op,$params));
if (array_key_exists($sz,$PERMISSIONS_ALREADY_LOGGED)) return;
$PERMISSIONS_ALREADY_LOGGED[$sz]=1;
if ($result) return;
require_code('permissions2');
_handle_permission_check_logging($member,$op,$params,$result);
}
void access_denied(ID_TEXT class, string param, boolean force_login)
Show a helpful access-denied page. Has a login ability if it senses that logging in could curtail the error.
Parameters…
| Name |
class |
| Description |
The class of error (e.g. SPECIFIC_PERMISSION) |
| Type |
ID_TEXT |
| Name |
param |
| Description |
The parameteter given to the error message |
| Default value |
|
| Type |
string |
| Name |
force_login |
| Description |
Force the user to login (even if perhaps they are logged in already) |
| Default value |
boolean-false |
| Type |
boolean |
(No return value)
function access_denied($class,$param='',$force_login=false)
{
require_code('failure');
_access_denied($class,$param,$force_login);
}
boolean has_zone_access(MEMBER member, ID_TEXT zone)
Find if a member's has access to a specified zone
Parameters…
| Name |
member |
| Description |
The member being checked whether to have the access |
| Type |
MEMBER |
| Name |
zone |
| Description |
The ID code for the zone being checked |
| Type |
ID_TEXT |
Returns…
| Description |
Whether the member has zone access |
| Type |
boolean |
function has_zone_access($member,$zone)
{
if (running_script('upgrader')) return true;
if ($zone=='') return true;
global $ZONE_ACCESS_CACHE;
if ((!isset($ZONE_ACCESS_CACHE[$member])) && (function_exists('persistant_cache_get')) && (is_guest($member)))
{
$ZONE_ACCESS_CACHE=persistant_cache_get('GUEST_ZONE_ACCESS');
}
if (isset($ZONE_ACCESS_CACHE[$member]))
{
$result=isset($ZONE_ACCESS_CACHE[$member][$zone])?$ZONE_ACCESS_CACHE[$member][$zone]:false;
handle_permission_check_logging($member,'has_zone_access',array($zone),$result);
return $result;
}
$groups=_get_where_clause_groups($member);
if ($groups===NULL) return true;
global $SITE_INFO;
if (((isset($SITE_INFO['mysql_old'])) && ($SITE_INFO['mysql_old']=='1')) || ((!isset($SITE_INFO['mysql_old'])) && (is_file(get_file_base().'/mysql_old'))))
{
$rows=$GLOBALS['SITE_DB']->query('SELECT DISTINCT zone_name FROM '.get_table_prefix().'group_zone_access WHERE ('.$groups.')',NULL,NULL,false,true);
} else
{
$rows=$GLOBALS['SITE_DB']->query('SELECT DISTINCT zone_name FROM '.get_table_prefix().'group_zone_access WHERE ('.$groups.') UNION ALL SELECT DISTINCT zone_name FROM '.get_table_prefix().'member_zone_access WHERE member_id='.strval((integer)$member).' AND active_until>'.strval(time()),NULL,NULL,false,true);
}
$ZONE_ACCESS_CACHE[$member]=array();
foreach ($rows as $row)
{
$ZONE_ACCESS_CACHE[$member][$row['zone_name']]=true;
}
if (!array_key_exists($zone,$ZONE_ACCESS_CACHE[$member])) $ZONE_ACCESS_CACHE[$member][$zone]=false;
if ((function_exists('persistant_cache_set')) && (is_guest($member)))
{
persistant_cache_set('GUEST_ZONE_ACCESS',$ZONE_ACCESS_CACHE);
}
$result=$ZONE_ACCESS_CACHE[$member][$zone];
handle_permission_check_logging($member,'has_zone_access',array($zone),$result);
return $result;
}
boolean has_actual_page_access(?MEMBER member, ?ID_TEXT page, ?ID_TEXT zone, ?array cats, ?mixed sp)
Find if a member's has access to a specified page. Zone permissions are taken into account for wherever the page is found at. Also support for category access and privileges. No support for entry-point checks, which are only carried out as an extension of page permissions when actually at a page.
Parameters…
| Name |
member |
| Description |
The member being checked whether to have the access (NULL: current member) |
| Default value |
|
| Type |
?MEMBER |
| Name |
page |
| Description |
The ID code for the page being checked (NULL: current page) |
| Default value |
|
| Type |
?ID_TEXT |
| Name |
zone |
| Description |
The ID code for the zone being checked (NULL: search) |
| Default value |
|
| Type |
?ID_TEXT |
| Name |
cats |
| Description |
A list of cat details to require access to (c-type-1,c-id-1,c-type-2,c-d-2,...) (NULL: N/A) |
| Default value |
|
| Type |
?array |
| Name |
sp |
| Description |
Either the ID code of a privilege, an array of alternatives that are acceptable (NULL: none required) |
| Default value |
|
| Type |
?mixed |
Returns…
| Description |
Whether the member has zone and page access |
| Type |
boolean |
function has_actual_page_access($member=NULL,$page=NULL,$zone=NULL,$cats=NULL,$sp=NULL)
{
if (running_script('upgrader')) return true;
if ($member===NULL) $member=get_member();
if ($page===NULL) // Assumes $zone is null too
{
$page=get_page_name();
$zone=get_zone_name();
} else
{
if ($zone==='_SELF') $zone=get_zone_name();
elseif (($zone===NULL) || ($zone=='_SEARCH')) $zone=get_module_zone($page);
if ($zone===NULL) $zone=get_zone_name(); // Weird problem that can happen on some AJAX hooks
}
if (!has_zone_access($member,$zone)) return false;
if (!has_page_access($member,$page,$zone)) return false;
if ($cats!==NULL)
{
for ($i=0;$i<intval(floor(floatval(count($cats))/2.0));$i++)
{
if (is_null($cats[$i*2])) continue;
if (!has_category_access($member,$cats[$i*2+0],$cats[$i*2+1])) return false;
}
}
if ($sp!==NULL)
{
if (!is_array($sp)) $sp=array($sp);
$sp_acceptable=false;
foreach ($sp as $perm)
{
if (has_specific_permission($member,$perm,$page,$cats)) $sp_acceptable=true;
}
if (!$sp_acceptable) return false;
}
return true;
}
void load_up_all_self_page_permissions(MEMBER member)
For efficiency reasons, load up loads of page permissions.
Parameters…
| Name |
member |
| Description |
The member being checked whether to have the access |
| Type |
MEMBER |
(No return value)
function load_up_all_self_page_permissions($member)
{
global $TOTAL_PP_CACHE;
$groups=_get_where_clause_groups($member);
if (is_null($groups)) return;
if (array_key_exists($groups,$TOTAL_PP_CACHE)) return;
$TOTAL_PP_CACHE[$groups]=$GLOBALS['SITE_DB']->query('SELECT page_name,zone_name,group_id FROM '.get_table_prefix().'group_page_access WHERE '.$groups);
}
boolean has_page_access(MEMBER member, ID_TEXT page, ID_TEXT zone, boolean at_now)
Find if a member's has access to a specified page, in a specific zone. Note that page access does not imply zone access; you have access a page, but not the zone, so still couldn't see it.
Parameters…
| Name |
member |
| Description |
The member being checked whether to have the access |
| Type |
MEMBER |
| Name |
page |
| Description |
The ID code for the page being checked |
| Type |
ID_TEXT |
| Name |
zone |
| Description |
The ID code for the zone being checked |
| Type |
ID_TEXT |
| Name |
at_now |
| Description |
Whether we want to check we have access to the CURRENT page, using any match tag permissions |
| Default value |
boolean-false |
| Type |
boolean |
Returns…
| Description |
Whether the member has page access |
| Type |
boolean |
function has_page_access($member,$page,$zone,$at_now=false)
{
if (running_script('upgrader')) return true;
global $PAGE_ACCESS_CACHE;
if ((!isset($PAGE_ACCESS_CACHE[$member])) && (function_exists('persistant_cache_get')) && (is_guest($member)))
{
$PAGE_ACCESS_CACHE=persistant_cache_get('GUEST_PAGE_ACCESS');
}
if ((isset($PAGE_ACCESS_CACHE[$member])) && (isset($PAGE_ACCESS_CACHE[$member][$zone.':'.$page])) && ((!$at_now) || ($PAGE_ACCESS_CACHE[$member][$zone.':'.$page])))
{
handle_permission_check_logging($member,'has_page_access',array($page,$zone),$PAGE_ACCESS_CACHE[$member][$zone.':'.$page]);
return $PAGE_ACCESS_CACHE[$member][$zone.':'.$page];
}
$groups=_get_where_clause_groups($member);
if ($groups===NULL) return true;
$pg_where='('.db_string_equal_to('zone_name',$zone).' AND '.db_string_equal_to('page_name',$page).')';
$select='page_name,zone_name';
if ($at_now)
{
$pg_where.=' OR page_name LIKE \''.db_encode_like('\_WILD:'.$page.':%').'\'';
$pg_where.=' OR page_name LIKE \''.db_encode_like($zone.':'.$page.':%').'\'';
$pg_where.=' OR page_name LIKE \''.db_encode_like('\_WILD:\_WILD:%').'\'';
$pg_where.=' OR page_name LIKE \''.db_encode_like($zone.':\_WILD:%').'\'';
$pg_where.=' OR page_name LIKE \''.db_encode_like('\_WILD:'.$page).'\'';
$pg_where.=' OR page_name LIKE \''.db_encode_like($zone.':'.$page).'\'';
$pg_where.=' OR page_name LIKE \''.db_encode_like('\_WILD:\_WILD').'\'';
$pg_where.=' OR page_name LIKE \''.db_encode_like($zone.':\_WILD').'\'';
$pg_where.=' OR page_name LIKE \''.db_encode_like($zone).'\'';
}
$select.=',group_id';
$perhaps=((array_key_exists($groups,$GLOBALS['TOTAL_PP_CACHE'])) && (!$at_now))?$GLOBALS['TOTAL_PP_CACHE'][$groups]:$GLOBALS['SITE_DB']->query('SELECT '.$select.' FROM '.get_table_prefix().'group_page_access WHERE ('.$pg_where.') AND ('.$groups.')');
$groups2=$GLOBALS['FORUM_DRIVER']->get_members_groups($member,false);
$found_match_key_one=false;
$denied_groups=array();
foreach ($groups2 as $group)
{
foreach ($perhaps as $praps)
{
if (strpos($praps['page_name'],':')!==false) $found_match_key_one=true;
if (($praps['group_id']==$group) && (($praps['zone_name']==$zone) || ($praps['zone_name']=='/')))
{
if (($praps['page_name']==$page) || (($at_now) && ($praps['zone_name']=='/') && (match_key_match($praps['page_name'],true))))
{
$denied_groups[$group]=1;
}
}
}
}
if (!$found_match_key_one) $at_now=false; // We found it makes no difference. Let our caching work better.
if (count($denied_groups)==count($groups2))
{
$test=$GLOBALS['SITE_DB']->query_value_null_ok_full('SELECT member_id FROM '.get_table_prefix().'member_page_access WHERE ('.$pg_where.') AND (member_id='.strval((integer)$member).' AND active_until>'.strval(time()).')');
if (!is_null($test))
{
$result=true;
handle_permission_check_logging($member,'has_page_access',array($page,$zone),$result);
if (!$at_now)
{
$PAGE_ACCESS_CACHE[$member][$zone.':'.$page]=$result;
}
if ((function_exists('persistant_cache_set')) && (is_guest($member)))
{
persistant_cache_set('GUEST_PAGE_ACCESS',$PAGE_ACCESS_CACHE);
}
return $result;
}
}
$result=(count($denied_groups)!=count($groups2)); // Has to be explicitly denied to all the usergroups they're in
handle_permission_check_logging($member,'has_page_access',array($page,$zone),$result);
if (!$at_now)
{
$PAGE_ACCESS_CACHE[$member][$zone.':'.$page]=$result;
}
if ((function_exists('persistant_cache_set')) && (is_guest($member)))
{
persistant_cache_set('GUEST_PAGE_ACCESS',$PAGE_ACCESS_CACHE);
}
return $result;
}
void load_up_all_module_category_permissions(MEMBER member, ?ID_TEXT module)
For efficiency reasons, load up loads of category permissions.
Parameters…
| Name |
member |
| Description |
The member being checked whether to have the access |
| Type |
MEMBER |
| Name |
module |
| Description |
The ID code for the module being checked for category access (NULL: all categories) |
| Default value |
|
| Type |
?ID_TEXT |
(No return value)
function load_up_all_module_category_permissions($member,$module=NULL)
{
$groups=_get_where_clause_groups($member);
if ($groups===NULL) return;
global $CATEGORY_ACCESS_CACHE,$LOADED_ALL_CATEGORY_PERMISSIONS_FOR;
if ((array_key_exists($module,$LOADED_ALL_CATEGORY_PERMISSIONS_FOR)) && ($LOADED_ALL_CATEGORY_PERMISSIONS_FOR[$module]))
return;
if (!is_null($module))
{
$catclause='('.db_string_equal_to('module_the_name',$module).') AND ';
$select='category_name';
} else
{
$catclause='';
$select='category_name,module_the_name';
}
$db=$GLOBALS[($module=='forums')?'FORUM_DB':'SITE_DB'];
if ($db->query_value_null_ok_full('SELECT COUNT(*) FROM '.$db->get_table_prefix().'group_category_access WHERE '.$catclause.'('.$groups.')')>1000) return; // Performance issue
global $SITE_INFO;
if (((isset($SITE_INFO['mysql_old'])) && ($SITE_INFO['mysql_old']=='1')) || ((!isset($SITE_INFO['mysql_old'])) && (is_file(get_file_base().'/mysql_old'))))
{
$perhaps=$db->query('SELECT '.$select.' FROM '.$db->get_table_prefix().'group_category_access WHERE '.$catclause.'('.$groups.')',NULL,NULL,false,true);
} else
{
$perhaps=$db->query('SELECT '.$select.' FROM '.$db->get_table_prefix().'group_category_access WHERE '.$catclause.'('.$groups.') UNION ALL SELECT '.$select.' FROM '.$db->get_table_prefix().'member_category_access WHERE '.$catclause.'(member_id='.strval((integer)$member).' AND active_until>'.strval(time()).')',NULL,NULL,false,true);
}
$LOADED_ALL_CATEGORY_PERMISSIONS_FOR[$module]=true;
$CATEGORY_ACCESS_CACHE[$member]=array();
foreach ($perhaps as $row)
{
if (!is_null($module))
{
$for=$module.'/'.$row['category_name'];
} else
{
$for=$row['module_the_name'].'/'.$row['category_name'];
}
$CATEGORY_ACCESS_CACHE[$member][$for]=true;
}
}
boolean has_category_access(MEMBER member, ID_TEXT module, ID_TEXT category)
Find if a member's has access to a specified category
Parameters…
| Name |
member |
| Description |
The member being checked whether to have the access |
| Type |
MEMBER |
| Name |
module |
| Description |
The ID code for the module being checked for category access |
| Type |
ID_TEXT |
| Name |
category |
| Description |
The ID code for the category being checked for access (often, a number cast to a string) |
| Type |
ID_TEXT |
Returns…
| Description |
Whether the member has category access |
| Type |
boolean |
function has_category_access($member,$module,$category)
{
if (running_script('upgrader')) return true;
global $CATEGORY_ACCESS_CACHE,$LOADED_ALL_CATEGORY_PERMISSIONS_FOR;
if ((isset($CATEGORY_ACCESS_CACHE[$member])) && (isset($CATEGORY_ACCESS_CACHE[$member][$module.'/'.$category])))
{
handle_permission_check_logging($member,'has_category_access',array($module,$category),$CATEGORY_ACCESS_CACHE[$member][$module.'/'.$category]);
return $CATEGORY_ACCESS_CACHE[$member][$module.'/'.$category];
}
if (array_key_exists($module,$LOADED_ALL_CATEGORY_PERMISSIONS_FOR))
{
handle_permission_check_logging($member,'has_category_access',array($module,$category),false);
return false;
}
$groups=_get_where_clause_groups($member);
if ($groups===NULL) return true;
$_category=db_string_equal_to('category_name',$category);
$db=$GLOBALS[($module=='forums')?'FORUM_DB':'SITE_DB'];
global $SITE_INFO;
if (((isset($SITE_INFO['mysql_old'])) && ($SITE_INFO['mysql_old']=='1')) || ((!isset($SITE_INFO['mysql_old'])) && (is_file(get_file_base().'/mysql_old'))) || ($member==$GLOBALS['FORUM_DRIVER']->get_guest_id()))
{
$perhaps=$db->query('SELECT category_name FROM '.$db->get_table_prefix().'group_category_access WHERE ('.db_string_equal_to('module_the_name',$module).' AND '.$_category.') AND ('.$groups.')',1,NULL,false,true);
} else
{
$perhaps=$db->query('SELECT category_name FROM '.$db->get_table_prefix().'group_category_access WHERE ('.db_string_equal_to('module_the_name',$module).' AND '.$_category.') AND ('.$groups.') UNION ALL SELECT category_name FROM '.$db->get_table_prefix().'member_category_access WHERE ('.db_string_equal_to('module_the_name',$module).' AND '.$_category.') AND (member_id='.strval((integer)$member).' AND active_until>'.strval(time()).')',1,NULL,false,true);
}
$result=(count($perhaps)>0);
handle_permission_check_logging($member,'has_category_access',array($module,$category),$result);
$CATEGORY_ACCESS_CACHE[$member][$module.'/'.$category]=$result;
return $result;
}
?string _get_where_clause_groups(MEMBER member)
Get the SQL WHERE clause to select for any the given member is in (gets combined with some condition, to check against every).
Parameters…
| Name |
member |
| Description |
The member who's usergroups will be OR'd |
| Type |
MEMBER |
Returns…
| Description |
The SQL query fragment (NULL: admin, so permission regardless) |
| Type |
?string |
function _get_where_clause_groups($member)
{
if ($GLOBALS['FORUM_DRIVER']->is_super_admin($member)) return NULL;
$groups=$GLOBALS['FORUM_DRIVER']->get_members_groups($member,false);
$out='';
foreach ($groups as $id)
{
if (!is_numeric($id)) $id=-10; // Workaround problems in some forum driver data
if ($out!='') $out.=' OR ';
$out.='group_id='.strval($id);
}
if ($out=='') fatal_exit(do_lang_tempcode('USER_NO_GROUP')); // Shouldn't happen
return $out;
}
void enforce_personal_access(MEMBER member_id, ?ID_TEXT permission, ?ID_TEXT permission2, ?MEMBER member_viewing)
Only allow members here that are either the give member, admins, or have a privilege. All other members come up to an error message wall.
Parameters…
| Name |
member_id |
| Description |
The member who typically (i.e. when it's not an administrative override) we want the current member to be. |
| Type |
MEMBER |
| Name |
permission |
| Description |
The override permission the current member must have (NULL: no general override). |
| Default value |
|
| Type |
?ID_TEXT |
| Name |
permission2 |
| Description |
An alternative permission to the 'assume_any_member' permission (NULL: no override). |
| Default value |
|
| Type |
?ID_TEXT |
| Name |
member_viewing |
| Description |
The member who is doing the viewing (NULL: current member). |
| Default value |
|
| Type |
?MEMBER |
(No return value)
function enforce_personal_access($member_id,$permission=NULL,$permission2=NULL,$member_viewing=NULL)
{
if (is_null($member_viewing)) $member_viewing=get_member();
if (is_guest($member_id)) warn_exit(do_lang_tempcode('INTERNAL_ERROR'));
if ((!has_specific_permission($member_viewing,'assume_any_member')) && ((is_null($permission2)) || (!has_specific_permission($member_viewing,$permission2))))
{
if (($member_id!=$member_viewing) || ((!is_null($permission)) && (!has_specific_permission($member_viewing,$permission))))
{
if (!is_null($permission)) access_denied('SPECIFIC_PERMISSION',$permission);
else access_denied('SPECIFIC_PERMISSION',is_null($permission2)?'assume_any_member':$permission2);
}
}
}
void check_specific_permission(ID_TEXT permission, ?array cats, ?MEMBER member_id)
Require presence of a permission for the current member; otherwise exit.
Parameters…
| Name |
permission |
| Description |
The permission to require |
| Type |
ID_TEXT |
| Name |
cats |
| Description |
A list of cat details to require access to (c-type-1,c-id-1,c-type-2,c-d-2,...) (NULL: N/A) |
| Default value |
|
| Type |
?array |
| Name |
member_id |
| Description |
Member to check for (NULL: current user) |
| Default value |
|
| Type |
?MEMBER |
(No return value)
function check_specific_permission($permission,$cats=NULL,$member_id=NULL)
{
if (is_null($member_id)) $member_id=get_member();
if (!has_specific_permission($member_id,$permission,get_page_name(),$cats)) access_denied('SPECIFIC_PERMISSION',$permission);
}
boolean has_some_cat_specific_permission(MEMBER member, ID_TEXT permission, ?ID_TEXT page, ID_TEXT permission_module)
Find if a member has a specified permission in any category
Parameters…
| Name |
member |
| Description |
The member being checked whether to have the permission |
| Type |
MEMBER |
| Name |
permission |
| Description |
The ID code for the permission being checked for |
| Type |
ID_TEXT |
| Name |
page |
| Description |
The ID code for the page being checked (NULL: current page) |
| Type |
?ID_TEXT |
| Name |
permission_module |
| Description |
The ID code for the permission module being checked for |
| Type |
ID_TEXT |
Returns…
| Description |
Whether the member has the permission |
| Type |
boolean |
function has_some_cat_specific_permission($member,$permission,$page,$permission_module)
{
$page_wide_test=has_specific_permission($member,$permission,$page); // To make sure permissions are cached, and test if page-wide or site-wide exists
if ($page_wide_test) return true;
global $SPECIFIC_PERMISSION_CACHE;
if ((array_key_exists($member,$SPECIFIC_PERMISSION_CACHE)) && (array_key_exists($permission,$SPECIFIC_PERMISSION_CACHE[$member])) && (array_key_exists('',$SPECIFIC_PERMISSION_CACHE[$member][$permission])) && (array_key_exists($permission_module,$SPECIFIC_PERMISSION_CACHE[$member][$permission][''])))
{
foreach ($SPECIFIC_PERMISSION_CACHE[$member][$permission][''][$permission_module] as $_permission)
{
if ($_permission==1) return true;
}
}
return false;
}
boolean has_specific_permission(MEMBER member, ID_TEXT permission, ?ID_TEXT page, ?array cats)
Find if a member has a specified permission
Parameters…
| Name |
member |
| Description |
The member being checked whether to have the permission |
| Type |
MEMBER |
| Name |
permission |
| Description |
The ID code for the permission being checked for |
| Type |
ID_TEXT |
| Name |
page |
| Description |
The ID code for the page being checked (NULL: current page) |
| Default value |
|
| Type |
?ID_TEXT |
| Name |
cats |
| Description |
A list of cat details to require access to (c-type-1,c-id-1,c-type-2,c-d-2,...) (NULL: N/A) |
| Default value |
|
| Type |
?array |
Returns…
| Description |
Whether the member has the permission |
| Type |
boolean |
function has_specific_permission($member,$permission,$page=NULL,$cats=NULL)
{
if (running_script('upgrader')) return true;
if ($GLOBALS['IN_MINIKERNEL_VERSION']==1) return true;
if ($page===NULL) $page=get_page_name();
$groups=_get_where_clause_groups($member);
if ($groups===NULL) return true;
global $SPECIFIC_PERMISSION_CACHE;
if (isset($SPECIFIC_PERMISSION_CACHE[$member]))
{
if ($cats!==NULL)
{
$okay=false;
for ($i=0;$i<intval(floor((float)count($cats)/2.0));$i++)
{
if (is_null($cats[$i*2])) continue;
if (isset($SPECIFIC_PERMISSION_CACHE[$member][$permission][''][$cats[$i*2+0]][$cats[$i*2+1]]))
{
$result=$SPECIFIC_PERMISSION_CACHE[$member][$permission][''][$cats[$i*2+0]][$cats[$i*2+1]]==1;
if (!$result)
{
handle_permission_check_logging($member,'has_specific_permission',array_merge(array($permission,$page),is_null($cats)?array():$cats),$result);
return $result;
}
$okay=true;
}
}
if ($okay)
{
$result=$okay;
handle_permission_check_logging($member,'has_specific_permission',array_merge(array($permission,$page),is_null($cats)?array():$cats),$result);
return $result;
}
}
if ($page!='')
{
if (isset($SPECIFIC_PERMISSION_CACHE[$member][$permission][$page]['']['']))
{
$result=$SPECIFIC_PERMISSION_CACHE[$member][$permission][$page]['']['']==1;
handle_permission_check_logging($member,'has_specific_permission',array_merge(array($permission,$page),is_null($cats)?array():$cats),$result);
return $result;
}
}
if (isset($SPECIFIC_PERMISSION_CACHE[$member][$permission]['']['']['']))
{
$result=$SPECIFIC_PERMISSION_CACHE[$member][$permission]['']['']['']==1;
handle_permission_check_logging($member,'has_specific_permission',array_merge(array($permission,$page),is_null($cats)?array():$cats),$result);
return $result;
}
$result=false;
handle_permission_check_logging($member,'has_specific_permission',array_merge(array($permission,$page),($cats===NULL)?array():$cats),$result);
return $result;
}
$groups_list=$GLOBALS['FORUM_DRIVER']->get_members_groups($member,false);
global $SITE_INFO;
$where='';
if ($member!=get_member()) $where.=' AND '.db_string_equal_to('specific_permission',$permission);
if (((isset($SITE_INFO['mysql_old'])) && ($SITE_INFO['mysql_old']=='1')) || ((!isset($SITE_INFO['mysql_old'])) && (is_file(get_file_base().'/mysql_old'))))
{
$perhaps=$GLOBALS['SITE_DB']->query('SELECT specific_permission,the_page,module_the_name,category_name,the_value FROM '.$GLOBALS['SITE_DB']->get_table_prefix().'gsp WHERE ('.$groups.')'.$where,NULL,NULL,false,true);
if ((isset($GLOBALS['FORUM_DB'])) && ($GLOBALS['SITE_DB']->connection_write!=$GLOBALS['FORUM_DB']->connection_write) && (get_forum_type()=='ocf'))
{
$perhaps=array_merge($perhaps,$GLOBALS['FORUM_DB']->query('SELECT specific_permission,the_page,module_the_name,category_name,the_value FROM '.$GLOBALS['FORUM_DB']->get_table_prefix().'gsp WHERE ('.$groups.') AND '.db_string_equal_to('module_the_name','forums').$where,NULL,NULL,false,true));
}
} else
{
$perhaps=$GLOBALS['SITE_DB']->query('SELECT specific_permission,the_page,module_the_name,category_name,the_value FROM '.$GLOBALS['SITE_DB']->get_table_prefix().'gsp WHERE ('.$groups.')'.$where.' UNION ALL SELECT specific_permission,the_page,module_the_name,category_name,the_value FROM '.$GLOBALS['SITE_DB']->get_table_prefix().'msp WHERE member_id='.strval((integer)$member).' AND active_until>'.strval(time()).$where,NULL,NULL,false,true);
if ((isset($GLOBALS['FORUM_DB'])) && ($GLOBALS['SITE_DB']->connection_write!=$GLOBALS['FORUM_DB']->connection_write) && (get_forum_type()=='ocf'))
{
$perhaps=array_merge($perhaps,$GLOBALS['FORUM_DB']->query('SELECT specific_permission,the_page,module_the_name,category_name,the_value FROM '.$GLOBALS['FORUM_DB']->get_table_prefix().'gsp WHERE ('.$groups.') AND '.db_string_equal_to('module_the_name','forums').$where.' UNION ALL SELECT specific_permission,the_page,module_the_name,category_name,the_value FROM '.$GLOBALS['FORUM_DB']->get_table_prefix().'msp WHERE '.db_string_equal_to('module_the_name','forums').' AND member_id='.strval((integer)$member).' AND active_until>'.strval(time()).$where,NULL,NULL,false,true));
}
}
$SPECIFIC_PERMISSION_CACHE[$member]=array();
foreach ($perhaps as $p)
{
if (@$SPECIFIC_PERMISSION_CACHE[$member][$p['specific_permission']][$p['the_page']][$p['module_the_name']][$p['category_name']]!=1)
$SPECIFIC_PERMISSION_CACHE[$member][$p['specific_permission']][$p['the_page']][$p['module_the_name']][$p['category_name']]=$p['the_value'];
}
// Note: due to the way the "detect at override level" code works, the "best of" permission system does not hold with inconsistant overriding against all usergroups
$result=has_specific_permission($member,$permission,$page,$cats);
handle_permission_check_logging($member,'has_specific_permission',array_merge(array($permission,$page),is_null($cats)?array():$cats),$result);
if ($member!=get_member()) unset($SPECIFIC_PERMISSION_CACHE[$member]);
return $result;
}
void check_submit_permission(string range, ?array cats, ?ID_TEXT page)
Check to see if a member's has permission to submit an item. If it doesn't, an error message is outputted.
Parameters…
| Name |
range |
| Description |
The range of permission we are checking to see if they have; these ranges are like trust levels |
| Type |
string |
| Values restricted to |
low mid high cat_low cat_mid cat_high |
| Name |
cats |
| Description |
A list of cat details to require access to (c-type-1,c-id-1,c-type-2,c-d-2,...) (NULL: N/A) |
| Default value |
|
| Type |
?array |
| Name |
page |
| Description |
The ID code for the page being checked (NULL: current page) |
| Default value |
|
| Type |
?ID_TEXT |
(No return value)
function check_submit_permission($range,$cats=NULL,$page=NULL)
{
if (is_null($page)) $page=get_page_name();
if (!has_submit_permission($range,get_member(),get_ip_address(),$page,$cats))
access_denied('SPECIFIC_PERMISSION','submit_'.$range.'range_content');
}
boolean has_submit_permission(string range, MEMBER member, IP ip, ?ID_TEXT page, ?array cats)
Find if a member's has permission to submit
Parameters…
| Name |
range |
| Description |
The range of permission we are checking to see if they have; these ranges are like trust levels |
| Type |
string |
| Values restricted to |
low mid high cat_low cat_mid cat_high |
| Name |
member |
| Description |
The member being checked whether to have the access |
| Type |
MEMBER |
| Name |
ip |
| Description |
The member's IP address |
| Type |
IP |
| Name |
page |
| Description |
The ID code for the page being checked (NULL: current page) |
| Type |
?ID_TEXT |
| Name |
cats |
| Description |
A list of cat details to require access to (c-type-1,c-id-1,c-type-2,c-d-2,...) (NULL: N/A) |
| Default value |
|
| Type |
?array |
Returns…
| Description |
Whether the member can submit in this range |
| Type |
boolean |
function has_submit_permission($range,$member,$ip,$page,$cats=NULL)
{
global $SUBMIT_PERMISSION_CACHE;
if (isset($SUBMIT_PERMISSION_CACHE[$range][$member][$ip][$page][serialize($cats)]))
return $SUBMIT_PERMISSION_CACHE[$range][$member][$ip][$page][serialize($cats)];
$result=NULL;
if (addon_installed('securitylogging'))
{
$test=$GLOBALS['SITE_DB']->query_value_null_ok('usersubmitban_member','the_member',array('the_member'=>$member));
if (!is_null($test)) $result=false;
}
if (is_null($result))
{
$result=has_specific_permission($member,'submit_'.$range.'range_content',$page,$cats);
}
$SUBMIT_PERMISSION_CACHE[$range][$member][$ip][$page][serialize($cats)]=$result;
return $result;
}
void check_some_edit_permission(string range, ?array cats)
Check to see if a member's has permission to edit an item. If it doesn't, an error message is outputted.
Parameters…
| Name |
range |
| Description |
The range of permission we are checking to see if they have; these ranges are like trust levels |
| Type |
string |
| Values restricted to |
low mid high cat_low cat_mid cat_high |
| Name |
cats |
| Description |
A list of cat details to require access to (c-type-1,c-id-1,c-type-2,c-d-2,...) (NULL: N/A) |
| Default value |
|
| Type |
?array |
(No return value)
function check_some_edit_permission($range,$cats=NULL)
{
$ret=false;
$member=get_member();
if (is_guest($member)) $ret=false;
if (has_specific_permission($member,'edit_'.$range.'range_content',get_page_name(),$cats)) $ret=true;
if (has_specific_permission($member,'edit_own_'.$range.'range_content',get_page_name(),$cats)) $ret=true;
if (!$ret) access_denied('SPECIFIC_PERMISSION','edit_own_'.$range.'range_content');
}
void check_edit_permission(string range, ?MEMBER resource_owner, ?array cats, ?ID_TEXT page)
Check to see if a member's has permission to edit an item. If it doesn't, an error message is outputted.
Parameters…
| Name |
range |
| Description |
The range of permission we are checking to see if they have; these ranges are like trust levels |
| Type |
string |
| Values restricted to |
low mid high cat_low cat_mid cat_high |
| Name |
resource_owner |
| Description |
The member that owns this resource (NULL: no-one) |
| Type |
?MEMBER |
| Name |
cats |
| Description |
A list of cat details to require access to (c-type-1,c-id-1,c-type-2,c-d-2,...) (NULL: N/A) |
| Default value |
|
| Type |
?array |
| Name |
page |
| Description |
The ID code for the page being checked (NULL: current page) |
| Default value |
|
| Type |
?ID_TEXT |
(No return value)
function check_edit_permission($range,$resource_owner,$cats=NULL,$page=NULL)
{
if (is_null($page)) $page=get_page_name();
if (!has_edit_permission($range,get_member(),$resource_owner,$page,$cats))
access_denied('SPECIFIC_PERMISSION','edit_'.(($resource_owner==get_member())?'own_':'').$range.'range_content');
}
boolean has_edit_permission(string range, MEMBER member, ?MEMBER resource_owner, ?ID_TEXT page, ?array cats)
Find if a member's has permission to edit
Parameters…
| Name |
range |
| Description |
The range of permission we are checking to see if they have; these ranges are like trust levels |
| Type |
string |
| Values restricted to |
low mid high cat_low cat_mid cat_high |
| Name |
member |
| Description |
The member being checked for access |
| Type |
MEMBER |
| Name |
resource_owner |
| Description |
The member that owns this resource (NULL: no-one) |
| Type |
?MEMBER |
| Name |
page |
| Description |
The ID code for the page being checked (NULL: current page) |
| Type |
?ID_TEXT |
| Name |
cats |
| Description |
A list of cat details to require access to (c-type-1,c-id-1,c-type-2,c-d-2,...) (NULL: N/A) |
| Default value |
|
| Type |
?array |
Returns…
| Description |
Whether the member may edit the resource |
| Type |
boolean |
function has_edit_permission($range,$member,$resource_owner,$page,$cats=NULL)
{
if (is_guest($member)) return false;
if ((!is_null($resource_owner)) && ($member==$resource_owner) && (has_specific_permission($member,'edit_own_'.$range.'range_content',$page,$cats))) return true;
if (has_specific_permission($member,'edit_'.$range.'range_content',$page,$cats)) return true;
return false;
}
void check_delete_permission(string range, ?MEMBER resource_owner, ?array cats, ?ID_TEXT page)
Check if a member's has permission to delete a specific resource. If it doesn't, an error message is outputted.
Parameters…
| Name |
range |
| Description |
The range of permission we are checking to see if they have; these ranges are like trust levels |
| Type |
string |
| Values restricted to |
low mid high cat_low cat_mid cat_high |
| Name |
resource_owner |
| Description |
The member that owns this resource (NULL: no-one) |
| Type |
?MEMBER |
| Name |
cats |
| Description |
A list of cat details to require access to (c-type-1,c-id-1,c-type-2,c-d-2,...) (NULL: N/A) |
| Default value |
|
| Type |
?array |
| Name |
page |
| Description |
The ID code for the page being checked (NULL: current page) |
| Default value |
|
| Type |
?ID_TEXT |
(No return value)
function check_delete_permission($range,$resource_owner,$cats=NULL,$page=NULL)
{
if (is_null($page)) $page=get_page_name();
if (!has_delete_permission($range,get_member(),$resource_owner,$page,$cats))
access_denied('SPECIFIC_PERMISSION','delete_'.(($resource_owner==get_member())?'own_':'').$range.'range_content');
}
boolean has_delete_permission(string range, MEMBER member, ?MEMBER resource_owner, ?ID_TEXT page, ?array cats)
Check to see if a member's has permission to delete a specific resource
Parameters…
| Name |
range |
| Description |
The range of permission we are checking to see if they have; these ranges are like trust levels |
| Type |
string |
| Values restricted to |
low mid high cat_low cat_mid cat_high |
| Name |
member |
| Description |
The member being checked for access |
| Type |
MEMBER |
| Name |
resource_owner |
| Description |
The member that owns this resource (NULL: no-one) |
| Type |
?MEMBER |
| Name |
page |
| Description |
The ID code for the page being checked (NULL: current page) |
| Type |
?ID_TEXT |
| Name |
cats |
| Description |
A list of cat details to require access to (c-type-1,c-id-1,c-type-2,c-d-2,...) (NULL: N/A) |
| Default value |
|
| Type |
?array |
Returns…
| Description |
Whether the member may delete the resource |
| Type |
boolean |
function has_delete_permission($range,$member,$resource_owner,$page,$cats=NULL)
{
if (is_guest($member)) return false;
if ((!is_null($resource_owner)) && ($member==$resource_owner) && (has_specific_permission($member,'delete_own_'.$range.'range_content',$page,$cats))) return true;
if (has_specific_permission($member,'delete_'.$range.'range_content',$page,$cats)) return true;
return false;
}
Tutorial - Adding a Permission
Adding a permission is quite important if you want to stop some people from doing something…you will need a module, and something to protect.
1) In the install function for your module, add the following code to actually add the permission:
Code (php)
add_specific_permission('FOO_SECTION','allowed_access_foobar',false);
That code adds the permission 'allowed_access_foobar' to a section of options named 'FOO_SECTION', and sets it to false for every usergroup.
2) To check if someone's usergroup has this permission, use the following code:
Code (php)
if (has_specific_permission(get_member(),'allowed_access_foobar')) {
That code checks to see if the member has the permission. Things get more complex if the permission may be overrided by pages or categories.
0 reviews: Unrated (average)
There have been no comments yet