Member site page(s) access permissions using LIKE to compare members permissions field against site page permissions field.

6 posts by 2 authors in: Forums > CMS Builder
Last Post: January 15, 2016   (RSS)

By Mikey - January 14, 2016

I'm trying to set up an intranet for a client. The way I'm setting site page access permissions are as follows:

I have an category menu called "intranet_access_categories" were 30 plus categories exist within the name field. The site administrator will have the ability to create additional categories as need over time.

In the "members" section I have a multi-select field called "department_intranet_access" which pulls it's list data from the "intranet_access_categories".   A member can have one selection or multiple selections from the "department_intranet_access" to give them access to various site pages with matching (LIKE) .

There are various intranet site page section editors. In regards to this post I'm referencing the section editor "accounting_intranet" which has a field called "dept_intranet_access" which also pulls it's list data from the ""intranet_access_categories". An intranet site page can have one selection or multiple selections from the "dept_intranet_access" to give members with matching (LIKE) categories. 

If a site visitor is not a user they are redirected to the home page using !$CURRENT_USER
If a member is not given permission to access the intranet they are redirected to the home page using $CURRENT_USER['intranet_access'] == '0'
And if a member's access permissions do not match that of the site page, they are redirected to the home page using $membersRecords == !$intranetString

That's the idea of what needs to be achieve, however there's an issue with the $intranetString LIKE filtering. What's wrong is that if a member has ANY category in "department_intranet_access" that matches any intranet site page's "dept_intranet_access" permission then they have access to all intranet site pages regardless of whether the remaining intranet site pages match the same category or not.

I suspect that my filtering method is incorrect, of the $membersRecords == !$intranetString is bad.

Anyone have any suggestions?

Here's my code:

  // load record from 'accounting_intranet'
  list($accounting_intranetRecords, $accounting_intranetMetaData) = getRecords(array(
    'tableName'   => 'accounting_intranet',
    'where'       => whereRecordNumberInUrl(0),
    'loadUploads' => true,
    'allowSearch' => false,
    'limit'       => '1',
  ));
  $accounting_intranetRecord = @$accounting_intranetRecords[0]; // get first record
  if (!$accounting_intranetRecord) { dieWith404("Record not found!"); } // show error message if no record found
  
//=========== permission filter ==========//
// members can have access to multiple site pages within the intranet, so there's a multi-select list that a member can be given access to multiple labels' values using a num value comparison of LIKE.

// compare accounting_intranetRecord's multi-select settings for the field "dept_intranet_access" and compare it to the members accounts field "department_intranet_access". If there's a match, allow acces to site page, otherwise redirect to home page. 
  $intranetString = '';
  if(is_array(@$accounting_intranetRecord['dept_intranet_access:values'])){
  
    $arrayCounters = count($accounting_intranetRecord['dept_intranet_access:values']);

    foreach($accounting_intranetRecord['dept_intranet_access:values'] as $keys => $filterItems){
      $intranetString .= "department_intranet_access LIKE '%\t$filterItems\t%'";
  
      if(($keys+1) != $arrayCounters){
        $intranetString .= " OR ";
      }
    }
  }
//=========== members access filtered ==========//  
// load records from 'members'
  list($membersRecords, $membersMetaData) = getRecords(array(
    'tableName'   => 'members',
    'where'       => $intranetString,
    'loadUploads' => true,
    'allowSearch' => false,
  ));
// If there's no match in the LIKE comparison intranetString, then redirect member to home page. 
  if (!$CURRENT_USER || $CURRENT_USER['intranet_access'] == '0' || $membersRecords == !$intranetString) { redirectBrowserToUrl("http://domainname.com/"); }

Thanks, Zicky

By gregThomas - January 14, 2016 - edited: January 14, 2016

Hey Zicky, 

I think this line might be the cause of the issue:

// If there's no match in the LIKE comparison intranetString, then redirect member to home page.   if (!$CURRENT_USER || $CURRENT_USER['intranet_access'] == '0' || $membersRecords == !$intranetString) { redirectBrowserToUrl("http://domainname.com/"); }

So this bit:

!$CURRENT_USER || $CURRENT_USER['intranet_access'] == '0'

looks good to me, but I'm not sure what this bit is meant to do:

 || $membersRecords == !$intranetString

The member records are returned as an array, and $intranetString is a string, so I think those two items could never match. Also the ! at the beginning of $intranetString would mean it's being treated as a boolean instead of a string.

Could you give me a few more details on what this line of code needs to do?

Cheers,

Greg

Greg Thomas







PHP Programmer - interactivetools.com

By Mikey - January 14, 2016 - edited: January 14, 2016

PS: the line $membersRecords == !$intranetString is a complete failure... I think it's looping within itself, but I was attempting to write the code to redirect if the comparison of the member's permissions and the department's permissions did not match.

By gregThomas - January 15, 2016

Hi Zicky,

Thanks for the detailed explanation, now I understand what's needed. I've written some code that I think will do what you're looking for:


// load record from 'accounting_intranet'
list($accounting_intranetRecords, $accounting_intranetMetaData) = getRecords(array(
  'tableName'   => 'accounting_intranet',
  'where'       => whereRecordNumberInUrl(0),
  'loadUploads' => true,
  'allowSearch' => false,
  'limit'       => '1',
));
$accounting_intranetRecord = @$accounting_intranetRecords[0]; // get first record
if (!$accounting_intranetRecord) { dieWith404("Record not found!"); } // show error message if no record found
  
//Convert the departments the user has access to from a string to an array.
$userDeptValues = explode("\t", trim($CURRENT_USER['department_intranet_access'], "\t"));

//Cycle through the department access items, and check if we have matching values in the user department values.
if(is_array(@$accounting_intranetRecord['dept_intranet_access:values'])){
  $hasAccess = false;
  foreach($accounting_intranetRecord['dept_intranet_access:values'] as $keys => $value){
    if(in_array($value, $userDeptValues)){
      $hasAccess = true;
    }
  }
}

//If the user doesn't have access, redirect them away from this page.
if(!$hasAccess){
  redirectBrowserToUrl("http://domainname.com/"); 
  exit;
}

I've re-written the code so instead of looking for the member in the members section, we look through the current users access by converting their access levels from a string into an array. 

After this is done, we cycle through the sections access levels and check if the user and and sections departments ever match up. If they do we set the variable hasAccess to true. 

If the hasAccess variable is true then we allow the user to see the page, if not we redirect the user to a different page.

Cheers,

Greg

Greg Thomas







PHP Programmer - interactivetools.com

By Mikey - January 15, 2016

Hey Greg,

Thanks for the help... works like a charm, and does exactly what I needed it to do.
Many thanks!!!

Zicky