diff --git a/.gitattributes b/.gitattributes index ce1d2a3266..a214b04574 100644 --- a/.gitattributes +++ b/.gitattributes @@ -8,4 +8,9 @@ *.tpl text eol=crlf *.html text eol=crlf +bin/command text eol=lf + +.gitattributes text eol=crlf +.gitignore text eol=crlf + *.png binary diff --git a/application/Espo/Core/EntryPoint/EntryPointManager.php b/application/Espo/Core/EntryPoint/EntryPointManager.php index c1f465e088..a4020cd829 100644 --- a/application/Espo/Core/EntryPoint/EntryPointManager.php +++ b/application/Espo/Core/EntryPoint/EntryPointManager.php @@ -32,6 +32,7 @@ namespace Espo\Core\EntryPoint; use Espo\Core\Exceptions\NotFound; use Espo\Core\{ + Exceptions\NotFoundSilent, InjectableFactory, Utils\ClassFinder, Api\Request, @@ -44,7 +45,6 @@ use Espo\Core\{ class EntryPointManager { private InjectableFactory $injectableFactory; - private ClassFinder $classFinder; public function __construct(InjectableFactory $injectableFactory, ClassFinder $classFinder) @@ -53,12 +53,15 @@ class EntryPointManager $this->classFinder = $classFinder; } + /** + * @throws NotFound + */ public function checkAuthRequired(string $name): bool { $className = $this->getClassName($name); if (!$className) { - throw new NotFound("Entry point '{$name}' not found."); + throw new NotFoundSilent("Entry point '{$name}' not found."); } $noAuth = false; @@ -75,23 +78,29 @@ class EntryPointManager return $className::$authRequired ?? true; } + /** + * @throws NotFound + */ public function checkNotStrictAuth(string $name): bool { $className = $this->getClassName($name); if (!$className) { - throw new NotFound("Entry point '{$name}' not found."); + throw new NotFoundSilent("Entry point '{$name}' not found."); } return $className::$notStrictAuth ?? false; } + /** + * @throws NotFound + */ public function run(string $name, Request $request, Response $response): void { $className = $this->getClassName($name); if (!$className) { - throw new NotFound("Entry point '{$name}' not found."); + throw new NotFoundSilent("Entry point '{$name}' not found."); } $entryPoint = $this->injectableFactory->create($className); diff --git a/application/Espo/Core/EntryPoint/Starter.php b/application/Espo/Core/EntryPoint/Starter.php index aeee9c11ae..eb4fedb7e3 100644 --- a/application/Espo/Core/EntryPoint/Starter.php +++ b/application/Espo/Core/EntryPoint/Starter.php @@ -33,6 +33,7 @@ use Espo\Core\Exceptions\BadRequest; use Espo\Core\Application\Runner\Params as RunnerParams; use Espo\Core\EntryPoint\EntryPointManager; use Espo\Core\ApplicationUser; +use Espo\Core\Exceptions\NotFound; use Espo\Core\Portal\Application as PortalApplication; use Espo\Core\Authentication\AuthenticationFactory; use Espo\Core\Authentication\AuthToken\Manager as AuthTokenManager; @@ -89,7 +90,7 @@ class Starter /** * @throws BadRequest - * @throws \Espo\Core\Exceptions\NotFound + * @throws NotFound */ public function start(?string $entryPoint = null, bool $final = false): void { @@ -110,8 +111,19 @@ class Starter throw new BadRequest("No 'entryPoint' param."); } - $authRequired = $this->entryPointManager->checkAuthRequired($entryPoint); - $authNotStrict = $this->entryPointManager->checkNotStrictAuth($entryPoint); + $responseWrapped = new ResponseWrapper(new Response()); + + try { + $authRequired = $this->entryPointManager->checkAuthRequired($entryPoint); + $authNotStrict = $this->entryPointManager->checkNotStrictAuth($entryPoint); + } + catch (NotFound $exception) { + $this->errorOutput->processWithBodyPrinting($requestWrapped, $responseWrapped, $exception); + + (new ResponseEmitter())->emit($responseWrapped->getResponse()); + + return; + } if ($authRequired && !$authNotStrict && !$final) { $portalId = $this->detectPortalId($requestWrapped); @@ -123,8 +135,6 @@ class Starter } } - $responseWrapped = new ResponseWrapper(new Response()); - $this->processRequest( $entryPoint, $requestWrapped, diff --git a/application/Espo/Resources/metadata/recordDefs/AuthToken.json b/application/Espo/Resources/metadata/recordDefs/AuthToken.json index 9e75be28c1..9e77ee7f65 100644 --- a/application/Espo/Resources/metadata/recordDefs/AuthToken.json +++ b/application/Espo/Resources/metadata/recordDefs/AuthToken.json @@ -1,12 +1,4 @@ { - "assignmentNotificatorClassName": "Espo\\Classes\\AssignmentNotificators\\Email", - "readLoaderClassNameList": [ - "Espo\\Classes\\FieldProcessing\\Email\\AddressDataLoader", - "Espo\\Classes\\FieldProcessing\\Email\\UserColumnsLoader" - ], - "listLoaderClassNameList": [ - "Espo\\Classes\\FieldProcessing\\Email\\StringDataLoader" - ], "massActions": { "update": { "allowed": true diff --git a/client/res/templates/fields/array/list-link.tpl b/client/res/templates/fields/array/list-link.tpl new file mode 100644 index 0000000000..9049308f4f --- /dev/null +++ b/client/res/templates/fields/array/list-link.tpl @@ -0,0 +1,6 @@ +{{#if value}}{{{value}}}{{else}}{{translate 'None'}}{{/if}} diff --git a/client/src/app.js b/client/src/app.js index 2d4c50aca0..eb40a07638 100644 --- a/client/src/app.js +++ b/client/src/app.js @@ -994,7 +994,7 @@ function ( resolve(options); return; - }; + } this.requestUserData(data => { options = data; diff --git a/client/src/view-helper.js b/client/src/view-helper.js index 7ffd63e605..5c5190c205 100644 --- a/client/src/view-helper.js +++ b/client/src/view-helper.js @@ -437,7 +437,7 @@ function (marked, DOMPurify, /** typeof Handlebars */Handlebars) { return value.indexOf(name) !== -1; } - return value === name; + return value === name || !value && !name; }; options.hash = options.hash || {}; diff --git a/client/src/views/fields/array.js b/client/src/views/fields/array.js index 062d6b15c3..3115a7dd6f 100644 --- a/client/src/views/fields/array.js +++ b/client/src/views/fields/array.js @@ -43,6 +43,8 @@ function (Dep, RegExpPattern, /** module:ui/multi-select*/MultiSelect) { listTemplate: 'fields/array/list', + listLinkTemplate: 'fields/array/list-link', + detailTemplate: 'fields/array/detail', editTemplate: 'fields/array/edit', diff --git a/diff.js b/diff.js index 9081e8c8dd..3950eed570 100644 --- a/diff.js +++ b/diff.js @@ -31,8 +31,19 @@ * From a specified version to the current version or all packages needed for a release. * Examples: - * * `node diff 5.9.0` - builds an upgrade from 5.9.0 to the current version; + * * `node diff 5.9.0` - builds an upgrade from 5.9.0 to the current version; * * `node diff --all` - builds all upgrades needed for a release. + * + * Data for upgrade packages is defined in `upgrades/{x.x|x.x.x-x.x.x}/data.json`. + * + * Parameters: + * * `mandatoryFiles` – {string[]} – mandatory files to include in upgrade + * (even files that were not changed in version control); + * * `beforeUpgradeFiles` – {string[]} – files to copy in the beginning of the upgrade process; + * * `manifest` – {object} – upgrade manifest parameters. + * + * Manifest parameters: + * * `delete` – {string[]} – additional files to be deleted (usually those that are not in version control). */ const Diff = require('./js/diff'); diff --git a/js/diff.js b/js/diff.js index 6e5a469b8c..cf34bedc7f 100644 --- a/js/diff.js +++ b/js/diff.js @@ -253,7 +253,7 @@ class Diff process.chdir(buildPath); - let fileList = []; + let fileList = upgradeData.mandatoryFiles || []; let stdout = cp.execSync('git diff --name-only ' + versionFrom).toString(); diff --git a/package-lock.json b/package-lock.json index 99434f65dd..44cdd5dff6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "espocrm", - "version": "7.2.4", + "version": "7.2.5", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/package.json b/package.json index 87433f1dca..ef9fa28615 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "espocrm", - "version": "7.2.4", + "version": "7.2.5", "description": "Open-source CRM.", "repository": { "type": "git", diff --git a/upgrades/7.2.4-7.2.5/data.json b/upgrades/7.2.4-7.2.5/data.json new file mode 100644 index 0000000000..8e6c987429 --- /dev/null +++ b/upgrades/7.2.4-7.2.5/data.json @@ -0,0 +1,5 @@ +{ + "mandatoryFiles": [ + "bin/command" + ] +} diff --git a/upgrades/7.2/data.json b/upgrades/7.2/data.json index 533bf63be5..fa1239f4aa 100644 --- a/upgrades/7.2/data.json +++ b/upgrades/7.2/data.json @@ -1,4 +1,7 @@ { + "mandatoryFiles": [ + "bin/command" + ], "manifest": { "delete": [ "client/css/espo/espo-vertical.css",