Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unify logic of e_user_model::checkAdminPerms() and getperms() #5070

Merged
merged 1 commit into from Sep 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
91 changes: 37 additions & 54 deletions class2.php
Expand Up @@ -1309,33 +1309,54 @@ function check_class($var, $userclass = null, $uid = 0)


/**
* @param $arg
* @param bool|mixed|string $ap
* @param mixed $path
* @return bool
* Check a requested permission set against admin permissions or plugin admin permissions.
*
* The constant {@link ADMIN} must be truthy or this function will always return {@link false}.
*
* @param string $arg The serialized requested access code or codes which will match if any of the codes are
* in the admin user's admin permissions.
* This is a pipe-delimited (`|`) list of access codes.
* Example for admin permissions: `C|4`.
* Use this exact value to enter plugin admin permissions checking mode: `P`.
* @param string|int|null $ap The serialized admin permissions or plugin admin permissions to check against.
* Exclude or use {@link null} to use the global {@link ADMINPERMS} constant.
* This is a dot-delimited (`.`) list of access codes.
* Accepts an integer that will be cast to a string for backwards compatibility.
* Example: `C.F.G.1.U0.U1.U2.P3.P4.English`.
* @param string|null $path The path to the file requesting the permission check.
* This is only used when checking plugin admin permissions.
* Exclude or use {@link null} to use the current page, which auto-detects the plugin path.
* Example: `http://localhost/e107v2/e107_plugins/gallery/admin_config.php` along with the
* first argument set to `P` will check the plugin admin permissions for plugin `gallery`.
* @return bool true if the user has the requested admin permissions, false otherwise.
* @see class2Test::testGetPerms() for examples.
* @deprecated v2.3.3 Use one of the object-oriented alternatives:
* {@link e_user_model::checkAdminPerms()} to check a specific user's admin permissions.
* {@link e_user_model::checkPluginAdminPerms()} to check a specific user's plugin admin
* permissions.
* {@link e_userperms::simulateHasAdminPerms()} to simulate a user's admin permissions.
* {@link e_userperms::simulateHasPluginAdminPerms()} to simulate a user's plugin admin
* permissions.
* {@link e107::getUser()} can be used to get the current user.
*/
function getperms($arg, $ap = ADMINPERMS, $path = e_SELF)
function getperms($arg, $ap = null, $path = null)
{
// $ap = "4"; // Just for testing.
if(trim($ap) === '')
if(is_null($ap))
{
return false;
$ap = defset('ADMINPERMS', e107::getUser()->getAdminPerms());
}

if(deftrue('USE_NEW_GETPERMS')) // Add to e107_config.php.
if(is_null($path))
{
return e107::getUser()->checkAdminPerms($arg,$ap,$path);
$path = defset('e_SELF');
}

if(!deftrue('ADMIN'))
{
return false;
}

if($arg === 0) // Common-error avoidance with getperms(0)
{
$arg = '0';
}
$arg = trim((string) $arg); // Common-error avoidance with getperms(0) or getperms(' ').

if ($ap === '0' || $ap === '0.') // BC fix.
{
Expand All @@ -1345,38 +1366,11 @@ function getperms($arg, $ap = ADMINPERMS, $path = e_SELF)
if ($arg === 'P' && preg_match('#(.*?)/' .e107::getInstance()->getFolder('plugins'). '(.*?)/(.*?)#', $path, $matches))
{
$sql = e107::getDb('psql');
/* $id = e107::getPlug()->load($matches[2])->getId();
$arg = 'P'.$id;*/

if ($sql->select('plugin', 'plugin_id', "plugin_path = '".$matches[2]."' LIMIT 1 "))
{
$row = $sql->fetch();
$arg = 'P'.$row['plugin_id'];
}
}

$ap_array = explode('.',$ap);

if (in_array($arg,$ap_array,false))
{
return true;
}

if(strpos($arg, "|"))
{
$tmp = explode("|", $arg);
foreach($tmp as $val)
{
if(in_array($val,$ap_array))
{
return true;
}
}
return e_userperms::simulateHasPluginAdminPerms($sql, $matches[2], $ap);
}


return false;

return e_userperms::simulateHasAdminPerms($arg, $ap);
}

/**
Expand Down Expand Up @@ -1639,17 +1633,6 @@ function init_session()
define('USERJOINED', '');
define('e_CLASS_REGEXP', '(^|,)(253|254|250|251|0)(,|$)');
define('e_NOBODY_REGEXP', '(^|,)255(,|$)');

if(deftrue('USE_NEW_GETPERMS')) // Add to e107_config.php.
{
$user->set('user_id', 1);
$user->set('user_name','e107-cli');
$user->set('user_admin', 1);
$user->set('user_perms', '0');
$user->set('user_class', '');
$user->set('user_join', '');
}

return;
}

Expand Down
76 changes: 76 additions & 0 deletions e107_handlers/user_handler.php
Expand Up @@ -2460,4 +2460,80 @@ function updatePerms($uid, $permArray)
e107::getLog()->add('ADMIN_01',$logMsg,E_LOG_INFORMATIVE,'');
}

/**
* Simulate whether a user has admin permissions based on the requested access code(s) and admin's permissions.
*
* @param string $requestedAccess The serialized requested access code or codes which will match if any of the
* codes are in the admin user's admin permissions.
* This is a pipe-delimited (`|`) list of access codes.
* Example: `C|4`
* @param string $adminPermissions The serialized admin user's admin permissions.
* This is a dot-delimited (`.`) list of access codes.
* Example: `C.F.G.L.T.1.X.I.8.K.3.4.U0.U1.U2.U3.6.A.A1.A2.TMP.2.Z.P3.P4.English`
* @return bool true if the user has matching permissions, false otherwise.
*/
public static function simulateHasAdminPerms($requestedAccess, $adminPermissions)
{
if(trim($adminPermissions) === '')
{
return false;
}

if($requestedAccess === 0)
{
$requestedAccess = '0';
}

if($adminPermissions === '0' || $adminPermissions === '0.')
{
return true;
}

$adminPermissionsArray = explode('.', $adminPermissions);

if(in_array($requestedAccess, $adminPermissionsArray, false))
{
return true;
}

if(strpos($requestedAccess, '|'))
{
$requestedAccessCodes = explode('|', $requestedAccess);
foreach($requestedAccessCodes as $requestedAccessCode)
{
if(in_array($requestedAccessCode, $adminPermissionsArray))
{
return true;
}
}
}

return false;
}

/**
* Simulate whether a user has admin permissions to a plugin.
*
* @param e_db $db The database handle to query installed plugins.
* @param string $pluginName The plugin name, not the plugin path like in {@link getperms()}.
* @param string $adminPermissions The serialized admin user's admin permissions.
* This is a dot-delimited (`.`) list of access codes.
* Example: `C.F.G.L.T.1.X.I.8.K.3.4.U0.U1.U2.U3.6.A.A1.A2.TMP.2.Z.P3.P4.English`
* @return bool true if the user has matching permissions, false otherwise.
*/
public static function simulateHasPluginAdminPerms($db, $pluginName, $adminPermissions)
{
$arg = "0";
if($db->select(
'plugin',
'plugin_id',
"plugin_path = :plugin_path LIMIT 1",
["plugin_path" => $pluginName]
))
{
$row = $db->fetch();
$arg = 'P' . $row['plugin_id'];
}
return self::simulateHasAdminPerms($arg, $adminPermissions);
}
}
77 changes: 22 additions & 55 deletions e107_handlers/user_model.php
Expand Up @@ -646,70 +646,37 @@ final public function checkClass($class, $allowMain = true)
}

