mirror of
https://github.com/espocrm/espocrm.git
synced 2026-03-10 04:47:02 +00:00
Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c5bc7136c7 | ||
|
|
18ba671417 | ||
|
|
6141bfd1fb | ||
|
|
4e4b51c4f1 | ||
|
|
83ac300aa3 | ||
|
|
f641a3c9c6 | ||
|
|
18a4782bf1 | ||
|
|
f1fddb7325 | ||
|
|
9c864af409 | ||
|
|
7cd332228a | ||
|
|
54c534736f | ||
|
|
6f07862572 | ||
|
|
54863ca6a4 | ||
|
|
70499e504c | ||
|
|
697565f95c | ||
|
|
94f1501c96 | ||
|
|
145b0e2c7b | ||
|
|
7057b3ba82 | ||
|
|
f6eecce135 | ||
|
|
1f0d105685 | ||
|
|
7caf841edd | ||
|
|
7cd82b1e03 | ||
|
|
2c8a21fc04 | ||
|
|
102ec389b9 | ||
|
|
f07895eeb0 | ||
|
|
a1570c7666 |
@@ -35,6 +35,7 @@ use Espo\Core\{
|
||||
Exceptions\Conflict,
|
||||
Exceptions\Error,
|
||||
Utils\Log,
|
||||
Utils\Config,
|
||||
};
|
||||
|
||||
use Throwable;
|
||||
@@ -72,9 +73,12 @@ class ErrorOutput
|
||||
|
||||
private $log;
|
||||
|
||||
public function __construct(Log $log)
|
||||
private $config;
|
||||
|
||||
public function __construct(Log $log, Config $config)
|
||||
{
|
||||
$this->log = $log;
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
public function process(
|
||||
@@ -138,6 +142,10 @@ class ErrorOutput
|
||||
|
||||
$logMessage = "($statusCode) " . implode("; ", $logMessageItemList);
|
||||
|
||||
if ($this->toPrintTrace()) {
|
||||
$logMessage .= " :: " . $exception->getTraceAsString();
|
||||
}
|
||||
|
||||
$this->log->log($logLevel, $logMessage);
|
||||
|
||||
$toPrintBodyXStatusReason = !in_array(
|
||||
@@ -256,4 +264,9 @@ class ErrorOutput
|
||||
|
||||
$this->log->log('debug', $logMessage);
|
||||
}
|
||||
|
||||
private function toPrintTrace(): bool
|
||||
{
|
||||
return (bool) $this->config->get('logger.printTrace');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,6 +314,10 @@ class Htmlizer
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($additionalData && array_key_exists($attribute, $additionalData)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$type = $entity->getAttributeType($attribute);
|
||||
|
||||
$fieldType = $entity->getAttributeParam($attribute, 'fieldType');
|
||||
|
||||
@@ -416,7 +416,7 @@ class Importer
|
||||
$parentType = $email->get('parentType');
|
||||
$parentId = $email->get('parentId');
|
||||
|
||||
if (!$parentId || ~$parentType) {
|
||||
if (!$parentId || !$parentType) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -164,12 +164,12 @@ class ConfigWriter
|
||||
unset($data[$key]);
|
||||
}
|
||||
|
||||
$this->saveData($configPath, $data, 'microtime');
|
||||
|
||||
if ($toSaveInternal) {
|
||||
$this->saveData($internalConfigPath, $dataInternal, 'microtimeInternal');
|
||||
}
|
||||
|
||||
$this->saveData($configPath, $data, 'microtime');
|
||||
|
||||
$this->changedData = [];
|
||||
$this->removeParamList = [];
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ class CaseObj extends \Espo\Core\Repositories\Database implements
|
||||
|
||||
protected $streamService;
|
||||
|
||||
public function afterSave(Entity $entity, array $options = [])
|
||||
protected function afterSave(Entity $entity, array $options = [])
|
||||
{
|
||||
parent::afterSave($entity, $options);
|
||||
|
||||
|
||||
@@ -329,7 +329,7 @@ class Activities implements
|
||||
$seed->hasAttribute('dateEndDate') ?
|
||||
['dateEndDate', 'dateEndDate'] : ['""', 'dateEndDate']
|
||||
),
|
||||
['"Meeting"', '_scope'],
|
||||
['"' . $targetEntityType . '"', '_scope'],
|
||||
'assignedUserId',
|
||||
'assignedUserName',
|
||||
'parentType',
|
||||
|
||||
@@ -68,6 +68,7 @@ return [
|
||||
'level' => 'WARNING', /** DEBUG, INFO, NOTICE, WARNING, ERROR, CRITICAL, ALERT, EMERGENCY */
|
||||
'rotation' => true,
|
||||
'maxFileNumber' => 30,
|
||||
'printTrace' => false,
|
||||
],
|
||||
'authenticationMethod' => 'Espo',
|
||||
'globalSearchEntityList' => [
|
||||
|
||||
@@ -234,6 +234,10 @@ class Attachment extends Record
|
||||
throw new Error("Field type '{$fieldType}' is not allowed for {$role}.");
|
||||
}
|
||||
|
||||
if ($this->getUser()->isAdmin() && $relatedEntityType === 'Settings') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
!$this->getAcl()->checkScope($relatedEntityType, 'create')
|
||||
&&
|
||||
|
||||
@@ -399,7 +399,6 @@ class InboundEmail extends RecordService implements
|
||||
if ($emailAccount->get('keepFetchedEmailsUnread')) {
|
||||
if (
|
||||
is_array($flags) &&
|
||||
count($flags) &&
|
||||
empty($flags[Storage::FLAG_SEEN])
|
||||
) {
|
||||
unset($flags[Storage::FLAG_RECENT]);
|
||||
|
||||
@@ -123,7 +123,7 @@ class Language
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$this->acl->check($scope)) {
|
||||
if (!$this->acl->tryCheck($scope)) {
|
||||
unset($data[$scope]);
|
||||
unset($data['Global']['scopeNames'][$scope]);
|
||||
unset($data['Global']['scopeNamesPlural'][$scope]);
|
||||
@@ -179,7 +179,7 @@ class Language
|
||||
if (!$aclScope) {
|
||||
continue;
|
||||
}
|
||||
if (!$this->acl->check($aclScope)) {
|
||||
if (!$this->acl->tryCheck($aclScope)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -166,6 +166,7 @@ class Layout
|
||||
}
|
||||
|
||||
$layout = $this->getRecordFromSet($scope, $nameReal, $layoutSetId, true);
|
||||
|
||||
if ($layout) {
|
||||
$data = $layout->get('data');
|
||||
}
|
||||
@@ -173,8 +174,10 @@ class Layout
|
||||
|
||||
if (!$data) {
|
||||
$dataString = $this->layout->get($scope, $name);
|
||||
|
||||
$data = json_decode($dataString);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
$dataString = json_encode($data);
|
||||
}
|
||||
|
||||
@@ -196,11 +199,12 @@ class Layout
|
||||
->get(['entityDefs', $scope, 'links', $link, 'entity']);
|
||||
|
||||
if ($foreignEntityType) {
|
||||
if (!$this->acl->check($foreignEntityType)) {
|
||||
if (!$this->acl->tryCheck($foreignEntityType)) {
|
||||
unset($data[$i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$data = array_values($data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ class Metadata
|
||||
foreach ($dashletList as $item) {
|
||||
$aclScope = $this->metadata->get(['dashlets', $item, 'aclScope']);
|
||||
|
||||
if ($aclScope && !$this->acl->check($aclScope)) {
|
||||
if ($aclScope && !$this->acl->tryCheck($aclScope)) {
|
||||
unset($data->dashlets->$item);
|
||||
}
|
||||
}
|
||||
@@ -195,7 +195,7 @@ class Metadata
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$this->acl->check($aclScope)) {
|
||||
if (!$this->acl->tryCheck($aclScope)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -196,14 +196,16 @@ class Settings
|
||||
foreach ($this->access->getAdminParamList() as $item) {
|
||||
$ignoreItemList[] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->config->get('restrictedMode') && !$user->isSuperAdmin()) {
|
||||
foreach ($this->access->getSuperAdminParamList() as $item) {
|
||||
$ignoreItemList[] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->config->get('restrictedMode') && !$user->isSuperAdmin()) {
|
||||
// @todo Maybe add restriction level for non-super admins.
|
||||
}
|
||||
|
||||
foreach ($ignoreItemList as $item) {
|
||||
unset($data->$item);
|
||||
}
|
||||
@@ -230,7 +232,7 @@ class Settings
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->acl->check($scope)) {
|
||||
if ($this->acl->tryCheck($scope)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ class User extends Record implements
|
||||
|
||||
protected $allowedUserTypeList = ['regular', 'admin', 'portal', 'api'];
|
||||
|
||||
public function getEntity(?string $id = null): Entity
|
||||
public function getEntity(?string $id = null): ?Entity
|
||||
{
|
||||
if (isset($id) && $id == 'system') {
|
||||
throw new Forbidden();
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
Espo.define('views/dashlets/records', 'views/dashlets/abstract/record-list', function (Dep) {
|
||||
define('views/dashlets/records', 'views/dashlets/abstract/record-list', function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
@@ -40,18 +40,24 @@ Espo.define('views/dashlets/records', 'views/dashlets/abstract/record-list', fun
|
||||
|
||||
init: function () {
|
||||
Dep.prototype.init.call(this);
|
||||
|
||||
this.scope = this.getOption('entityType');
|
||||
},
|
||||
|
||||
getSearchData: function () {
|
||||
var data = {
|
||||
primary: this.getOption('primaryFilter')
|
||||
primary: this.getOption('primaryFilter'),
|
||||
};
|
||||
|
||||
if (data.primary === 'all') {
|
||||
data.primary = null;
|
||||
}
|
||||
|
||||
var bool = {};
|
||||
(this.getOption('boolFilterList') || []).forEach(function (item) {
|
||||
|
||||
(this.getOption('boolFilterList') || []).forEach(item => {
|
||||
bool[item] = true;
|
||||
}, this);
|
||||
});
|
||||
|
||||
data.bool = bool;
|
||||
|
||||
@@ -60,12 +66,13 @@ Espo.define('views/dashlets/records', 'views/dashlets/abstract/record-list', fun
|
||||
|
||||
setupActionList: function () {
|
||||
var scope = this.getOption('entityType');
|
||||
|
||||
if (scope && this.getAcl().checkScope(scope, 'create')) {
|
||||
this.actionList.unshift({
|
||||
name: 'create',
|
||||
html: this.translate('Create ' + scope, 'labels', scope),
|
||||
iconHtml: '<span class="fas fa-plus"></span>',
|
||||
url: '#' + scope + '/create'
|
||||
url: '#' + scope + '/create',
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -219,7 +219,7 @@ define('views/fields/link', 'views/fields/base', function (Dep) {
|
||||
this.searchData.idValue = this.getSearchParamsData().idValue ||
|
||||
this.searchParams.idValue || this.searchParams.value;
|
||||
|
||||
this.searchData.nameValue = this.getSearchParamsData().nameValue |
|
||||
this.searchData.nameValue = this.getSearchParamsData().nameValue ||
|
||||
this.searchParams.nameValue || this.searchParams.valueName;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,8 +43,6 @@ use Espo\Core\{
|
||||
Upgrades\ExtensionManager,
|
||||
};
|
||||
|
||||
use Exception;
|
||||
|
||||
$arg = isset($_SERVER['argv'][1]) ? trim($_SERVER['argv'][1]) : '';
|
||||
|
||||
if (empty($arg)) {
|
||||
@@ -78,13 +76,13 @@ try {
|
||||
$upgradeId = $upgradeManager->upload($fileData);
|
||||
$upgradeManager->install(array('id' => $upgradeId));
|
||||
}
|
||||
catch (Exception $e) {
|
||||
catch (\Exception $e) {
|
||||
die("Error: " . $e->getMessage() . "\n");
|
||||
}
|
||||
|
||||
try {
|
||||
(new Application())->run(Rebuild::class);
|
||||
}
|
||||
catch (Exception $e) {}
|
||||
catch (\Exception $e) {}
|
||||
|
||||
echo "Extension installation is complete.\n";
|
||||
|
||||
@@ -685,6 +685,8 @@ class Diff
|
||||
let composerLockNewContents = cp.execSync("cat " + currentPath + "/composer.lock").toString();
|
||||
let composerNewContents = cp.execSync("cat " + currentPath + "/composer.json").toString();
|
||||
|
||||
composerNewContents = composerNewContents.replace(/(\r\n)/g, '\n');
|
||||
|
||||
if (
|
||||
composerLockNewContents === composerLockOldContents &&
|
||||
composerOldContents === composerNewContents
|
||||
|
||||
2
package-lock.json
generated
2
package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "espocrm",
|
||||
"version": "7.0.0",
|
||||
"version": "7.0.2",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "espocrm",
|
||||
"version": "7.0.0",
|
||||
"version": "7.0.2",
|
||||
"description": "Open-source CRM.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -181,8 +181,8 @@ class ConfigWriterTest extends \PHPUnit\Framework\TestCase
|
||||
->withConsecutive(
|
||||
[$this->configPath],
|
||||
[$this->internalConfigPath],
|
||||
[$this->configPath],
|
||||
[$this->internalConfigPath],
|
||||
[$this->configPath],
|
||||
)
|
||||
->willReturnOnConsecutiveCalls(
|
||||
[],
|
||||
@@ -192,8 +192,8 @@ class ConfigWriterTest extends \PHPUnit\Framework\TestCase
|
||||
$this->fileManager
|
||||
->method('putPhpcontents')
|
||||
->withConsecutive(
|
||||
[$this->configPath, ['k1' => 'v1', 'cacheTimestamp' => 1, 'microtime' => 1.0]],
|
||||
[$this->internalConfigPath, ['k2' => 'v2', 'microtimeInternal' => 1.0]],
|
||||
[$this->configPath, ['k1' => 'v1', 'cacheTimestamp' => 1, 'microtime' => 1.0]],
|
||||
);
|
||||
|
||||
$this->configWriter->save();
|
||||
|
||||
@@ -43,8 +43,6 @@ use Espo\Core\{
|
||||
Upgrades\UpgradeManager,
|
||||
};
|
||||
|
||||
use Exception;
|
||||
|
||||
$arg = isset($_SERVER['argv'][1]) ? trim($_SERVER['argv'][1]) : '';
|
||||
|
||||
if ($arg == 'version' || $arg == '-v') {
|
||||
@@ -87,13 +85,13 @@ try {
|
||||
|
||||
$upgradeManager->install(['id' => $upgradeId]);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
catch (\Exception $e) {
|
||||
die("Error: " . $e->getMessage() . "\n");
|
||||
}
|
||||
|
||||
try {
|
||||
(new Application())->run(Rebuild::class);
|
||||
}
|
||||
catch (Exception $e) {}
|
||||
catch (\Exception $e) {}
|
||||
|
||||
echo "Upgrade is complete. Current version is " . $config->get('version') . ". \n";
|
||||
|
||||
@@ -37,8 +37,6 @@ use Espo\Core\Utils\File\Permission;
|
||||
|
||||
use Espo\ORM\EntityManager;
|
||||
|
||||
use Throwable;
|
||||
|
||||
class AfterUpgrade
|
||||
{
|
||||
public function run(Container $container): void
|
||||
@@ -61,7 +59,7 @@ class AfterUpgrade
|
||||
$container->get('injectableFactory')->create(ConfigWriter::class)
|
||||
);
|
||||
}
|
||||
catch (Throwable $e) {}
|
||||
catch (\Throwable $e) {}
|
||||
|
||||
$this->setPermissions(
|
||||
$container->get('injectableFactory')->create(Permission::class)
|
||||
|
||||
@@ -38,6 +38,27 @@ class BeforeUpgrade
|
||||
$this->container = $container;
|
||||
|
||||
$this->processCheckExtensions();
|
||||
$this->processCheckCache();
|
||||
|
||||
// Load to prevent fail if run in a single process.
|
||||
$container->get('entityManager')->getQueryBuilder()->update();
|
||||
}
|
||||
|
||||
private function processCheckCache()
|
||||
{
|
||||
$isCli = (substr(php_sapi_name(), 0, 3) == 'cli') ? true : false;
|
||||
|
||||
if (!$isCli) {
|
||||
return;
|
||||
}
|
||||
|
||||
$cacheParam = 'opcache.enable_cli';
|
||||
|
||||
$value = ini_get($cacheParam);
|
||||
|
||||
if ($value === '1') {
|
||||
throw new Error("PHP parameter '{$cacheParam}' should be set to '0'.");
|
||||
}
|
||||
}
|
||||
|
||||
private function processCheckExtensions(): void
|
||||
|
||||
Reference in New Issue
Block a user