File permissions changes

This commit is contained in:
Taras Machyshyn
2019-12-16 16:28:48 +02:00
parent 5e877dd374
commit dfdde2ef83
7 changed files with 146 additions and 147 deletions
+9 -6
View File
@@ -44,7 +44,6 @@ class Manager
if (isset($config)) {
$params = array(
'defaultPermissions' => $config->get('defaultPermissions'),
'permissionMap' => $config->get('permissionMap'),
);
}
@@ -381,11 +380,11 @@ class Manager
{
$fullPath = $this->concatPaths($path);
if (file_exists($fullPath) && is_dir($path)) {
if (file_exists($fullPath) && is_dir($fullPath)) {
return true;
}
$defaultPermissions = $this->getPermissionUtils()->getDefaultPermissions();
$defaultPermissions = $this->getPermissionUtils()->getRequiredPermissions($fullPath);
if (!isset($permission)) {
$permission = (string) $defaultPermissions['dir'];
@@ -393,7 +392,11 @@ class Manager
}
try {
$umask = @umask(0);
$result = mkdir($fullPath, $permission, true);
if ($umask) {
@umask($umask);
}
if (!empty($defaultPermissions['user'])) {
$this->getPermissionUtils()->chown($fullPath);
@@ -484,11 +487,11 @@ class Manager
*/
public function checkCreateFile($filePath)
{
$defaultPermissions = $this->getPermissionUtils()->getDefaultPermissions();
$defaultPermissions = $this->getPermissionUtils()->getRequiredPermissions($filePath);
if (file_exists($filePath)) {
if (!is_writable($filePath) && !in_array($this->getPermissionUtils()->getCurrentPermission($filePath), array($defaultPermissions['file'], $defaultPermissions['dir']))) {
return $this->getPermissionUtils()->setDefaultPermissions($filePath, true);
return $this->getPermissionUtils()->setDefaultPermissions($filePath);
}
return true;
}
@@ -504,7 +507,7 @@ class Manager
}
if (touch($filePath)) {
return $this->getPermissionUtils()->setDefaultPermissions($filePath, true);
return $this->getPermissionUtils()->setDefaultPermissions($filePath);
}
return false;
+85 -94
View File
@@ -28,8 +28,9 @@
************************************************************************/
namespace Espo\Core\Utils\File;
use Espo\Core\Utils,
Espo\Core\Exceptions\Error;
use Espo\Core\Utils;
use Espo\Core\Exceptions\Error;
class Permission
{
@@ -44,47 +45,45 @@ class Permission
protected $permissionErrorRules = null;
protected $params = array(
'defaultPermissions' => array (
'dir' => '0775',
'file' => '0664',
'user' => '',
'group' => '',
),
'permissionMap' => array(
protected $writableMap = [
'data' => [
'recursive' => true,
],
'application/Espo/Modules' => [
'recursive' => false,
],
'client/modules' => [
'recursive' => false,
],
'custom/Espo/Custom' => [
'recursive' => true,
],
];
/** array('0664', '0775') */
'writable' => array(
'data',
'custom',
),
/** array('0644', '0755') */
'readable' => array(
'api',
'application',
'client',
'vendor',
'index.php',
'cron.php',
'rebuild.php',
'main.html',
'reset.html',
),
),
);
protected $permissionRules = array(
'writable' => array('0664', '0775'),
'readable' => array('0644', '0755'),
);
protected $defaultPermissions = [
'dir' => '0755',
'file' => '0644',
'user' => null,
'group' => null,
];
protected $writablePermissions = [
'file' => '0664',
'dir' => '0775',
];
public function __construct(Manager $fileManager, array $params = null)
{
$this->fileManager = $fileManager;
if (isset($params)) {
$this->params = $params;
if ($params) {
foreach ($params as $paramName => $paramValue) {
switch ($paramName) {
case 'defaultPermissions':
$this->defaultPermissions = array_merge($this->defaultPermissions, $paramValue);
break;
}
}
}
}
@@ -93,11 +92,6 @@ class Permission
return $this->fileManager;
}
protected function getParams()
{
return $this->params;
}
/**
* Get default settings
*
@@ -105,14 +99,34 @@ class Permission
*/
public function getDefaultPermissions()
{
$params = $this->getParams();
return $params['defaultPermissions'];
return $this->defaultPermissions;
}
public function getPermissionRules()
public function getWritableMap()
{
return $this->permissionRules;
return $this->writableMap;
}
public function getWritableList()
{
return array_keys($this->writableMap);
}
public function getRequiredPermissions($path)
{
$permission = $this->getDefaultPermissions();
foreach ($this->getWritableMap() as $writablePath => $writableOptions) {
if (!$writableOptions['recursive'] && $path == $writablePath) {
return array_merge($permission, $this->writablePermissions);
}
if ($writableOptions['recursive'] && substr($path, 0, strlen($writablePath)) == $writablePath) {
return array_merge($permission, $this->writablePermissions);
}
}
return $permission;
}
/**
@@ -129,7 +143,7 @@ class Permission
return false;
}
$permission = $this->getDefaultPermissions();
$permission = $this->getRequiredPermissions($path);
$result = $this->chmod($path, array($permission['file'], $permission['dir']), $recurse);
if (!empty($permission['user'])) {
@@ -342,8 +356,8 @@ class Permission
*
* @return bool
*/
protected function chgrpRecurse($path, $group) {
protected function chgrpRecurse($path, $group)
{
if (!file_exists($path)) {
return false;
}
@@ -461,60 +475,38 @@ class Permission
*
* @return bool
*/
public function setMapPermission($mode = null)
public function setMapPermission()
{
$this->permissionError = array();
$this->permissionErrorRules = array();
$params = $this->getParams();
$permissionRules = $this->permissionRules;
if (isset($mode)) {
foreach ($permissionRules as &$value) {
$value = $mode;
}
}
$result = true;
foreach ($params['permissionMap'] as $type => $items) {
$permission = $permissionRules[$type];
foreach ($this->getWritableMap() as $path => $options) {
if (!file_exists($path)) continue;
foreach ($items as $item) {
try {
$this->chmod($path, $this->writablePermissions, $options['recursive']);
} catch (\Throwable $e) {}
if (file_exists($item)) {
/** check is writable */
$res = is_writable($path);
try {
$this->chmod($item, $permission, true);
} catch (\Exception $e) {
}
$res = is_readable($item);
/** check is wtitable */
if ($type == 'writable') {
$res &= is_writable($item);
if (is_dir($item)) {
$name = uniqid();
try {
$res &= $this->getFileManager()->putContents(array($item, $name), 'test');
$res &= $this->getFileManager()->removeFile($name, $item);
} catch (\Exception $e) {
$res = false;
}
}
}
if (!$res) {
$result = false;
$this->permissionError[] = $item;
$this->permissionErrorRules[$item] = $permission;
}
if (is_dir($path)) {
try {
$name = uniqid();
$res &= $this->getFileManager()->putContents([$path, $name], 'test');
$res &= $this->getFileManager()->removeFile($name, $path);
} catch (\Throwable $e) {
$res = false;
}
}
if (!$res) {
$result = false;
$this->permissionError[] = $path;
$this->permissionErrorRules[$path] = $this->writablePermissions;
}
}
return $result;
@@ -607,4 +599,3 @@ class Permission
}
}
@@ -159,11 +159,12 @@ class SystemRequirements
{
return $this->getRequiredList('permissionRequirements', [
'permissionMap.writable',
'permissionMap.readable',
], $additionalData);
], $additionalData, [
'permissionMap.writable' => $this->getFileManager()->getPermissionUtils()->getWritableList(),
]);
}
protected function getRequiredList($type, $checkList, array $additionalData = null)
protected function getRequiredList($type, $checkList, array $additionalData = null, array $predefinedData = [])
{
$config = $this->getConfig();
@@ -172,7 +173,8 @@ class SystemRequirements
foreach ($checkList as $itemName) {
$methodName = 'check' . ucfirst($type);
if (method_exists($this, $methodName)) {
$result = $this->$methodName($itemName, $config->get($itemName), $additionalData);
$itemValue = isset($predefinedData[$itemName]) ? $predefinedData[$itemName] : $config->get($itemName);
$result = $this->$methodName($itemName, $itemValue, $additionalData);
$list = array_merge($list, $result);
}
}
@@ -29,31 +29,9 @@
return [
'defaultPermissions' => [
'dir' => '0775',
'file' => '0664',
'user' => '',
'group' => ''
],
'permissionMap' => [
/** array('0664', '0775') */
'writable' => [
'data',
'custom',
'application/Espo/Modules',
'client/modules'
],
/** array('0644', '0755') */
'readable' => [
'api',
'application',
'client',
'vendor',
'index.php',
'cron.php',
'rebuild.php',
'clear_cache.php'
],
],
'jobMaxPortion' => 15, /** Max number of jobs per one execution. */
'jobPeriod' => 7800, /** Max execution time (in seconds) allocated for a sinle job. If exceeded then set to Failed.*/
'jobPeriodForActiveProcess' => 36000, /** Max execution time (in seconds) allocated for a sinle job with active process. If exceeded then set to Failed.*/
@@ -89,10 +67,8 @@ return [
'crud',
'logger',
'isInstalled',
'defaultPermissions',
'systemUser',
'permissionMap',
'permissionRules',
'defaultPermissions',
'passwordSalt',
'cryptKey',
'apiSecretKeys',
-6
View File
@@ -45,8 +45,6 @@ class Installer
protected $isAuth = false;
protected $permissionMap;
protected $permissionError;
private $passwordHash;
@@ -88,10 +86,6 @@ class Installer
require_once('install/core/SystemHelper.php');
$this->systemHelper = new SystemHelper();
$configPath = $this->getConfig()->getConfigPath();
$this->permissionMap = $this->getConfig()->get('permissionMap');
$this->permissionMap['writable'][] = $configPath;
$this->databaseHelper = new \Espo\Core\Utils\Database\Helper($this->getConfig());
}
+44 -11
View File
@@ -41,6 +41,8 @@ class SystemHelper extends \Espo\Core\Utils\System
protected $combineOperator = '&&';
protected $writableMap;
public function __construct()
{
$this->config = include('config.php');
@@ -50,6 +52,9 @@ class SystemHelper extends \Espo\Core\Utils\System
}
$this->apiPath = $this->config['apiPath'];
$permission = new \Espo\Core\Utils\File\Permission(new \Espo\Core\Utils\File\Manager());
$this->writableMap = $permission->getWritableMap();
}
protected function getMainConfig($optionName, $returns = null)
@@ -124,7 +129,7 @@ class SystemHelper extends \Espo\Core\Utils\System
return $cd.$sudoStr.'chown -R '.$owner.':'.$group.' '.$path;
}
public function getChmodCommand($path, $permissions = array('755'), $isSudo = false, $isFile = null, $isCd = true)
public function getChmodCommand($path, $permissions = ['755'], $isRecursive = true, $isSudo = false, $isFile = null)
{
$path = empty($path) ? '.' : $path;
if (is_array($path)) {
@@ -133,27 +138,32 @@ class SystemHelper extends \Espo\Core\Utils\System
$sudoStr = $isSudo ? 'sudo ' : '';
$cd = $isCd ? $this->getCd(true) : '';
if (is_string($permissions)) {
$permissions = (array) $permissions;
}
if (!isset($isFile) && count($permissions) == 1) {
return $cd. $sudoStr . 'find '.$path.' -type d -exec ' . $sudoStr . 'chmod '.$permissions[0].' {} +';
if ($isRecursive) {
return $sudoStr . 'find '. $path .' -type d -exec ' . $sudoStr . 'chmod '. $permissions[0] .' {} +';
}
return $sudoStr . 'chmod '. $permissions[0] .' '. $path;
}
$bufPerm = (count($permissions) == 1) ? array_fill(0, 2, $permissions[0]) : $permissions;
$commands = array();
if ($isCd) {
$commands[] = $this->getCd();
if ($isRecursive) {
$commands[] = $sudoStr. 'find '.$path.' -type f -exec ' .$sudoStr.'chmod '.$bufPerm[0].' {} +';
$commands[] = $sudoStr . 'find '.$path.' -type d -exec ' .$sudoStr. 'chmod '.$bufPerm[1].' {} +';
} else {
if (file_exists($path) && is_file($path)) {
$commands[] = $sudoStr. 'chmod '. $bufPerm[0] .' '. $path;
} else {
$commands[] = $sudoStr. 'chmod '. $bufPerm[1] .' '. $path;
}
}
$commands[] = $sudoStr. 'find '.$path.' -type f -exec ' .$sudoStr.'chmod '.$bufPerm[0].' {} +';//.'chmod '.$bufPerm[0].' $(find '.$path.' -type f)';
$commands[] = $sudoStr . 'find '.$path.' -type d -exec ' .$sudoStr. 'chmod '.$bufPerm[1].' {} +';//.'chmod '.$bufPerm[1].' $(find '.$path.' -type d)';
if (count($permissions) >= 2) {
return implode(' ' . $this->combineOperator . ' ', $commands);
}
@@ -187,7 +197,7 @@ class SystemHelper extends \Espo\Core\Utils\System
* @param bool $isFile
* @return string
*/
public function getPermissionCommands($path, $permissions = array('644', '755'), $isSudo = false, $isFile = null, $changeOwner = true)
public function getPermissionCommands($path, $permissions = ['644', '755'], $isSudo = false, $isFile = null, $changeOwner = true, $isCd = true)
{
if (is_string($path)) {
$path = array_fill(0, 2, $path);
@@ -195,7 +205,30 @@ class SystemHelper extends \Espo\Core\Utils\System
list($chmodPath, $chownPath) = $path;
$commands = array();
$commands[] = $this->getChmodCommand($chmodPath, $permissions, $isSudo, $isFile);
if ($isCd) {
$commands[] = $this->getCd();
}
$chmodPath = (array) $chmodPath;
$pathList = [];
$recursivePathList = [];
foreach ($chmodPath as $pathItem) {
if (isset($this->writableMap[$pathItem]) && !$this->writableMap[$pathItem]['recursive']) {
$pathList[] = $pathItem;
continue;
}
$recursivePathList[] = $pathItem;
}
if (!empty($pathList)) {
$commands[] = $this->getChmodCommand($pathList, $permissions, false, $isSudo, $isFile);
}
if (!empty($recursivePathList)) {
$commands[] = $this->getChmodCommand($recursivePathList, $permissions, true, $isSudo, $isFile);
}
if ($changeOwner) {
$chown = $this->getChownCommand($chownPath, $isSudo, false);
+1 -1
View File
@@ -50,7 +50,7 @@ if (!$installer->checkPermission()) {
$changeOwner = false;
}
}
$result['errorMsg'] = $langs['messages']['Permission denied to'] . ':<br><pre>/'.implode('<br>/', $urls).'</pre>';
$result['errorMsg'] = $langs['messages']['Permission denied to'] . ':<br><pre>'.implode('<br>', $urls).'</pre>';
$result['errorFixInstruction'] = str_replace( '"{C}"' , $instruction, $langs['messages']['permissionInstruction']) . "<br>" .
str_replace( '{CSU}' , $instructionSU, $langs['messages']['operationNotPermitted']);
}