/**
* @param str $arg
* @param str $ap
* @param str $path
* @return bool
* Check if this user has the provided admin permissions.
*
* @param string $perm_str The serialized requested access code or codes which will match if any of the codes are in
* the admin user's admin permissions.
* This is a pipe-delimited (`|`) list of access codes.
* Example: `C|4`
* @return bool true if the user has the matching admin permissions, false otherwise.
*/
final public function checkAdminPerms($arg, $ap = null, $path = null)
final public function checkAdminPerms($perm_str)
{
// FIXME - method to replace getperms()

if(!$this->isAdmin())
{
return false;
}

if($ap === null)
{
$ap = $this->getAdminPerms();
}

if($arg === 0) // Common-error avoidance with getperms(0)
{
$arg = '0';
}

if ($ap === '0' || $ap === '0.') // BC fix.
{
return true;
}

if ($arg === 'P' && !empty($path) && preg_match('#(.*?)/' .e107::getInstance()->getFolder('plugins'). '(.*?)/(.*?)#', $path, $matches))
{
$sql = e107::getDb('psql');
/* $id = e107::getPlug()->load($matches[2])->getId();
$arg = 'P'.$id;*/

if ($sql->select('plugin', 'plugin_id', "plugin_path = '".$matches[2]."' LIMIT 1 "))
{
$row = $sql->fetch();
$arg = 'P'.$row['plugin_id'];
}
}

$ap_array = explode('.',$ap);

if (in_array($arg,$ap_array,false))
{
return true;
}

if(strpos($arg, "|"))
{
$tmp = explode("|", $arg);
foreach($tmp as $val)
{
if(in_array($val,$ap_array))
{
return true;
}
}
}
$ap = $this->getAdminPerms();

return e_userperms::simulateHasAdminPerms($perm_str, $ap);
}

return false;
//return ($this->isAdmin() && getperms($perm_str, $this->getAdminPerms()));
/**
* Check if this user has permissions to administer the given plugin.
*
* @param string $plugin_name The name of the plugin, not the path like in {@see getperms()}.
* @return bool true if the user has admin permissions for the plugin, false otherwise.
*/
final public function checkPluginAdminPerms($plugin_name)
{
$sql = e107::getDb('psql');
$ap = $this->getAdminPerms();
return e_userperms::simulateHasPluginAdminPerms($sql, $plugin_name, $ap);
}

/**
Expand Down
4 changes: 4 additions & 0 deletions e107_tests/tests/unit/class2Test.php
Expand Up @@ -52,7 +52,11 @@ function testGetPerms()
$result = getperms('U1|U2', '0.');
$this->assertTrue($result);

$result = getperms('0', ' ');
$this->assertFalse($result);

$result = getperms(0, '0');
$this->assertTrue($result);

$pid = e107::getDb()->retrieve('plugin', 'plugin_id', "plugin_path = 'gallery'");

Expand Down