Hack to MenuManager to easier Menu Navigation control based on FEU Groups
Posted: Sun Mar 16, 2008 12:33 am
I looked for a long time on the forum and various places to see how best to implement something simple, like a way to control display of the menu navigation based on group access from FEU. I saw the funny page alias exclude prefix thing, but that appears to require me to hack up a simple nav menu template and force a kind of ordering that I may not want and makes it harder to assign permissions for each page.
So assuming there was not a better way, I just added the following code to action.default.php for CustomContent which, before it passes all the nav menu nodes to smarty, runs through each node and does an access check. If the access is not allowed, based on group membership, it deletes the node. NOTE: This in no way restricts access for the given page if someone where to just access the url directly - you should check that on your on. But this will hide the nav link for the page which is sometimes a good poor man's approach to security if your stuff isn't all that sensitive.
I decided to make the allowed group access to be overloaded in the Title Attribute field for a given content page. This seemed to be the only place I could put something without adding a whole new database field and a lot more code changes in other files.
The format is: 'access:group1[,group2,] ..." in that field. The field is cleansed of this data before it is passed on to be rendered so that if you use it, it won't show up. So you could have something like "access:Managers This is my description" in the field and when rendered, just the "This is my description" will show up.
Hope this might be helpful to others, I really like CMSMS, a very cool package. The code below is a snippet with a few lines of code before it to give you an indicator of where to plug it in:
#See if origdepth was ever set... if not, then get it from the prevdepth set earlier
if ($origdepth == 0)
$origdepth = $prevdepth;
if (isset($rootnode) && $getchildren)
$this->GetChildNodes($rootnode, $nodelist, $gCms, $prevdepth, $count, $params, $origdepth, $showparents);
// Hack by DML - add access control - if the access: xxxx is on the titleattribute for the node, then restrict access
// First setup an ability to access the FEU module to look at groups
$feu_module =& $this->GetModuleInstance('FrontEndUsers');
$feu_uid = $feu_module->LoggedInId();
foreach ($nodelist as $nodeid => $node) {
// See if we have the special access:x,y,z tag in tite attribute, if so grab it, if not, skip
if (!preg_match('/access:\s*(.*)?\s*/',$node->titleattribute, $matches)) {
// Nothing here to see ... keep moving along folks
continue ;
}
$access_allowed = false ; // Assume the worst
// We have a winner ...
// Before we forget, remove the nonstandard access: stuff from the title attribute field
$nodelist[$nodeid]->titleattribute = preg_replace('/access:.*?\s*/','',$node->titleattribute) ;
// split out the access as csv and check each group against our access list
$groups = explode(',',$matches[1]) ;
// Logic is to loop until we find a match, once we do we set a good flag and break out
foreach ($groups as $group) {
$feu_gid = $feu_module->GetGroupID($group);
// If they have access, then mark it and break out
if( $feu_module->MemberOfGroup($feu_uid, $feu_gid) ) {
$access_allowed = true ;
break ;
}
}
// If access not allowed, we delete the node completed so it doesn't get passed into smarty at all
if (!$access_allowed) {
unset($nodelist[$nodeid]) ; // Remove this bad boy so it won't be seen
}
}
// End of hack
So assuming there was not a better way, I just added the following code to action.default.php for CustomContent which, before it passes all the nav menu nodes to smarty, runs through each node and does an access check. If the access is not allowed, based on group membership, it deletes the node. NOTE: This in no way restricts access for the given page if someone where to just access the url directly - you should check that on your on. But this will hide the nav link for the page which is sometimes a good poor man's approach to security if your stuff isn't all that sensitive.
I decided to make the allowed group access to be overloaded in the Title Attribute field for a given content page. This seemed to be the only place I could put something without adding a whole new database field and a lot more code changes in other files.
The format is: 'access:group1[,group2,] ..." in that field. The field is cleansed of this data before it is passed on to be rendered so that if you use it, it won't show up. So you could have something like "access:Managers This is my description" in the field and when rendered, just the "This is my description" will show up.
Hope this might be helpful to others, I really like CMSMS, a very cool package. The code below is a snippet with a few lines of code before it to give you an indicator of where to plug it in:
#See if origdepth was ever set... if not, then get it from the prevdepth set earlier
if ($origdepth == 0)
$origdepth = $prevdepth;
if (isset($rootnode) && $getchildren)
$this->GetChildNodes($rootnode, $nodelist, $gCms, $prevdepth, $count, $params, $origdepth, $showparents);
// Hack by DML - add access control - if the access: xxxx is on the titleattribute for the node, then restrict access
// First setup an ability to access the FEU module to look at groups
$feu_module =& $this->GetModuleInstance('FrontEndUsers');
$feu_uid = $feu_module->LoggedInId();
foreach ($nodelist as $nodeid => $node) {
// See if we have the special access:x,y,z tag in tite attribute, if so grab it, if not, skip
if (!preg_match('/access:\s*(.*)?\s*/',$node->titleattribute, $matches)) {
// Nothing here to see ... keep moving along folks
continue ;
}
$access_allowed = false ; // Assume the worst
// We have a winner ...
// Before we forget, remove the nonstandard access: stuff from the title attribute field
$nodelist[$nodeid]->titleattribute = preg_replace('/access:.*?\s*/','',$node->titleattribute) ;
// split out the access as csv and check each group against our access list
$groups = explode(',',$matches[1]) ;
// Logic is to loop until we find a match, once we do we set a good flag and break out
foreach ($groups as $group) {
$feu_gid = $feu_module->GetGroupID($group);
// If they have access, then mark it and break out
if( $feu_module->MemberOfGroup($feu_uid, $feu_gid) ) {
$access_allowed = true ;
break ;
}
}
// If access not allowed, we delete the node completed so it doesn't get passed into smarty at all
if (!$access_allowed) {
unset($nodelist[$nodeid]) ; // Remove this bad boy so it won't be seen
}
}
// End of hack