From d3c6448295e664ad95831bdaa82074b7bf85ccb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D?= Date: Sat, 27 Jul 2024 11:10:50 +0200 Subject: [PATCH] test(IT): Setup integration tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rubén D --- app/modules/api/Bootstrap.php | 2 +- .../Controllers/Config/BackupController.php | 11 +- .../Controllers/Config/ExportController.php | 21 +- .../api/Controllers/ControllerBase.php | 31 +- app/modules/api/Init.php | 5 + app/modules/cli/Commands/BackupCommand.php | 42 +- app/modules/cli/module.php | 6 +- app/modules/web/Bootstrap.php | 3 +- .../AccessManager/IndexController.php | 152 +-- .../Bootstrap/GetEnvironmentController.php | 13 +- .../DownloadBackupAppController.php | 23 +- .../DownloadBackupDbController.php | 22 +- .../ConfigBackup/DownloadExportController.php | 17 +- .../ConfigBackup/FileBackupController.php | 18 +- .../ConfigBackup/XmlExportController.php | 25 +- .../ConfigGeneral/DownloadLogController.php | 32 +- .../ConfigGeneral/SaveController.php | 44 +- .../ConfigManager/IndexController.php | 42 +- .../web/Controllers/ControllerBase.php | 24 +- .../Helpers/Account/AccountSearchData.php | 5 +- .../Controllers/Helpers/Grid/AccountGrid.php | 16 +- .../Helpers/Grid/AccountHistoryGrid.php | 5 +- .../Helpers/Grid/AuthTokenGrid.php | 14 +- .../Controllers/Helpers/Grid/CategoryGrid.php | 26 +- .../Controllers/Helpers/Grid/ClientGrid.php | 23 +- .../Helpers/Grid/CustomFieldGrid.php | 2 +- .../Controllers/Helpers/Grid/EventlogGrid.php | 23 +- .../web/Controllers/Helpers/Grid/FileGrid.php | 26 +- .../web/Controllers/Helpers/Grid/GridBase.php | 21 +- .../Helpers/Grid/ItemPresetGrid.php | 33 +- .../Helpers/Grid/NotificationGrid.php | 5 +- .../Controllers/Helpers/Grid/PluginGrid.php | 6 +- .../Helpers/Grid/PublicLinkGrid.php | 9 +- .../web/Controllers/Helpers/Grid/TagGrid.php | 7 +- .../Controllers/Helpers/Grid/TrackGrid.php | 8 +- .../web/Controllers/Helpers/Grid/UserGrid.php | 8 +- .../Helpers/Grid/UserGroupGrid.php | 7 +- .../Helpers/Grid/UserProfileGrid.php | 8 +- .../web/Controllers/Helpers/HelperBase.php | 30 +- .../Controllers/Resource/CssController.php | 13 +- .../web/Controllers/Resource/JsController.php | 13 +- .../web/Controllers/Resource/ResourceBase.php | 8 +- .../web/Controllers/Traits/ConfigTrait.php | 20 +- app/modules/web/Init.php | 67 +- app/modules/web/module.php | 35 +- .../web/themes/material-blue/inc/Icons.php | 4 +- composer.json | 6 +- composer.lock | 1071 ++++++++--------- lib/Base.php | 46 +- lib/BaseFunctions.php | 4 + lib/SP/Core/Acl/Actions.php | 10 +- lib/SP/Core/AppLock.php | 87 ++ lib/SP/Core/Application.php | 7 - lib/SP/Core/Bootstrap/BootstrapBase.php | 25 +- lib/SP/Core/Bootstrap/Path.php | 50 + lib/SP/Core/Bootstrap/PathsContext.php | 110 ++ lib/SP/Core/Crypt/Cookie.php | 5 - lib/SP/Core/Crypt/CryptPKI.php | 4 +- lib/SP/Core/Definitions/CoreDefinitions.php | 180 ++- lib/SP/Core/Definitions/DomainDefinitions.php | 34 +- lib/SP/Core/HttpModuleBase.php | 26 +- lib/SP/Core/Language.php | 18 +- lib/SP/Core/MimeTypes.php | 4 - lib/SP/Core/ModuleBase.php | 4 +- lib/SP/Core/UI/Theme.php | 7 +- .../Account/Ports/AccountCryptService.php | 18 +- .../Ports/AccountMasterPasswordService.php | 49 + lib/SP/Domain/Account/Services/Account.php | 1 + lib/SP/Domain/Account/Services/AccountAcl.php | 25 +- .../Domain/Account/Services/AccountCrypt.php | 211 +--- .../Services/AccountMasterPassword.php | 256 ++++ .../Domain/Account/Services/AccountPreset.php | 6 +- .../Services/Builders/AccountFilter.php | 10 +- lib/SP/Domain/Auth/Providers/AclHandler.php | 13 +- lib/SP/Domain/Common/Adapters/Serde.php | 5 +- lib/SP/Domain/Common/Providers/Image.php | 10 +- lib/SP/Domain/Config/Services/ConfigFile.php | 5 - lib/SP/Domain/Config/Services/ConfigUtil.php | 11 +- .../Domain/Core/Bootstrap/ModuleInterface.php | 3 + lib/SP/Domain/Core/LanguageInterface.php | 5 +- .../Crypt/Ports/SecureSessionService.php | 3 +- lib/SP/Domain/Crypt/Services/MasterPass.php | 17 +- .../Domain/Crypt/Services/SecureSession.php | 6 +- .../Domain/Export/Ports/BackupFileService.php | 2 +- lib/SP/Domain/Export/Services/BackupFile.php | 2 +- lib/SP/Domain/Export/Services/XmlVerify.php | 3 +- lib/SP/Domain/Install/Services/Installer.php | 4 +- .../Upgrade/Services/UpgradeDatabase.php | 3 +- lib/SP/Domain/User/Dtos/UserDataDto.php | 5 + .../DataGrid/Action/DataGridActionBase.php | 2 +- lib/SP/Html/DataGrid/DataGridBase.php | 2 +- .../DataGrid/Layout/DataGridHeaderBase.php | 3 +- .../DataGrid/Layout/DataGridPagerBase.php | 5 +- lib/SP/Infrastructure/File/FileSystem.php | 54 +- .../Validators/PasswordValidator.php | 3 +- tests/SP/Core/Acl/ActionsTest.php | 12 +- tests/SP/Core/Definitions/DefinitionsTest.php | 4 +- tests/SP/Core/LanguageTest.php | 5 +- .../Account/Services/AccountAclTest.php | 7 +- .../Account/Services/AccountCryptTest.php | 205 +--- .../Account/Services/AccountFileTest.php | 5 +- .../Services/AccountMasterPasswordTest.php | 250 ++++ .../Account/Services/AccountPresetTest.php | 3 +- .../Domain/Auth/Providers/AclHandlerTest.php | 13 +- .../SP/Domain/Common/Providers/ImageTest.php | 17 +- .../Domain/Crypt/Services/MasterPassTest.php | 21 +- .../Services/SecureSessionServiceTest.php | 10 +- .../Export/Services/FileBackupServiceTest.php | 7 +- .../Domain/Export/Services/XmlVerifyTest.php | 3 +- .../Upgrade/Services/UpgradeDatabaseTest.php | 5 +- tests/SP/IntegrationTestCase.php | 203 ++++ tests/SP/Modules/Api/ApiTestCase.php | 4 - .../AccessManager/IndexControllerTest.php | 111 ++ tests/SP/PHPUnitHelper.php | 24 + tests/SP/UnitaryTestCase.php | 11 +- tests/SP/bootstrap.php | 56 +- tests/phpunit.xml | 7 +- tests/res/config/actions.xml | 868 ------------- tests/res/config/actions.yaml | 606 ++++++++++ tests/res/config/mime.xml | 209 ---- tests/res/config/mimetypes.yaml | 126 ++ 121 files changed, 3329 insertions(+), 2878 deletions(-) create mode 100644 lib/SP/Core/AppLock.php create mode 100644 lib/SP/Core/Bootstrap/Path.php create mode 100644 lib/SP/Core/Bootstrap/PathsContext.php create mode 100644 lib/SP/Domain/Account/Ports/AccountMasterPasswordService.php create mode 100644 lib/SP/Domain/Account/Services/AccountMasterPassword.php create mode 100644 tests/SP/Domain/Account/Services/AccountMasterPasswordTest.php create mode 100644 tests/SP/IntegrationTestCase.php create mode 100644 tests/SP/Modules/Web/Controllers/AccessManager/IndexControllerTest.php delete mode 100644 tests/res/config/actions.xml create mode 100644 tests/res/config/actions.yaml delete mode 100644 tests/res/config/mime.xml create mode 100644 tests/res/config/mimetypes.yaml diff --git a/app/modules/api/Bootstrap.php b/app/modules/api/Bootstrap.php index 69675787..9a03063c 100644 --- a/app/modules/api/Bootstrap.php +++ b/app/modules/api/Bootstrap.php @@ -78,7 +78,7 @@ final class Bootstrap extends BootstrapBase $apiRequest = $this->buildInstanceFor(ApiRequestService::class); [$controllerName, $actionName] = explode('/', $apiRequest->getMethod()); - $controllerClass = self::getClassFor($controllerName, $actionName); + $controllerClass = self::getClassFor($this->module->getName(), $controllerName, $actionName); $method = $actionName . 'Action'; if (!method_exists($controllerClass, $method)) { diff --git a/app/modules/api/Controllers/Config/BackupController.php b/app/modules/api/Controllers/Config/BackupController.php index e8acd161..1f68a1fc 100644 --- a/app/modules/api/Controllers/Config/BackupController.php +++ b/app/modules/api/Controllers/Config/BackupController.php @@ -27,6 +27,8 @@ namespace SP\Modules\Api\Controllers\Config; use Exception; use Klein\Klein; use SP\Core\Application; +use SP\Core\Bootstrap\Path; +use SP\Core\Bootstrap\PathsContext; use SP\Core\Events\Event; use SP\Core\Events\EventMessage; use SP\Domain\Api\Dtos\ApiResponse; @@ -39,6 +41,10 @@ use SP\Domain\Export\Ports\BackupFileService; use SP\Modules\Api\Controllers\ControllerBase; use SP\Modules\Api\Controllers\Help\ConfigHelp; +use function SP\__; +use function SP\__u; +use function SP\processException; + /** * Class BackupController * @@ -55,7 +61,8 @@ final class BackupController extends ControllerBase ApiService $apiService, AclInterface $acl, private readonly BackupFileService $fileBackupService, - private readonly BackupFiles $backupFiles + private readonly BackupFiles $backupFiles, + private readonly PathsContext $pathsContext ) { parent::__construct($application, $router, $apiService, $acl); @@ -70,7 +77,7 @@ final class BackupController extends ControllerBase try { $this->setupApi(AclActionsInterface::CONFIG_BACKUP_RUN); - $path = $this->apiService->getParamString('path', false, BACKUP_PATH); + $path = $this->apiService->getParamString('path', false, $this->pathsContext[Path::BACKUP]); $this->fileBackupService->doBackup($path); diff --git a/app/modules/api/Controllers/Config/ExportController.php b/app/modules/api/Controllers/Config/ExportController.php index 21b2f534..9b696a56 100644 --- a/app/modules/api/Controllers/Config/ExportController.php +++ b/app/modules/api/Controllers/Config/ExportController.php @@ -28,6 +28,8 @@ namespace SP\Modules\Api\Controllers\Config; use Exception; use Klein\Klein; use SP\Core\Application; +use SP\Core\Bootstrap\Path; +use SP\Core\Bootstrap\PathsContext; use SP\Core\Events\Event; use SP\Core\Events\EventMessage; use SP\Domain\Api\Dtos\ApiResponse; @@ -40,27 +42,28 @@ use SP\Infrastructure\File\DirectoryHandler; use SP\Modules\Api\Controllers\ControllerBase; use SP\Modules\Api\Controllers\Help\ConfigHelp; +use function SP\__u; +use function SP\processException; + /** * Class ExportController */ final class ExportController extends ControllerBase { - private XmlExportService $xmlExportService; /** * @throws InvalidClassException */ public function __construct( - Application $application, - Klein $router, - ApiService $apiService, - AclInterface $acl, - XmlExportService $xmlExportService + Application $application, + Klein $router, + ApiService $apiService, + AclInterface $acl, + private readonly XmlExportService $xmlExportService, + private readonly PathsContext $pathsContext ) { parent::__construct($application, $router, $apiService, $acl); - $this->xmlExportService = $xmlExportService; - $this->apiService->setHelpClass(ConfigHelp::class); } @@ -73,7 +76,7 @@ final class ExportController extends ControllerBase $this->setupApi(AclActionsInterface::CONFIG_EXPORT_RUN); $password = $this->apiService->getParamString('password'); - $path = $this->apiService->getParamString('path', false, BACKUP_PATH); + $path = $this->apiService->getParamString('path', false, $this->pathsContext[Path::BACKUP]); $this->eventDispatcher->notify( 'run.export.start', diff --git a/app/modules/api/Controllers/ControllerBase.php b/app/modules/api/Controllers/ControllerBase.php index 7e013d2a..9d063907 100644 --- a/app/modules/api/Controllers/ControllerBase.php +++ b/app/modules/api/Controllers/ControllerBase.php @@ -27,10 +27,8 @@ namespace SP\Modules\Api\Controllers; use Exception; use Klein\Klein; use League\Fractal\Manager; -use SP\Core\Acl\Acl; use SP\Core\Application; use SP\Core\Bootstrap\BootstrapBase; -use SP\Core\Events\EventDispatcher; use SP\Domain\Api\Dtos\ApiResponse; use SP\Domain\Api\Ports\ApiService; use SP\Domain\Api\Services\JsonRpcResponse; @@ -38,6 +36,7 @@ use SP\Domain\Common\Services\ServiceException; use SP\Domain\Config\Ports\ConfigDataInterface; use SP\Domain\Core\Acl\AclInterface; use SP\Domain\Core\Context\Context; +use SP\Domain\Core\Events\EventDispatcherInterface; use SP\Domain\Core\Exceptions\SPException; use SP\Domain\Http\Services\JsonResponse; @@ -50,29 +49,23 @@ abstract class ControllerBase { protected const SEARCH_COUNT_ITEMS = 25; - protected string $controllerName; - protected Context $context; - protected EventDispatcher $eventDispatcher; - protected ApiService $apiService; - protected Klein $router; - protected ConfigDataInterface $configData; - protected Manager $fractal; - protected Acl $acl; - protected string $actionName; - private bool $isAuthenticated = false; + protected string $controllerName; + protected Context $context; + protected EventDispatcherInterface $eventDispatcher; + protected ConfigDataInterface $configData; + protected Manager $fractal; + protected string $actionName; + private bool $isAuthenticated = false; public function __construct( - Application $application, - Klein $router, - ApiService $apiService, - AclInterface $acl + Application $application, + protected readonly Klein $router, + protected readonly ApiService $apiService, + protected readonly AclInterface $acl ) { $this->context = $application->getContext(); $this->configData = $application->getConfig()->getConfigData(); $this->eventDispatcher = $application->getEventDispatcher(); - $this->router = $router; - $this->apiService = $apiService; - $this->acl = $acl; $this->fractal = new Manager(); $this->controllerName = $this->getControllerName(); diff --git a/app/modules/api/Init.php b/app/modules/api/Init.php index 1f771cd7..7e05d6df 100644 --- a/app/modules/api/Init.php +++ b/app/modules/api/Init.php @@ -123,4 +123,9 @@ final class Init extends HttpModuleBase throw new InitializationException('Not installed'); } } + + public function getName(): string + { + return 'api'; + } } diff --git a/app/modules/cli/Commands/BackupCommand.php b/app/modules/cli/Commands/BackupCommand.php index c5ffa8d3..00152239 100644 --- a/app/modules/cli/Commands/BackupCommand.php +++ b/app/modules/cli/Commands/BackupCommand.php @@ -27,15 +27,19 @@ namespace SP\Modules\Cli\Commands; use Exception; use Psr\Log\LoggerInterface; use RuntimeException; +use SP\Core\Bootstrap\Path; +use SP\Core\Bootstrap\PathsContext; use SP\Domain\Config\Ports\ConfigFileService; use SP\Domain\Export\Ports\BackupFileService; -use SP\Domain\Export\Services\BackupFile; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\StyleInterface; use Symfony\Component\Console\Style\SymfonyStyle; +use function SP\__; +use function SP\__u; + /** * Class BackupCommand * @@ -52,17 +56,14 @@ final class BackupCommand extends CommandBase /** * @var string */ - protected static $defaultName = 'sp:backup'; - private BackupFile $fileBackupService; + protected static $defaultName = 'sp:backup'; public function __construct( - BackupFileService $fileBackupService, - LoggerInterface $logger, - ConfigFileService $config - ) - { - $this->fileBackupService = $fileBackupService; - + private readonly BackupFileService $fileBackupService, + LoggerInterface $logger, + ConfigFileService $config, + private readonly PathsContext $pathsContext + ) { parent::__construct($logger, $config); } @@ -70,18 +71,19 @@ final class BackupCommand extends CommandBase { $this->setDescription(__('Backup actions')) ->setHelp(__('This command performs a file based backup from sysPass database and application')) - ->addOption('path', + ->addOption( + 'path', null, InputOption::VALUE_OPTIONAL, __('Path where to store the backup files'), - BACKUP_PATH); + $this->pathsContext[Path::BACKUP] + ); } protected function execute( - InputInterface $input, + InputInterface $input, OutputInterface $output - ): int - { + ): int { $style = new SymfonyStyle($input, $output); try { @@ -91,7 +93,7 @@ final class BackupCommand extends CommandBase $this->logger->info(sprintf(__u('Backup path set to: %s'), $path)); - $this->fileBackupService->doBackup($path); + $this->fileBackupService->doBackup($path, $this->pathsContext[Path::APP]); $this->logger->info(__u('Application and database backup completed successfully')); @@ -111,7 +113,8 @@ final class BackupCommand extends CommandBase private function checkInstalled(): void { if (!defined('TEST_ROOT') - && !$this->configData->isInstalled()) { + && !$this->configData->isInstalled() + ) { throw new RuntimeException(__u('sysPass is not installed')); } } @@ -126,7 +129,10 @@ final class BackupCommand extends CommandBase if (empty($path)) { $this->logger->debug(__u('Ask for path')); - return $style->ask(__('Please enter the path where to store the backup files'), BACKUP_PATH); + return $style->ask( + __('Please enter the path where to store the backup files'), + $this->pathsContext[Path::BACKUP] + ); } return $path; diff --git a/app/modules/cli/module.php b/app/modules/cli/module.php index fcc5123f..18cf12df 100644 --- a/app/modules/cli/module.php +++ b/app/modules/cli/module.php @@ -25,6 +25,8 @@ use Monolog\Handler\StreamHandler; use Monolog\Logger; use Psr\Log\LoggerInterface; +use SP\Core\Bootstrap\Path; +use SP\Core\Bootstrap\PathsContext; use SP\Domain\Core\Bootstrap\ModuleInterface; use SP\Modules\Cli\Init; use Symfony\Component\Console\Application; @@ -40,7 +42,9 @@ const MODULE_PATH = __DIR__; const PLUGINS_PATH = MODULE_PATH . DIRECTORY_SEPARATOR . 'plugins'; return [ - LoggerInterface::class => static fn(Logger $logger) => $logger->pushHandler(new StreamHandler(LOG_FILE)), + LoggerInterface::class => static fn(Logger $logger, PathsContext $pathsContext) => $logger->pushHandler( + new StreamHandler($pathsContext[Path::LOG_FILE]) + ), Application::class => create(Application::class), OutputInterface::class => create(ConsoleOutput::class) ->constructor(OutputInterface::VERBOSITY_NORMAL, true), diff --git a/app/modules/web/Bootstrap.php b/app/modules/web/Bootstrap.php index 031d4780..f2d4ce77 100644 --- a/app/modules/web/Bootstrap.php +++ b/app/modules/web/Bootstrap.php @@ -74,6 +74,7 @@ final class Bootstrap extends BootstrapBase logger('WEB route'); $controllerClass = self::getClassFor( + $this->module->getName(), $this->routeContextData->getController(), $this->routeContextData->getActionName() ); @@ -87,8 +88,6 @@ final class Bootstrap extends BootstrapBase return $response; } - $this->context->setTrasientKey(self::CONTEXT_ACTION_NAME, $this->routeContextData->getActionName()); - $this->setCors($response); $this->initializeCommon(); diff --git a/app/modules/web/Controllers/AccessManager/IndexController.php b/app/modules/web/Controllers/AccessManager/IndexController.php index 6950e23c..562e611d 100644 --- a/app/modules/web/Controllers/AccessManager/IndexController.php +++ b/app/modules/web/Controllers/AccessManager/IndexController.php @@ -24,19 +24,19 @@ namespace SP\Modules\Web\Controllers\AccessManager; -use SP\Core\Acl\Acl; use SP\Core\Application; use SP\Core\Events\Event; use SP\Domain\Account\Ports\PublicLinkService; use SP\Domain\Auth\Ports\AuthTokenService; +use SP\Domain\Auth\Services\AuthException; use SP\Domain\Core\Acl\AclActionsInterface; use SP\Domain\Core\Dtos\ItemSearchDto; use SP\Domain\Core\Exceptions\ConstraintException; use SP\Domain\Core\Exceptions\QueryException; +use SP\Domain\Core\Exceptions\SessionTimeout; use SP\Domain\User\Ports\UserGroupService; use SP\Domain\User\Ports\UserProfileService; use SP\Domain\User\Ports\UserService; -use SP\Html\DataGrid\DataGridTab; use SP\Modules\Web\Controllers\ControllerBase; use SP\Modules\Web\Controllers\Helpers\Grid\AuthTokenGrid; use SP\Modules\Web\Controllers\Helpers\Grid\PublicLinkGrid; @@ -53,50 +53,28 @@ use SP\Mvc\Controller\WebControllerHelper; */ final class IndexController extends ControllerBase { - protected ItemSearchDto $itemSearchData; - protected TabsGridHelper $tabsGridHelper; - private UserGrid $userGrid; - private UserGroupGrid $userGroupGrid; - private UserProfileGrid $userProfileGrid; - private AuthTokenGrid $authTokenGrid; - private PublicLinkGrid $publicLinkGrid; - private UserService $userService; - private UserGroupService $userGroupService; - private UserProfileService $userProfileService; - private AuthTokenService $authTokenService; - private PublicLinkService $publicLinkService; - + /** + * @throws AuthException + * @throws SessionTimeout + */ public function __construct( - Application $application, - WebControllerHelper $webControllerHelper, - TabsGridHelper $tabsGridHelper, - UserGrid $userGrid, - UserGroupGrid $userGroupGrid, - UserProfileGrid $userProfileGrid, - AuthTokenGrid $authTokenGrid, - PublicLinkGrid $publicLinkGrid, - UserService $userService, - UserGroupService $userGroupService, - UserProfileService $userProfileService, - AuthTokenService $authTokenService, - PublicLinkService $publicLinkService + Application $application, + WebControllerHelper $webControllerHelper, + protected TabsGridHelper $tabsGridHelper, + private readonly UserGrid $userGrid, + private readonly UserGroupGrid $userGroupGrid, + private readonly UserProfileGrid $userProfileGrid, + private readonly AuthTokenGrid $authTokenGrid, + private readonly PublicLinkGrid $publicLinkGrid, + private readonly UserService $userService, + private readonly UserGroupService $userGroupService, + private readonly UserProfileService $userProfileService, + private readonly AuthTokenService $authTokenService, + private readonly PublicLinkService $publicLinkService ) { parent::__construct($application, $webControllerHelper); $this->checkLoggedIn(); - - $this->userGrid = $userGrid; - $this->userGroupGrid = $userGroupGrid; - $this->userProfileGrid = $userProfileGrid; - $this->authTokenGrid = $authTokenGrid; - $this->publicLinkGrid = $publicLinkGrid; - $this->userService = $userService; - $this->userGroupService = $userGroupService; - $this->userProfileService = $userProfileService; - $this->authTokenService = $authTokenService; - $this->publicLinkService = $publicLinkService; - $this->tabsGridHelper = $tabsGridHelper; - $this->itemSearchData = new ItemSearchDto(); } /** @@ -116,102 +94,50 @@ final class IndexController extends ControllerBase */ protected function getGridTabs(): void { - $this->itemSearchData->setLimitCount($this->configData->getAccountCount()); + $itemSearchData = new ItemSearchDto(null, 0, $this->configData->getAccountCount()); if ($this->checkAccess(AclActionsInterface::USER)) { - $this->tabsGridHelper->addTab($this->getUsersList()); + $this->tabsGridHelper->addTab( + $this->userGrid->getGrid($this->userService->search($itemSearchData))->updatePager() + ); } if ($this->checkAccess(AclActionsInterface::GROUP)) { - $this->tabsGridHelper->addTab($this->getUsersGroupList()); + $this->tabsGridHelper->addTab( + $this->userGroupGrid->getGrid($this->userGroupService->search($itemSearchData))->updatePager() + ); } if ($this->checkAccess(AclActionsInterface::PROFILE)) { - $this->tabsGridHelper->addTab($this->getUsersProfileList()); + $this->tabsGridHelper->addTab( + $this->userProfileGrid->getGrid($this->userProfileService->search($itemSearchData))->updatePager() + ); } if ($this->checkAccess(AclActionsInterface::AUTHTOKEN)) { - $this->tabsGridHelper->addTab($this->getAuthTokensList()); + $this->tabsGridHelper->addTab( + $this->authTokenGrid->getGrid($this->authTokenService->search($itemSearchData))->updatePager() + ); } if ($this->configData->isPublinksEnabled() - && $this->checkAccess(AclActionsInterface::PUBLICLINK)) { - $this->tabsGridHelper->addTab($this->getPublicLinksList()); + && $this->checkAccess(AclActionsInterface::PUBLICLINK) + ) { + $this->tabsGridHelper->addTab( + $this->publicLinkGrid->getGrid($this->publicLinkService->search($itemSearchData))->updatePager() + ); } - $this->eventDispatcher->notify( - 'show.itemlist.accesses', - new Event($this) - ); + $this->eventDispatcher->notify('show.itemlist.accesses', new Event($this)); $this->tabsGridHelper->renderTabs( - Acl::getActionRoute(AclActionsInterface::ACCESS_MANAGE), + $this->acl->getRouteFor(AclActionsInterface::ACCESS_MANAGE), $this->request->analyzeInt('tabIndex', 0) ); $this->view(); } - /** - * Returns users' data tab - * - * @return DataGridTab - * @throws ConstraintException - * @throws QueryException - */ - protected function getUsersList(): DataGridTab - { - return $this->userGrid->getGrid($this->userService->search($this->itemSearchData))->updatePager(); - } - - /** - * Returns users group data tab - * - * @return DataGridTab - * @throws ConstraintException - * @throws QueryException - */ - protected function getUsersGroupList(): DataGridTab - { - return $this->userGroupGrid->getGrid($this->userGroupService->search($this->itemSearchData))->updatePager(); - } - - /** - * Returns users profile data tab - * - * @return DataGridTab - * @throws ConstraintException - * @throws QueryException - */ - protected function getUsersProfileList(): DataGridTab - { - return $this->userProfileGrid->getGrid($this->userProfileService->search($this->itemSearchData))->updatePager(); - } - - /** - * Returns API tokens data tab - * - * @return DataGridTab - * @throws ConstraintException - * @throws QueryException - */ - protected function getAuthTokensList(): DataGridTab - { - return $this->authTokenGrid->getGrid($this->authTokenService->search($this->itemSearchData))->updatePager(); - } - - /** - * Returns public links data tab - * - * @return DataGridTab - * @throws ConstraintException - * @throws QueryException - */ - protected function getPublicLinksList(): DataGridTab - { - return $this->publicLinkGrid->getGrid($this->publicLinkService->search($this->itemSearchData))->updatePager(); - } - /** * @return TabsGridHelper */ diff --git a/app/modules/web/Controllers/Bootstrap/GetEnvironmentController.php b/app/modules/web/Controllers/Bootstrap/GetEnvironmentController.php index bff67bea..95d42180 100644 --- a/app/modules/web/Controllers/Bootstrap/GetEnvironmentController.php +++ b/app/modules/web/Controllers/Bootstrap/GetEnvironmentController.php @@ -27,13 +27,17 @@ namespace SP\Modules\Web\Controllers\Bootstrap; use Exception; use JsonException; use SP\Core\Application; +use SP\Core\Bootstrap\Path; +use SP\Core\Bootstrap\PathsContext; use SP\Core\Crypt\CryptPKI; use SP\Domain\Auth\Providers\Browser\BrowserAuthService; use SP\Domain\Core\Crypt\CryptPKIHandler; +use SP\Domain\Core\Exceptions\InvalidClassException; use SP\Domain\Core\Exceptions\SPException; use SP\Domain\Import\Services\ImportStrategy; use SP\Domain\Plugin\Ports\PluginManagerService; use SP\Infrastructure\File\FileException; +use SP\Infrastructure\File\FileSystem; use SP\Modules\Web\Controllers\SimpleControllerBase; use SP\Modules\Web\Controllers\Traits\JsonTrait; use SP\Mvc\Controller\SimpleControllerHelper; @@ -53,9 +57,10 @@ final class GetEnvironmentController extends SimpleControllerBase public function __construct( Application $application, SimpleControllerHelper $simpleControllerHelper, - private readonly CryptPKIHandler $cryptPKI, + private readonly CryptPKIHandler $cryptPKI, private readonly BrowserAuthService $browser, - private readonly PluginManagerService $pluginManagerService + private readonly PluginManagerService $pluginManagerService, + private readonly PathsContext $pathsContext ) { parent::__construct($application, $simpleControllerHelper); } @@ -100,10 +105,12 @@ final class GetEnvironmentController extends SimpleControllerBase /** * @return array + * @throws FileException + * @throws InvalidClassException */ private function getJsLang(): array { - return require RESOURCES_PATH . DIRECTORY_SEPARATOR . 'strings.js.inc'; + return FileSystem::require(FileSystem::buildPath($this->pathsContext[Path::RESOURCES], 'strings.js.inc')); } /** diff --git a/app/modules/web/Controllers/ConfigBackup/DownloadBackupAppController.php b/app/modules/web/Controllers/ConfigBackup/DownloadBackupAppController.php index faf0f5a2..ab08d9c0 100644 --- a/app/modules/web/Controllers/ConfigBackup/DownloadBackupAppController.php +++ b/app/modules/web/Controllers/ConfigBackup/DownloadBackupAppController.php @@ -26,6 +26,9 @@ namespace SP\Modules\Web\Controllers\ConfigBackup; use Exception; +use SP\Core\Application; +use SP\Core\Bootstrap\Path; +use SP\Core\Bootstrap\PathsContext; use SP\Core\Context\Session; use SP\Core\Events\Event; use SP\Core\Events\EventMessage; @@ -38,6 +41,10 @@ use SP\Domain\Export\Dtos\BackupType; use SP\Infrastructure\File\FileHandler; use SP\Modules\Web\Controllers\SimpleControllerBase; use SP\Modules\Web\Controllers\Traits\JsonTrait; +use SP\Mvc\Controller\SimpleControllerHelper; + +use function SP\__u; +use function SP\processException; /** * Class DownloadBackupController @@ -46,6 +53,15 @@ final class DownloadBackupAppController extends SimpleControllerBase { use JsonTrait; + public function __construct( + Application $application, + SimpleControllerHelper $simpleControllerHelper, + private readonly PathsContext $pathsContext + ) { + parent::__construct($application, $simpleControllerHelper); + } + + /** * @return string */ @@ -58,7 +74,12 @@ final class DownloadBackupAppController extends SimpleControllerBase try { Session::close(); - $filePath = new BackupFile(BackupType::app, $this->configData->getBackupHash(), BACKUP_PATH, 'gz'); + $filePath = new BackupFile( + BackupType::app, + $this->configData->getBackupHash(), + $this->pathsContext[Path::BACKUP], + 'gz' + ); $file = new FileHandler((string)$filePath); $file->checkFileExists(); diff --git a/app/modules/web/Controllers/ConfigBackup/DownloadBackupDbController.php b/app/modules/web/Controllers/ConfigBackup/DownloadBackupDbController.php index be00dbec..03a9dcde 100644 --- a/app/modules/web/Controllers/ConfigBackup/DownloadBackupDbController.php +++ b/app/modules/web/Controllers/ConfigBackup/DownloadBackupDbController.php @@ -25,6 +25,9 @@ namespace SP\Modules\Web\Controllers\ConfigBackup; use Exception; +use SP\Core\Application; +use SP\Core\Bootstrap\Path; +use SP\Core\Bootstrap\PathsContext; use SP\Core\Context\Session; use SP\Core\Events\Event; use SP\Core\Events\EventMessage; @@ -37,6 +40,10 @@ use SP\Domain\Export\Dtos\BackupType; use SP\Infrastructure\File\FileHandler; use SP\Modules\Web\Controllers\SimpleControllerBase; use SP\Modules\Web\Controllers\Traits\JsonTrait; +use SP\Mvc\Controller\SimpleControllerHelper; + +use function SP\__u; +use function SP\processException; /** * Class ConfigBackupController @@ -47,6 +54,14 @@ final class DownloadBackupDbController extends SimpleControllerBase { use JsonTrait; + public function __construct( + Application $application, + SimpleControllerHelper $simpleControllerHelper, + private readonly PathsContext $pathsContext + ) { + parent::__construct($application, $simpleControllerHelper); + } + /** * @return string */ @@ -59,7 +74,12 @@ final class DownloadBackupDbController extends SimpleControllerBase try { Session::close(); - $filePath = new BackupFile(BackupType::db, $this->configData->getBackupHash(), BACKUP_PATH, 'gz'); + $filePath = new BackupFile( + BackupType::db, + $this->configData->getBackupHash(), + $this->pathsContext[Path::BACKUP], + 'gz' + ); $file = new FileHandler((string)$filePath); $file->checkFileExists(); diff --git a/app/modules/web/Controllers/ConfigBackup/DownloadExportController.php b/app/modules/web/Controllers/ConfigBackup/DownloadExportController.php index 38c8766d..ecfc1340 100644 --- a/app/modules/web/Controllers/ConfigBackup/DownloadExportController.php +++ b/app/modules/web/Controllers/ConfigBackup/DownloadExportController.php @@ -26,6 +26,9 @@ namespace SP\Modules\Web\Controllers\ConfigBackup; use Exception; +use SP\Core\Application; +use SP\Core\Bootstrap\Path; +use SP\Core\Bootstrap\PathsContext; use SP\Core\Context\Session; use SP\Core\Events\Event; use SP\Core\Events\EventMessage; @@ -38,6 +41,10 @@ use SP\Domain\Export\Dtos\BackupType; use SP\Infrastructure\File\FileHandler; use SP\Modules\Web\Controllers\SimpleControllerBase; use SP\Modules\Web\Controllers\Traits\JsonTrait; +use SP\Mvc\Controller\SimpleControllerHelper; + +use function SP\__u; +use function SP\processException; /** * Class DownloadExportController @@ -46,6 +53,14 @@ final class DownloadExportController extends SimpleControllerBase { use JsonTrait; + public function __construct( + Application $application, + SimpleControllerHelper $simpleControllerHelper, + private readonly PathsContext $pathsContext + ) { + parent::__construct($application, $simpleControllerHelper); + } + /** * @return string */ @@ -57,7 +72,7 @@ final class DownloadExportController extends SimpleControllerBase $filePath = (string)new BackupFileDto( BackupType::export, $this->configData->getExportHash() ?: '', - BACKUP_PATH, + $this->pathsContext[Path::BACKUP], 'gz' ); diff --git a/app/modules/web/Controllers/ConfigBackup/FileBackupController.php b/app/modules/web/Controllers/ConfigBackup/FileBackupController.php index 40048136..7060436c 100644 --- a/app/modules/web/Controllers/ConfigBackup/FileBackupController.php +++ b/app/modules/web/Controllers/ConfigBackup/FileBackupController.php @@ -27,6 +27,8 @@ namespace SP\Modules\Web\Controllers\ConfigBackup; use Exception; use SP\Core\Application; +use SP\Core\Bootstrap\Path; +use SP\Core\Bootstrap\PathsContext; use SP\Core\Context\Session; use SP\Core\Events\Event; use SP\Core\Events\EventMessage; @@ -40,6 +42,9 @@ use SP\Modules\Web\Controllers\SimpleControllerBase; use SP\Modules\Web\Controllers\Traits\ConfigTrait; use SP\Mvc\Controller\SimpleControllerHelper; +use function SP\__u; +use function SP\processException; + /** * Class FileBackupController */ @@ -47,16 +52,13 @@ final class FileBackupController extends SimpleControllerBase { use ConfigTrait; - private BackupFileService $fileBackupService; - public function __construct( - Application $application, - SimpleControllerHelper $simpleControllerHelper, - BackupFileService $fileBackupService + Application $application, + SimpleControllerHelper $simpleControllerHelper, + private readonly BackupFileService $fileBackupService, + private readonly PathsContext $pathsContext ) { parent::__construct($application, $simpleControllerHelper); - - $this->fileBackupService = $fileBackupService; } /** @@ -72,7 +74,7 @@ final class FileBackupController extends SimpleControllerBase try { Session::close(); - $this->fileBackupService->doBackup(BACKUP_PATH); + $this->fileBackupService->doBackup($this->pathsContext[Path::BACKUP], $this->pathsContext[Path::APP]); $this->eventDispatcher->notify( 'run.backup.end', diff --git a/app/modules/web/Controllers/ConfigBackup/XmlExportController.php b/app/modules/web/Controllers/ConfigBackup/XmlExportController.php index ba47977c..db870f9d 100644 --- a/app/modules/web/Controllers/ConfigBackup/XmlExportController.php +++ b/app/modules/web/Controllers/ConfigBackup/XmlExportController.php @@ -26,6 +26,8 @@ namespace SP\Modules\Web\Controllers\ConfigBackup; use Exception; use SP\Core\Application; +use SP\Core\Bootstrap\Path; +use SP\Core\Bootstrap\PathsContext; use SP\Core\Context\Session; use SP\Core\Events\Event; use SP\Core\Events\EventMessage; @@ -42,6 +44,9 @@ use SP\Modules\Web\Controllers\SimpleControllerBase; use SP\Modules\Web\Controllers\Traits\JsonTrait; use SP\Mvc\Controller\SimpleControllerHelper; +use function SP\__u; +use function SP\processException; + /** * Class XmlExportController */ @@ -49,19 +54,14 @@ final class XmlExportController extends SimpleControllerBase { use JsonTrait; - private XmlExportService $xmlExportService; - private XmlVerifyService $xmlVerifyService; - public function __construct( - Application $application, - SimpleControllerHelper $simpleControllerHelper, - XmlExportService $xmlExportService, - XmlVerifyService $xmlVerifyService + Application $application, + SimpleControllerHelper $simpleControllerHelper, + private readonly XmlExportService $xmlExportService, + private readonly XmlVerifyService $xmlVerifyService, + private readonly PathsContext $pathsContext ) { parent::__construct($application, $simpleControllerHelper); - - $this->xmlExportService = $xmlExportService; - $this->xmlVerifyService = $xmlVerifyService; } /** @@ -85,7 +85,10 @@ final class XmlExportController extends SimpleControllerBase Session::close(); - $file = $this->xmlExportService->export(new DirectoryHandler(BACKUP_PATH), $exportPassword); + $file = $this->xmlExportService->export( + new DirectoryHandler($this->pathsContext[Path::BACKUP]), + $exportPassword + ); $this->eventDispatcher->notify( 'run.export.end', diff --git a/app/modules/web/Controllers/ConfigGeneral/DownloadLogController.php b/app/modules/web/Controllers/ConfigGeneral/DownloadLogController.php index 7a940971..fade5d72 100644 --- a/app/modules/web/Controllers/ConfigGeneral/DownloadLogController.php +++ b/app/modules/web/Controllers/ConfigGeneral/DownloadLogController.php @@ -26,16 +26,23 @@ namespace SP\Modules\Web\Controllers\ConfigGeneral; use Exception; -use JsonException; +use SP\Core\Application; +use SP\Core\Bootstrap\Path; +use SP\Core\Bootstrap\PathsContext; use SP\Core\Context\Session; use SP\Core\Events\Event; use SP\Core\Events\EventMessage; use SP\Domain\Core\Acl\AclActionsInterface; use SP\Domain\Core\Acl\UnauthorizedPageException; use SP\Domain\Core\Exceptions\SessionTimeout; +use SP\Domain\Core\Exceptions\SPException; use SP\Infrastructure\File\FileHandler; use SP\Modules\Web\Controllers\SimpleControllerBase; use SP\Modules\Web\Controllers\Traits\JsonTrait; +use SP\Mvc\Controller\SimpleControllerHelper; + +use function SP\__u; +use function SP\processException; /** * Class DownloadLogController @@ -44,6 +51,14 @@ final class DownloadLogController extends SimpleControllerBase { use JsonTrait; + public function __construct( + Application $application, + SimpleControllerHelper $simpleControllerHelper, + private readonly PathsContext $pathsContext + ) { + parent::__construct($application, $simpleControllerHelper); + } + public function downloadLogAction(): string { if ($this->configData->isDemoEnabled()) { @@ -53,7 +68,7 @@ final class DownloadLogController extends SimpleControllerBase try { Session::close(); - $file = new FileHandler(LOG_FILE); + $file = new FileHandler($this->pathsContext[Path::LOG_FILE]); $file->checkFileExists(); $this->eventDispatcher->notify( @@ -62,7 +77,14 @@ final class DownloadLogController extends SimpleControllerBase $this, EventMessage::factory() ->addDescription(__u('File downloaded')) - ->addDetail(__u('File'), str_replace(APP_ROOT, '', $file->getFile())) + ->addDetail( + __u('File'), + str_replace( + $this->pathsContext[Path::APP], + '', + $file->getFile() + ) + ) ) ); @@ -72,7 +94,7 @@ final class DownloadLogController extends SimpleControllerBase $response->header('Content-type', $file->getFileType()); $response->header('Content-Description', ' sysPass file'); $response->header('Content-transfer-encoding', 'chunked'); - $response->header('Content-Disposition', 'attachment; filename="'.basename($file->getFile()).'"'); + $response->header('Content-Disposition', 'attachment; filename="' . basename($file->getFile()) . '"'); $response->header('Set-Cookie', 'fileDownload=true; path=/'); $response->send(); @@ -87,8 +109,8 @@ final class DownloadLogController extends SimpleControllerBase } /** - * @throws JsonException * @throws SessionTimeout + * @throws SPException */ protected function initialize(): void { diff --git a/app/modules/web/Controllers/ConfigGeneral/SaveController.php b/app/modules/web/Controllers/ConfigGeneral/SaveController.php index 82f7c1af..1ee9061c 100644 --- a/app/modules/web/Controllers/ConfigGeneral/SaveController.php +++ b/app/modules/web/Controllers/ConfigGeneral/SaveController.php @@ -25,6 +25,9 @@ namespace SP\Modules\Web\Controllers\ConfigGeneral; use JsonException; +use SP\Core\Application; +use SP\Core\AppLock; +use SP\Core\Bootstrap\BootstrapBase; use SP\Core\Events\Event; use SP\Core\Events\EventMessage; use SP\Domain\Config\Ports\ConfigDataInterface; @@ -34,10 +37,12 @@ use SP\Domain\Core\Acl\UnauthorizedPageException; use SP\Domain\Core\Exceptions\SessionTimeout; use SP\Domain\Core\Exceptions\SPException; use SP\Domain\Core\Exceptions\ValidationException; -use SP\Infrastructure\File\FileException; -use SP\Infrastructure\File\FileHandler; use SP\Modules\Web\Controllers\SimpleControllerBase; use SP\Modules\Web\Controllers\Traits\ConfigTrait; +use SP\Mvc\Controller\SimpleControllerHelper; + +use function SP\__u; +use function SP\logger; /** * Class ConfigGeneral @@ -48,8 +53,18 @@ final class SaveController extends SimpleControllerBase { use ConfigTrait; + public function __construct( + Application $application, + SimpleControllerHelper $simpleControllerHelper, + private readonly AppLock $appLock + ) { + parent::__construct($application, $simpleControllerHelper); + } + + /** * @throws JsonException + * @throws SPException */ public function saveAction(): bool { @@ -70,7 +85,12 @@ final class SaveController extends SimpleControllerBase $this->config, function () use ($eventMessage, $configData) { if ($configData->isMaintenance()) { - self::lockApp($this->session->getUserData()->getId(), 'config'); + $this->appLock->lock($this->session->getUserData()->getId(), 'config'); + } + + if (BootstrapBase::$LOCK !== false && $configData->isMaintenance() === false) { + $this->appLock->unlock(); + logger('Application unlocked'); } $this->eventDispatcher->notify('save.config.general', new Event($this, $eventMessage)); @@ -225,23 +245,7 @@ final class SaveController extends SimpleControllerBase } /** - * Bloquear la aplicación - * - * @throws JsonException - * @throws FileException - */ - private static function lockApp(int $userId, string $subject): void - { - $data = ['time' => time(), 'userId' => $userId, 'subject' => $subject]; - - $file = new FileHandler(LOCK_FILE); - $file->save(json_encode($data, JSON_THROW_ON_ERROR)); - - logger('Application locked out'); - } - - /** - * @throws JsonException + * @throws SPException * @throws SessionTimeout */ protected function initialize(): void diff --git a/app/modules/web/Controllers/ConfigManager/IndexController.php b/app/modules/web/Controllers/ConfigManager/IndexController.php index 9f46be11..a97fa162 100644 --- a/app/modules/web/Controllers/ConfigManager/IndexController.php +++ b/app/modules/web/Controllers/ConfigManager/IndexController.php @@ -30,6 +30,8 @@ use Psr\Container\ContainerExceptionInterface; use Psr\Container\NotFoundExceptionInterface; use SP\Core\Acl\Acl; use SP\Core\Application; +use SP\Core\Bootstrap\Path; +use SP\Core\Bootstrap\PathsContext; use SP\Core\Crypt\CryptSessionHandler; use SP\Core\Events\Event; use SP\Core\Language; @@ -37,6 +39,7 @@ use SP\Domain\Account\Ports\AccountService; use SP\Domain\Auth\Providers\Ldap\LdapMsAds; use SP\Domain\Auth\Providers\Ldap\LdapStd; use SP\Domain\Auth\Providers\Ldap\LdapTypeEnum; +use SP\Domain\Auth\Services\AuthException; use SP\Domain\Common\Services\ServiceException; use SP\Domain\Config\Ports\ConfigService; use SP\Domain\Core\Acl\AclActionsInterface; @@ -44,6 +47,7 @@ use SP\Domain\Core\AppInfoInterface; use SP\Domain\Core\Exceptions\CheckException; use SP\Domain\Core\Exceptions\ConstraintException; use SP\Domain\Core\Exceptions\QueryException; +use SP\Domain\Core\Exceptions\SessionTimeout; use SP\Domain\Core\Exceptions\SPException; use SP\Domain\Core\File\MimeType; use SP\Domain\Core\File\MimeTypesService; @@ -53,7 +57,6 @@ use SP\Domain\Export\Dtos\BackupFiles; use SP\Domain\Export\Dtos\BackupType; use SP\Domain\Log\Providers\LogInterface; use SP\Domain\Notification\Services\MailEvent; -use SP\Domain\Task\Services\Task; use SP\Domain\User\Ports\UserGroupService; use SP\Domain\User\Ports\UserProfileService; use SP\Domain\User\Ports\UserService; @@ -66,9 +69,10 @@ use SP\Modules\Web\Controllers\Helpers\TabsHelper; use SP\Mvc\Controller\WebControllerHelper; use SP\Mvc\View\Components\DataTab; use SP\Mvc\View\Components\SelectItemAdapter; -use SP\Plugin\PluginManager; use SP\Util\Util; +use function SP\__; + /** * Class ConfigManagerController */ @@ -82,21 +86,24 @@ final class IndexController extends ControllerBase private DatabaseUtil $databaseUtil; private ConfigService $configService; private AccountService $accountService; - private PluginManager $pluginManager; + /** + * @throws AuthException + * @throws SessionTimeout + */ public function __construct( - Application $application, - WebControllerHelper $webControllerHelper, - TabsHelper $tabsHelper, - UserService $userService, - UserGroupService $userGroupService, - UserProfileService $userProfileService, - MimeTypesService $mimeTypes, - DatabaseUtil $databaseUtil, - ConfigService $configService, - AccountService $accountService, - PluginManager $pluginManager, - private readonly BackupFiles $backupFiles + Application $application, + WebControllerHelper $webControllerHelper, + TabsHelper $tabsHelper, + UserService $userService, + UserGroupService $userGroupService, + UserProfileService $userProfileService, + MimeTypesService $mimeTypes, + DatabaseUtil $databaseUtil, + ConfigService $configService, + AccountService $accountService, + private readonly BackupFiles $backupFiles, + private readonly PathsContext $pathsContext ) { parent::__construct($application, $webControllerHelper); @@ -110,7 +117,6 @@ final class IndexController extends ControllerBase $this->databaseUtil = $databaseUtil; $this->configService = $configService; $this->accountService = $accountService; - $this->pluginManager = $pluginManager; } @@ -468,7 +474,7 @@ final class IndexController extends ControllerBase (string)new BackupFileDto( BackupType::export, $this->configData->getExportHash() ?: '', - BACKUP_PATH, + $this->pathsContext[Path::BACKUP], 'gz' ) ); @@ -569,7 +575,7 @@ final class IndexController extends ControllerBase ); $template->assign( 'downloadLog', - !$isDemo && is_readable(LOG_FILE) && $this->userData->getIsAdminApp() + !$isDemo && is_readable($this->pathsContext[Path::LOG_FILE]) && $this->userData->getIsAdminApp() ); return new DataTab(__('Information'), $template); diff --git a/app/modules/web/Controllers/ControllerBase.php b/app/modules/web/Controllers/ControllerBase.php index c947a890..16d70f03 100644 --- a/app/modules/web/Controllers/ControllerBase.php +++ b/app/modules/web/Controllers/ControllerBase.php @@ -25,10 +25,9 @@ namespace SP\Modules\Web\Controllers; use Exception; +use SebastianBergmann\RecursionContext\Context; use SP\Core\Application; -use SP\Core\Bootstrap\BootstrapBase; use SP\Core\Crypt\Hash; -use SP\Core\Events\EventDispatcher; use SP\Domain\Auth\Providers\Browser\BrowserAuthService; use SP\Domain\Auth\Services\AuthException; use SP\Domain\Config\Ports\ConfigDataInterface; @@ -37,6 +36,7 @@ use SP\Domain\Core\Acl\AclInterface; use SP\Domain\Core\Bootstrap\RouteContextData; use SP\Domain\Core\Bootstrap\UriContextInterface; use SP\Domain\Core\Context\SessionContext; +use SP\Domain\Core\Events\EventDispatcherInterface; use SP\Domain\Core\Exceptions\SessionTimeout; use SP\Domain\Core\Exceptions\SPException; use SP\Domain\Core\PhpExtensionCheckerService; @@ -61,23 +61,23 @@ abstract class ControllerBase protected const ERR_UNAVAILABLE = 0; - protected readonly EventDispatcher $eventDispatcher; + protected readonly EventDispatcherInterface $eventDispatcher; protected readonly ConfigFileService $config; - protected readonly SessionContext $session; + protected readonly Context|SessionContext $session; protected readonly ThemeInterface $theme; protected readonly AclInterface $acl; protected readonly ConfigDataInterface $configData; - protected readonly RequestService $request; + protected readonly RequestService $request; protected readonly PhpExtensionCheckerService $extensionChecker; protected readonly TemplateInterface $view; protected readonly LayoutHelper $layoutHelper; protected readonly UriContextInterface $uriContext; - protected readonly ?UserDataDto $userData; - protected readonly ProfileData $userProfileData; - protected readonly bool $isAjax; - protected readonly string $actionName; - protected readonly RouteContextData $routeContextData; - protected readonly string $controllerName; + protected ?UserDataDto $userData = null; + protected ?ProfileData $userProfileData = null; + protected readonly bool $isAjax; + protected readonly string $actionName; + protected readonly RouteContextData $routeContextData; + protected readonly string $controllerName; private readonly BrowserAuthService $browser; public function __construct(Application $application, WebControllerHelper $webControllerHelper) @@ -99,7 +99,7 @@ abstract class ControllerBase $this->uriContext = $webControllerHelper->getUriContext(); $this->isAjax = $this->request->isAjax(); - $this->actionName = $this->session->getTrasientKey(BootstrapBase::CONTEXT_ACTION_NAME); + $this->actionName = $this->routeContextData->getActionName(); $loggedIn = $this->session->isLoggedIn(); diff --git a/app/modules/web/Controllers/Helpers/Account/AccountSearchData.php b/app/modules/web/Controllers/Helpers/Account/AccountSearchData.php index 12087214..7102c168 100644 --- a/app/modules/web/Controllers/Helpers/Account/AccountSearchData.php +++ b/app/modules/web/Controllers/Helpers/Account/AccountSearchData.php @@ -73,7 +73,6 @@ use function SP\processException; */ final class AccountSearchData { - private const COLORS_CACHE_FILE = CACHE_PATH . DIRECTORY_SEPARATOR . 'colors.cache'; private const COLORS = [ '2196F3', '03A9F4', @@ -116,7 +115,7 @@ final class AccountSearchData private function loadColors(): void { try { - $this->accountColor = $this->fileCache->load(self::COLORS_CACHE_FILE); + $this->accountColor = $this->fileCache->load(); logger('Loaded accounts color cache'); } catch (FileException $e) { @@ -195,7 +194,7 @@ final class AccountSearchData $this->accountColor[$id] = '#' . self::COLORS[array_rand(self::COLORS)]; try { - $this->fileCache->save($this->accountColor, self::COLORS_CACHE_FILE); + $this->fileCache->save($this->accountColor); logger('Saved accounts color cache'); diff --git a/app/modules/web/Controllers/Helpers/Grid/AccountGrid.php b/app/modules/web/Controllers/Helpers/Grid/AccountGrid.php index ebfad9aa..f7d71651 100644 --- a/app/modules/web/Controllers/Helpers/Grid/AccountGrid.php +++ b/app/modules/web/Controllers/Helpers/Grid/AccountGrid.php @@ -26,6 +26,7 @@ namespace SP\Modules\Web\Controllers\Helpers\Grid; use SP\Core\Acl\Acl; use SP\Domain\Core\Acl\AclActionsInterface; +use SP\Domain\Core\Exceptions\SPException; use SP\Html\DataGrid\Action\DataGridAction; use SP\Html\DataGrid\Action\DataGridActionHelp; use SP\Html\DataGrid\Action\DataGridActionSearch; @@ -36,6 +37,8 @@ use SP\Html\DataGrid\DataGridTab; use SP\Html\DataGrid\Layout\DataGridHeader; use SP\Infrastructure\Database\QueryResult; +use function SP\__; + /** * Class AccountGrid * @@ -91,7 +94,7 @@ final class AccountGrid extends GridBase protected function getGridLayout(): DataGridInterface { // Grid - $gridTab = new DataGridTab($this->view->getTheme()); + $gridTab = new DataGridTab($this->theme); $gridTab->setId('tblAccounts'); $gridTab->setDataRowTemplate('datagrid-rows', 'grid'); $gridTab->setDataPagerTemplate('datagrid-nav-full', 'grid'); @@ -102,9 +105,6 @@ final class AccountGrid extends GridBase return $gridTab; } - /** - * @return DataGridHeader - */ protected function getHeader(): DataGridHeader { // Grid Header @@ -119,7 +119,7 @@ final class AccountGrid extends GridBase } /** - * @return DataGridData + * @throws SPException */ protected function getData(): DataGridData { @@ -136,9 +136,6 @@ final class AccountGrid extends GridBase return $gridData; } - /** - * @return DataGridActionSearch - */ private function getSearchAction(): DataGridActionSearch { $gridActionSearch = new DataGridActionSearch(); @@ -175,9 +172,6 @@ final class AccountGrid extends GridBase return $gridAction; } - /** - * @return DataGridAction - */ private function getDeleteAction(): DataGridAction { $gridAction = new DataGridAction(); diff --git a/app/modules/web/Controllers/Helpers/Grid/AccountHistoryGrid.php b/app/modules/web/Controllers/Helpers/Grid/AccountHistoryGrid.php index e3729359..254c9119 100644 --- a/app/modules/web/Controllers/Helpers/Grid/AccountHistoryGrid.php +++ b/app/modules/web/Controllers/Helpers/Grid/AccountHistoryGrid.php @@ -26,6 +26,7 @@ namespace SP\Modules\Web\Controllers\Helpers\Grid; use SP\Core\Acl\Acl; use SP\Domain\Core\Acl\AclActionsInterface; +use SP\Domain\Core\Exceptions\SPException; use SP\Html\DataGrid\Action\DataGridAction; use SP\Html\DataGrid\Action\DataGridActionSearch; use SP\Html\DataGrid\Action\DataGridActionType; @@ -83,7 +84,7 @@ final class AccountHistoryGrid extends GridBase protected function getGridLayout(): DataGridInterface { // Grid - $gridTab = new DataGridTab($this->view->getTheme()); + $gridTab = new DataGridTab($this->theme); $gridTab->setId('tblAccountsHistory'); $gridTab->setDataRowTemplate('datagrid-rows', 'grid'); $gridTab->setDataPagerTemplate('datagrid-nav-full', 'grid'); @@ -111,7 +112,7 @@ final class AccountHistoryGrid extends GridBase } /** - * @return DataGridData + * @throws SPException */ protected function getData(): DataGridData { diff --git a/app/modules/web/Controllers/Helpers/Grid/AuthTokenGrid.php b/app/modules/web/Controllers/Helpers/Grid/AuthTokenGrid.php index 5cf7ce42..586c02da 100644 --- a/app/modules/web/Controllers/Helpers/Grid/AuthTokenGrid.php +++ b/app/modules/web/Controllers/Helpers/Grid/AuthTokenGrid.php @@ -36,6 +36,9 @@ use SP\Html\DataGrid\DataGridTab; use SP\Html\DataGrid\Layout\DataGridHeader; use SP\Infrastructure\Database\QueryResult; +use function SP\__; +use function SP\getElapsedTime; + /** * Class AuthTokenGrid * @@ -78,13 +81,10 @@ final class AuthTokenGrid extends GridBase return $grid; } - /** - * @return DataGridInterface - */ protected function getGridLayout(): DataGridInterface { // Grid - $gridTab = new DataGridTab($this->view->getTheme()); + $gridTab = new DataGridTab($this->theme); $gridTab->setId('tblTokens'); $gridTab->setDataRowTemplate('datagrid-rows', 'grid'); $gridTab->setDataPagerTemplate('datagrid-nav-full', 'grid'); @@ -95,9 +95,6 @@ final class AuthTokenGrid extends GridBase return $gridTab; } - /** - * @return DataGridHeader - */ protected function getHeader(): DataGridHeader { // Grid Header @@ -108,9 +105,6 @@ final class AuthTokenGrid extends GridBase return $gridHeader; } - /** - * @return DataGridData - */ protected function getData(): DataGridData { // Grid Data diff --git a/app/modules/web/Controllers/Helpers/Grid/CategoryGrid.php b/app/modules/web/Controllers/Helpers/Grid/CategoryGrid.php index dedb93ce..8d8d81da 100644 --- a/app/modules/web/Controllers/Helpers/Grid/CategoryGrid.php +++ b/app/modules/web/Controllers/Helpers/Grid/CategoryGrid.php @@ -27,6 +27,7 @@ namespace SP\Modules\Web\Controllers\Helpers\Grid; use SP\Core\Acl\Acl; use SP\Domain\Core\Acl\AclActionsInterface; +use SP\Domain\Core\Exceptions\SPException; use SP\Html\DataGrid\Action\DataGridAction; use SP\Html\DataGrid\Action\DataGridActionSearch; use SP\Html\DataGrid\Action\DataGridActionType; @@ -36,6 +37,9 @@ use SP\Html\DataGrid\DataGridTab; use SP\Html\DataGrid\Layout\DataGridHeader; use SP\Infrastructure\Database\QueryResult; +use function SP\__; +use function SP\getElapsedTime; + /** * Class CategoryGrid * @@ -49,6 +53,7 @@ final class CategoryGrid extends GridBase * @param QueryResult $queryResult * * @return DataGridInterface + * @throws SPException */ public function getGrid(QueryResult $queryResult): DataGridInterface { @@ -78,12 +83,12 @@ final class CategoryGrid extends GridBase } /** - * @return DataGridInterface + * @throws SPException */ protected function getGridLayout(): DataGridInterface { // Grid - $gridTab = new DataGridTab($this->view->getTheme()); + $gridTab = new DataGridTab($this->theme); $gridTab->setId('tblCategories'); $gridTab->setDataRowTemplate('datagrid-rows', 'grid'); $gridTab->setDataPagerTemplate('datagrid-nav-full', 'grid'); @@ -94,9 +99,6 @@ final class CategoryGrid extends GridBase return $gridTab; } - /** - * @return DataGridHeader - */ protected function getHeader(): DataGridHeader { // Grid Header @@ -108,7 +110,7 @@ final class CategoryGrid extends GridBase } /** - * @return DataGridData + * @throws SPException */ protected function getData(): DataGridData { @@ -122,9 +124,6 @@ final class CategoryGrid extends GridBase return $gridData; } - /** - * @return DataGridActionSearch - */ private function getSearchAction(): DataGridActionSearch { // Grid Actions @@ -142,9 +141,6 @@ final class CategoryGrid extends GridBase return $gridActionSearch; } - /** - * @return DataGridAction - */ private function getCreateAction(): DataGridAction { $gridAction = new DataGridAction(); @@ -163,9 +159,6 @@ final class CategoryGrid extends GridBase return $gridAction; } - /** - * @return DataGridAction - */ private function getEditAction(): DataGridAction { $gridAction = new DataGridAction(); @@ -183,9 +176,6 @@ final class CategoryGrid extends GridBase return $gridAction; } - /** - * @return DataGridAction - */ private function getDeleteAction(): DataGridAction { $gridAction = new DataGridAction(); diff --git a/app/modules/web/Controllers/Helpers/Grid/ClientGrid.php b/app/modules/web/Controllers/Helpers/Grid/ClientGrid.php index e9578656..4b3b784b 100644 --- a/app/modules/web/Controllers/Helpers/Grid/ClientGrid.php +++ b/app/modules/web/Controllers/Helpers/Grid/ClientGrid.php @@ -26,6 +26,7 @@ namespace SP\Modules\Web\Controllers\Helpers\Grid; use SP\Core\Acl\Acl; use SP\Domain\Core\Acl\AclActionsInterface; +use SP\Domain\Core\Exceptions\SPException; use SP\Html\DataGrid\Action\DataGridAction; use SP\Html\DataGrid\Action\DataGridActionSearch; use SP\Html\DataGrid\Action\DataGridActionType; @@ -35,6 +36,9 @@ use SP\Html\DataGrid\DataGridTab; use SP\Html\DataGrid\Layout\DataGridHeader; use SP\Infrastructure\Database\QueryResult; +use function SP\__; +use function SP\getElapsedTime; + /** * Class ClientGrid * @@ -48,6 +52,7 @@ final class ClientGrid extends GridBase * @param QueryResult $queryResult * * @return DataGridInterface + * @throws SPException */ public function getGrid(QueryResult $queryResult): DataGridInterface { @@ -77,12 +82,12 @@ final class ClientGrid extends GridBase } /** - * @return DataGridInterface + * @throws SPException */ protected function getGridLayout(): DataGridInterface { // Grid - $gridTab = new DataGridTab($this->view->getTheme()); + $gridTab = new DataGridTab($this->theme); $gridTab->setId('tblClients'); $gridTab->setDataRowTemplate('datagrid-rows', 'grid'); $gridTab->setDataPagerTemplate('datagrid-nav-full', 'grid'); @@ -93,9 +98,6 @@ final class ClientGrid extends GridBase return $gridTab; } - /** - * @return DataGridHeader - */ protected function getHeader(): DataGridHeader { // Grid Header @@ -108,7 +110,7 @@ final class ClientGrid extends GridBase } /** - * @return DataGridData + * @throws SPException */ protected function getData(): DataGridData { @@ -129,9 +131,6 @@ final class ClientGrid extends GridBase return $gridData; } - /** - * @return DataGridActionSearch - */ private function getSearchAction(): DataGridActionSearch { // Grid Actions @@ -170,9 +169,6 @@ final class ClientGrid extends GridBase return $gridAction; } - /** - * @return DataGridAction - */ private function getEditAction(): DataGridAction { $gridAction = new DataGridAction(); @@ -190,9 +186,6 @@ final class ClientGrid extends GridBase return $gridAction; } - /** - * @return DataGridAction - */ private function getDeleteAction(): DataGridAction { $gridAction = new DataGridAction(); diff --git a/app/modules/web/Controllers/Helpers/Grid/CustomFieldGrid.php b/app/modules/web/Controllers/Helpers/Grid/CustomFieldGrid.php index 9e18d746..fefbab9c 100644 --- a/app/modules/web/Controllers/Helpers/Grid/CustomFieldGrid.php +++ b/app/modules/web/Controllers/Helpers/Grid/CustomFieldGrid.php @@ -85,7 +85,7 @@ final class CustomFieldGrid extends GridBase protected function getGridLayout(): DataGridInterface { // Grid - $gridTab = new DataGridTab($this->view->getTheme()); + $gridTab = new DataGridTab($this->theme); $gridTab->setId('tblCustomFields'); $gridTab->setDataRowTemplate('datagrid-rows', 'grid'); $gridTab->setDataPagerTemplate('datagrid-nav-full', 'grid'); diff --git a/app/modules/web/Controllers/Helpers/Grid/EventlogGrid.php b/app/modules/web/Controllers/Helpers/Grid/EventlogGrid.php index 6b1aa59f..7c3f4499 100644 --- a/app/modules/web/Controllers/Helpers/Grid/EventlogGrid.php +++ b/app/modules/web/Controllers/Helpers/Grid/EventlogGrid.php @@ -27,6 +27,7 @@ namespace SP\Modules\Web\Controllers\Helpers\Grid; use SP\Core\Acl\Acl; use SP\Domain\Core\Acl\AclActionsInterface; +use SP\Domain\Core\Exceptions\SPException; use SP\Html\DataGrid\Action\DataGridAction; use SP\Html\DataGrid\Action\DataGridActionSearch; use SP\Html\DataGrid\Action\DataGridActionType; @@ -36,6 +37,9 @@ use SP\Html\DataGrid\DataGridTab; use SP\Html\DataGrid\Layout\DataGridHeader; use SP\Infrastructure\Database\QueryResult; +use function SP\__; +use function SP\getElapsedTime; + /** * Class EventlogGrid * @@ -49,6 +53,7 @@ final class EventlogGrid extends GridBase * @param QueryResult $queryResult * * @return DataGridInterface + * @throws SPException */ public function getGrid(QueryResult $queryResult): DataGridInterface { @@ -70,12 +75,12 @@ final class EventlogGrid extends GridBase } /** - * @return DataGridInterface + * @throws SPException */ protected function getGridLayout(): DataGridInterface { // Grid - $gridTab = new DataGridTab($this->view->getTheme()); + $gridTab = new DataGridTab($this->theme); $gridTab->setId('tblEventLog'); $gridTab->setDataRowTemplate('datagrid-rows', 'grid'); $gridTab->setDataPagerTemplate('datagrid-nav-full', 'grid'); @@ -86,9 +91,6 @@ final class EventlogGrid extends GridBase return $gridTab; } - /** - * @return DataGridHeader - */ protected function getHeader(): DataGridHeader { // Grid Header @@ -105,7 +107,7 @@ final class EventlogGrid extends GridBase } /** - * @return DataGridData + * @throws SPException */ protected function getData(): DataGridData { @@ -162,9 +164,6 @@ final class EventlogGrid extends GridBase return $gridData; } - /** - * @return DataGridActionSearch - */ private function getSearchAction(): DataGridActionSearch { // Grid Actions @@ -182,9 +181,6 @@ final class EventlogGrid extends GridBase return $gridActionSearch; } - /** - * @return DataGridAction - */ private function getRefrestAction(): DataGridAction { $gridAction = new DataGridAction(); @@ -204,9 +200,6 @@ final class EventlogGrid extends GridBase return $gridAction; } - /** - * @return DataGridAction - */ private function getClearAction(): DataGridAction { $gridAction = new DataGridAction(); diff --git a/app/modules/web/Controllers/Helpers/Grid/FileGrid.php b/app/modules/web/Controllers/Helpers/Grid/FileGrid.php index c8c83f86..659fbdc8 100644 --- a/app/modules/web/Controllers/Helpers/Grid/FileGrid.php +++ b/app/modules/web/Controllers/Helpers/Grid/FileGrid.php @@ -26,6 +26,7 @@ namespace SP\Modules\Web\Controllers\Helpers\Grid; use SP\Core\Acl\Acl; use SP\Domain\Core\Acl\AclActionsInterface; +use SP\Domain\Core\Exceptions\SPException; use SP\Html\DataGrid\Action\DataGridAction; use SP\Html\DataGrid\Action\DataGridActionSearch; use SP\Html\DataGrid\Action\DataGridActionType; @@ -35,6 +36,9 @@ use SP\Html\DataGrid\DataGridTab; use SP\Html\DataGrid\Layout\DataGridHeader; use SP\Infrastructure\Database\QueryResult; +use function SP\__; +use function SP\getElapsedTime; + /** * Class FileGrid * @@ -77,13 +81,10 @@ final class FileGrid extends GridBase return $grid; } - /** - * @return DataGridInterface - */ protected function getGridLayout(): DataGridInterface { // Grid - $gridTab = new DataGridTab($this->view->getTheme()); + $gridTab = new DataGridTab($this->theme); $gridTab->setId('tblFiles'); $gridTab->setDataRowTemplate('datagrid-rows', 'grid'); $gridTab->setDataPagerTemplate('datagrid-nav-full', 'grid'); @@ -94,9 +95,6 @@ final class FileGrid extends GridBase return $gridTab; } - /** - * @return DataGridHeader - */ protected function getHeader(): DataGridHeader { // Grid Header @@ -111,7 +109,7 @@ final class FileGrid extends GridBase } /** - * @return DataGridData + * @throws SPException */ protected function getData(): DataGridData { @@ -134,9 +132,6 @@ final class FileGrid extends GridBase return $gridData; } - /** - * @return DataGridActionSearch - */ private function getSearchAction(): DataGridActionSearch { // Grid Actions @@ -154,9 +149,6 @@ final class FileGrid extends GridBase return $gridActionSearch; } - /** - * @return DataGridAction - */ private function getViewAction(): DataGridAction { $gridAction = new DataGridAction(); @@ -175,9 +167,6 @@ final class FileGrid extends GridBase return $gridAction; } - /** - * @return DataGridAction - */ private function getDownloadAction(): DataGridAction { $gridAction = new DataGridAction(); @@ -200,9 +189,6 @@ final class FileGrid extends GridBase return $gridAction; } - /** - * @return DataGridAction - */ private function getDeleteAction(): DataGridAction { $gridAction = new DataGridAction(); diff --git a/app/modules/web/Controllers/Helpers/Grid/GridBase.php b/app/modules/web/Controllers/Helpers/Grid/GridBase.php index 3d660ab5..916e5a46 100644 --- a/app/modules/web/Controllers/Helpers/Grid/GridBase.php +++ b/app/modules/web/Controllers/Helpers/Grid/GridBase.php @@ -24,11 +24,11 @@ namespace SP\Modules\Web\Controllers\Helpers\Grid; -use SP\Core\Acl\Acl; use SP\Core\Application; -use SP\Core\UI\ThemeIcons; use SP\Domain\Core\Acl\AclInterface; use SP\Domain\Core\Dtos\ItemSearchDto; +use SP\Domain\Core\UI\ThemeIconsInterface; +use SP\Domain\Core\UI\ThemeInterface; use SP\Domain\Http\Ports\RequestService; use SP\Html\DataGrid\Action\DataGridActionSearch; use SP\Html\DataGrid\DataGridData; @@ -45,21 +45,20 @@ use SP\Mvc\View\TemplateInterface; */ abstract class GridBase extends HelperBase implements GridInterface { - protected float $queryTimeStart; - protected ThemeIcons $icons; - protected Acl $acl; + protected float $queryTimeStart; + protected ThemeIconsInterface $icons; public function __construct( - Application $application, - TemplateInterface $template, - RequestService $request, - AclInterface $acl + Application $application, + TemplateInterface $template, + RequestService $request, + protected readonly AclInterface $acl, + protected readonly ThemeInterface $theme ) { parent::__construct($application, $template, $request); $this->queryTimeStart = microtime(true); - $this->acl = $acl; - $this->icons = $this->view->getTheme()->getIcons(); + $this->icons = $this->theme->getIcons(); } diff --git a/app/modules/web/Controllers/Helpers/Grid/ItemPresetGrid.php b/app/modules/web/Controllers/Helpers/Grid/ItemPresetGrid.php index 378e7df8..5b2f7f48 100644 --- a/app/modules/web/Controllers/Helpers/Grid/ItemPresetGrid.php +++ b/app/modules/web/Controllers/Helpers/Grid/ItemPresetGrid.php @@ -26,6 +26,7 @@ namespace SP\Modules\Web\Controllers\Helpers\Grid; use SP\Core\Acl\Acl; use SP\Domain\Core\Acl\AclActionsInterface; +use SP\Domain\Core\Exceptions\SPException; use SP\Domain\ItemPreset\Ports\ItemPresetInterface; use SP\Html\DataGrid\Action\DataGridAction; use SP\Html\DataGrid\Action\DataGridActionSearch; @@ -37,6 +38,7 @@ use SP\Html\DataGrid\Layout\DataGridHeader; use SP\Infrastructure\Database\QueryResult; use function SP\__; +use function SP\getElapsedTime; /** * Class AccountDefaultPermissionGrid @@ -82,13 +84,10 @@ final class ItemPresetGrid extends GridBase return $grid; } - /** - * @return DataGridInterface - */ protected function getGridLayout(): DataGridInterface { // Grid - $gridTab = new DataGridTab($this->view->getTheme()); + $gridTab = new DataGridTab($this->theme); $gridTab->setId('tblItemPreset'); $gridTab->setDataRowTemplate('datagrid-rows', 'grid'); $gridTab->setDataPagerTemplate('datagrid-nav-full', 'grid'); @@ -99,9 +98,6 @@ final class ItemPresetGrid extends GridBase return $gridTab; } - /** - * @return DataGridHeader - */ protected function getHeader(): DataGridHeader { // Grid Header @@ -117,7 +113,7 @@ final class ItemPresetGrid extends GridBase } /** - * @return DataGridData + * @throws SPException */ protected function getData(): DataGridData { @@ -135,9 +131,6 @@ final class ItemPresetGrid extends GridBase return $gridData; } - /** - * @return DataGridActionSearch - */ private function getSearchAction(): DataGridActionSearch { // Grid Actions @@ -155,9 +148,6 @@ final class ItemPresetGrid extends GridBase return $gridActionSearch; } - /** - * @return DataGridAction - */ private function getCreatePermissionAction(): DataGridAction { $gridAction = new DataGridAction(); @@ -180,9 +170,6 @@ final class ItemPresetGrid extends GridBase return $gridAction; } - /** - * @return DataGridAction - */ private function getCreatePrivateAction(): DataGridAction { $gridAction = new DataGridAction(); @@ -205,9 +192,6 @@ final class ItemPresetGrid extends GridBase return $gridAction; } - /** - * @return DataGridAction - */ private function getCreateSessionTimeoutAction(): DataGridAction { $gridAction = new DataGridAction(); @@ -230,9 +214,6 @@ final class ItemPresetGrid extends GridBase return $gridAction; } - /** - * @return DataGridAction - */ private function getCreateAccountPasswordAction(): DataGridAction { $gridAction = new DataGridAction(); @@ -255,9 +236,6 @@ final class ItemPresetGrid extends GridBase return $gridAction; } - /** - * @return DataGridAction - */ private function getEditAction(): DataGridAction { $gridAction = new DataGridAction(); @@ -275,9 +253,6 @@ final class ItemPresetGrid extends GridBase return $gridAction; } - /** - * @return DataGridAction - */ private function getDeleteAction(): DataGridAction { $gridAction = new DataGridAction(); diff --git a/app/modules/web/Controllers/Helpers/Grid/NotificationGrid.php b/app/modules/web/Controllers/Helpers/Grid/NotificationGrid.php index 2cf808e4..b051516d 100644 --- a/app/modules/web/Controllers/Helpers/Grid/NotificationGrid.php +++ b/app/modules/web/Controllers/Helpers/Grid/NotificationGrid.php @@ -28,6 +28,7 @@ namespace SP\Modules\Web\Controllers\Helpers\Grid; use SP\Core\Acl\Acl; use SP\Domain\Common\Adapters\Date; use SP\Domain\Core\Acl\AclActionsInterface; +use SP\Domain\Core\Exceptions\SPException; use SP\Domain\Html\Html; use SP\Html\DataGrid\Action\DataGridAction; use SP\Html\DataGrid\Action\DataGridActionInterface; @@ -40,6 +41,7 @@ use SP\Html\DataGrid\Layout\DataGridHeader; use SP\Infrastructure\Database\QueryResult; use function SP\__; +use function SP\getElapsedTime; /** * Class NotificationGrid @@ -103,7 +105,7 @@ final class NotificationGrid extends GridBase protected function getGridLayout(): DataGridInterface { // Grid - $dataGrid = new DataGrid($this->view->getTheme()); + $dataGrid = new DataGrid($this->theme); $dataGrid->setId('tblNotifications'); $dataGrid->setDataRowTemplate('datagrid-rows', 'grid'); $dataGrid->setDataPagerTemplate('datagrid-nav-full', 'grid'); @@ -133,6 +135,7 @@ final class NotificationGrid extends GridBase /** * @return DataGridData + * @throws SPException */ protected function getData(): DataGridData { diff --git a/app/modules/web/Controllers/Helpers/Grid/PluginGrid.php b/app/modules/web/Controllers/Helpers/Grid/PluginGrid.php index 16640e09..9ef28c4b 100644 --- a/app/modules/web/Controllers/Helpers/Grid/PluginGrid.php +++ b/app/modules/web/Controllers/Helpers/Grid/PluginGrid.php @@ -24,9 +24,9 @@ namespace SP\Modules\Web\Controllers\Helpers\Grid; - use SP\Core\Acl\Acl; use SP\Domain\Core\Acl\AclActionsInterface; +use SP\Domain\Core\Exceptions\SPException; use SP\Html\DataGrid\Action\DataGridAction; use SP\Html\DataGrid\Action\DataGridActionSearch; use SP\Html\DataGrid\Action\DataGridActionType; @@ -37,6 +37,7 @@ use SP\Html\DataGrid\Layout\DataGridHeader; use SP\Infrastructure\Database\QueryResult; use function SP\__; +use function SP\getElapsedTime; /** * Class PluginGrid @@ -80,7 +81,7 @@ final class PluginGrid extends GridBase protected function getGridLayout(): DataGridInterface { // Grid - $gridTab = new DataGridTab($this->view->getTheme()); + $gridTab = new DataGridTab($this->theme); $gridTab->setId('tblPlugins'); $gridTab->setDataRowTemplate('datagrid-rows', 'grid'); $gridTab->setDataPagerTemplate('datagrid-nav-full', 'grid'); @@ -106,6 +107,7 @@ final class PluginGrid extends GridBase /** * @return DataGridData + * @throws SPException */ protected function getData(): DataGridData { diff --git a/app/modules/web/Controllers/Helpers/Grid/PublicLinkGrid.php b/app/modules/web/Controllers/Helpers/Grid/PublicLinkGrid.php index c86b75b4..ac9c3a92 100644 --- a/app/modules/web/Controllers/Helpers/Grid/PublicLinkGrid.php +++ b/app/modules/web/Controllers/Helpers/Grid/PublicLinkGrid.php @@ -24,9 +24,9 @@ namespace SP\Modules\Web\Controllers\Helpers\Grid; - use SP\Core\Acl\Acl; use SP\Domain\Core\Acl\AclActionsInterface; +use SP\Domain\Core\Exceptions\SPException; use SP\Html\DataGrid\Action\DataGridAction; use SP\Html\DataGrid\Action\DataGridActionSearch; use SP\Html\DataGrid\Action\DataGridActionType; @@ -36,6 +36,9 @@ use SP\Html\DataGrid\DataGridTab; use SP\Html\DataGrid\Layout\DataGridHeader; use SP\Infrastructure\Database\QueryResult; +use function SP\__; +use function SP\getElapsedTime; + /** * Class PublicLinkGrid * @@ -85,7 +88,7 @@ final class PublicLinkGrid extends GridBase protected function getGridLayout(): DataGridInterface { // Grid - $gridTab = new DataGridTab($this->view->getTheme()); + $gridTab = new DataGridTab($this->theme); $gridTab->setId('tblLinks'); $gridTab->setDataRowTemplate('datagrid-rows', 'grid'); $gridTab->setDataPagerTemplate('datagrid-nav-full', 'grid'); @@ -115,7 +118,7 @@ final class PublicLinkGrid extends GridBase } /** - * @return DataGridData + * @throws SPException */ protected function getData(): DataGridData { diff --git a/app/modules/web/Controllers/Helpers/Grid/TagGrid.php b/app/modules/web/Controllers/Helpers/Grid/TagGrid.php index 5b0d0c92..7d15770b 100644 --- a/app/modules/web/Controllers/Helpers/Grid/TagGrid.php +++ b/app/modules/web/Controllers/Helpers/Grid/TagGrid.php @@ -27,6 +27,7 @@ namespace SP\Modules\Web\Controllers\Helpers\Grid; use SP\Core\Acl\Acl; use SP\Domain\Core\Acl\AclActionsInterface; +use SP\Domain\Core\Exceptions\SPException; use SP\Html\DataGrid\Action\DataGridAction; use SP\Html\DataGrid\Action\DataGridActionSearch; use SP\Html\DataGrid\Action\DataGridActionType; @@ -36,6 +37,9 @@ use SP\Html\DataGrid\DataGridTab; use SP\Html\DataGrid\Layout\DataGridHeader; use SP\Infrastructure\Database\QueryResult; +use function SP\__; +use function SP\getElapsedTime; + /** * Class TagGrid * @@ -83,7 +87,7 @@ final class TagGrid extends GridBase protected function getGridLayout(): DataGridInterface { // Grid - $gridTab = new DataGridTab($this->view->getTheme()); + $gridTab = new DataGridTab($this->theme); $gridTab->setId('tblTags'); $gridTab->setDataRowTemplate('datagrid-rows', 'grid'); $gridTab->setDataPagerTemplate('datagrid-nav-full', 'grid'); @@ -108,6 +112,7 @@ final class TagGrid extends GridBase /** * @return DataGridData + * @throws SPException */ protected function getData(): DataGridData { diff --git a/app/modules/web/Controllers/Helpers/Grid/TrackGrid.php b/app/modules/web/Controllers/Helpers/Grid/TrackGrid.php index 951b3696..c87fd340 100644 --- a/app/modules/web/Controllers/Helpers/Grid/TrackGrid.php +++ b/app/modules/web/Controllers/Helpers/Grid/TrackGrid.php @@ -26,6 +26,7 @@ namespace SP\Modules\Web\Controllers\Helpers\Grid; use SP\Core\Acl\Acl; use SP\Domain\Core\Acl\AclActionsInterface; +use SP\Domain\Core\Exceptions\SPException; use SP\Domain\Http\Adapters\Address; use SP\Html\DataGrid\Action\DataGridAction; use SP\Html\DataGrid\Action\DataGridActionSearch; @@ -36,6 +37,9 @@ use SP\Html\DataGrid\DataGridTab; use SP\Html\DataGrid\Layout\DataGridHeader; use SP\Infrastructure\Database\QueryResult; +use function SP\__; +use function SP\getElapsedTime; + /** * Class TrackGrid * @@ -76,7 +80,7 @@ final class TrackGrid extends GridBase protected function getGridLayout(): DataGridInterface { // Grid - $gridTab = new DataGridTab($this->view->getTheme()); + $gridTab = new DataGridTab($this->theme); $gridTab->setId('tblTracks'); $gridTab->setDataRowTemplate('datagrid-rows', 'grid'); $gridTab->setDataPagerTemplate('datagrid-nav-full', 'grid'); @@ -105,7 +109,7 @@ final class TrackGrid extends GridBase } /** - * @return DataGridData + * @throws SPException */ protected function getData(): DataGridData { diff --git a/app/modules/web/Controllers/Helpers/Grid/UserGrid.php b/app/modules/web/Controllers/Helpers/Grid/UserGrid.php index b769301f..f1358e73 100644 --- a/app/modules/web/Controllers/Helpers/Grid/UserGrid.php +++ b/app/modules/web/Controllers/Helpers/Grid/UserGrid.php @@ -27,6 +27,7 @@ namespace SP\Modules\Web\Controllers\Helpers\Grid; use SP\Core\Acl\Acl; use SP\Domain\Core\Acl\AclActionsInterface; +use SP\Domain\Core\Exceptions\SPException; use SP\Html\DataGrid\Action\DataGridAction; use SP\Html\DataGrid\Action\DataGridActionSearch; use SP\Html\DataGrid\Action\DataGridActionType; @@ -36,6 +37,9 @@ use SP\Html\DataGrid\DataGridTab; use SP\Html\DataGrid\Layout\DataGridHeader; use SP\Infrastructure\Database\QueryResult; +use function SP\__; +use function SP\getElapsedTime; + /** * Class UserGrid * @@ -85,7 +89,7 @@ final class UserGrid extends GridBase protected function getGridLayout(): DataGridInterface { // Grid - $gridTab = new DataGridTab($this->view->getTheme()); + $gridTab = new DataGridTab($this->theme); $gridTab->setId('tblUsers'); $gridTab->setDataRowTemplate('datagrid-rows', 'grid'); $gridTab->setDataPagerTemplate('datagrid-nav-full', 'grid'); @@ -113,7 +117,7 @@ final class UserGrid extends GridBase } /** - * @return DataGridData + * @throws SPException */ protected function getData(): DataGridData { diff --git a/app/modules/web/Controllers/Helpers/Grid/UserGroupGrid.php b/app/modules/web/Controllers/Helpers/Grid/UserGroupGrid.php index 30040a4b..ab68040f 100644 --- a/app/modules/web/Controllers/Helpers/Grid/UserGroupGrid.php +++ b/app/modules/web/Controllers/Helpers/Grid/UserGroupGrid.php @@ -27,6 +27,7 @@ namespace SP\Modules\Web\Controllers\Helpers\Grid; use SP\Core\Acl\Acl; use SP\Domain\Core\Acl\AclActionsInterface; +use SP\Domain\Core\Exceptions\SPException; use SP\Html\DataGrid\Action\DataGridAction; use SP\Html\DataGrid\Action\DataGridActionSearch; use SP\Html\DataGrid\Action\DataGridActionType; @@ -36,6 +37,9 @@ use SP\Html\DataGrid\DataGridTab; use SP\Html\DataGrid\Layout\DataGridHeader; use SP\Infrastructure\Database\QueryResult; +use function SP\__; +use function SP\getElapsedTime; + /** * Class UserGroupGrid * @@ -84,7 +88,7 @@ final class UserGroupGrid extends GridBase protected function getGridLayout(): DataGridInterface { // Grid - $gridTab = new DataGridTab($this->view->getTheme()); + $gridTab = new DataGridTab($this->theme); $gridTab->setId('tblGroups'); $gridTab->setDataRowTemplate('datagrid-rows', 'grid'); $gridTab->setDataPagerTemplate('datagrid-nav-full', 'grid'); @@ -110,6 +114,7 @@ final class UserGroupGrid extends GridBase /** * @return DataGridData + * @throws SPException */ protected function getData(): DataGridData { diff --git a/app/modules/web/Controllers/Helpers/Grid/UserProfileGrid.php b/app/modules/web/Controllers/Helpers/Grid/UserProfileGrid.php index 8eb70f4b..ff82b461 100644 --- a/app/modules/web/Controllers/Helpers/Grid/UserProfileGrid.php +++ b/app/modules/web/Controllers/Helpers/Grid/UserProfileGrid.php @@ -27,6 +27,7 @@ namespace SP\Modules\Web\Controllers\Helpers\Grid; use SP\Core\Acl\Acl; use SP\Domain\Core\Acl\AclActionsInterface; +use SP\Domain\Core\Exceptions\SPException; use SP\Html\DataGrid\Action\DataGridAction; use SP\Html\DataGrid\Action\DataGridActionSearch; use SP\Html\DataGrid\Action\DataGridActionType; @@ -36,6 +37,9 @@ use SP\Html\DataGrid\DataGridTab; use SP\Html\DataGrid\Layout\DataGridHeader; use SP\Infrastructure\Database\QueryResult; +use function SP\__; +use function SP\getElapsedTime; + /** * Class UserProfileGrid * @@ -84,7 +88,7 @@ final class UserProfileGrid extends GridBase protected function getGridLayout(): DataGridInterface { // Grid - $gridTab = new DataGridTab($this->view->getTheme()); + $gridTab = new DataGridTab($this->theme); $gridTab->setId('tblProfiles'); $gridTab->setDataRowTemplate('datagrid-rows', 'grid'); $gridTab->setDataPagerTemplate('datagrid-nav-full', 'grid'); @@ -108,7 +112,7 @@ final class UserProfileGrid extends GridBase } /** - * @return DataGridData + * @throws SPException */ protected function getData(): DataGridData { diff --git a/app/modules/web/Controllers/Helpers/HelperBase.php b/app/modules/web/Controllers/Helpers/HelperBase.php index cc197035..342b96c9 100644 --- a/app/modules/web/Controllers/Helpers/HelperBase.php +++ b/app/modules/web/Controllers/Helpers/HelperBase.php @@ -25,12 +25,11 @@ namespace SP\Modules\Web\Controllers\Helpers; use SP\Core\Application; -use SP\Core\Events\EventDispatcher; use SP\Domain\Config\Ports\ConfigDataInterface; -use SP\Domain\Config\Services\ConfigFile; +use SP\Domain\Config\Ports\ConfigFileService; use SP\Domain\Core\Context\Context; +use SP\Domain\Core\Events\EventDispatcherInterface; use SP\Domain\Http\Ports\RequestService; -use SP\Domain\Http\Services\Request; use SP\Mvc\View\TemplateInterface; /** @@ -40,29 +39,20 @@ use SP\Mvc\View\TemplateInterface; */ abstract class HelperBase { - protected TemplateInterface $view; - protected ConfigDataInterface $configData; - protected Context $context; - protected EventDispatcher $eventDispatcher; - protected ConfigFile $config; - protected Request $request; + protected TemplateInterface $view; + protected ConfigDataInterface $configData; + protected Context $context; + protected EventDispatcherInterface $eventDispatcher; + protected ConfigFileService $config; - /** - * Constructor - * - * @param Application $application - * @param TemplateInterface $template - * @param \SP\Domain\Http\Ports\RequestService $request - */ public function __construct( - Application $application, - TemplateInterface $template, - RequestService $request + Application $application, + TemplateInterface $template, + protected RequestService $request ) { $this->config = $application->getConfig(); $this->context = $application->getContext(); $this->eventDispatcher = $application->getEventDispatcher(); - $this->request = $request; $this->configData = $this->config->getConfigData(); $this->view = $template; } diff --git a/app/modules/web/Controllers/Resource/CssController.php b/app/modules/web/Controllers/Resource/CssController.php index 21fe75ab..dc0ae404 100644 --- a/app/modules/web/Controllers/Resource/CssController.php +++ b/app/modules/web/Controllers/Resource/CssController.php @@ -24,6 +24,7 @@ namespace SP\Modules\Web\Controllers\Resource; +use SP\Core\Bootstrap\Path; use SP\Domain\Http\Services\Request as HttpRequest; use SP\Infrastructure\File\FileHandler; use SP\Infrastructure\File\FileSystem; @@ -57,11 +58,19 @@ final class CssController extends ResourceBase ->addFiles($files) ->getMinified(); } else { - $files = $this->buildFiles(FileSystem::buildPath(PUBLIC_PATH, 'vendor', 'css'), self::CSS_MIN_FILES); + $files = $this->buildFiles( + FileSystem::buildPath($this->pathsContext[Path::PUBLIC], 'vendor', 'css'), + self::CSS_MIN_FILES + ); $this->minify->builder() ->addFiles($files, false) - ->addFile(new FileHandler(FileSystem::buildPath(PUBLIC_PATH, 'css', 'fonts.min.css')), false) + ->addFile( + new FileHandler( + FileSystem::buildPath($this->pathsContext[Path::PUBLIC], 'css', 'fonts.min.css') + ), + false + ) ->getMinified(); } } diff --git a/app/modules/web/Controllers/Resource/JsController.php b/app/modules/web/Controllers/Resource/JsController.php index e5f5bac7..37f177eb 100644 --- a/app/modules/web/Controllers/Resource/JsController.php +++ b/app/modules/web/Controllers/Resource/JsController.php @@ -24,6 +24,7 @@ namespace SP\Modules\Web\Controllers\Resource; +use SP\Core\Bootstrap\Path; use SP\Domain\Http\Services\Request as HttpRequest; use SP\Infrastructure\File\FileHandler; use SP\Infrastructure\File\FileSystem; @@ -34,7 +35,7 @@ use SP\Infrastructure\File\FileSystem; final class JsController extends ResourceBase { - private const JS_MIN_FILES = [ + private const JS_MIN_FILES = [ 'jquery-3.3.1.min.js', 'jquery.fileDownload.min.js', 'clipboard.min.js', @@ -80,7 +81,10 @@ final class JsController extends ResourceBase $this->minify ->builder() ->addFiles( - $this->buildFiles(FileSystem::buildPath(PUBLIC_PATH, 'vendor', 'js'), self::JS_MIN_FILES), + $this->buildFiles( + FileSystem::buildPath($this->pathsContext[Path::PUBLIC], 'vendor', 'js'), + self::JS_MIN_FILES + ), false ) ->getMinified(); @@ -88,7 +92,10 @@ final class JsController extends ResourceBase $this->minify ->builder() ->addFiles( - $this->buildFiles(FileSystem::buildPath(PUBLIC_PATH, 'js'), self::JS_APP_MIN_FILES), + $this->buildFiles( + FileSystem::buildPath($this->pathsContext[Path::PUBLIC], 'js'), + self::JS_APP_MIN_FILES + ), false ) ->getMinified(); diff --git a/app/modules/web/Controllers/Resource/ResourceBase.php b/app/modules/web/Controllers/Resource/ResourceBase.php index 4c1b67a5..6b3b64aa 100644 --- a/app/modules/web/Controllers/Resource/ResourceBase.php +++ b/app/modules/web/Controllers/Resource/ResourceBase.php @@ -25,6 +25,7 @@ namespace SP\Modules\Web\Controllers\Resource; use SP\Core\Application; +use SP\Core\Bootstrap\PathsContext; use SP\Domain\Core\Exceptions\SessionTimeout; use SP\Domain\Core\Exceptions\SPException; use SP\Domain\Html\Ports\MinifyService; @@ -42,9 +43,10 @@ abstract class ResourceBase extends SimpleControllerBase * @throws SPException */ public function __construct( - Application $application, - SimpleControllerHelper $simpleControllerHelper, - protected readonly MinifyService $minify + Application $application, + SimpleControllerHelper $simpleControllerHelper, + protected readonly MinifyService $minify, + protected readonly PathsContext $pathsContext ) { parent::__construct($application, $simpleControllerHelper); diff --git a/app/modules/web/Controllers/Traits/ConfigTrait.php b/app/modules/web/Controllers/Traits/ConfigTrait.php index bbb291d4..53f2a067 100644 --- a/app/modules/web/Controllers/Traits/ConfigTrait.php +++ b/app/modules/web/Controllers/Traits/ConfigTrait.php @@ -26,12 +26,13 @@ namespace SP\Modules\Web\Controllers\Traits; use Exception; use JsonException; -use SP\Core\Bootstrap\BootstrapBase; use SP\Domain\Config\Ports\ConfigDataInterface; use SP\Domain\Config\Ports\ConfigFileService; +use SP\Domain\Core\Exceptions\SPException; use SP\Domain\Http\Dtos\JsonMessage; -use function SP\logger; +use function SP\__u; +use function SP\processException; /** * Trait ConfigTrait @@ -46,6 +47,7 @@ trait ConfigTrait * Guardar la configuración * * @throws JsonException + * @throws SPException */ protected function saveConfig( ConfigDataInterface $configData, @@ -59,10 +61,6 @@ trait ConfigTrait $config->save($configData); - if (BootstrapBase::$LOCK !== false && $configData->isMaintenance() === false) { - self::unlockApp(); - } - if ($onSuccess !== null) { $onSuccess(); } @@ -78,14 +76,4 @@ trait ConfigTrait ); } } - - /** - * Desbloquear la aplicación - */ - private static function unlockApp(): bool - { - logger('Application unlocked'); - - return @unlink(LOCK_FILE); - } } diff --git a/app/modules/web/Init.php b/app/modules/web/Init.php index 70933f54..7ce72080 100644 --- a/app/modules/web/Init.php +++ b/app/modules/web/Init.php @@ -24,22 +24,21 @@ namespace SP\Modules\Web; -use Defuse\Crypto\Exception\EnvironmentIsBrokenException; use Exception; -use JsonException; use Klein\Klein; use SP\Core\Application; +use SP\Core\AppLock; use SP\Core\Context\ContextBase; +use SP\Core\Context\ContextException; use SP\Core\Context\Session; use SP\Core\Context\SessionLifecycleHandler; -use SP\Core\Crypt\Csrf; use SP\Core\Crypt\Session as CryptSession; use SP\Core\HttpModuleBase; -use SP\Core\Language; use SP\Core\ProvidersHelper; use SP\Domain\Common\Providers\Http; use SP\Domain\Core\Bootstrap\UriContextInterface; use SP\Domain\Core\Crypt\CsrfHandler; +use SP\Domain\Core\Exceptions\ConfigException; use SP\Domain\Core\Exceptions\ConstraintException; use SP\Domain\Core\Exceptions\CryptException; use SP\Domain\Core\Exceptions\InitializationException; @@ -48,19 +47,15 @@ use SP\Domain\Core\Exceptions\NoSuchPropertyException; use SP\Domain\Core\Exceptions\QueryException; use SP\Domain\Core\Exceptions\SPException; use SP\Domain\Core\LanguageInterface; -use SP\Domain\Crypt\Ports\SecureSessionService; -use SP\Domain\Crypt\Services\SecureSession; use SP\Domain\Http\Adapters\Address; use SP\Domain\Http\Ports\RequestService; use SP\Domain\Http\Providers\Uri; use SP\Domain\ItemPreset\Models\SessionTimeout; use SP\Domain\ItemPreset\Ports\ItemPresetInterface; -use SP\Domain\ItemPreset\Services\ItemPreset; +use SP\Domain\ItemPreset\Ports\ItemPresetService; use SP\Domain\User\Ports\UserProfileService; -use SP\Domain\User\Services\UserProfile; use SP\Infrastructure\Common\Repositories\NoSuchItemException; use SP\Infrastructure\Database\DatabaseUtil; -use SP\Infrastructure\File\FileException; use SP\Modules\Web\Controllers\Bootstrap\GetEnvironmentController; use SP\Modules\Web\Controllers\Error\DatabaseConnectionController; use SP\Modules\Web\Controllers\Error\DatabaseErrorController; @@ -131,43 +126,29 @@ final class Init extends HttpModuleBase public const ROUTE_UPGRADE = 'upgrade'; - private Csrf $csrf; - private Language $language; - private SecureSession $secureSessionService; - private PluginManager $pluginManager; - private ItemPreset $itemPresetService; - private DatabaseUtil $databaseUtil; - private UserProfile $userProfileService; - private bool $isIndex = false; + private bool $isIndex = false; public function __construct( Application $application, ProvidersHelper $providersHelper, - RequestService $request, + RequestService $request, Klein $router, - CsrfHandler $csrf, - LanguageInterface $language, - SecureSessionService $secureSessionService, - PluginManager $pluginManager, - ItemPreset $itemPresetService, - DatabaseUtil $databaseUtil, - UserProfileService $userProfileService, - private readonly UriContextInterface $uriContext + AppLock $appLock, + private readonly CsrfHandler $csrf, + private readonly LanguageInterface $language, + private readonly ItemPresetService $itemPresetService, + private readonly DatabaseUtil $databaseUtil, + private readonly UserProfileService $userProfileService, + private readonly UriContextInterface $uriContext, + ) { parent::__construct( $application, $providersHelper, $request, - $router + $router, + $appLock ); - - $this->csrf = $csrf; - $this->language = $language; - $this->secureSessionService = $secureSessionService; - $this->pluginManager = $pluginManager; - $this->itemPresetService = $itemPresetService; - $this->databaseUtil = $databaseUtil; - $this->userProfileService = $userProfileService; } /** @@ -175,15 +156,13 @@ final class Init extends HttpModuleBase * * @param string $controller * - * @throws EnvironmentIsBrokenException - * @throws JsonException * @throws ConstraintException * @throws InitializationException + * @throws NoSuchItemException * @throws QueryException * @throws SPException - * @throws NoSuchItemException - * @throws FileException - * @throws Exception + * @throws ContextException + * @throws ConfigException */ public function initialize(string $controller): void { @@ -260,8 +239,7 @@ final class Init extends HttpModuleBase $this->initUserSession(); } - // Load plugins - $this->pluginManager->loadPlugins(); + //TODO:Load plugins if ($this->context->isLoggedIn() && $this->context->getAppStatus() === ContextBase::APP_STATUS_RELOADED @@ -396,4 +374,9 @@ final class Init extends HttpModuleBase return $default; } + + public function getName(): string + { + return 'web'; + } } diff --git a/app/modules/web/module.php b/app/modules/web/module.php index 1d7c8595..1617ea0d 100644 --- a/app/modules/web/module.php +++ b/app/modules/web/module.php @@ -22,6 +22,8 @@ * along with sysPass. If not, see . */ +use SP\Core\Bootstrap\Path; +use SP\Core\Bootstrap\PathsContext; use SP\Core\Context\Session; use SP\Core\Crypt\Csrf; use SP\Domain\Config\Ports\ConfigDataInterface; @@ -31,19 +33,24 @@ use SP\Domain\Core\Context\Context; use SP\Domain\Core\Crypt\CsrfHandler; use SP\Domain\Html\Services\MinifyCss; use SP\Domain\Html\Services\MinifyJs; +use SP\Infrastructure\File\FileCache; +use SP\Infrastructure\File\FileSystem; use SP\Modules\Web\Bootstrap; +use SP\Modules\Web\Controllers\Helpers\Account\AccountSearchData; use SP\Modules\Web\Controllers\Resource\CssController; use SP\Modules\Web\Controllers\Resource\JsController; use SP\Modules\Web\Init; +use function DI\add; use function DI\autowire; use function DI\factory; - -const MODULE_PATH = __DIR__; -const VIEW_PATH = MODULE_PATH . DIRECTORY_SEPARATOR . 'themes'; -const PLUGINS_PATH = MODULE_PATH . DIRECTORY_SEPARATOR . 'plugins'; +use function DI\get; return [ + 'paths' => add([ + [Path::VIEW, FileSystem::buildPath(__DIR__, 'themes')], + [Path::PLUGINS, FileSystem::buildPath(__DIR__, 'plugins')], + ]), BootstrapInterface::class => autowire(Bootstrap::class), ModuleInterface::class => autowire(Init::class), CssController::class => autowire( @@ -53,13 +60,19 @@ return [ JsController::class )->constructorParameter('minify', autowire(MinifyJs::class)), Context::class => factory( - static function (ConfigDataInterface $configData, SessionHandlerInterface $sessionHandler) { - if ($configData->isEncryptSession()) { - return new Session($sessionHandler); - } - - return new Session(); + static function (ConfigDataInterface $configData, SessionHandlerInterface $sessionHandler = null) { + return new Session($sessionHandler); } ), - CsrfHandler::class => autowire(Csrf::class), + CsrfHandler::class => autowire(Csrf::class) + ->constructorParameter('context', get(Context::class)), + AccountSearchData::class => autowire(AccountSearchData::class) + ->constructorParameter( + 'fileCache', + factory(static function (PathsContext $pathsContext) { + return new FileCache( + FileSystem::buildPath($pathsContext[Path::CACHE], 'colors.cache') + ); + }) + ) ]; diff --git a/app/modules/web/themes/material-blue/inc/Icons.php b/app/modules/web/themes/material-blue/inc/Icons.php index a7ef8a1e..97bb75e7 100644 --- a/app/modules/web/themes/material-blue/inc/Icons.php +++ b/app/modules/web/themes/material-blue/inc/Icons.php @@ -27,6 +27,8 @@ defined('APP_ROOT') || die(); use SP\Core\UI\ThemeIcons; use SP\Html\Assets\FontIcon; +use function SP\__u; + $themeIcons = new ThemeIcons(); $themeIcons->addIcon('add', new FontIcon('add', 'mdl-color-text--indigo-A200', __u('Add'))); $themeIcons->addIcon('view', new FontIcon('visibility', 'mdl-color-text--indigo-A200', __u('View Details'))); @@ -70,4 +72,4 @@ $themeIcons->addIcon('last', new FontIcon('last_page', null, __u('Last page'))); $themeIcons->addIcon('up', new FontIcon('arrow_drop_up')); $themeIcons->addIcon('down', new FontIcon('arrow_drop_down')); -return $themeIcons; \ No newline at end of file +return $themeIcons; diff --git a/composer.json b/composer.json index bda38e23..c4957a7c 100644 --- a/composer.json +++ b/composer.json @@ -60,14 +60,14 @@ }, "require-dev": { "roave/security-advisories": "dev-latest", - "symfony/debug": "^v3.4", + "symfony/error-handler": "@stable", "phpunit/phpunit": "^11", "fakerphp/faker": "^v1.23", - "fabpot/goutte": "^v3.2", "nikic/php-parser": "^v5", "squizlabs/php_codesniffer": "^3", "phpstan/phpstan": "^1.9", - "mikey179/vfsstream": "@stable" + "mikey179/vfsstream": "@stable", + "symfony/dom-crawler": "@stable" }, "scripts": { "phpcs": "phpcs --standard=PSR2 lib", diff --git a/composer.lock b/composer.lock index 3610a8ec..7f00ba42 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "d5f090fa8e4c2fad146516fbfcb45cd2", + "content-hash": "e922e1972a06590741237e2f09e3a951", "packages": [ { "name": "ademarre/binary-to-text-php", @@ -1775,16 +1775,16 @@ }, { "name": "php-di/php-di", - "version": "7.0.6", + "version": "7.0.7", "source": { "type": "git", "url": "https://github.com/PHP-DI/PHP-DI.git", - "reference": "8097948a89f6ec782839b3e958432f427cac37fd" + "reference": "e87435e3c0e8f22977adc5af0d5cdcc467e15cf1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/8097948a89f6ec782839b3e958432f427cac37fd", - "reference": "8097948a89f6ec782839b3e958432f427cac37fd", + "url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/e87435e3c0e8f22977adc5af0d5cdcc467e15cf1", + "reference": "e87435e3c0e8f22977adc5af0d5cdcc467e15cf1", "shasum": "" }, "require": { @@ -1832,7 +1832,7 @@ ], "support": { "issues": "https://github.com/PHP-DI/PHP-DI/issues", - "source": "https://github.com/PHP-DI/PHP-DI/tree/7.0.6" + "source": "https://github.com/PHP-DI/PHP-DI/tree/7.0.7" }, "funding": [ { @@ -1844,7 +1844,7 @@ "type": "tidelift" } ], - "time": "2023-11-02T10:04:50+00:00" + "time": "2024-07-21T15:55:45+00:00" }, { "name": "phpmailer/phpmailer", @@ -1929,16 +1929,16 @@ }, { "name": "phpoption/phpoption", - "version": "1.9.2", + "version": "1.9.3", "source": { "type": "git", "url": "https://github.com/schmittjoh/php-option.git", - "reference": "80735db690fe4fc5c76dfa7f9b770634285fa820" + "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/80735db690fe4fc5c76dfa7f9b770634285fa820", - "reference": "80735db690fe4fc5c76dfa7f9b770634285fa820", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/e3fac8b24f56113f7cb96af14958c0dd16330f54", + "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54", "shasum": "" }, "require": { @@ -1946,13 +1946,13 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" + "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" }, "type": "library", "extra": { "bamarni-bin": { "bin-links": true, - "forward-command": true + "forward-command": false }, "branch-alias": { "dev-master": "1.9-dev" @@ -1988,7 +1988,7 @@ ], "support": { "issues": "https://github.com/schmittjoh/php-option/issues", - "source": "https://github.com/schmittjoh/php-option/tree/1.9.2" + "source": "https://github.com/schmittjoh/php-option/tree/1.9.3" }, "funding": [ { @@ -2000,7 +2000,7 @@ "type": "tidelift" } ], - "time": "2023-11-12T21:59:55+00:00" + "time": "2024-07-20T21:41:07+00:00" }, { "name": "phpseclib/phpseclib", @@ -2363,16 +2363,16 @@ }, { "name": "symfony/console", - "version": "v5.4.40", + "version": "v5.4.42", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "aa73115c0c24220b523625bfcfa655d7d73662dd" + "reference": "cef62396a0477e94fc52e87a17c6e5c32e226b7f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/aa73115c0c24220b523625bfcfa655d7d73662dd", - "reference": "aa73115c0c24220b523625bfcfa655d7d73662dd", + "url": "https://api.github.com/repos/symfony/console/zipball/cef62396a0477e94fc52e87a17c6e5c32e226b7f", + "reference": "cef62396a0477e94fc52e87a17c6e5c32e226b7f", "shasum": "" }, "require": { @@ -2442,7 +2442,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.4.40" + "source": "https://github.com/symfony/console/tree/v5.4.42" }, "funding": [ { @@ -2458,7 +2458,7 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:33:22+00:00" + "time": "2024-07-26T12:21:55+00:00" }, { "name": "symfony/deprecation-contracts", @@ -2608,16 +2608,16 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4" + "reference": "0424dff1c58f028c451efff2045f5d92410bd540" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4", - "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/0424dff1c58f028c451efff2045f5d92410bd540", + "reference": "0424dff1c58f028c451efff2045f5d92410bd540", "shasum": "" }, "require": { @@ -2667,7 +2667,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.30.0" }, "funding": [ { @@ -2683,20 +2683,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-05-31T15:07:36+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f" + "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f", - "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/64647a7c30b2283f5d49b874d84a18fc22054b7a", + "reference": "64647a7c30b2283f5d49b874d84a18fc22054b7a", "shasum": "" }, "require": { @@ -2745,7 +2745,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.30.0" }, "funding": [ { @@ -2761,20 +2761,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-05-31T15:07:36+00:00" }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "a287ed7475f85bf6f61890146edbc932c0fff919" + "reference": "a6e83bdeb3c84391d1dfe16f42e40727ce524a5c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/a287ed7475f85bf6f61890146edbc932c0fff919", - "reference": "a287ed7475f85bf6f61890146edbc932c0fff919", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/a6e83bdeb3c84391d1dfe16f42e40727ce524a5c", + "reference": "a6e83bdeb3c84391d1dfe16f42e40727ce524a5c", "shasum": "" }, "require": { @@ -2829,7 +2829,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.30.0" }, "funding": [ { @@ -2845,20 +2845,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-05-31T15:07:36+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "bc45c394692b948b4d383a08d7753968bed9a83d" + "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d", - "reference": "bc45c394692b948b4d383a08d7753968bed9a83d", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/a95281b0be0d9ab48050ebd988b967875cdb9fdb", + "reference": "a95281b0be0d9ab48050ebd988b967875cdb9fdb", "shasum": "" }, "require": { @@ -2910,7 +2910,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.30.0" }, "funding": [ { @@ -2926,20 +2926,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-05-31T15:07:36+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec" + "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec", - "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fd22ab50000ef01661e2a31d850ebaa297f8e03c", + "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c", "shasum": "" }, "require": { @@ -2990,7 +2990,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.30.0" }, "funding": [ { @@ -3006,20 +3006,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-06-19T12:30:46+00:00" }, { "name": "symfony/polyfill-php72", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "861391a8da9a04cbad2d232ddd9e4893220d6e25" + "reference": "10112722600777e02d2745716b70c5db4ca70442" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/861391a8da9a04cbad2d232ddd9e4893220d6e25", - "reference": "861391a8da9a04cbad2d232ddd9e4893220d6e25", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/10112722600777e02d2745716b70c5db4ca70442", + "reference": "10112722600777e02d2745716b70c5db4ca70442", "shasum": "" }, "require": { @@ -3063,7 +3063,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php72/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-php72/tree/v1.30.0" }, "funding": [ { @@ -3079,20 +3079,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-06-19T12:30:46+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "21bd091060673a1177ae842c0ef8fe30893114d2" + "reference": "ec444d3f3f6505bb28d11afa41e75faadebc10a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/21bd091060673a1177ae842c0ef8fe30893114d2", - "reference": "21bd091060673a1177ae842c0ef8fe30893114d2", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/ec444d3f3f6505bb28d11afa41e75faadebc10a1", + "reference": "ec444d3f3f6505bb28d11afa41e75faadebc10a1", "shasum": "" }, "require": { @@ -3139,7 +3139,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-php73/tree/v1.30.0" }, "funding": [ { @@ -3155,20 +3155,20 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-05-31T15:07:36+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.29.0", + "version": "v1.30.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b" + "reference": "77fa7995ac1b21ab60769b7323d600a991a90433" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", - "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/77fa7995ac1b21ab60769b7323d600a991a90433", + "reference": "77fa7995ac1b21ab60769b7323d600a991a90433", "shasum": "" }, "require": { @@ -3219,7 +3219,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.29.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.30.0" }, "funding": [ { @@ -3235,7 +3235,7 @@ "type": "tidelift" } ], - "time": "2024-01-29T20:11:03+00:00" + "time": "2024-05-31T15:07:36+00:00" }, { "name": "symfony/service-contracts", @@ -3322,16 +3322,16 @@ }, { "name": "symfony/string", - "version": "v6.4.8", + "version": "v6.4.10", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "a147c0f826c4a1f3afb763ab8e009e37c877a44d" + "reference": "ccf9b30251719567bfd46494138327522b9a9446" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/a147c0f826c4a1f3afb763ab8e009e37c877a44d", - "reference": "a147c0f826c4a1f3afb763ab8e009e37c877a44d", + "url": "https://api.github.com/repos/symfony/string/zipball/ccf9b30251719567bfd46494138327522b9a9446", + "reference": "ccf9b30251719567bfd46494138327522b9a9446", "shasum": "" }, "require": { @@ -3388,7 +3388,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.4.8" + "source": "https://github.com/symfony/string/tree/v6.4.10" }, "funding": [ { @@ -3404,7 +3404,7 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-07-22T10:21:14+00:00" }, { "name": "symfony/yaml", @@ -3562,66 +3562,6 @@ } ], "packages-dev": [ - { - "name": "fabpot/goutte", - "version": "v3.3.1", - "source": { - "type": "git", - "url": "https://github.com/FriendsOfPHP/Goutte.git", - "reference": "80a23b64f44d54dd571d114c473d9d7e9ed84ca5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/Goutte/zipball/80a23b64f44d54dd571d114c473d9d7e9ed84ca5", - "reference": "80a23b64f44d54dd571d114c473d9d7e9ed84ca5", - "shasum": "" - }, - "require": { - "guzzlehttp/guzzle": "^6.0", - "php": ">=7.1.3", - "symfony/browser-kit": "^4.4|^5.0", - "symfony/css-selector": "^4.4|^5.0", - "symfony/dom-crawler": "^4.4|^5.0" - }, - "require-dev": { - "symfony/phpunit-bridge": "^5.0" - }, - "type": "application", - "extra": { - "branch-alias": { - "dev-master": "3.3-dev" - } - }, - "autoload": { - "psr-4": { - "Goutte\\": "Goutte" - }, - "exclude-from-classmap": [ - "Goutte/Tests" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - } - ], - "description": "A simple PHP Web Scraper", - "homepage": "https://github.com/FriendsOfPHP/Goutte", - "keywords": [ - "scraper" - ], - "support": { - "issues": "https://github.com/FriendsOfPHP/Goutte/issues", - "source": "https://github.com/FriendsOfPHP/Goutte/tree/v3.3.1" - }, - "abandoned": "symfony/browser-kit", - "time": "2020-11-01T09:30:18+00:00" - }, { "name": "fakerphp/faker", "version": "v1.23.1", @@ -3685,6 +3625,73 @@ }, "time": "2024-01-02T13:46:09+00:00" }, + { + "name": "masterminds/html5", + "version": "2.9.0", + "source": { + "type": "git", + "url": "https://github.com/Masterminds/html5-php.git", + "reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f5ac2c0b0a2eefca70b2ce32a5809992227e75a6", + "reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8 || ^9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Masterminds\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matt Butcher", + "email": "technosophos@gmail.com" + }, + { + "name": "Matt Farina", + "email": "matt@mattfarina.com" + }, + { + "name": "Asmir Mustafic", + "email": "goetas@gmail.com" + } + ], + "description": "An HTML5 parser and serializer.", + "homepage": "http://masterminds.github.io/html5-php", + "keywords": [ + "HTML5", + "dom", + "html", + "parser", + "querypath", + "serializer", + "xml" + ], + "support": { + "issues": "https://github.com/Masterminds/html5-php/issues", + "source": "https://github.com/Masterminds/html5-php/tree/2.9.0" + }, + "time": "2024-03-31T07:05:07+00:00" + }, { "name": "mikey179/vfsstream", "version": "v1.6.11", @@ -3798,16 +3805,16 @@ }, { "name": "nikic/php-parser", - "version": "v5.0.2", + "version": "v5.1.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13" + "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/139676794dc1e9231bf7bcd123cfc0c99182cb13", - "reference": "139676794dc1e9231bf7bcd123cfc0c99182cb13", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/683130c2ff8c2739f4822ff7ac5c873ec529abd1", + "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1", "shasum": "" }, "require": { @@ -3818,7 +3825,7 @@ }, "require-dev": { "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + "phpunit/phpunit": "^9.0" }, "bin": [ "bin/php-parse" @@ -3850,9 +3857,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.2" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.1.0" }, - "time": "2024-03-05T20:51:40+00:00" + "time": "2024-07-01T20:03:41+00:00" }, { "name": "phar-io/manifest", @@ -3974,16 +3981,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.11.4", + "version": "1.11.8", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "9100a76ce8015b9aa7125b9171ae3a76887b6c82" + "reference": "6adbd118e6c0515dd2f36b06cde1d6da40f1b8ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/9100a76ce8015b9aa7125b9171ae3a76887b6c82", - "reference": "9100a76ce8015b9aa7125b9171ae3a76887b6c82", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/6adbd118e6c0515dd2f36b06cde1d6da40f1b8ec", + "reference": "6adbd118e6c0515dd2f36b06cde1d6da40f1b8ec", "shasum": "" }, "require": { @@ -4028,20 +4035,20 @@ "type": "github" } ], - "time": "2024-06-06T12:19:22+00:00" + "time": "2024-07-24T07:01:22+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "11.0.3", + "version": "11.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "7e35a2cbcabac0e6865fd373742ea432a3c34f92" + "reference": "19b6365ab8b59a64438c0c3f4241feeb480c9861" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7e35a2cbcabac0e6865fd373742ea432a3c34f92", - "reference": "7e35a2cbcabac0e6865fd373742ea432a3c34f92", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/19b6365ab8b59a64438c0c3f4241feeb480c9861", + "reference": "19b6365ab8b59a64438c0c3f4241feeb480c9861", "shasum": "" }, "require": { @@ -4098,7 +4105,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.3" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.5" }, "funding": [ { @@ -4106,20 +4113,20 @@ "type": "github" } ], - "time": "2024-03-12T15:35:40+00:00" + "time": "2024-07-03T05:05:37+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "5.0.0", + "version": "5.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "99e95c94ad9500daca992354fa09d7b99abe2210" + "reference": "6ed896bf50bbbfe4d504a33ed5886278c78e4a26" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/99e95c94ad9500daca992354fa09d7b99abe2210", - "reference": "99e95c94ad9500daca992354fa09d7b99abe2210", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6ed896bf50bbbfe4d504a33ed5886278c78e4a26", + "reference": "6ed896bf50bbbfe4d504a33ed5886278c78e4a26", "shasum": "" }, "require": { @@ -4159,7 +4166,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.0.0" + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.0.1" }, "funding": [ { @@ -4167,20 +4174,20 @@ "type": "github" } ], - "time": "2024-02-02T06:05:04+00:00" + "time": "2024-07-03T05:06:37+00:00" }, { "name": "phpunit/php-invoker", - "version": "5.0.0", + "version": "5.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "5d8d9355a16d8cc5a1305b0a85342cfa420612be" + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5d8d9355a16d8cc5a1305b0a85342cfa420612be", - "reference": "5d8d9355a16d8cc5a1305b0a85342cfa420612be", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2", + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2", "shasum": "" }, "require": { @@ -4223,7 +4230,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-invoker/issues", "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.0" + "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.1" }, "funding": [ { @@ -4231,20 +4238,20 @@ "type": "github" } ], - "time": "2024-02-02T06:05:50+00:00" + "time": "2024-07-03T05:07:44+00:00" }, { "name": "phpunit/php-text-template", - "version": "4.0.0", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "d38f6cbff1cdb6f40b03c9811421561668cc133e" + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/d38f6cbff1cdb6f40b03c9811421561668cc133e", - "reference": "d38f6cbff1cdb6f40b03c9811421561668cc133e", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964", + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964", "shasum": "" }, "require": { @@ -4283,7 +4290,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-text-template/issues", "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.0" + "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.1" }, "funding": [ { @@ -4291,20 +4298,20 @@ "type": "github" } ], - "time": "2024-02-02T06:06:56+00:00" + "time": "2024-07-03T05:08:43+00:00" }, { "name": "phpunit/php-timer", - "version": "7.0.0", + "version": "7.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "8a59d9e25720482ee7fcdf296595e08795b84dc5" + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/8a59d9e25720482ee7fcdf296595e08795b84dc5", - "reference": "8a59d9e25720482ee7fcdf296595e08795b84dc5", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", "shasum": "" }, "require": { @@ -4343,7 +4350,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-timer/issues", "security": "https://github.com/sebastianbergmann/php-timer/security/policy", - "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.0" + "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.1" }, "funding": [ { @@ -4351,20 +4358,20 @@ "type": "github" } ], - "time": "2024-02-02T06:08:01+00:00" + "time": "2024-07-03T05:09:35+00:00" }, { "name": "phpunit/phpunit", - "version": "11.2.1", + "version": "11.2.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "1b8775732e9c401bda32df3ffbdf90dec7533ceb" + "reference": "a7a29e8d3113806f18f99d670f580a30e8ffff39" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1b8775732e9c401bda32df3ffbdf90dec7533ceb", - "reference": "1b8775732e9c401bda32df3ffbdf90dec7533ceb", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a7a29e8d3113806f18f99d670f580a30e8ffff39", + "reference": "a7a29e8d3113806f18f99d670f580a30e8ffff39", "shasum": "" }, "require": { @@ -4374,25 +4381,25 @@ "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.3", - "phar-io/version": "^3.0.2", + "myclabs/deep-copy": "^1.12.0", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", "php": ">=8.2", - "phpunit/php-code-coverage": "^11.0", - "phpunit/php-file-iterator": "^5.0", - "phpunit/php-invoker": "^5.0", - "phpunit/php-text-template": "^4.0", - "phpunit/php-timer": "^7.0", - "sebastian/cli-parser": "^3.0", - "sebastian/code-unit": "^3.0", - "sebastian/comparator": "^6.0", - "sebastian/diff": "^6.0", - "sebastian/environment": "^7.0", - "sebastian/exporter": "^6.0", - "sebastian/global-state": "^7.0", - "sebastian/object-enumerator": "^6.0", - "sebastian/type": "^5.0", - "sebastian/version": "^5.0" + "phpunit/php-code-coverage": "^11.0.5", + "phpunit/php-file-iterator": "^5.0.1", + "phpunit/php-invoker": "^5.0.1", + "phpunit/php-text-template": "^4.0.1", + "phpunit/php-timer": "^7.0.1", + "sebastian/cli-parser": "^3.0.2", + "sebastian/code-unit": "^3.0.1", + "sebastian/comparator": "^6.0.1", + "sebastian/diff": "^6.0.2", + "sebastian/environment": "^7.2.0", + "sebastian/exporter": "^6.1.3", + "sebastian/global-state": "^7.0.2", + "sebastian/object-enumerator": "^6.0.1", + "sebastian/type": "^5.0.1", + "sebastian/version": "^5.0.1" }, "suggest": { "ext-soap": "To be able to generate mocks based on WSDL files" @@ -4435,7 +4442,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/11.2.1" + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.2.8" }, "funding": [ { @@ -4451,7 +4458,7 @@ "type": "tidelift" } ], - "time": "2024-06-11T07:30:35+00:00" + "time": "2024-07-18T14:56:37+00:00" }, { "name": "roave/security-advisories", @@ -4459,12 +4466,12 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "c1fa2bf9896d5ce592bd78a9d01dc6ba836da82f" + "reference": "0816697098823477b1a95d07d2b94bf3cfe1a2f8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/c1fa2bf9896d5ce592bd78a9d01dc6ba836da82f", - "reference": "c1fa2bf9896d5ce592bd78a9d01dc6ba836da82f", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/0816697098823477b1a95d07d2b94bf3cfe1a2f8", + "reference": "0816697098823477b1a95d07d2b94bf3cfe1a2f8", "shasum": "" }, "conflict": { @@ -4472,8 +4479,11 @@ "admidio/admidio": "<4.2.13", "adodb/adodb-php": "<=5.20.20|>=5.21,<=5.21.3", "aheinze/cockpit": "<2.2", - "aimeos/ai-client-html": ">=2020.04.1,<2020.10.27|>=2021.04.1,<2021.10.21|>=2022.04.1,<2022.10.12|>=2023.04.1,<2023.10.14|>=2024.04.1,<2024.04.4", - "aimeos/aimeos-core": "<2024.04.7", + "aimeos/ai-admin-graphql": ">=2022.04.1,<2022.10.10|>=2023.04.1,<2023.10.6|>=2024.04.1,<2024.04.6", + "aimeos/ai-admin-jsonadm": "<2020.10.13|>=2021.04.1,<2021.10.6|>=2022.04.1,<2022.10.3|>=2023.04.1,<2023.10.4|==2024.04.1", + "aimeos/ai-client-html": ">=2020.04.1,<2020.10.27|>=2021.04.1,<2021.10.22|>=2022.04.1,<2022.10.13|>=2023.04.1,<2023.10.15|>=2024.04.1,<2024.04.7", + "aimeos/ai-controller-frontend": "<2020.10.15|>=2021.04.1,<2021.10.8|>=2022.04.1,<2022.10.8|>=2023.04.1,<2023.10.9", + "aimeos/aimeos-core": ">=2022.04.1,<2022.10.17|>=2023.04.1,<2023.10.17|>=2024.04.1,<2024.04.7", "aimeos/aimeos-typo3": "<19.10.12|>=20,<20.10.5", "airesvsg/acf-to-rest-api": "<=3.1", "akaunting/akaunting": "<2.1.13", @@ -4498,12 +4508,13 @@ "athlon1600/php-proxy": "<=5.1", "athlon1600/php-proxy-app": "<=3", "austintoddj/canvas": "<=3.4.2", - "automad/automad": "<=1.10.9", + "auth0/wordpress": "<=4.6", + "automad/automad": "<=2.0.0.0-alpha5", "automattic/jetpack": "<9.8", "awesome-support/awesome-support": "<=6.0.7", "aws/aws-sdk-php": "<3.288.1", "azuracast/azuracast": "<0.18.3", - "backdrop/backdrop": "<1.24.2", + "backdrop/backdrop": "<1.27.3|>=1.28,<1.28.2", "backpack/crud": "<3.4.9", "bacula-web/bacula-web": "<8.0.0.0-RC2-dev", "badaso/core": "<2.7", @@ -4568,7 +4579,7 @@ "contao/managed-edition": "<=1.5", "corveda/phpsandbox": "<1.3.5", "cosenary/instagram": "<=2.3", - "craftcms/cms": "<4.6.2", + "craftcms/cms": "<4.6.2|>=5.0.0.0-beta1,<=5.2.2", "croogo/croogo": "<4", "cuyz/valinor": "<0.12", "czproject/git-php": "<4.0.3", @@ -4603,7 +4614,7 @@ "ec-cube/ec-cube": "<2.4.4|>=2.11,<=2.17.1|>=3,<=3.0.18.0-patch4|>=4,<=4.1.2", "ecodev/newsletter": "<=4", "ectouch/ectouch": "<=2.7.2", - "egroupware/egroupware": "<16.1.20170922", + "egroupware/egroupware": "<23.1.20240624", "elefant/cms": "<2.0.7", "elgg/elgg": "<3.3.24|>=4,<4.0.5", "elijaa/phpmemcacheadmin": "<=1.3", @@ -4666,7 +4677,7 @@ "friendsofsymfony/rest-bundle": ">=1.2,<1.2.2", "friendsofsymfony/user-bundle": ">=1,<1.3.5", "friendsofsymfony1/swiftmailer": ">=4,<5.4.13|>=6,<6.2.5", - "friendsofsymfony1/symfony1": ">=1.1,<1.15.19", + "friendsofsymfony1/symfony1": ">=1.1,<1.5.19", "friendsoftypo3/mediace": ">=7.6.2,<7.6.5", "friendsoftypo3/openid": ">=4.5,<4.5.31|>=4.7,<4.7.16|>=6,<6.0.11|>=6.1,<6.1.6", "froala/wysiwyg-editor": "<3.2.7|>=4.0.1,<=4.1.3", @@ -4690,7 +4701,7 @@ "gos/web-socket-bundle": "<1.10.4|>=2,<2.6.1|>=3,<3.3", "gree/jose": "<2.2.1", "gregwar/rst": "<1.0.3", - "grumpydictator/firefly-iii": "<6.1.7", + "grumpydictator/firefly-iii": "<6.1.17", "gugoan/economizzer": "<=0.9.0.0-beta1", "guzzlehttp/guzzle": "<6.5.8|>=7,<7.4.5", "guzzlehttp/psr7": "<1.9.1|>=2,<2.4.5", @@ -4747,6 +4758,7 @@ "jsdecena/laracom": "<2.0.9", "jsmitty12/phpwhois": "<5.1", "juzaweb/cms": "<=3.4", + "jweiland/events2": "<8.3.8|>=9,<9.0.6", "kazist/phpwhois": "<=4.2.6", "kelvinmo/simplexrd": "<3.1.1", "kevinpapst/kimai2": "<1.16.7", @@ -4784,11 +4796,11 @@ "lms/routes": "<2.1.1", "localizationteam/l10nmgr": "<7.4|>=8,<8.7|>=9,<9.2", "luyadev/yii-helpers": "<1.2.1", - "magento/community-edition": "<2.4.3.0-patch3|>=2.4.4,<2.4.5", + "magento/community-edition": "<2.4.5|==2.4.5|>=2.4.5.0-patch1,<2.4.5.0-patch8|==2.4.6|>=2.4.6.0-patch1,<2.4.6.0-patch6|==2.4.7", "magento/core": "<=1.9.4.5", "magento/magento1ce": "<1.9.4.3-dev", "magento/magento1ee": ">=1,<1.14.4.3-dev", - "magento/product-community-edition": ">=2,<2.2.10|>=2.3,<2.3.2.0-patch2", + "magento/product-community-edition": "<2.4.4.0-patch9|>=2.4.5,<2.4.5.0-patch8|>=2.4.6,<2.4.6.0-patch6|>=2.4.7,<2.4.7.0-patch1", "magneto/core": "<1.9.4.4-dev", "maikuolan/phpmussel": ">=1,<1.6", "mainwp/mainwp": "<=4.4.3.3", @@ -4817,7 +4829,7 @@ "mojo42/jirafeau": "<4.4", "mongodb/mongodb": ">=1,<1.9.2", "monolog/monolog": ">=1.8,<1.12", - "moodle/moodle": "<4.3.4", + "moodle/moodle": "<4.3.5|>=4.4.0.0-beta,<4.4.1", "mos/cimage": "<0.7.19", "movim/moxl": ">=0.8,<=0.10", "movingbytes/social-network": "<=1.2.1", @@ -4854,12 +4866,12 @@ "october/cms": "<1.0.469|==1.0.469|==1.0.471|==1.1.1", "october/october": "<=3.4.4", "october/rain": "<1.0.472|>=1.1,<1.1.2", - "october/system": "<1.0.476|>=1.1,<1.1.12|>=2,<2.2.34|>=3,<3.5.2", + "october/system": "<1.0.476|>=1.1,<1.1.12|>=2,<2.2.34|>=3,<3.5.15", "omeka/omeka-s": "<4.0.3", "onelogin/php-saml": "<2.10.4", "oneup/uploader-bundle": ">=1,<1.9.3|>=2,<2.1.5", "open-web-analytics/open-web-analytics": "<1.7.4", - "opencart/opencart": "<=3.0.3.7|>=4,<4.0.2.3-dev", + "opencart/opencart": ">=0", "openid/php-openid": "<2.3", "openmage/magento-lts": "<20.5", "opensolutions/vimbadmin": "<=3.0.15", @@ -4871,6 +4883,7 @@ "oro/crm-call-bundle": ">=4.2,<=4.2.5|>=5,<5.0.4|>=5.1,<5.1.1", "oro/customer-portal": ">=4.1,<=4.1.13|>=4.2,<=4.2.10|>=5,<=5.0.11|>=5.1,<=5.1.3", "oro/platform": ">=1.7,<1.7.4|>=3.1,<3.1.29|>=4.1,<4.1.17|>=4.2,<=4.2.10|>=5,<=5.0.12|>=5.1,<=5.1.3", + "oveleon/contao-cookiebar": "<1.16.3|>=2,<2.1.3", "oxid-esales/oxideshop-ce": "<4.5", "oxid-esales/paymorrow-module": ">=1,<1.0.2|>=2,<2.0.1", "packbackbooks/lti-1-3-php-library": "<5", @@ -4935,8 +4948,8 @@ "prestashop/ps_emailsubscription": "<2.6.1", "prestashop/ps_facetedsearch": "<3.4.1", "prestashop/ps_linklist": "<3.1", - "privatebin/privatebin": "<1.4", - "processwire/processwire": "<=3.0.210", + "privatebin/privatebin": "<1.4|>=1.5,<1.7.4", + "processwire/processwire": "<=3.0.229", "propel/propel": ">=2.0.0.0-alpha1,<=2.0.0.0-alpha7", "propel/propel1": ">=1,<=1.7.1", "pterodactyl/panel": "<1.11.6", @@ -4975,9 +4988,9 @@ "shopware/core": "<6.5.8.8-dev|>=6.6.0.0-RC1-dev,<6.6.1", "shopware/platform": "<6.5.8.8-dev|>=6.6.0.0-RC1-dev,<6.6.1", "shopware/production": "<=6.3.5.2", - "shopware/shopware": "<6.2.3", + "shopware/shopware": "<=5.7.17", "shopware/storefront": "<=6.4.8.1|>=6.5.8,<6.5.8.7-dev", - "shopxo/shopxo": "<2.2.6", + "shopxo/shopxo": "<=6.1", "showdoc/showdoc": "<2.10.4", "silverstripe-australia/advancedreports": ">=1,<=2", "silverstripe/admin": "<1.13.19|>=2,<2.1.8", @@ -4985,11 +4998,12 @@ "silverstripe/cms": "<4.11.3", "silverstripe/comments": ">=1.3,<3.1.1", "silverstripe/forum": "<=0.6.1|>=0.7,<=0.7.3", - "silverstripe/framework": "<4.13.39|>=5,<5.1.11", + "silverstripe/framework": "<5.2.16", "silverstripe/graphql": ">=2,<2.0.5|>=3,<3.8.2|>=4,<4.3.7|>=5,<5.1.3", "silverstripe/hybridsessions": ">=1,<2.4.1|>=2.5,<2.5.1", "silverstripe/recipe-cms": ">=4.5,<4.5.3", "silverstripe/registry": ">=2.1,<2.1.2|>=2.2,<2.2.1", + "silverstripe/reports": "<5.2.3", "silverstripe/restfulserver": ">=1,<1.0.9|>=2,<2.0.4|>=2.1,<2.1.2", "silverstripe/silverstripe-omnipay": "<2.5.2|>=3,<3.0.2|>=3.1,<3.1.4|>=3.2,<3.2.1", "silverstripe/subsites": ">=2,<2.6.1", @@ -5010,7 +5024,7 @@ "slim/slim": "<2.6", "slub/slub-events": "<3.0.3", "smarty/smarty": "<4.5.3|>=5,<5.1.1", - "snipe/snipe-it": "<=6.2.2", + "snipe/snipe-it": "<6.4.2", "socalnick/scn-social-auth": "<1.15.2", "socialiteproviders/steam": "<1.1", "spatie/browsershot": "<3.57.4", @@ -5019,10 +5033,11 @@ "spoon/library": "<1.4.1", "spoonity/tcpdf": "<6.2.22", "squizlabs/php_codesniffer": ">=1,<2.8.1|>=3,<3.0.1", - "ssddanbrown/bookstack": "<22.02.3", + "ssddanbrown/bookstack": "<24.05.1", "statamic/cms": "<4.46|>=5.3,<5.6.2", "stormpath/sdk": "<9.9.99", "studio-42/elfinder": "<2.1.62", + "studiomitte/friendlycaptcha": "<0.1.4", "subhh/libconnect": "<7.0.8|>=8,<8.1", "sukohi/surpass": "<1", "sulu/form-bundle": ">=2,<2.5.3", @@ -5037,7 +5052,7 @@ "sylius/grid-bundle": "<1.10.1", "sylius/paypal-plugin": ">=1,<1.2.4|>=1.3,<1.3.1", "sylius/resource-bundle": ">=1,<1.3.14|>=1.4,<1.4.7|>=1.5,<1.5.2|>=1.6,<1.6.4", - "sylius/sylius": "<1.9.10|>=1.10,<1.10.11|>=1.11,<1.11.2|>=1.12.0.0-alpha1,<1.12.16|>=1.13.0.0-alpha1,<1.13.1", + "sylius/sylius": "<1.12.19|>=1.13.0.0-alpha1,<1.13.4", "symbiote/silverstripe-multivaluefield": ">=3,<3.1", "symbiote/silverstripe-queuedjobs": ">=3,<3.0.2|>=3.1,<3.1.4|>=4,<4.0.7|>=4.1,<4.1.2|>=4.2,<4.2.4|>=4.3,<4.3.3|>=4.4,<4.4.3|>=4.5,<4.5.1|>=4.6,<4.6.4", "symbiote/silverstripe-seed": "<6.0.3", @@ -5089,14 +5104,14 @@ "thorsten/phpmyfaq": "<3.2.2", "tikiwiki/tiki-manager": "<=17.1", "timber/timber": ">=0.16.6,<1.23.1|>=1.24,<1.24.1|>=2,<2.1", - "tinymce/tinymce": "<7", + "tinymce/tinymce": "<7.2", "tinymighty/wiki-seo": "<1.2.2", "titon/framework": "<9.9.99", "tobiasbg/tablepress": "<=2.0.0.0-RC1", "topthink/framework": "<6.0.17|>=6.1,<6.1.5|>=8,<8.0.4", "topthink/think": "<=6.1.1", "topthink/thinkphp": "<=3.2.3", - "torrentpier/torrentpier": "<=2.4.1", + "torrentpier/torrentpier": "<=2.4.3", "tpwd/ke_search": "<4.0.3|>=4.1,<4.6.6|>=5,<5.0.2", "tribalsystems/zenario": "<9.5.60602", "truckersmp/phpwhois": "<=4.3.1", @@ -5138,7 +5153,8 @@ "wallabag/tcpdf": "<6.2.22", "wallabag/wallabag": "<2.6.7", "wanglelecc/laracms": "<=1.0.3", - "web-auth/webauthn-framework": ">=3.3,<3.3.4", + "web-auth/webauthn-framework": ">=3.3,<3.3.4|>=4.5,<4.9", + "web-auth/webauthn-lib": ">=4.5,<4.9", "web-feet/coastercms": "==5.5", "webbuilders-group/silverstripe-kapost-bridge": "<0.4", "webcoast/deferred-image-processing": "<1.0.2", @@ -5168,7 +5184,7 @@ "yidashi/yii2cmf": "<=2", "yii2mod/yii2-cms": "<1.9.2", "yiisoft/yii": "<1.1.29", - "yiisoft/yii2": "<2.0.50", + "yiisoft/yii2": "<2.0.49.4-dev", "yiisoft/yii2-authclient": "<2.2.15", "yiisoft/yii2-bootstrap": "<2.0.4", "yiisoft/yii2-dev": "<2.0.43", @@ -5254,20 +5270,20 @@ "type": "tidelift" } ], - "time": "2024-06-12T20:04:30+00:00" + "time": "2024-07-26T15:04:59+00:00" }, { "name": "sebastian/cli-parser", - "version": "3.0.1", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "00a74d5568694711f0222e54fb281e1d15fdf04a" + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/00a74d5568694711f0222e54fb281e1d15fdf04a", - "reference": "00a74d5568694711f0222e54fb281e1d15fdf04a", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180", + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180", "shasum": "" }, "require": { @@ -5303,7 +5319,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/cli-parser/issues", "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.1" + "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.2" }, "funding": [ { @@ -5311,20 +5327,20 @@ "type": "github" } ], - "time": "2024-03-02T07:26:58+00:00" + "time": "2024-07-03T04:41:36+00:00" }, { "name": "sebastian/code-unit", - "version": "3.0.0", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "6634549cb8d702282a04a774e36a7477d2bd9015" + "reference": "6bb7d09d6623567178cf54126afa9c2310114268" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/6634549cb8d702282a04a774e36a7477d2bd9015", - "reference": "6634549cb8d702282a04a774e36a7477d2bd9015", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/6bb7d09d6623567178cf54126afa9c2310114268", + "reference": "6bb7d09d6623567178cf54126afa9c2310114268", "shasum": "" }, "require": { @@ -5360,7 +5376,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/code-unit/issues", "security": "https://github.com/sebastianbergmann/code-unit/security/policy", - "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.0" + "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.1" }, "funding": [ { @@ -5368,20 +5384,20 @@ "type": "github" } ], - "time": "2024-02-02T05:50:41+00:00" + "time": "2024-07-03T04:44:28+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", - "version": "4.0.0", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "df80c875d3e459b45c6039e4d9b71d4fbccae25d" + "reference": "183a9b2632194febd219bb9246eee421dad8d45e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/df80c875d3e459b45c6039e4d9b71d4fbccae25d", - "reference": "df80c875d3e459b45c6039e4d9b71d4fbccae25d", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e", "shasum": "" }, "require": { @@ -5416,7 +5432,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.0" + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.1" }, "funding": [ { @@ -5424,20 +5440,20 @@ "type": "github" } ], - "time": "2024-02-02T05:52:17+00:00" + "time": "2024-07-03T04:45:54+00:00" }, { "name": "sebastian/comparator", - "version": "6.0.0", + "version": "6.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "bd0f2fa5b9257c69903537b266ccb80fcf940db8" + "reference": "131942b86d3587291067a94f295498ab6ac79c20" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/bd0f2fa5b9257c69903537b266ccb80fcf940db8", - "reference": "bd0f2fa5b9257c69903537b266ccb80fcf940db8", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/131942b86d3587291067a94f295498ab6ac79c20", + "reference": "131942b86d3587291067a94f295498ab6ac79c20", "shasum": "" }, "require": { @@ -5493,7 +5509,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/6.0.0" + "source": "https://github.com/sebastianbergmann/comparator/tree/6.0.1" }, "funding": [ { @@ -5501,20 +5517,20 @@ "type": "github" } ], - "time": "2024-02-02T05:53:45+00:00" + "time": "2024-07-03T04:48:07+00:00" }, { "name": "sebastian/complexity", - "version": "4.0.0", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "88a434ad86150e11a606ac4866b09130712671f0" + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/88a434ad86150e11a606ac4866b09130712671f0", - "reference": "88a434ad86150e11a606ac4866b09130712671f0", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0", + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0", "shasum": "" }, "require": { @@ -5551,7 +5567,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/complexity/issues", "security": "https://github.com/sebastianbergmann/complexity/security/policy", - "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.0" + "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.1" }, "funding": [ { @@ -5559,20 +5575,20 @@ "type": "github" } ], - "time": "2024-02-02T05:55:19+00:00" + "time": "2024-07-03T04:49:50+00:00" }, { "name": "sebastian/diff", - "version": "6.0.1", + "version": "6.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "ab83243ecc233de5655b76f577711de9f842e712" + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ab83243ecc233de5655b76f577711de9f842e712", - "reference": "ab83243ecc233de5655b76f577711de9f842e712", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544", "shasum": "" }, "require": { @@ -5618,7 +5634,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", "security": "https://github.com/sebastianbergmann/diff/security/policy", - "source": "https://github.com/sebastianbergmann/diff/tree/6.0.1" + "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2" }, "funding": [ { @@ -5626,20 +5642,20 @@ "type": "github" } ], - "time": "2024-03-02T07:30:33+00:00" + "time": "2024-07-03T04:53:05+00:00" }, { "name": "sebastian/environment", - "version": "7.1.0", + "version": "7.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "4eb3a442574d0e9d141aab209cd4aaf25701b09a" + "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/4eb3a442574d0e9d141aab209cd4aaf25701b09a", - "reference": "4eb3a442574d0e9d141aab209cd4aaf25701b09a", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", + "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", "shasum": "" }, "require": { @@ -5654,7 +5670,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "7.1-dev" + "dev-main": "7.2-dev" } }, "autoload": { @@ -5682,7 +5698,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", "security": "https://github.com/sebastianbergmann/environment/security/policy", - "source": "https://github.com/sebastianbergmann/environment/tree/7.1.0" + "source": "https://github.com/sebastianbergmann/environment/tree/7.2.0" }, "funding": [ { @@ -5690,20 +5706,20 @@ "type": "github" } ], - "time": "2024-03-23T08:56:34+00:00" + "time": "2024-07-03T04:54:44+00:00" }, { "name": "sebastian/exporter", - "version": "6.0.1", + "version": "6.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "f291e5a317c321c0381fa9ecc796fa2d21b186da" + "reference": "c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/f291e5a317c321c0381fa9ecc796fa2d21b186da", - "reference": "f291e5a317c321c0381fa9ecc796fa2d21b186da", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e", + "reference": "c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e", "shasum": "" }, "require": { @@ -5712,12 +5728,12 @@ "sebastian/recursion-context": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^11.0" + "phpunit/phpunit": "^11.2" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "6.0-dev" + "dev-main": "6.1-dev" } }, "autoload": { @@ -5760,7 +5776,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", "security": "https://github.com/sebastianbergmann/exporter/security/policy", - "source": "https://github.com/sebastianbergmann/exporter/tree/6.0.1" + "source": "https://github.com/sebastianbergmann/exporter/tree/6.1.3" }, "funding": [ { @@ -5768,20 +5784,20 @@ "type": "github" } ], - "time": "2024-03-02T07:28:20+00:00" + "time": "2024-07-03T04:56:19+00:00" }, { "name": "sebastian/global-state", - "version": "7.0.1", + "version": "7.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "c3a307e832f2e69c7ef869e31fc644fde0e7cb3e" + "reference": "3be331570a721f9a4b5917f4209773de17f747d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/c3a307e832f2e69c7ef869e31fc644fde0e7cb3e", - "reference": "c3a307e832f2e69c7ef869e31fc644fde0e7cb3e", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7", "shasum": "" }, "require": { @@ -5822,7 +5838,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", "security": "https://github.com/sebastianbergmann/global-state/security/policy", - "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.1" + "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.2" }, "funding": [ { @@ -5830,20 +5846,20 @@ "type": "github" } ], - "time": "2024-03-02T07:32:10+00:00" + "time": "2024-07-03T04:57:36+00:00" }, { "name": "sebastian/lines-of-code", - "version": "3.0.0", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "376c5b3f6b43c78fdc049740bca76a7c846706c0" + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/376c5b3f6b43c78fdc049740bca76a7c846706c0", - "reference": "376c5b3f6b43c78fdc049740bca76a7c846706c0", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a", "shasum": "" }, "require": { @@ -5880,7 +5896,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.0" + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.1" }, "funding": [ { @@ -5888,20 +5904,20 @@ "type": "github" } ], - "time": "2024-02-02T06:00:36+00:00" + "time": "2024-07-03T04:58:38+00:00" }, { "name": "sebastian/object-enumerator", - "version": "6.0.0", + "version": "6.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "f75f6c460da0bbd9668f43a3dde0ec0ba7faa678" + "reference": "f5b498e631a74204185071eb41f33f38d64608aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f75f6c460da0bbd9668f43a3dde0ec0ba7faa678", - "reference": "f75f6c460da0bbd9668f43a3dde0ec0ba7faa678", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa", "shasum": "" }, "require": { @@ -5938,7 +5954,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.0" + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.1" }, "funding": [ { @@ -5946,20 +5962,20 @@ "type": "github" } ], - "time": "2024-02-02T06:01:29+00:00" + "time": "2024-07-03T05:00:13+00:00" }, { "name": "sebastian/object-reflector", - "version": "4.0.0", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "bb2a6255d30853425fd38f032eb64ced9f7f132d" + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/bb2a6255d30853425fd38f032eb64ced9f7f132d", - "reference": "bb2a6255d30853425fd38f032eb64ced9f7f132d", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9", "shasum": "" }, "require": { @@ -5994,7 +6010,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/object-reflector/issues", "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.0" + "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.1" }, "funding": [ { @@ -6002,20 +6018,20 @@ "type": "github" } ], - "time": "2024-02-02T06:02:18+00:00" + "time": "2024-07-03T05:01:32+00:00" }, { "name": "sebastian/recursion-context", - "version": "6.0.0", + "version": "6.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "b75224967b5a466925c6d54e68edd0edf8dd4ed4" + "reference": "694d156164372abbd149a4b85ccda2e4670c0e16" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b75224967b5a466925c6d54e68edd0edf8dd4ed4", - "reference": "b75224967b5a466925c6d54e68edd0edf8dd4ed4", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/694d156164372abbd149a4b85ccda2e4670c0e16", + "reference": "694d156164372abbd149a4b85ccda2e4670c0e16", "shasum": "" }, "require": { @@ -6058,7 +6074,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.0" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.2" }, "funding": [ { @@ -6066,20 +6082,20 @@ "type": "github" } ], - "time": "2024-02-02T06:08:48+00:00" + "time": "2024-07-03T05:10:34+00:00" }, { "name": "sebastian/type", - "version": "5.0.0", + "version": "5.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "b8502785eb3523ca0dd4afe9ca62235590020f3f" + "reference": "fb6a6566f9589e86661291d13eba708cce5eb4aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b8502785eb3523ca0dd4afe9ca62235590020f3f", - "reference": "b8502785eb3523ca0dd4afe9ca62235590020f3f", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb6a6566f9589e86661291d13eba708cce5eb4aa", + "reference": "fb6a6566f9589e86661291d13eba708cce5eb4aa", "shasum": "" }, "require": { @@ -6115,7 +6131,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/type/issues", "security": "https://github.com/sebastianbergmann/type/security/policy", - "source": "https://github.com/sebastianbergmann/type/tree/5.0.0" + "source": "https://github.com/sebastianbergmann/type/tree/5.0.1" }, "funding": [ { @@ -6123,20 +6139,20 @@ "type": "github" } ], - "time": "2024-02-02T06:09:34+00:00" + "time": "2024-07-03T05:11:49+00:00" }, { "name": "sebastian/version", - "version": "5.0.0", + "version": "5.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "13999475d2cb1ab33cb73403ba356a814fdbb001" + "reference": "45c9debb7d039ce9b97de2f749c2cf5832a06ac4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/13999475d2cb1ab33cb73403ba356a814fdbb001", - "reference": "13999475d2cb1ab33cb73403ba356a814fdbb001", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/45c9debb7d039ce9b97de2f749c2cf5832a06ac4", + "reference": "45c9debb7d039ce9b97de2f749c2cf5832a06ac4", "shasum": "" }, "require": { @@ -6169,7 +6185,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/version/issues", "security": "https://github.com/sebastianbergmann/version/security/policy", - "source": "https://github.com/sebastianbergmann/version/tree/5.0.0" + "source": "https://github.com/sebastianbergmann/version/tree/5.0.1" }, "funding": [ { @@ -6177,20 +6193,20 @@ "type": "github" } ], - "time": "2024-02-02T06:10:47+00:00" + "time": "2024-07-03T05:13:08+00:00" }, { "name": "squizlabs/php_codesniffer", - "version": "3.10.1", + "version": "3.10.2", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "8f90f7a53ce271935282967f53d0894f8f1ff877" + "reference": "86e5f5dd9a840c46810ebe5ff1885581c42a3017" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/8f90f7a53ce271935282967f53d0894f8f1ff877", - "reference": "8f90f7a53ce271935282967f53d0894f8f1ff877", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/86e5f5dd9a840c46810ebe5ff1885581c42a3017", + "reference": "86e5f5dd9a840c46810ebe5ff1885581c42a3017", "shasum": "" }, "require": { @@ -6257,245 +6273,30 @@ "type": "open_collective" } ], - "time": "2024-05-22T21:24:41+00:00" - }, - { - "name": "symfony/browser-kit", - "version": "v5.4.40", - "source": { - "type": "git", - "url": "https://github.com/symfony/browser-kit.git", - "reference": "92c8ba1e5ee12d07120744c90898516132b4e58b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/92c8ba1e5ee12d07120744c90898516132b4e58b", - "reference": "92c8ba1e5ee12d07120744c90898516132b4e58b", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/dom-crawler": "^4.4|^5.0|^6.0", - "symfony/polyfill-php80": "^1.16" - }, - "require-dev": { - "symfony/css-selector": "^4.4|^5.0|^6.0", - "symfony/http-client": "^4.4|^5.0|^6.0", - "symfony/mime": "^4.4|^5.0|^6.0", - "symfony/process": "^4.4|^5.0|^6.0" - }, - "suggest": { - "symfony/process": "" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\BrowserKit\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Simulates the behavior of a web browser, allowing you to make requests, click on links and submit forms programmatically", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/browser-kit/tree/v5.4.40" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-05-31T14:33:22+00:00" - }, - { - "name": "symfony/css-selector", - "version": "v5.4.40", - "source": { - "type": "git", - "url": "https://github.com/symfony/css-selector.git", - "reference": "ea43887e9afd2029509662d4f95e8b5ef6fc9bbb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/ea43887e9afd2029509662d4f95e8b5ef6fc9bbb", - "reference": "ea43887e9afd2029509662d4f95e8b5ef6fc9bbb", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "symfony/polyfill-php80": "^1.16" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\CssSelector\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Jean-François Simon", - "email": "jeanfrancois.simon@sensiolabs.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Converts CSS selectors to XPath expressions", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/css-selector/tree/v5.4.40" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-05-31T14:33:22+00:00" - }, - { - "name": "symfony/debug", - "version": "v3.4.47", - "source": { - "type": "git", - "url": "https://github.com/symfony/debug.git", - "reference": "ab42889de57fdfcfcc0759ab102e2fd4ea72dcae" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/ab42889de57fdfcfcc0759ab102e2fd4ea72dcae", - "reference": "ab42889de57fdfcfcc0759ab102e2fd4ea72dcae", - "shasum": "" - }, - "require": { - "php": "^5.5.9|>=7.0.8", - "psr/log": "~1.0" - }, - "conflict": { - "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" - }, - "require-dev": { - "symfony/http-kernel": "~2.8|~3.0|~4.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Debug\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Debug Component", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/debug/tree/v3.4.47" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "abandoned": "symfony/error-handler", - "time": "2020-10-24T10:57:07+00:00" + "time": "2024-07-21T23:26:44+00:00" }, { "name": "symfony/dom-crawler", - "version": "v5.4.40", + "version": "v7.1.1", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "2ad469c3e07fdba677b278d0e266071a51aa0dac" + "reference": "01ce8174447f1f1dd33a5854b01beef79061d9fa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/2ad469c3e07fdba677b278d0e266071a51aa0dac", - "reference": "2ad469c3e07fdba677b278d0e266071a51aa0dac", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/01ce8174447f1f1dd33a5854b01beef79061d9fa", + "reference": "01ce8174447f1f1dd33a5854b01beef79061d9fa", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", + "masterminds/html5": "^2.6", + "php": ">=8.2", "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "^1.16" - }, - "conflict": { - "masterminds/html5": "<2.6" + "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { - "masterminds/html5": "^2.6", - "symfony/css-selector": "^4.4|^5.0|^6.0" - }, - "suggest": { - "symfony/css-selector": "" + "symfony/css-selector": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -6523,7 +6324,7 @@ "description": "Eases DOM navigation for HTML and XML documents", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dom-crawler/tree/v5.4.40" + "source": "https://github.com/symfony/dom-crawler/tree/v7.1.1" }, "funding": [ { @@ -6539,7 +6340,167 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:33:22+00:00" + "time": "2024-05-31T14:57:53+00:00" + }, + { + "name": "symfony/error-handler", + "version": "v7.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/error-handler.git", + "reference": "432bb369952795c61ca1def65e078c4a80dad13c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/432bb369952795c61ca1def65e078c4a80dad13c", + "reference": "432bb369952795c61ca1def65e078c4a80dad13c", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/log": "^1|^2|^3", + "symfony/var-dumper": "^6.4|^7.0" + }, + "conflict": { + "symfony/deprecation-contracts": "<2.5", + "symfony/http-kernel": "<6.4" + }, + "require-dev": { + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0" + }, + "bin": [ + "Resources/bin/patch-type-declarations" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\ErrorHandler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to manage errors and ease debugging PHP code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/error-handler/tree/v7.1.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-07-26T13:02:51+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v6.4.10", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "a71cc3374f5fb9759da1961d28c452373b343dd4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/a71cc3374f5fb9759da1961d28c452373b343dd4", + "reference": "a71cc3374f5fb9759da1961d28c452373b343dd4", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/console": "<5.4" + }, + "require-dev": { + "ext-iconv": "*", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/error-handler": "^6.3|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/uid": "^5.4|^6.0|^7.0", + "twig/twig": "^2.13|^3.0.4" + }, + "bin": [ + "Resources/bin/var-dump-server" + ], + "type": "library", + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides mechanisms for walking through any arbitrary PHP variable", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "support": { + "source": "https://github.com/symfony/var-dumper/tree/v6.4.10" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-07-26T12:30:32+00:00" }, { "name": "theseer/tokenizer", @@ -6598,7 +6559,9 @@ "ademarre/binary-to-text-php": 20, "symfony/yaml": 0, "roave/security-advisories": 20, - "mikey179/vfsstream": 0 + "symfony/error-handler": 0, + "mikey179/vfsstream": 0, + "symfony/dom-crawler": 0 }, "prefer-stable": false, "prefer-lowest": false, diff --git a/lib/Base.php b/lib/Base.php index 7aa7b470..8f011828 100644 --- a/lib/Base.php +++ b/lib/Base.php @@ -26,32 +26,20 @@ use DI\ContainerBuilder; use Dotenv\Dotenv; use SP\Core\Definitions\CoreDefinitions; use SP\Core\Definitions\DomainDefinitions; +use SP\Infrastructure\File\FileSystem; use function SP\getFromEnv; use function SP\initModule; use function SP\processException; -// Core PATHS -const DS = DIRECTORY_SEPARATOR; - if (!defined('APP_ROOT')) { - define('APP_ROOT', realpath(__DIR__ . DS . '..')); + define('APP_ROOT', realpath(__DIR__ . DIRECTORY_SEPARATOR . '..')); } -const APP_PATH = APP_ROOT . DS . 'app'; -const VENDOR_PATH = APP_ROOT . DS . 'vendor'; -const SQL_PATH = APP_ROOT . DS . 'schemas'; -const PUBLIC_PATH = APP_ROOT . DS . 'public'; -const XML_SCHEMA = SQL_PATH . DS . 'syspass.xsd'; -const RESOURCES_PATH = APP_PATH . DS . 'resources'; -const MODULES_PATH = APP_PATH . DS . 'modules'; -const LOCALES_PATH = APP_PATH . DS . 'locales'; +require 'BaseFunctions.php'; +require FileSystem::buildPath(APP_ROOT, 'vendor', 'autoload.php'); -// Start tracking the memory used -$memInit = memory_get_usage(); - -require __DIR__ . DS . 'BaseFunctions.php'; -require VENDOR_PATH . DS . 'autoload.php'; +define('APP_PATH', FileSystem::buildPath(APP_ROOT, 'app')); $dotenv = Dotenv::createImmutable(APP_ROOT); $dotenv->load(); @@ -59,19 +47,6 @@ $dotenv->load(); defined('APP_MODULE') || define('APP_MODULE', 'web'); define('DEBUG', getFromEnv('DEBUG', false)); -define('IS_TESTING', getFromEnv('IS_TESTING', defined('TEST_ROOT'))); -define('CONFIG_PATH', getFromEnv('CONFIG_PATH', APP_PATH . DS . 'config')); -define('CONFIG_FILE', getFromEnv('CONFIG_FILE', CONFIG_PATH . DS . 'config.xml')); -define('ACTIONS_FILE', getFromEnv('ACTIONS_FILE', RESOURCES_PATH . DS . 'actions.yaml')); -define('MIMETYPES_FILE', getFromEnv('MIMETYPES_FILE', RESOURCES_PATH . DS . 'mimetypes.yaml')); -define('LOG_FILE', getFromEnv('LOG_FILE', CONFIG_PATH . DS . 'syspass.log')); - -const LOCK_FILE = CONFIG_PATH . DS . '.lock'; - -// Setup application paths -define('BACKUP_PATH', getFromEnv('BACKUP_PATH', APP_PATH . DS . 'backup')); -define('CACHE_PATH', getFromEnv('CACHE_PATH', APP_PATH . DS . 'cache')); -define('TMP_PATH', getFromEnv('TMP_PATH', APP_PATH . DS . 'temp')); try { $moduleDefinitions = initModule(APP_MODULE); @@ -79,12 +54,17 @@ try { $containerBuilder = new ContainerBuilder(); if (!DEBUG) { - $containerBuilder->enableCompilation(CACHE_PATH); - $containerBuilder->writeProxiesToFile(true, CACHE_PATH . DS . 'proxies'); + $cachePath = getFromEnv('CACHE_PATH', FileSystem::buildPath(APP_PATH, 'cache')); + $containerBuilder->enableCompilation($cachePath); + $containerBuilder->writeProxiesToFile(true, FileSystem::buildPath($cachePath, 'proxies')); } return $containerBuilder - ->addDefinitions(CoreDefinitions::getDefinitions(), DomainDefinitions::getDefinitions(), $moduleDefinitions) + ->addDefinitions( + CoreDefinitions::getDefinitions(APP_ROOT, APP_MODULE), + DomainDefinitions::getDefinitions(), + $moduleDefinitions + ) ->build(); } catch (Exception $e) { processException($e); diff --git a/lib/BaseFunctions.php b/lib/BaseFunctions.php index 4a5490ac..d6aae3a2 100644 --- a/lib/BaseFunctions.php +++ b/lib/BaseFunctions.php @@ -38,6 +38,10 @@ const LOG_FORMAT = "[%s] [%s] %s"; */ const LOG_FORMAT_OWN = '[%s] syspass.%s: logger {"message":"%s","caller":"%s"}' . PHP_EOL; +define('MODULES_PATH', FileSystem::buildPath(APP_PATH, 'modules')); + +define('LOG_FILE', getFromEnv('LOG_FILE', FileSystem::buildPath(APP_PATH, 'config', 'syspass.log'))); + /** * Basic logger to handle some debugging and exception messages. * diff --git a/lib/SP/Core/Acl/Actions.php b/lib/SP/Core/Acl/Actions.php index 7cea5e70..ce295d1e 100644 --- a/lib/SP/Core/Acl/Actions.php +++ b/lib/SP/Core/Acl/Actions.php @@ -42,10 +42,6 @@ use function SP\processException; */ class Actions implements ActionsInterface { - /** - * Cache file name - */ - public const ACTIONS_CACHE_FILE = CACHE_PATH . DIRECTORY_SEPARATOR . 'actions.cache'; /** * Cache expire time */ @@ -109,7 +105,9 @@ class Actions implements ActionsInterface { $this->actions = []; - foreach ($this->yamlFileStorage->load() as $a) { + $yaml = $this->yamlFileStorage->load(); + + foreach ($yaml['actions'] as $a) { $this->actions[$a['id']] = new Action($a['id'], $a['name'], $a['text'], $a['route']); } } @@ -147,7 +145,7 @@ class Actions implements ActionsInterface */ public function reset(): void { - @unlink(self::ACTIONS_CACHE_FILE); + $this->fileCache->delete(); $this->loadCache(); } diff --git a/lib/SP/Core/AppLock.php b/lib/SP/Core/AppLock.php new file mode 100644 index 00000000..018c16e6 --- /dev/null +++ b/lib/SP/Core/AppLock.php @@ -0,0 +1,87 @@ +. + */ + +declare(strict_types=1); + +namespace SP\Core; + +use SP\Core\Bootstrap\Path; +use SP\Core\Bootstrap\PathsContext; +use SP\Domain\Common\Adapters\Serde; +use SP\Domain\Core\Exceptions\SPException; +use SP\Infrastructure\File\FileException; +use SP\Infrastructure\File\FileHandler; +use SP\Infrastructure\File\FileSystem; + +use function SP\logger; + +/** + * Class AppLock + */ +final readonly class AppLock +{ + + private string $lockFile; + + public function __construct(PathsContext $pathsContext) + { + $this->lockFile = FileSystem::buildPath($pathsContext[Path::CONFIG], '.lock'); + } + + /** + * Comprueba si la aplicación está bloqueada + * + * @return bool|string + * @throws SPException + */ + public function getLock(): bool|string + { + try { + $file = new FileHandler($this->lockFile); + + return Serde::deserializeJson($file->readToString())->userId; + } catch (FileException) { + return false; + } + } + + /** + * @throws FileException + * @throws SPException + */ + public function lock(int $userId, string $subject): void + { + $data = ['time' => time(), 'userId' => $userId, 'subject' => $subject]; + + $file = new FileHandler($this->lockFile); + $file->save(Serde::serializeJson($data)); + + logger('Application locked out'); + } + + public function unlock(): void + { + @unlink($this->lockFile); + } +} diff --git a/lib/SP/Core/Application.php b/lib/SP/Core/Application.php index 0dc835f6..cb0f61b5 100644 --- a/lib/SP/Core/Application.php +++ b/lib/SP/Core/Application.php @@ -36,13 +36,6 @@ use SP\Domain\Core\Events\EventDispatcherInterface; */ final readonly class Application { - /** - * Module constructor. - * - * @param ConfigFileService $config - * @param EventDispatcherInterface $eventDispatcher - * @param Context $context - */ public function __construct( private ConfigFileService $config, private EventDispatcherInterface $eventDispatcher, diff --git a/lib/SP/Core/Bootstrap/BootstrapBase.php b/lib/SP/Core/Bootstrap/BootstrapBase.php index a11ffb4d..d6ea0725 100644 --- a/lib/SP/Core/Bootstrap/BootstrapBase.php +++ b/lib/SP/Core/Bootstrap/BootstrapBase.php @@ -34,7 +34,6 @@ use Psr\Container\ContainerExceptionInterface; use Psr\Container\ContainerInterface; use Psr\Container\NotFoundExceptionInterface; use RuntimeException; -use SP\Core\Language; use SP\Core\PhpExtensionChecker; use SP\Domain\Common\Providers\Environment; use SP\Domain\Config\Ports\ConfigDataInterface; @@ -46,8 +45,9 @@ use SP\Domain\Core\Context\Context; use SP\Domain\Core\Exceptions\CheckException; use SP\Domain\Core\Exceptions\ConfigException; use SP\Domain\Core\Exceptions\InitializationException; +use SP\Domain\Core\LanguageInterface; use SP\Domain\Http\Ports\RequestService; -use Symfony\Component\Debug\Debug; +use Symfony\Component\ErrorHandler\Debug; use Throwable; use function SP\__; @@ -74,10 +74,12 @@ abstract class BootstrapBase implements BootstrapInterface protected readonly Context $context, private readonly ContainerInterface $container, protected readonly Response $response, - protected readonly RouteContextData $routeContextData + protected readonly RouteContextData $routeContextData, + LanguageInterface $language, + protected readonly PathsContext $pathsContext ) { // Set the default language - Language::setLocales('en_US'); + $language->setLocales('en_US'); $this->initRouter(); $this->configureRouter(); @@ -123,11 +125,11 @@ abstract class BootstrapBase implements BootstrapInterface abstract public static function run(BootstrapInterface $bootstrap, ModuleInterface $initModule): void; - final protected static function getClassFor(string $controllerName, string $actionName): string + final protected static function getClassFor(string $module, string $controllerName, string $actionName): string { return sprintf( 'SP\Modules\%s\Controllers\%s\%sController', - ucfirst(APP_MODULE), + ucfirst($module), ucfirst($controllerName), ucfirst($actionName) ); @@ -203,7 +205,6 @@ abstract class BootstrapBase implements BootstrapInterface private function initPHPVars(): void { if (DEBUG) { - /** @noinspection ForgottenDebugOutputInspection */ Debug::enable(); } else { error_reporting(E_ALL & ~(E_DEPRECATED | E_STRICT | E_NOTICE)); @@ -213,11 +214,13 @@ abstract class BootstrapBase implements BootstrapInterface } } - if (!file_exists(LOG_FILE) - && touch(LOG_FILE) - && chmod(LOG_FILE, 0600) + $logFile = $this->pathsContext[Path::LOG_FILE]; + + if (!file_exists($logFile) + && touch($logFile) + && chmod($logFile, 0600) ) { - logger('Setup log file: ' . LOG_FILE); + logger('Setup log file: ' . $logFile); } if (date_default_timezone_get() === 'UTC') { diff --git a/lib/SP/Core/Bootstrap/Path.php b/lib/SP/Core/Bootstrap/Path.php new file mode 100644 index 00000000..0eb84dc7 --- /dev/null +++ b/lib/SP/Core/Bootstrap/Path.php @@ -0,0 +1,50 @@ +. + */ + +namespace SP\Core\Bootstrap; + +/** + * Enum Path + */ +enum Path +{ + case APP; + case SQL; + case PUBLIC; + case XML_SCHEMA; + case RESOURCES; + case MODULES; + case LOCALES; + case CONFIG; + case CONFIG_FILE; + case ACTIONS_FILE; + case MIMETYPES_FILE; + case SQL_FILE; + case VIEW; + case BACKUP; + case CACHE; + case TMP; + case LOG_FILE; + case PLUGINS; +} diff --git a/lib/SP/Core/Bootstrap/PathsContext.php b/lib/SP/Core/Bootstrap/PathsContext.php new file mode 100644 index 00000000..83286797 --- /dev/null +++ b/lib/SP/Core/Bootstrap/PathsContext.php @@ -0,0 +1,110 @@ +. + */ + +declare(strict_types=1); + +namespace SP\Core\Bootstrap; + +use ArrayAccess; +use SplObjectStorage; +use ValueError; + +/** + * Class PathsContext + * + * @template-implements ArrayAccess + */ +final readonly class PathsContext implements ArrayAccess +{ + /** + * @var SplObjectStorage + */ + private SplObjectStorage $paths; + + public function __construct() + { + $this->paths = new SplObjectStorage(); + } + + /** + * @inheritDoc + */ + public function offsetExists(mixed $offset): bool + { + return $this->paths->contains($offset); + } + + /** + * @inheritDoc + */ + public function offsetGet(mixed $offset): mixed + { + return $this->paths->offsetGet($offset); + } + + /** + * @inheritDoc + */ + public function offsetSet(mixed $offset, mixed $value): void + { + $this->addPath($offset, $value); + } + + /** + * @param Path $path + * @param string $value + * @return void + */ + public function addPath(Path $path, string $value): void + { + if ($this->paths->contains($path)) { + throw new ValueError('Duplicated path found: ' . $path->name); + } + + $this->paths->attach($path, $value); + } + + /** + * @param array $paths + * @return void + */ + public function addPaths(array $paths): void + { + foreach ($paths as $pathSpec) { + if (!is_array($pathSpec)) { + throw new ValueError('Path spec must be an array'); + } + + $this->addPath(...$pathSpec); + } + } + + /** + * @inheritDoc + */ + public function offsetUnset(mixed $offset): void + { + $this->paths->offsetUnset($offset); + } +} diff --git a/lib/SP/Core/Crypt/Cookie.php b/lib/SP/Core/Crypt/Cookie.php index 533ec4ed..d319859d 100644 --- a/lib/SP/Core/Crypt/Cookie.php +++ b/lib/SP/Core/Crypt/Cookie.php @@ -91,11 +91,6 @@ abstract class Cookie */ protected function setCookie(string $data): bool { - // Do not try to set cookies when testing - if (IS_TESTING) { - return true; - } - if (headers_sent()) { logger('Headers already sent', 'ERROR'); diff --git a/lib/SP/Core/Crypt/CryptPKI.php b/lib/SP/Core/Crypt/CryptPKI.php index dafc29b8..3d1e58da 100644 --- a/lib/SP/Core/Crypt/CryptPKI.php +++ b/lib/SP/Core/Crypt/CryptPKI.php @@ -40,8 +40,8 @@ use function SP\processException; final class CryptPKI implements CryptPKIHandler { public const KEY_SIZE = 1024; - public const PUBLIC_KEY_FILE = CONFIG_PATH . DIRECTORY_SEPARATOR . 'pubkey.pem'; - public const PRIVATE_KEY_FILE = CONFIG_PATH . DIRECTORY_SEPARATOR . 'key.pem'; + public const PUBLIC_KEY_FILE = 'pubkey.pem'; + public const PRIVATE_KEY_FILE = 'key.pem'; /** * @throws SPException diff --git a/lib/SP/Core/Definitions/CoreDefinitions.php b/lib/SP/Core/Definitions/CoreDefinitions.php index 102099ca..dc06f18e 100644 --- a/lib/SP/Core/Definitions/CoreDefinitions.php +++ b/lib/SP/Core/Definitions/CoreDefinitions.php @@ -32,11 +32,14 @@ use Monolog\Handler\StreamHandler; use Monolog\Handler\SyslogHandler as MSyslogHandler; use Monolog\Handler\SyslogUdpHandler; use Monolog\Logger; +use phpseclib\Crypt\RSA; use Psr\Container\ContainerInterface; use Psr\Log\LoggerInterface; use SessionHandlerInterface; use SP\Core\Acl\Acl; use SP\Core\Acl\Actions; +use SP\Core\Bootstrap\Path; +use SP\Core\Bootstrap\PathsContext; use SP\Core\Bootstrap\RouteContext; use SP\Core\Bootstrap\UriContext; use SP\Core\Context\Stateless; @@ -114,6 +117,7 @@ use SP\Domain\Notification\Services\MailEvent; use SP\Domain\Notification\Services\NotificationEvent; use SP\Domain\Notification\Services\PhpMailerService; use SP\Domain\Storage\Ports\FileCacheService; +use SP\Domain\Upgrade\Services\UpgradeDatabase; use SP\Infrastructure\Database\Database; use SP\Infrastructure\Database\DatabaseConnectionData; use SP\Infrastructure\Database\MysqlFileParser; @@ -135,15 +139,23 @@ use function DI\autowire; use function DI\create; use function DI\factory; use function DI\get; +use function SP\getFromEnv; /** * Class CoreDefinitions */ final class CoreDefinitions { - public static function getDefinitions(): array + public static function getDefinitions(string $rootPath, string $module): array { return [ + 'paths' => self::getPaths($rootPath), + PathsContext::class => factory(static function (ContainerInterface $container) { + $pathsContext = new PathsContext(); + $pathsContext->addPaths($container->get('paths')); + + return $pathsContext; + }), KleinRequest::class => factory([KleinRequest::class, 'createFromGlobals']), RequestService::class => autowire(Request::class), UriContextInterface::class => autowire(UriContext::class), @@ -152,8 +164,18 @@ final class CoreDefinitions ConfigFileService::class => create(ConfigFile::class) ->constructor( create(XmlFileStorage::class) - ->constructor(create(FileHandler::class)->constructor(CONFIG_FILE)), - create(FileCache::class)->constructor(ConfigFile::CONFIG_CACHE_FILE), + ->constructor( + create(FileHandler::class) + ->constructor( + factory(static fn(PathsContext $p) => $p[Path::CONFIG_FILE]) + ) + ), + create(FileCache::class) + ->constructor( + factory( + static fn(PathsContext $p) => FileSystem::buildPath($p[Path::CACHE], 'config.cache') + ) + ), get(Context::class) ), ConfigDataInterface::class => factory([ConfigFileService::class, 'getConfigData']), @@ -171,32 +193,42 @@ final class CoreDefinitions DatabaseFileInterface::class => create(MysqlFileParser::class) ->constructor( create(FileHandler::class) - ->constructor(FileSystem::buildPath(SQL_PATH, 'dbstructure.sql')) + ->constructor(factory(static fn(PathsContext $pathsContext) => $pathsContext[Path::SQL_FILE])) ), DbStorageHandler::class => autowire(MysqlHandler::class), DatabaseSetupService::class => autowire(MysqlSetup::class), ActionsInterface::class => - static fn() => new Actions( - new FileCache(Actions::ACTIONS_CACHE_FILE), - new YamlFileStorage(new FileHandler(ACTIONS_FILE)) + static fn(PathsContext $pathsContext) => new Actions( + new FileCache(FileSystem::buildPath($pathsContext[Path::CACHE], 'actions.cache')), + new YamlFileStorage(new FileHandler($pathsContext[Path::ACTIONS_FILE])) ), MimeTypesService::class => - static fn() => new MimeTypes( - new FileCache(MimeTypes::MIME_CACHE_FILE), - new XmlFileStorage(new FileHandler(MIMETYPES_FILE)) + static fn(PathsContext $pathsContext) => new MimeTypes( + new FileCache(FileSystem::buildPath($pathsContext[Path::CACHE], 'mime.cache')), + new YamlFileStorage(new FileHandler($pathsContext[Path::MIMETYPES_FILE])) ), AclInterface::class => autowire(Acl::class) ->constructorParameter('actions', get(ActionsInterface::class)), ThemeContextInterface::class => autowire(ThemeContext::class) - ->constructorParameter('basePath', VIEW_PATH) + ->constructorParameter( + 'basePath', + factory(static fn(PathsContext $p) => $p[Path::VIEW]) + ) ->constructorParameter('baseUri', factory([UriContextInterface::class, 'getWebRoot'])) - ->constructorParameter('module', APP_MODULE) + ->constructorParameter('module', $module) ->constructorParameter('name', factory([Theme::class, 'getThemeName'])), ThemeIconsInterface::class => factory([ThemeIcons::class, 'loadIcons']) ->parameter( 'cache', create(FileCache::class) - ->constructor(FileSystem::buildPath(CACHE_PATH, ThemeIcons::ICONS_CACHE_FILE)) + ->constructor( + factory( + static fn(PathsContext $p) => FileSystem::buildPath( + $p[Path::CACHE], + ThemeIcons::ICONS_CACHE_FILE + ) + ) + ) ), ThemeInterface::class => autowire(Theme::class), TemplateInterface::class => autowire(Template::class) @@ -229,9 +261,9 @@ final class CoreDefinitions return $authProvider; } ), - LoggerInterface::class => factory(function (ConfigDataInterface $configData) { + LoggerInterface::class => factory(function (ConfigDataInterface $configData, PathsContext $pathsContext) { $handlers = []; - $handlers[] = new StreamHandler(LOG_FILE); + $handlers[] = new StreamHandler($pathsContext[Path::LOG_FILE]); if ($configData->isInstalled()) { if ($configData->isSyslogRemoteEnabled() @@ -257,7 +289,12 @@ final class CoreDefinitions }), \GuzzleHttp\Client::class => create(\GuzzleHttp\Client::class) ->constructor(factory([Client::class, 'getOptions'])), - LanguageInterface::class => autowire(Language::class), + LanguageInterface::class => autowire(Language::class)->constructorParameter( + 'localesPath', + factory( + static fn(PathsContext $p) => $p[Path::LOCALES] + ) + ), DatabaseInterface::class => autowire(Database::class), PhpMailerService::class => autowire(PhpMailerService::class), MailerInterface::class => factory([PhpMailerService::class, 'configure']) @@ -283,22 +320,30 @@ final class CoreDefinitions QueryFactory::class => create(QueryFactory::class) ->constructor('mysql', QueryFactory::COMMON), CryptInterface::class => create(Crypt::class), - CryptPKIHandler::class => autowire(CryptPKI::class) - ->constructorParameter( - 'publicKeyFile', - create(FileHandler::class)->constructor(CryptPKI::PUBLIC_KEY_FILE, 'w') - ) - ->constructorParameter( - 'privateKeyFile', - create(FileHandler::class)->constructor(CryptPKI::PRIVATE_KEY_FILE, 'w') - ), + CryptPKIHandler::class => factory(static function (PathsContext $pathsContext) { + $publicKeyPath = FileSystem::buildPath( + $pathsContext[Path::CONFIG], + CryptPKI::PUBLIC_KEY_FILE + ); + + $privateKeyPath = FileSystem::buildPath( + $pathsContext[Path::CONFIG], + CryptPKI::PRIVATE_KEY_FILE + ); + + return new CryptPKI( + new RSA(), + new FileHandler($publicKeyPath, 'w'), + new FileHandler($privateKeyPath, 'w') + ); + }), FileCacheService::class => create(FileCache::class), RequestBasedPasswordInterface::class => autowire(RequestBasedPassword::class), PhpExtensionCheckerService::class => create(PhpExtensionChecker::class), - BackupFiles::class => factory(static function () { + BackupFiles::class => factory(static function (PathsContext $pathsContext) { $hash = BackupFiles::buildHash(); - $appBackupFile = new BackupFileDto(BackupType::app, $hash, BACKUP_PATH, 'tar'); - $dbBackupFile = new BackupFileDto(BackupType::db, $hash, BACKUP_PATH, 'sql'); + $appBackupFile = new BackupFileDto(BackupType::app, $hash, $pathsContext[Path::BACKUP], 'tar'); + $dbBackupFile = new BackupFileDto(BackupType::db, $hash, $pathsContext[Path::BACKUP], 'sql'); return new BackupFiles($appBackupFile, $dbBackupFile); }), @@ -321,7 +366,15 @@ final class CoreDefinitions ->constructorParameter( 'dbBackupFile', create(FileHandler::class) - ->constructor(FileSystem::buildPath(BACKUP_PATH, 'database.sql'), 'wb+') + ->constructor( + factory( + static fn(PathsContext $pathsContext) => FileSystem::buildPath( + $pathsContext[Path::BACKUP], + 'database.sql' + ) + ), + 'wb+' + ) ) ->constructorParameter('dbArchiveHandler', get('backup.dbArchiveHandler')) ->constructorParameter('appArchiveHandler', get('backup.appArchiveHandler')), @@ -332,17 +385,78 @@ final class CoreDefinitions ->constructorParameter( 'fileCache', factory( - static function (UuidCookieInterface $uuidCookie, ConfigDataInterface $configData) { + static function ( + UuidCookieInterface $uuidCookie, + ConfigDataInterface $configData, + PathsContext $pathsContext + ) { return new FileCache( - SecureSession::getFileNameFrom($uuidCookie, $configData->getPasswordSalt()) + SecureSession::getFileNameFrom( + $uuidCookie, + $configData->getPasswordSalt(), + $pathsContext[Path::CACHE] + ) ); } )->parameter('uuidCookie', factory([UuidCookie::class, 'factory'])) ), - SessionHandlerInterface::class => autowire(CryptSessionHandler::class) + CryptSessionHandler::class => autowire(CryptSessionHandler::class) ->constructorParameter('key', factory([SecureSessionService::class, 'getKey'])), + SessionHandlerInterface::class => factory( + function (ContainerInterface $c, ConfigDataInterface $configData) { + if ($configData->isEncryptSession()) { + return $c->get(CryptSessionHandler::class); + } + + return null; + } + ), OutputHandlerInterface::class => create(OutputHandler::class), - TemplateResolverInterface::class => autowire(TemplateResolver::class) + TemplateResolverInterface::class => autowire(TemplateResolver::class), + UpgradeDatabase::class => autowire(UpgradeDatabase::class)->constructorParameter( + 'sqlPath', + factory(static fn(PathsContext $p) => $p[Path::SQL]) + ) + ]; + } + + private static function getPaths(string $rootPath): array + { + $appPath = FileSystem::buildPath($rootPath, 'app'); + $sqlPath = FileSystem::buildPath($rootPath, 'schemas'); + $resourcesPath = FileSystem::buildPath($appPath, 'resources'); + $configPath = getFromEnv('CONFIG_PATH', FileSystem::buildPath($appPath, 'config')); + $logFile = getFromEnv('LOG_FILE', FileSystem::buildPath($configPath, 'syspass.log')); + + return [ + [Path::APP, $appPath], + [Path::SQL, $sqlPath], + [Path::PUBLIC, FileSystem::buildPath($rootPath, 'public')], + [Path::XML_SCHEMA, FileSystem::buildPath($sqlPath, 'syspass.xsd')], + [Path::RESOURCES, $resourcesPath], + [Path::MODULES, FileSystem::buildPath($appPath, 'modules')], + [Path::LOCALES, FileSystem::buildPath($appPath, 'locales')], + [Path::BACKUP, FileSystem::buildPath($appPath, 'backup')], + [Path::CACHE, FileSystem::buildPath($appPath, 'cache')], + [Path::TMP, FileSystem::buildPath($appPath, 'temp')], + [Path::CONFIG, $configPath], + [Path::SQL_FILE, FileSystem::buildPath($sqlPath, 'dbstructure.sql')], + [Path::LOG_FILE, $logFile], + [ + Path::CONFIG_FILE, + getFromEnv('CONFIG_FILE', FileSystem::buildPath($configPath, 'config.xml')) + ], + [ + Path::ACTIONS_FILE, + getFromEnv('ACTIONS_FILE', FileSystem::buildPath($resourcesPath, 'actions.yaml')) + ], + [ + Path::MIMETYPES_FILE, + getFromEnv( + 'MIMETYPES_FILE', + FileSystem::buildPath($resourcesPath, 'mimetypes.yaml') + ) + ], ]; } } diff --git a/lib/SP/Core/Definitions/DomainDefinitions.php b/lib/SP/Core/Definitions/DomainDefinitions.php index 26de5b87..ffbd7b8d 100644 --- a/lib/SP/Core/Definitions/DomainDefinitions.php +++ b/lib/SP/Core/Definitions/DomainDefinitions.php @@ -26,7 +26,14 @@ declare(strict_types=1); namespace SP\Core\Definitions; +use SP\Core\Bootstrap\Path; +use SP\Core\Bootstrap\PathsContext; +use SP\Domain\Common\Providers\Image; +use SP\Domain\Image\Ports\ImageService; +use SP\Infrastructure\File\FileSystem; + use function DI\autowire; +use function DI\factory; /** * Class DomainDefinitions @@ -56,17 +63,38 @@ final class DomainDefinitions private const PORTS = [ 'Service' => 'SP\Domain\%s\Services\*', 'Repository' => 'SP\Infrastructure\%s\Repositories\*', - 'Adapter' => 'SP\Domain\%s\Adapters\*' + 'Adapter' => 'SP\Domain\%s\Adapters\*', + 'Builder' => 'SP\Domain\%s\Services\Builders\*' ]; public static function getDefinitions(): array { - $sources = []; + $sources = [ + ImageService::class => autowire(Image::class) + ->constructorParameter( + 'font', + factory( + static fn(PathsContext $p) => FileSystem::buildPath( + $p[Path::PUBLIC], + 'vendor', + 'fonts', + 'NotoSans-Regular-webfont.ttf' + ) + ) + ) + ->constructorParameter( + 'tempPath', + factory(static fn(PathsContext $p) => $p[Path::TMP]) + ) + ]; foreach (self::DOMAINS as $domain) { foreach (self::PORTS as $suffix => $target) { $key = sprintf('SP\Domain\%s\Ports\*%s', $domain, $suffix); - $sources[$key] = autowire(sprintf($target, $domain)); + + if (!array_key_exists($key, $sources)) { + $sources[$key] = autowire(sprintf($target, $domain)); + } } } diff --git a/lib/SP/Core/HttpModuleBase.php b/lib/SP/Core/HttpModuleBase.php index 12a5e465..b846c32f 100644 --- a/lib/SP/Core/HttpModuleBase.php +++ b/lib/SP/Core/HttpModuleBase.php @@ -1,4 +1,5 @@ configData->isMaintenance()) { - BootstrapBase::$LOCK = self::getAppLock(); + BootstrapBase::$LOCK = $this->appLock->getLock(); return !$this->request->isAjax() || !(BootstrapBase::$LOCK !== false @@ -68,21 +67,4 @@ abstract class HttpModuleBase extends ModuleBase return false; } - - /** - * Comprueba si la aplicación está bloqueada - * - * @return bool|string - * @throws SPException - */ - private static function getAppLock(): bool|string - { - try { - $file = new FileHandler(LOCK_FILE); - - return Serde::deserializeJson($file->readToString()); - } catch (FileException) { - return false; - } - } } diff --git a/lib/SP/Core/Language.php b/lib/SP/Core/Language.php index db0b61cf..4de8cfee 100644 --- a/lib/SP/Core/Language.php +++ b/lib/SP/Core/Language.php @@ -1,4 +1,5 @@ context->setLocale($lang); } - self::setLocales($lang); + $this->setLocales($lang); } /** @@ -150,7 +152,7 @@ final class Language implements LanguageInterface /** * Establecer las locales de gettext */ - public static function setLocales(string $lang): void + public function setLocales(string $lang): void { $lang .= '.utf8'; @@ -163,12 +165,12 @@ final class Language implements LanguageInterface if ($locale === false) { logger('Could not set locale to ' . $lang, 'ERROR'); - logger('Domain path: ' . LOCALES_PATH); + logger('Domain path: ' . $this->localesPath); } else { logger('Locale set to: ' . $locale); } - bindtextdomain('messages', LOCALES_PATH); + bindtextdomain('messages', $this->localesPath); textdomain('messages'); bind_textdomain_codeset('messages', 'UTF-8'); } @@ -183,7 +185,7 @@ final class Language implements LanguageInterface } if ($this->configData->getSiteLang() !== $this->context->getLocale()) { - self::setLocales($this->configData->getSiteLang()); + $this->setLocales($this->configData->getSiteLang()); self::$appSet = true; } @@ -195,7 +197,7 @@ final class Language implements LanguageInterface public function unsetAppLocales(): void { if (self::$appSet === true) { - self::setLocales($this->context->getLocale()); + $this->setLocales($this->context->getLocale()); self::$appSet = false; } diff --git a/lib/SP/Core/MimeTypes.php b/lib/SP/Core/MimeTypes.php index b01bdd6a..5ecf9abc 100644 --- a/lib/SP/Core/MimeTypes.php +++ b/lib/SP/Core/MimeTypes.php @@ -42,10 +42,6 @@ use function SP\processException; */ final class MimeTypes implements MimeTypesService { - /** - * Cache file name - */ - public const MIME_CACHE_FILE = CACHE_PATH . DIRECTORY_SEPARATOR . 'mime.cache'; /** * Cache expire time */ diff --git a/lib/SP/Core/ModuleBase.php b/lib/SP/Core/ModuleBase.php index a25c0db9..3012c49f 100644 --- a/lib/SP/Core/ModuleBase.php +++ b/lib/SP/Core/ModuleBase.php @@ -27,7 +27,7 @@ declare(strict_types=1); namespace SP\Core; use SP\Domain\Config\Ports\ConfigDataInterface; -use SP\Domain\Config\Services\ConfigFile; +use SP\Domain\Config\Ports\ConfigFileService; use SP\Domain\Core\Bootstrap\ModuleInterface; use SP\Domain\Core\Context\Context; use SP\Domain\Core\Events\EventDispatcherInterface; @@ -37,7 +37,7 @@ use SP\Domain\Core\Events\EventDispatcherInterface; */ abstract class ModuleBase implements ModuleInterface { - protected ConfigFile $config; + protected ConfigFileService $config; protected ConfigDataInterface $configData; protected Context $context; private EventDispatcherInterface $eventDispatcher; diff --git a/lib/SP/Core/UI/Theme.php b/lib/SP/Core/UI/Theme.php index c0d969dc..568fa285 100644 --- a/lib/SP/Core/UI/Theme.php +++ b/lib/SP/Core/UI/Theme.php @@ -1,4 +1,5 @@ . + */ + +namespace SP\Domain\Account\Ports; + +use SP\Domain\Common\Services\ServiceException; +use SP\Domain\Crypt\Dtos\UpdateMasterPassRequest; + +/** + * Interface AccountMasterPasswordService + */ +interface AccountMasterPasswordService +{ + /** + * Actualiza las claves de todas las cuentas con la nueva clave maestra. + * + * @param UpdateMasterPassRequest $updateMasterPassRequest + * @throws ServiceException + */ + public function updateMasterPassword(UpdateMasterPassRequest $updateMasterPassRequest): void; + + /** + * Actualiza las claves de todas las cuentas con la nueva clave maestra. + * + * @throws ServiceException + */ + public function updateHistoryMasterPassword(UpdateMasterPassRequest $updateMasterPassRequest): void; +} diff --git a/lib/SP/Domain/Account/Services/Account.php b/lib/SP/Domain/Account/Services/Account.php index 7f21bc73..d7be7e0d 100644 --- a/lib/SP/Domain/Account/Services/Account.php +++ b/lib/SP/Domain/Account/Services/Account.php @@ -1,4 +1,5 @@ context->getUserData()->getId(); - return self::ACL_PATH - . $userId - . DIRECTORY_SEPARATOR - . $accountId - . DIRECTORY_SEPARATOR - . md5($userId . $accountId . $actionId) - . '.cache'; + return FileSystem::buildPath( + $this->pathsContext[Path::CACHE], + 'accountAcl', + (string)$userId, + (string)$accountId, + md5($userId . $accountId . $actionId), + '.cache' + ); } /** diff --git a/lib/SP/Domain/Account/Services/AccountCrypt.php b/lib/SP/Domain/Account/Services/AccountCrypt.php index 4efedbb3..112e3977 100644 --- a/lib/SP/Domain/Account/Services/AccountCrypt.php +++ b/lib/SP/Domain/Account/Services/AccountCrypt.php @@ -1,4 +1,5 @@ eventDispatcher->notify( - 'update.masterPassword.accounts.start', - new Event( - $this, - EventMessage::factory() - ->addDescription(__u('Update Master Password')) - ) - ); - - $eventMessage = $this->processAccounts( - $this->accountService->getAccountsPassData(), - function (int $accountId, EncryptedPassword $encryptedPassword) { - $this->accountService->updatePasswordMasterPass($accountId, $encryptedPassword); - }, - $updateMasterPassRequest - ); - - $this->eventDispatcher->notify( - 'update.masterPassword.accounts.end', - new Event($this, $eventMessage) - ); - } catch (Exception $e) { - $this->eventDispatcher->notify('exception', new Event($e)); - - throw new ServiceException( - __u('Error while updating the accounts\' passwords'), - SPException::ERROR, - null, - $e->getCode(), - $e - ); - } - } - - /** - * @param Account[] $accounts - * @param callable $passUpdater - * @param UpdateMasterPassRequest $updateMasterPassRequest - * - * @return EventMessage - */ - private function processAccounts( - array $accounts, - callable $passUpdater, - UpdateMasterPassRequest $updateMasterPassRequest - ): EventMessage { - set_time_limit(0); - - $accountsOk = []; - $errorCount = 0; - $counter = 0; - $startTime = time(); - $numAccounts = count($accounts); - - $eventMessage = EventMessage::factory(); - - if ($numAccounts === 0) { - $eventMessage->addDescription(__u('There are no accounts for processing')); - $eventMessage->addDetail(__u('Accounts updated'), __u('N/A')); - $eventMessage->addDetail(__u('Errors'), 0); - - return $eventMessage; - } - - $configData = $this->config->getConfigData(); - $currentMasterPassHash = $updateMasterPassRequest->getCurrentHash(); - - foreach ($accounts as $account) { - // No realizar cambios si está en modo demo - if ($configData->isDemoEnabled()) { - $accountsOk[] = $account->getId(); - continue; - } - - if ($counter % 100 === 0) { - $eta = self::getETA($startTime, $counter, $numAccounts); - - logger( - sprintf( - __('Updated accounts: %d / %d - %d%% - ETA: %ds (%.2f/s)'), - $counter, - $numAccounts, - round(($counter * 100) / $numAccounts, 2), - $eta[0], - $eta[1] - ) - ); - } - - if (isset($account->mPassHash) && $account->mPassHash !== $currentMasterPassHash) { - $eventMessage->addDescription(__u('The record\'s master password does not match')); - $eventMessage->addDetail($account->getName(), $account->getId()); - continue; - } - - try { - $encryptedPassword = $this->getPasswordEncrypted( - $this->crypt->decrypt( - $account->getPass(), - $account->getKey(), - $updateMasterPassRequest->getCurrentMasterPass() - ), - $updateMasterPassRequest->getNewMasterPass() - ); - - // Call the specific updater - $passUpdater($account->getId(), $encryptedPassword); - - $accountsOk[] = $account->getId(); - $counter++; - } catch (SPException $e) { - $this->eventDispatcher->notify('exception', new Event($e)); - - $errorCount++; - - $eventMessage->addDescription(__u('Error while updating the account\'s password')); - $eventMessage->addDetail($account->getName(), $account->getId()); - } - } - - $eventMessage->addDetail(__u('Accounts updated'), implode(',', $accountsOk)); - $eventMessage->addDetail(__u('Errors'), $errorCount); - - return $eventMessage; - } - - /** - * Devolver el tiempo aproximado en segundos de una operación - * - * @return array Con el tiempo estimado y los elementos por segundo - */ - public static function getETA(int $startTime, int $numItems, int $totalItems): array - { - if ($numItems > 0 && $totalItems > 0) { - $runtime = time() - $startTime; - $eta = (int)((($totalItems * $runtime) / $numItems) - $runtime); - - return [$eta, $numItems / $runtime]; - } - - return [0, 0]; - } - /** * Devolver los datos de la clave encriptados * @@ -239,50 +77,9 @@ final class AccountCrypt extends Service implements AccountCryptService return $encryptedPassword; } catch (CryptException $e) { - throw new ServiceException(__u('Internal error'), SPException::ERROR, null, $e->getCode(), $e); + throw ServiceException::error(__u('Internal error'), null, $e->getCode(), $e); } } - /** - * Actualiza las claves de todas las cuentas con la nueva clave maestra. - * - * @throws ServiceException - */ - public function updateHistoryMasterPassword( - UpdateMasterPassRequest $updateMasterPassRequest - ): void { - try { - $this->eventDispatcher->notify( - 'update.masterPassword.accountsHistory.start', - new Event( - $this, - EventMessage::factory() - ->addDescription(__u('Update Master Password (H)')) - ) - ); - $eventMessage = $this->processAccounts( - $this->accountHistoryService->getAccountsPassData(), - function (int $accountId, EncryptedPassword $encryptedPassword) { - $this->accountHistoryService->updatePasswordMasterPass($accountId, $encryptedPassword); - }, - $updateMasterPassRequest - ); - - $this->eventDispatcher->notify( - 'update.masterPassword.accountsHistory.end', - new Event($this, $eventMessage) - ); - } catch (Exception $e) { - $this->eventDispatcher->notify('exception', new Event($e)); - - throw new ServiceException( - __u('Error while updating the accounts\' passwords in history'), - SPException::ERROR, - null, - $e->getCode(), - $e - ); - } - } } diff --git a/lib/SP/Domain/Account/Services/AccountMasterPassword.php b/lib/SP/Domain/Account/Services/AccountMasterPassword.php new file mode 100644 index 00000000..9352514c --- /dev/null +++ b/lib/SP/Domain/Account/Services/AccountMasterPassword.php @@ -0,0 +1,256 @@ +. + */ + +declare(strict_types=1); + +namespace SP\Domain\Account\Services; + +use Exception; +use SP\Core\Application; +use SP\Core\Events\Event; +use SP\Core\Events\EventMessage; +use SP\Domain\Account\Dtos\EncryptedPassword; +use SP\Domain\Account\Models\Account; +use SP\Domain\Account\Ports\AccountCryptService; +use SP\Domain\Account\Ports\AccountHistoryService; +use SP\Domain\Account\Ports\AccountMasterPasswordService; +use SP\Domain\Account\Ports\AccountService; +use SP\Domain\Common\Services\Service; +use SP\Domain\Common\Services\ServiceException; +use SP\Domain\Core\Crypt\CryptInterface; +use SP\Domain\Core\Exceptions\SPException; +use SP\Domain\Crypt\Dtos\UpdateMasterPassRequest; + +use function SP\__; +use function SP\__u; +use function SP\logger; + +/** + * Class AccountMasterPassword + */ +final class AccountMasterPassword extends Service implements AccountMasterPasswordService +{ + public function __construct( + Application $application, + private readonly AccountService $accountService, + private readonly AccountHistoryService $accountHistoryService, + private readonly CryptInterface $crypt, + private readonly AccountCryptService $accountCryptService + ) { + parent::__construct($application); + } + + /** + * Actualiza las claves de todas las cuentas con la nueva clave maestra. + * + * @param UpdateMasterPassRequest $updateMasterPassRequest + * @throws ServiceException + */ + public function updateMasterPassword(UpdateMasterPassRequest $updateMasterPassRequest): void + { + try { + $this->eventDispatcher->notify( + 'update.masterPassword.accounts.start', + new Event( + $this, + EventMessage::factory() + ->addDescription(__u('Update Master Password')) + ) + ); + + $eventMessage = $this->processAccounts( + $this->accountService->getAccountsPassData(), + function (int $accountId, EncryptedPassword $encryptedPassword) { + $this->accountService->updatePasswordMasterPass($accountId, $encryptedPassword); + }, + $updateMasterPassRequest + ); + + $this->eventDispatcher->notify( + 'update.masterPassword.accounts.end', + new Event($this, $eventMessage) + ); + } catch (Exception $e) { + $this->eventDispatcher->notify('exception', new Event($e)); + + throw ServiceException::error( + __u('Error while updating the accounts\' passwords'), + null, + $e->getCode(), + $e + ); + } + } + + /** + * @param Account[] $accounts + * @param callable $passUpdater + * @param UpdateMasterPassRequest $updateMasterPassRequest + * + * @return EventMessage + */ + private function processAccounts( + array $accounts, + callable $passUpdater, + UpdateMasterPassRequest $updateMasterPassRequest + ): EventMessage { + set_time_limit(0); + + $accountsOk = []; + $errorCount = 0; + $counter = 0; + $startTime = time(); + $numAccounts = count($accounts); + + $eventMessage = EventMessage::factory(); + + if ($numAccounts === 0) { + $eventMessage->addDescription(__u('There are no accounts for processing')); + $eventMessage->addDetail(__u('Accounts updated'), __u('N/A')); + $eventMessage->addDetail(__u('Errors'), 0); + + return $eventMessage; + } + + $configData = $this->config->getConfigData(); + $currentMasterPassHash = $updateMasterPassRequest->getCurrentHash(); + + foreach ($accounts as $account) { + // No realizar cambios si está en modo demo + if ($configData->isDemoEnabled()) { + $accountsOk[] = $account->getId(); + continue; + } + + if ($counter % 100 === 0) { + $eta = self::getETA($startTime, $counter, $numAccounts); + + logger( + sprintf( + __('Updated accounts: %d / %d - %d%% - ETA: %ds (%.2f/s)'), + $counter, + $numAccounts, + round(($counter * 100) / $numAccounts, 2), + $eta[0], + $eta[1] + ) + ); + } + + if (isset($account->mPassHash) && $account->mPassHash !== $currentMasterPassHash) { + $eventMessage->addDescription(__u('The record\'s master password does not match')); + $eventMessage->addDetail($account->getName(), $account->getId()); + continue; + } + + try { + $encryptedPassword = $this->accountCryptService + ->getPasswordEncrypted( + $this->crypt->decrypt( + $account->getPass(), + $account->getKey(), + $updateMasterPassRequest->getCurrentMasterPass() + ), + $updateMasterPassRequest->getNewMasterPass() + ); + + // Call the specific updater + $passUpdater($account->getId(), $encryptedPassword); + + $accountsOk[] = $account->getId(); + $counter++; + } catch (SPException $e) { + $this->eventDispatcher->notify('exception', new Event($e)); + + $errorCount++; + + $eventMessage->addDescription(__u('Error while updating the account\'s password')); + $eventMessage->addDetail($account->getName(), $account->getId()); + } + } + + $eventMessage->addDetail(__u('Accounts updated'), implode(',', $accountsOk)); + $eventMessage->addDetail(__u('Errors'), $errorCount); + + return $eventMessage; + } + + /** + * Devolver el tiempo aproximado en segundos de una operación + * + * @return array Con el tiempo estimado y los elementos por segundo + */ + public static function getETA(int $startTime, int $numItems, int $totalItems): array + { + if ($numItems > 0 && $totalItems > 0) { + $runtime = time() - $startTime; + $eta = (int)((($totalItems * $runtime) / $numItems) - $runtime); + + return [$eta, $numItems / $runtime]; + } + + return [0, 0]; + } + + /** + * Actualiza las claves de todas las cuentas con la nueva clave maestra. + * + * @throws ServiceException + */ + public function updateHistoryMasterPassword(UpdateMasterPassRequest $updateMasterPassRequest): void + { + try { + $this->eventDispatcher->notify( + 'update.masterPassword.accountsHistory.start', + new Event( + $this, + EventMessage::factory() + ->addDescription(__u('Update Master Password (H)')) + ) + ); + + $eventMessage = $this->processAccounts( + $this->accountHistoryService->getAccountsPassData(), + function (int $accountId, EncryptedPassword $encryptedPassword) { + $this->accountHistoryService->updatePasswordMasterPass($accountId, $encryptedPassword); + }, + $updateMasterPassRequest + ); + + $this->eventDispatcher->notify( + 'update.masterPassword.accountsHistory.end', + new Event($this, $eventMessage) + ); + } catch (Exception $e) { + $this->eventDispatcher->notify('exception', new Event($e)); + + throw ServiceException::error( + __u('Error while updating the accounts\' passwords in history'), + null, + $e->getCode(), + $e + ); + } + } +} diff --git a/lib/SP/Domain/Account/Services/AccountPreset.php b/lib/SP/Domain/Account/Services/AccountPreset.php index fad64499..a3fd07fe 100644 --- a/lib/SP/Domain/Account/Services/AccountPreset.php +++ b/lib/SP/Domain/Account/Services/AccountPreset.php @@ -40,7 +40,7 @@ use SP\Domain\ItemPreset\Models\AccountPermission; use SP\Domain\ItemPreset\Models\Password; use SP\Domain\ItemPreset\Ports\ItemPresetInterface; use SP\Domain\ItemPreset\Ports\ItemPresetService; -use SP\Mvc\Controller\Validators\ValidatorInterface; +use SP\Mvc\Controller\Validators\PasswordValidator; /** * Class AccountPreset @@ -53,7 +53,7 @@ final class AccountPreset extends Service implements AccountPresetService private readonly AccountToUserGroupRepository $accountToUserGroupRepository, private readonly AccountToUserRepository $accountToUserRepository, private readonly ConfigDataInterface $configData, - private readonly ValidatorInterface $validator + private readonly PasswordValidator $passwordValidator ) { parent::__construct($application); } @@ -72,7 +72,7 @@ final class AccountPreset extends Service implements AccountPresetService if ($itemPreset !== null && $itemPreset->getFixed() === 1) { $passwordPreset = $itemPreset->hydrate(Password::class); - $this->validator->validate($passwordPreset, $accountDto->getPass()); + $this->passwordValidator->validate($passwordPreset, $accountDto->getPass()); if ($this->configData->isAccountExpireEnabled()) { $expireTimePreset = $passwordPreset->getExpireTime(); diff --git a/lib/SP/Domain/Account/Services/Builders/AccountFilter.php b/lib/SP/Domain/Account/Services/Builders/AccountFilter.php index f7bf6cbc..960a7608 100644 --- a/lib/SP/Domain/Account/Services/Builders/AccountFilter.php +++ b/lib/SP/Domain/Account/Services/Builders/AccountFilter.php @@ -37,15 +37,15 @@ use SP\Domain\User\Dtos\UserDataDto; use SP\Domain\User\Models\ProfileData; /** - * Class AccountFilterUser + * Class AccountFilter */ -final class AccountFilter implements AccountFilterBuilder +final readonly class AccountFilter implements AccountFilterBuilder { public function __construct( - private readonly Context $context, - private readonly ConfigDataInterface $configData, - private readonly QueryFactory $queryFactory + private Context $context, + private ConfigDataInterface $configData, + private QueryFactory $queryFactory ) { } diff --git a/lib/SP/Domain/Auth/Providers/AclHandler.php b/lib/SP/Domain/Auth/Providers/AclHandler.php index 142d9f48..db622d25 100644 --- a/lib/SP/Domain/Auth/Providers/AclHandler.php +++ b/lib/SP/Domain/Auth/Providers/AclHandler.php @@ -1,4 +1,5 @@ pathsContext[Path::CACHE], 'accountAcl', (string)$userId); + + if (FileSystem::rmdirRecursive($path) === false) { + logger(sprintf('Unable to delete %s directory', $path)); return false; } diff --git a/lib/SP/Domain/Common/Adapters/Serde.php b/lib/SP/Domain/Common/Adapters/Serde.php index 1307b993..e7cf3cff 100644 --- a/lib/SP/Domain/Common/Adapters/Serde.php +++ b/lib/SP/Domain/Common/Adapters/Serde.php @@ -1,4 +1,5 @@ |null $class - * @return T&object + * @return T&object|array * * @throws SPException */ - public static function deserialize(string $data, ?string $class = null): object + public static function deserialize(string $data, ?string $class = null): object|array { $value = unserialize($data); diff --git a/lib/SP/Domain/Common/Providers/Image.php b/lib/SP/Domain/Common/Providers/Image.php index d9bf48cc..8b99a743 100644 --- a/lib/SP/Domain/Common/Providers/Image.php +++ b/lib/SP/Domain/Common/Providers/Image.php @@ -42,11 +42,13 @@ use function SP\processException; final class Image implements ImageService { private const IMAGE_WIDTH = 48; - private const IMAGE_FONT = PUBLIC_PATH . '/vendor/fonts/NotoSans-Regular-webfont.ttf'; private const TMP_PREFFIX = 'syspass'; - public function __construct(PhpExtensionCheckerService $checker, private readonly string $font = self::IMAGE_FONT) - { + public function __construct( + PhpExtensionCheckerService $checker, + private readonly string $font, + private readonly string $tempPath + ) { $checker->checkCurl(true); } @@ -82,7 +84,7 @@ final class Image implements ImageService */ private function createPngImage(GdImage $gdImage): string { - if (($tmpFile = tempnam(TMP_PATH, self::TMP_PREFFIX)) !== false + if (($tmpFile = tempnam($this->tempPath, self::TMP_PREFFIX)) !== false && imagepng($gdImage, $tmpFile) ) { $file = new FileHandler($tmpFile); diff --git a/lib/SP/Domain/Config/Services/ConfigFile.php b/lib/SP/Domain/Config/Services/ConfigFile.php index baeadc75..68c18f25 100644 --- a/lib/SP/Domain/Config/Services/ConfigFile.php +++ b/lib/SP/Domain/Config/Services/ConfigFile.php @@ -51,11 +51,6 @@ use function SP\processException; */ class ConfigFile implements ConfigFileService { - /** - * Cache file name - */ - public const CONFIG_CACHE_FILE = CACHE_PATH . DIRECTORY_SEPARATOR . 'config.cache'; - /** * @throws ConfigException */ diff --git a/lib/SP/Domain/Config/Services/ConfigUtil.php b/lib/SP/Domain/Config/Services/ConfigUtil.php index ac58020e..b417eac8 100644 --- a/lib/SP/Domain/Config/Services/ConfigUtil.php +++ b/lib/SP/Domain/Config/Services/ConfigUtil.php @@ -1,4 +1,5 @@ repository->transactionAware( function () use ($request) { - $this->accountCryptService->updateMasterPassword($request); - $this->accountCryptService->updateHistoryMasterPassword($request); + $this->accountMasterPasswordService->updateMasterPassword($request); + $this->accountMasterPasswordService->updateHistoryMasterPassword($request); $this->customFieldCryptService->updateMasterPassword($request); }, $this diff --git a/lib/SP/Domain/Crypt/Services/SecureSession.php b/lib/SP/Domain/Crypt/Services/SecureSession.php index b115e494..45d3e766 100644 --- a/lib/SP/Domain/Crypt/Services/SecureSession.php +++ b/lib/SP/Domain/Crypt/Services/SecureSession.php @@ -38,6 +38,7 @@ use SP\Domain\Core\Crypt\UuidCookieInterface; use SP\Domain\Crypt\Ports\SecureSessionService; use SP\Domain\Storage\Ports\FileCacheService; use SP\Infrastructure\File\FileException; +use SP\Infrastructure\File\FileSystem; use function SP\logger; use function SP\processException; @@ -48,7 +49,6 @@ use function SP\processException; final class SecureSession extends Service implements SecureSessionService { private const CACHE_EXPIRE_TIME = 86400; - private const CACHE_PATH = CACHE_PATH . DIRECTORY_SEPARATOR . 'secure_session'; public function __construct( Application $application, @@ -64,7 +64,7 @@ final class SecureSession extends Service implements SecureSessionService * * @throws ServiceException */ - public static function getFileNameFrom(UuidCookieInterface $cookie, string $seed): string + public static function getFileNameFrom(UuidCookieInterface $cookie, string $seed, string $cachePath): string { if (($uuid = $cookie->load($seed)) === false && ($uuid = $cookie->create($seed)) === false @@ -72,7 +72,7 @@ final class SecureSession extends Service implements SecureSessionService throw new ServiceException('Unable to get UUID for filename'); } - return self::CACHE_PATH . DIRECTORY_SEPARATOR . $uuid; + return FileSystem::buildPath($cachePath, 'secure_session', $uuid); } /** diff --git a/lib/SP/Domain/Export/Ports/BackupFileService.php b/lib/SP/Domain/Export/Ports/BackupFileService.php index 2f56d2c8..997fbfa6 100644 --- a/lib/SP/Domain/Export/Ports/BackupFileService.php +++ b/lib/SP/Domain/Export/Ports/BackupFileService.php @@ -38,5 +38,5 @@ interface BackupFileService * * @throws ServiceException */ - public function doBackup(string $backupPath = BACKUP_PATH, string $applicationPath = APP_ROOT): void; + public function doBackup(string $backupPath, string $applicationPath): void; } diff --git a/lib/SP/Domain/Export/Services/BackupFile.php b/lib/SP/Domain/Export/Services/BackupFile.php index ae1ed5a2..4d0c9e20 100644 --- a/lib/SP/Domain/Export/Services/BackupFile.php +++ b/lib/SP/Domain/Export/Services/BackupFile.php @@ -75,7 +75,7 @@ final class BackupFile extends Service implements BackupFileService * * @throws ServiceException */ - public function doBackup(string $backupPath = BACKUP_PATH, string $applicationPath = APP_ROOT): void + public function doBackup(string $backupPath, string $applicationPath): void { set_time_limit(0); diff --git a/lib/SP/Domain/Export/Services/XmlVerify.php b/lib/SP/Domain/Export/Services/XmlVerify.php index f8ec8637..ad05fd7b 100644 --- a/lib/SP/Domain/Export/Services/XmlVerify.php +++ b/lib/SP/Domain/Export/Services/XmlVerify.php @@ -1,4 +1,5 @@ installData->getDbAdminPass()) - ) { + if (empty($this->installData->getDbAdminPass())) { throw new InvalidArgumentException( __u('Please, enter the database password'), SPException::ERROR, diff --git a/lib/SP/Domain/Upgrade/Services/UpgradeDatabase.php b/lib/SP/Domain/Upgrade/Services/UpgradeDatabase.php index 1fa6b87b..98d311c4 100644 --- a/lib/SP/Domain/Upgrade/Services/UpgradeDatabase.php +++ b/lib/SP/Domain/Upgrade/Services/UpgradeDatabase.php @@ -53,6 +53,7 @@ final class UpgradeDatabase extends Service implements UpgradeHandlerService public function __construct( Application $application, private readonly DatabaseInterface $database, + private readonly string $sqlPath ) { parent::__construct($application); } @@ -117,7 +118,7 @@ final class UpgradeDatabase extends Service implements UpgradeHandlerService */ private function getQueriesFromFile(string $version): iterable { - $filename = FileSystem::buildPath(SQL_PATH, str_replace('.', '', $version) . '.sql'); + $filename = FileSystem::buildPath($this->sqlPath, str_replace('.', '', $version) . '.sql'); try { return (new MysqlFileParser(new FileHandler($filename)))->parse('$$'); diff --git a/lib/SP/Domain/User/Dtos/UserDataDto.php b/lib/SP/Domain/User/Dtos/UserDataDto.php index f73128b6..b2ab3ee2 100644 --- a/lib/SP/Domain/User/Dtos/UserDataDto.php +++ b/lib/SP/Domain/User/Dtos/UserDataDto.php @@ -1,4 +1,5 @@ preferences = $this->user?->hydrate(UserPreferences::class); diff --git a/lib/SP/Html/DataGrid/Action/DataGridActionBase.php b/lib/SP/Html/DataGrid/Action/DataGridActionBase.php index ca49fefb..f350e867 100644 --- a/lib/SP/Html/DataGrid/Action/DataGridActionBase.php +++ b/lib/SP/Html/DataGrid/Action/DataGridActionBase.php @@ -147,7 +147,7 @@ abstract class DataGridActionBase implements DataGridActionInterface public function getId(): string { - return $this->id; + return (string)$this->id; } public function setId(int $id): DataGridActionBase diff --git a/lib/SP/Html/DataGrid/DataGridBase.php b/lib/SP/Html/DataGrid/DataGridBase.php index 2af54f33..901c8aff 100644 --- a/lib/SP/Html/DataGrid/DataGridBase.php +++ b/lib/SP/Html/DataGrid/DataGridBase.php @@ -329,7 +329,7 @@ abstract class DataGridBase implements DataGridInterface public function setTime(int|float $time): DataGridInterface { - $this->time = $time; + $this->time = (int)$time; return $this; } diff --git a/lib/SP/Html/DataGrid/Layout/DataGridHeaderBase.php b/lib/SP/Html/DataGrid/Layout/DataGridHeaderBase.php index a225e3b5..89c83ed6 100644 --- a/lib/SP/Html/DataGrid/Layout/DataGridHeaderBase.php +++ b/lib/SP/Html/DataGrid/Layout/DataGridHeaderBase.php @@ -1,4 +1,5 @@ headers[] = $header; $numHeaders = count($this->headers); - $this->width = ($numHeaders > 0) ? floor(65 / $numHeaders) : 65; + $this->width = $numHeaders > 0 ? (int)floor(65 / $numHeaders) : 65; } public function getWidth(): int diff --git a/lib/SP/Html/DataGrid/Layout/DataGridPagerBase.php b/lib/SP/Html/DataGrid/Layout/DataGridPagerBase.php index 7cfc60b2..2ea5126d 100644 --- a/lib/SP/Html/DataGrid/Layout/DataGridPagerBase.php +++ b/lib/SP/Html/DataGrid/Layout/DataGridPagerBase.php @@ -1,4 +1,5 @@ limitStart + 1) / $this->limitCount); + return $this->limitCount > 0 ? (int)ceil(($this->limitStart + 1) / $this->limitCount) : 1; } /** @@ -174,7 +175,7 @@ abstract class DataGridPagerBase implements DataGridPagerInterface */ public function getLastPage(): int { - return ceil($this->totalRows / $this->limitCount); + return $this->limitCount > 0 ? (int)ceil($this->totalRows / $this->limitCount) : 1; } /** diff --git a/lib/SP/Infrastructure/File/FileSystem.php b/lib/SP/Infrastructure/File/FileSystem.php index cae7ff7b..fde0bb25 100644 --- a/lib/SP/Infrastructure/File/FileSystem.php +++ b/lib/SP/Infrastructure/File/FileSystem.php @@ -108,49 +108,6 @@ class FileSystem throw FileException::error(sprintf(__('File not found: %s'), $file)); } - /** - * Comprueba y devuelve un directorio temporal válido - * - * @return false|string - */ - public static function getTempDir(): false|string - { - $sysTmp = sys_get_temp_dir(); - - $checkDir = static function ($dir) { - $path = self::buildPath($dir, 'syspass.test'); - - if (file_exists($path)) { - return $dir; - } - - if (is_dir($dir) || mkdir($dir) || is_dir($dir)) { - if (touch($path)) { - return $dir; - } - } - - return false; - }; - - if ($checkDir(TMP_PATH)) { - return TMP_PATH; - } - - return $checkDir($sysTmp); - } - - /** - * Return a well-formed path - * - * @param string ...$parts - * @return string - */ - public static function buildPath(string ...$parts): string - { - return implode(DIRECTORY_SEPARATOR, $parts); - } - /** * Delete files using {@link glob()} patterns * @@ -165,4 +122,15 @@ class FileSystem array_merge(...array_map(static fn(string $pattern) => glob(self::buildPath($path, $pattern)), $patterns)) ); } + + /** + * Return a well-formed path + * + * @param string ...$parts + * @return string + */ + public static function buildPath(string ...$parts): string + { + return implode(DIRECTORY_SEPARATOR, $parts); + } } diff --git a/lib/SP/Mvc/Controller/Validators/PasswordValidator.php b/lib/SP/Mvc/Controller/Validators/PasswordValidator.php index 891cc9a8..b3fc31a0 100644 --- a/lib/SP/Mvc/Controller/Validators/PasswordValidator.php +++ b/lib/SP/Mvc/Controller/Validators/PasswordValidator.php @@ -1,4 +1,5 @@ new Action($a['id'], $a['name'], $a['text'], $a['route']), - $actions + $actions['actions'] ); $this->fileCache @@ -143,7 +143,7 @@ class ActionsTest extends UnitaryTestCase $actionsId ); - return array_combine($actionsId, $actions); + return ['actions' => array_combine($actionsId, $actions)]; } /** @@ -159,7 +159,7 @@ class ActionsTest extends UnitaryTestCase ->with(Actions::CACHE_EXPIRE) ->willReturn(false); - $actions = $this->getActions(); + $actions = $this->getActions()['actions']; $actionsMapped = array_map( static fn(array $a) => new Action($a['id'], $a['name'], $a['text'], $a['route']), @@ -208,7 +208,7 @@ class ActionsTest extends UnitaryTestCase * @throws FileException * @throws Exception */ - public function testResetWithXmlFileException() + public function testResetWithFileException() { $this->fileCache ->expects(self::once()) @@ -252,7 +252,7 @@ class ActionsTest extends UnitaryTestCase $actionsMapped = array_map( static fn(array $a) => new Action($a['id'], $a['name'], $a['text'], $a['route']), - $actions + $actions['actions'] ); $this->fileCache @@ -272,7 +272,7 @@ class ActionsTest extends UnitaryTestCase { $actionsMapped = array_map( static fn(array $a) => new Action($a['id'], $a['name'], $a['text'], $a['route']), - $this->getActions() + $this->getActions()['actions'] ); $this->fileCache diff --git a/tests/SP/Core/Definitions/DefinitionsTest.php b/tests/SP/Core/Definitions/DefinitionsTest.php index 431b188a..3bf83c38 100644 --- a/tests/SP/Core/Definitions/DefinitionsTest.php +++ b/tests/SP/Core/Definitions/DefinitionsTest.php @@ -98,10 +98,10 @@ class DefinitionsTest extends TestCase ConfigDataInterface::class => $configData, LdapConnectionInterface::class => $this->createStub(LdapConnectionInterface::class), 'backup.dbArchiveHandler' => $this->createStub(ArchiveHandler::class), - 'backup.appArchiveHandler' => $this->createStub(ArchiveHandler::class), + 'backup.appArchiveHandler' => $this->createStub(ArchiveHandler::class) ]; - $definitions = CoreDefinitions::getDefinitions(); + $definitions = CoreDefinitions::getDefinitions(TEST_ROOT, 'test'); $containerBuilder = new ContainerBuilder(); $containerBuilder->addDefinitions(DomainDefinitions::getDefinitions(), $definitions, $mockedDefinitions); diff --git a/tests/SP/Core/LanguageTest.php b/tests/SP/Core/LanguageTest.php index dd83599b..e2d206f0 100644 --- a/tests/SP/Core/LanguageTest.php +++ b/tests/SP/Core/LanguageTest.php @@ -1,4 +1,5 @@ language->setLocales($locale); $this->assertEquals($locale . '.utf8', Language::$localeStatus); $this->assertEquals($locale . '.utf8', getenv('LANG')); @@ -189,6 +190,6 @@ class LanguageTest extends UnitaryTestCase $this->configData = $this->createMock(ConfigDataInterface::class); $this->request = $this->createMock(RequestService::class); - $this->language = new Language($this->context, $this->configData, $this->request); + $this->language = new Language($this->context, $this->configData, $this->request, RESOURCE_PATH); } } diff --git a/tests/SP/Domain/Account/Services/AccountAclTest.php b/tests/SP/Domain/Account/Services/AccountAclTest.php index 3221f524..939bb469 100644 --- a/tests/SP/Domain/Account/Services/AccountAclTest.php +++ b/tests/SP/Domain/Account/Services/AccountAclTest.php @@ -220,7 +220,8 @@ class AccountAclTest extends UnitaryTestCase $accountAcl = new AccountAcl( $this->application, $this->acl, - $this->userToUserGroupService + $this->userToUserGroupService, + $this->pathsContext ); foreach (self::ACTIONS as $action) { @@ -706,6 +707,7 @@ class AccountAclTest extends UnitaryTestCase $this->application, new Acl($this->context, $this->application->getEventDispatcher(), $actions), $userToUserGroupService, + $this->pathsContext, $fileCache ); @@ -745,6 +747,7 @@ class AccountAclTest extends UnitaryTestCase $this->application, new Acl($this->context, $this->application->getEventDispatcher(), $actions), $userToUserGroupService, + $this->pathsContext, $fileCache ); @@ -792,6 +795,7 @@ class AccountAclTest extends UnitaryTestCase $this->application, new Acl($this->context, $this->application->getEventDispatcher(), $actions), $userToUserGroupService, + $this->pathsContext, $fileCache ); @@ -828,6 +832,7 @@ class AccountAclTest extends UnitaryTestCase $this->application, new Acl($this->context, $this->application->getEventDispatcher(), $actions), $userToUserGroupService, + $this->pathsContext, $fileCache ); diff --git a/tests/SP/Domain/Account/Services/AccountCryptTest.php b/tests/SP/Domain/Account/Services/AccountCryptTest.php index 1b71f8e5..553daad6 100644 --- a/tests/SP/Domain/Account/Services/AccountCryptTest.php +++ b/tests/SP/Domain/Account/Services/AccountCryptTest.php @@ -1,4 +1,5 @@ password, - self::$faker->password, - self::$faker->sha1 - ); - $accountData = array_map(static fn() => AccountDataGenerator::factory()->buildAccount(), range(0, 9)); - - $this->account->expects(self::once()) - ->method('getAccountsPassData') - ->willReturn($accountData); - $this->account->expects(self::exactly(10)) - ->method('updatePasswordMasterPass'); - $this->crypt->expects(self::exactly(10)) - ->method('decrypt'); - $this->crypt->expects(self::exactly(10)) - ->method('makeSecuredKey') - ->willReturn(self::$faker->password); - $this->crypt->expects(self::exactly(10)) - ->method('encrypt') - ->willReturn(self::$faker->password); - - $this->accountCrypt->updateMasterPassword($request); - } - - /** - * @throws ServiceException - */ - public function testUpdateMasterPasswordWithNoAccounts(): void - { - $request = - new UpdateMasterPassRequest( - self::$faker->password, - self::$faker->password, - self::$faker->sha1 - ); - - $this->account->expects(self::once()) - ->method('getAccountsPassData') - ->willReturn([]); - $this->account->expects(self::never()) - ->method('updatePasswordMasterPass'); - $this->crypt->expects(self::never()) - ->method('decrypt'); - $this->crypt->expects(self::never()) - ->method('makeSecuredKey'); - $this->crypt->expects(self::never()) - ->method('encrypt'); - - $this->accountCrypt->updateMasterPassword($request); - } - - /** - * @throws ServiceException - */ - public function testUpdateMasterPasswordDoesNotThrowException(): void - { - $request = new UpdateMasterPassRequest(self::$faker->password, self::$faker->password, self::$faker->sha1); - $accountData = array_map(static fn() => AccountDataGenerator::factory()->buildAccount(), range(0, 9)); - - $this->account->expects(self::once()) - ->method('getAccountsPassData') - ->willReturn($accountData); - $this->crypt->expects(self::exactly(10)) - ->method('decrypt') - ->willThrowException(new SPException('test')); - - $this->accountCrypt->updateMasterPassword($request); - } - - /** - * @throws ServiceException - */ - public function testUpdateMasterPasswordThrowException(): void - { - $request = new UpdateMasterPassRequest(self::$faker->password, self::$faker->password, self::$faker->sha1); - - $this->account->expects(self::once()) - ->method('getAccountsPassData') - ->willThrowException(new RuntimeException('test')); - - $this->expectException(ServiceException::class); - $this->expectExceptionMessage('Error while updating the accounts\' passwords'); - - $this->accountCrypt->updateMasterPassword($request); - } - - /** - * @throws Exception - * @throws ServiceException - */ - public function testUpdateHistoryMasterPassword(): void - { - $request = new UpdateMasterPassRequest( - self::$faker->password, - self::$faker->password, - self::$faker->sha1 - ); - $accountData = array_map(static fn() => AccountDataGenerator::factory()->buildAccount(), range(0, 9)); - - $this->accountHistory->expects(self::once()) - ->method('getAccountsPassData') - ->willReturn($accountData); - $this->accountHistory->expects(self::exactly(10)) - ->method('updatePasswordMasterPass'); - $this->crypt->expects(self::exactly(10)) - ->method('decrypt'); - - $this->accountCrypt->updateHistoryMasterPassword($request); - } - - /** - * @throws ServiceException - */ - public function testUpdateHistoryMasterPasswordWithNoAccounts(): void - { - $request = - new UpdateMasterPassRequest( - self::$faker->password, - self::$faker->password, - self::$faker->sha1 - ); - - $this->accountHistory->expects(self::once()) - ->method('getAccountsPassData') - ->willReturn([]); - $this->accountHistory->expects(self::never()) - ->method('updatePasswordMasterPass'); - $this->crypt->expects(self::never()) - ->method('decrypt'); - $this->crypt->expects(self::never()) - ->method('makeSecuredKey'); - $this->crypt->expects(self::never()) - ->method('encrypt'); - - $this->accountCrypt->updateHistoryMasterPassword($request); - } - - /** - * @throws ServiceException - */ - public function testUpdateHistoryMasterPasswordThrowException(): void - { - $request = new UpdateMasterPassRequest(self::$faker->password, self::$faker->password, self::$faker->sha1); - - $this->accountHistory->expects(self::once()) - ->method('getAccountsPassData') - ->willThrowException(new RuntimeException('test')); - - $this->expectException(ServiceException::class); - $this->expectExceptionMessage('Error while updating the accounts\' passwords in history'); - - $this->accountCrypt->updateHistoryMasterPassword($request); - } - - /** - * @throws ServiceException - */ - public function testUpdateHistoryMasterPasswordDoesNotThrowException(): void - { - $request = new UpdateMasterPassRequest(self::$faker->password, self::$faker->password, self::$faker->sha1); - $accountData = array_map(static fn() => AccountDataGenerator::factory()->buildAccount(), range(0, 9)); - - $this->accountHistory->expects(self::once()) - ->method('getAccountsPassData') - ->willReturn($accountData); - $this->crypt->expects(self::exactly(10)) - ->method('decrypt') - ->willThrowException(new SPException('test')); - - $this->accountCrypt->updateHistoryMasterPassword($request); - } + private AccountCrypt $accountCrypt; + private MockObject|CryptInterface $crypt; /** * @throws ServiceException @@ -337,16 +148,8 @@ class AccountCryptTest extends UnitaryTestCase { parent::setUp(); - $this->account = $this->createMock(AccountService::class); - $this->accountHistory = $this->createMock(AccountHistoryService::class); $this->crypt = $this->createMock(CryptInterface::class); - $this->accountCrypt = - new AccountCrypt( - $this->application, - $this->account, - $this->accountHistory, - $this->crypt - ); + $this->accountCrypt = new AccountCrypt($this->application, $this->crypt); } } diff --git a/tests/SP/Domain/Account/Services/AccountFileTest.php b/tests/SP/Domain/Account/Services/AccountFileTest.php index fca37516..20e1b0a8 100644 --- a/tests/SP/Domain/Account/Services/AccountFileTest.php +++ b/tests/SP/Domain/Account/Services/AccountFileTest.php @@ -1,4 +1,5 @@ buildFileData()) - ->mutate( - ['type' => self::$faker->mimeType()] - ); + ->mutate(['type' => self::$faker->mimeType()]); $this->imageUtil ->expects(self::never()) diff --git a/tests/SP/Domain/Account/Services/AccountMasterPasswordTest.php b/tests/SP/Domain/Account/Services/AccountMasterPasswordTest.php new file mode 100644 index 00000000..d496df30 --- /dev/null +++ b/tests/SP/Domain/Account/Services/AccountMasterPasswordTest.php @@ -0,0 +1,250 @@ +. + */ + +declare(strict_types=1); + +namespace SP\Tests\Domain\Account\Services; + +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\MockObject\Exception; +use PHPUnit\Framework\MockObject\MockObject; +use RuntimeException; +use SP\Domain\Account\Dtos\EncryptedPassword; +use SP\Domain\Account\Ports\AccountCryptService; +use SP\Domain\Account\Ports\AccountHistoryService; +use SP\Domain\Account\Ports\AccountService; +use SP\Domain\Account\Services\AccountMasterPassword; +use SP\Domain\Common\Services\ServiceException; +use SP\Domain\Core\Crypt\CryptInterface; +use SP\Domain\Core\Exceptions\SPException; +use SP\Domain\Crypt\Dtos\UpdateMasterPassRequest; +use SP\Tests\Generators\AccountDataGenerator; +use SP\Tests\UnitaryTestCase; + +/** + * Class AccountMasterPasswordTest + */ +#[Group('unitary')] +class AccountMasterPasswordTest extends UnitaryTestCase +{ + private MockObject|AccountService $account; + private MockObject|AccountHistoryService $accountHistory; + private AccountMasterPassword $accountMasterPassword; + private MockObject|CryptInterface $crypt; + private MockObject|AccountCryptService $accountCrypt; + + /** + * @throws ServiceException + */ + public function testUpdateMasterPassword(): void + { + $request = + new UpdateMasterPassRequest( + self::$faker->password, + self::$faker->password, + self::$faker->sha1 + ); + $accountData = array_map(static fn() => AccountDataGenerator::factory()->buildAccount(), range(0, 9)); + + $this->account->expects(self::once()) + ->method('getAccountsPassData') + ->willReturn($accountData); + $this->accountCrypt->expects(self::exactly(10)) + ->method('getPasswordEncrypted') + ->willReturn(new EncryptedPassword('a_password', 'a_key')); + $this->account->expects(self::exactly(10)) + ->method('updatePasswordMasterPass') + ->with(self::anything(), new EncryptedPassword('a_password', 'a_key')); + + $this->accountMasterPassword->updateMasterPassword($request); + } + + /** + * @throws ServiceException + */ + public function testUpdateMasterPasswordWithNoAccounts(): void + { + $request = + new UpdateMasterPassRequest( + self::$faker->password, + self::$faker->password, + self::$faker->sha1 + ); + + $this->account->expects(self::once()) + ->method('getAccountsPassData') + ->willReturn([]); + $this->account->expects(self::never()) + ->method('updatePasswordMasterPass'); + $this->crypt->expects(self::never()) + ->method('decrypt'); + $this->crypt->expects(self::never()) + ->method('makeSecuredKey'); + $this->crypt->expects(self::never()) + ->method('encrypt'); + + $this->accountMasterPassword->updateMasterPassword($request); + } + + /** + * @throws ServiceException + */ + public function testUpdateMasterPasswordDoesNotThrowException(): void + { + $request = new UpdateMasterPassRequest(self::$faker->password, self::$faker->password, self::$faker->sha1); + $accountData = array_map(static fn() => AccountDataGenerator::factory()->buildAccount(), range(0, 9)); + + $this->account->expects(self::once()) + ->method('getAccountsPassData') + ->willReturn($accountData); + $this->crypt->expects(self::exactly(10)) + ->method('decrypt') + ->willThrowException(new SPException('test')); + + $this->accountMasterPassword->updateMasterPassword($request); + } + + /** + * @throws ServiceException + */ + public function testUpdateMasterPasswordThrowException(): void + { + $request = new UpdateMasterPassRequest(self::$faker->password, self::$faker->password, self::$faker->sha1); + + $this->account->expects(self::once()) + ->method('getAccountsPassData') + ->willThrowException(new RuntimeException('test')); + + $this->expectException(ServiceException::class); + $this->expectExceptionMessage('Error while updating the accounts\' passwords'); + + $this->accountMasterPassword->updateMasterPassword($request); + } + + /** + * @throws Exception + * @throws ServiceException + */ + public function testUpdateHistoryMasterPassword(): void + { + $request = new UpdateMasterPassRequest( + self::$faker->password, + self::$faker->password, + self::$faker->sha1 + ); + $accountData = array_map(static fn() => AccountDataGenerator::factory()->buildAccount(), range(0, 9)); + + $this->accountHistory->expects(self::once()) + ->method('getAccountsPassData') + ->willReturn($accountData); + $this->accountHistory->expects(self::exactly(10)) + ->method('updatePasswordMasterPass'); + $this->accountCrypt->expects(self::exactly(10)) + ->method('getPasswordEncrypted') + ->willReturn(new EncryptedPassword('a_password', 'a_key')); + + $this->accountMasterPassword->updateHistoryMasterPassword($request); + } + + /** + * @throws ServiceException + */ + public function testUpdateHistoryMasterPasswordWithNoAccounts(): void + { + $request = + new UpdateMasterPassRequest( + self::$faker->password, + self::$faker->password, + self::$faker->sha1 + ); + + $this->accountHistory->expects(self::once()) + ->method('getAccountsPassData') + ->willReturn([]); + $this->accountHistory->expects(self::never()) + ->method('updatePasswordMasterPass'); + $this->crypt->expects(self::never()) + ->method('decrypt'); + $this->crypt->expects(self::never()) + ->method('makeSecuredKey'); + $this->crypt->expects(self::never()) + ->method('encrypt'); + + $this->accountMasterPassword->updateHistoryMasterPassword($request); + } + + /** + * @throws ServiceException + */ + public function testUpdateHistoryMasterPasswordThrowException(): void + { + $request = new UpdateMasterPassRequest(self::$faker->password, self::$faker->password, self::$faker->sha1); + + $this->accountHistory->expects(self::once()) + ->method('getAccountsPassData') + ->willThrowException(new RuntimeException('test')); + + $this->expectException(ServiceException::class); + $this->expectExceptionMessage('Error while updating the accounts\' passwords in history'); + + $this->accountMasterPassword->updateHistoryMasterPassword($request); + } + + /** + * @throws ServiceException + */ + public function testUpdateHistoryMasterPasswordDoesNotThrowException(): void + { + $request = new UpdateMasterPassRequest(self::$faker->password, self::$faker->password, self::$faker->sha1); + $accountData = array_map(static fn() => AccountDataGenerator::factory()->buildAccount(), range(0, 9)); + + $this->accountHistory->expects(self::once()) + ->method('getAccountsPassData') + ->willReturn($accountData); + $this->crypt->expects(self::exactly(10)) + ->method('decrypt') + ->willThrowException(new SPException('test')); + + $this->accountMasterPassword->updateHistoryMasterPassword($request); + } + + protected function setUp(): void + { + parent::setUp(); + + $this->account = $this->createMock(AccountService::class); + $this->accountHistory = $this->createMock(AccountHistoryService::class); + $this->crypt = $this->createMock(CryptInterface::class); + $this->accountCrypt = $this->createMock(AccountCryptService::class); + + $this->accountMasterPassword = + new AccountMasterPassword( + $this->application, + $this->account, + $this->accountHistory, + $this->crypt, + $this->accountCrypt + ); + } +} diff --git a/tests/SP/Domain/Account/Services/AccountPresetTest.php b/tests/SP/Domain/Account/Services/AccountPresetTest.php index bd718d0e..8e647ff4 100644 --- a/tests/SP/Domain/Account/Services/AccountPresetTest.php +++ b/tests/SP/Domain/Account/Services/AccountPresetTest.php @@ -40,6 +40,7 @@ use SP\Domain\Core\Exceptions\ValidationException; use SP\Domain\ItemPreset\Models\Password; use SP\Domain\ItemPreset\Ports\ItemPresetInterface; use SP\Domain\ItemPreset\Ports\ItemPresetService; +use SP\Mvc\Controller\Validators\PasswordValidator; use SP\Mvc\Controller\Validators\ValidatorInterface; use SP\Tests\Generators\AccountDataGenerator; use SP\Tests\Generators\ItemPresetDataGenerator; @@ -251,7 +252,7 @@ class AccountPresetTest extends UnitaryTestCase $configData->setAccountExpireEnabled(true); $this->itemPresetService = $this->createMock(ItemPresetService::class); - $this->passwordValidator = $this->createMock(ValidatorInterface::class); + $this->passwordValidator = $this->createMock(PasswordValidator::class); $this->accountToUserGroupRepository = $this->createMock(AccountToUserGroupRepository::class); $this->accountToUserRepository = $this->createMock(AccountToUserRepository::class); diff --git a/tests/SP/Domain/Auth/Providers/AclHandlerTest.php b/tests/SP/Domain/Auth/Providers/AclHandlerTest.php index eda7e2f5..e49c9a98 100644 --- a/tests/SP/Domain/Auth/Providers/AclHandlerTest.php +++ b/tests/SP/Domain/Auth/Providers/AclHandlerTest.php @@ -1,4 +1,5 @@ userProfileService = $this->createMock(UserProfileService::class); $this->userGroupService = $this->createMock(UserGroupService::class); - $this->aclHandler = new \SP\Domain\Auth\Providers\AclHandler( + $this->aclHandler = new AclHandler( $this->application, $this->userProfileService, - $this->userGroupService + $this->userGroupService, + $this->pathsContext ); } diff --git a/tests/SP/Domain/Common/Providers/ImageTest.php b/tests/SP/Domain/Common/Providers/ImageTest.php index 5c1610b7..a22ba516 100644 --- a/tests/SP/Domain/Common/Providers/ImageTest.php +++ b/tests/SP/Domain/Common/Providers/ImageTest.php @@ -1,4 +1,5 @@ getPathsContext(); + $phpExtensionCheckerService = $this->createMock(PhpExtensionCheckerStub::class); $phpExtensionCheckerService->expects($this->once()) ->method('checkCurl') ->with(true); - $this->imageUtil = new Image($phpExtensionCheckerService, '/usr/share/fonts/freefont/FreeSans.otf'); + $this->imageUtil = new Image( + $phpExtensionCheckerService, + '/usr/share/fonts/freefont/FreeSans.otf', + $this->pathsContext[Path::TMP] + ); } } diff --git a/tests/SP/Domain/Crypt/Services/MasterPassTest.php b/tests/SP/Domain/Crypt/Services/MasterPassTest.php index 4d2db49b..e73a6299 100644 --- a/tests/SP/Domain/Crypt/Services/MasterPassTest.php +++ b/tests/SP/Domain/Crypt/Services/MasterPassTest.php @@ -1,4 +1,5 @@ accountCryptService + $this->accountMasterPasswordService ->expects(self::once()) ->method('updateMasterPassword') ->with($request); - $this->accountCryptService + $this->accountMasterPasswordService ->expects(self::once()) ->method('updateHistoryMasterPassword') ->with($request); @@ -218,14 +219,14 @@ class MasterPassTest extends UnitaryTestCase parent::setUp(); $this->configService = $this->createMock(ConfigService::class); - $this->accountCryptService = $this->createMock(AccountCryptService::class); + $this->accountMasterPasswordService = $this->createMock(AccountMasterPasswordService::class); $this->customFieldCryptService = $this->createMock(CustomFieldCryptService::class); $this->repository = $this->createMock(Repository::class); $this->masterPass = new MasterPass( $this->application, $this->configService, - $this->accountCryptService, + $this->accountMasterPasswordService, $this->customFieldCryptService, $this->repository ); diff --git a/tests/SP/Domain/Crypt/Services/SecureSessionServiceTest.php b/tests/SP/Domain/Crypt/Services/SecureSessionServiceTest.php index a2de96e6..a95899f3 100644 --- a/tests/SP/Domain/Crypt/Services/SecureSessionServiceTest.php +++ b/tests/SP/Domain/Crypt/Services/SecureSessionServiceTest.php @@ -1,4 +1,5 @@ method('create') ->willReturn(uniqid('', true)); - $this->assertNotEmpty(SecureSession::getFileNameFrom($uuidCookie, self::$faker->password)); + $this->assertNotEmpty( + SecureSession::getFileNameFrom($uuidCookie, self::$faker->password, $this->pathsContext[Path::CACHE]) + ); } /** @@ -168,7 +172,7 @@ class SecureSessionServiceTest extends UnitaryTestCase $this->expectException(ServiceException::class); $this->expectExceptionMessage('Unable to get UUID for filename'); - SecureSession::getFileNameFrom($uuidCookie, self::$faker->password); + SecureSession::getFileNameFrom($uuidCookie, self::$faker->password, $this->pathsContext[Path::CACHE]); } /** @@ -184,7 +188,7 @@ class SecureSessionServiceTest extends UnitaryTestCase $this->expectException(ServiceException::class); $this->expectExceptionMessage('Unable to get UUID for filename'); - SecureSession::getFileNameFrom($uuidCookie, self::$faker->password); + SecureSession::getFileNameFrom($uuidCookie, self::$faker->password, $this->pathsContext[Path::CACHE]); } /** diff --git a/tests/SP/Domain/Export/Services/FileBackupServiceTest.php b/tests/SP/Domain/Export/Services/FileBackupServiceTest.php index 44a6ba13..10af1158 100644 --- a/tests/SP/Domain/Export/Services/FileBackupServiceTest.php +++ b/tests/SP/Domain/Export/Services/FileBackupServiceTest.php @@ -31,6 +31,7 @@ use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\Constraint\Callback; use PHPUnit\Framework\MockObject\Exception; use PHPUnit\Framework\MockObject\MockObject; +use SP\Core\Bootstrap\Path; use SP\Core\Context\ContextException; use SP\Domain\Common\Models\Simple; use SP\Domain\Common\Services\ServiceException; @@ -127,9 +128,9 @@ class FileBackupServiceTest extends UnitaryTestCase $this->appArchiveHandler ->expects($this->once()) ->method('compressDirectory') - ->with(APP_ROOT, BackupFile::BACKUP_INCLUDE_REGEX); + ->with(APP_PATH, BackupFile::BACKUP_INCLUDE_REGEX); - $this->fileBackupService->doBackup(TMP_PATH); + $this->fileBackupService->doBackup(TMP_PATH, APP_PATH); } private function buildCreateResult(string $type): QueryResult @@ -172,7 +173,7 @@ class FileBackupServiceTest extends UnitaryTestCase $this->expectException(ServiceException::class); $this->expectExceptionObject($exception); - $this->fileBackupService->doBackup(); + $this->fileBackupService->doBackup($this->pathsContext[Path::TMP], $this->pathsContext[Path::APP]); } /** diff --git a/tests/SP/Domain/Export/Services/XmlVerifyTest.php b/tests/SP/Domain/Export/Services/XmlVerifyTest.php index 6cacdaf3..382f69a1 100644 --- a/tests/SP/Domain/Export/Services/XmlVerifyTest.php +++ b/tests/SP/Domain/Export/Services/XmlVerifyTest.php @@ -28,6 +28,7 @@ namespace SP\Tests\Domain\Export\Services; use DOMDocument; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\MockObject\MockObject; +use SP\Core\Bootstrap\Path; use SP\Core\Crypt\Hash; use SP\Domain\Common\Services\ServiceException; use SP\Domain\Config\Adapters\ConfigData; @@ -248,6 +249,6 @@ class XmlVerifyTest extends UnitaryTestCase $this->crypt = $this->createMock(CryptInterface::class); - $this->xmlVerify = new XmlVerify($this->application, $this->crypt); + $this->xmlVerify = new XmlVerify($this->application, $this->crypt, $this->pathsContext[Path::XML_SCHEMA]); } } diff --git a/tests/SP/Domain/Upgrade/Services/UpgradeDatabaseTest.php b/tests/SP/Domain/Upgrade/Services/UpgradeDatabaseTest.php index fb31124b..98cc56a0 100644 --- a/tests/SP/Domain/Upgrade/Services/UpgradeDatabaseTest.php +++ b/tests/SP/Domain/Upgrade/Services/UpgradeDatabaseTest.php @@ -30,6 +30,7 @@ use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\MockObject\Exception; use PHPUnit\Framework\MockObject\MockObject; use RuntimeException; +use SP\Core\Bootstrap\Path; use SP\Domain\Config\Ports\ConfigDataInterface; use SP\Domain\Database\Ports\DatabaseInterface; use SP\Domain\Upgrade\Services\UpgradeDatabase; @@ -116,6 +117,8 @@ class UpgradeDatabaseTest extends UnitaryTestCase parent::setUp(); $this->database = $this->createMock(DatabaseInterface::class); - $this->upgradeDatabase = new UpgradeDatabase($this->application, $this->database); + $this->upgradeDatabase = new UpgradeDatabase( + $this->application, $this->database, $this->pathsContext[Path::SQL] + ); } } diff --git a/tests/SP/IntegrationTestCase.php b/tests/SP/IntegrationTestCase.php new file mode 100644 index 00000000..c9022a2f --- /dev/null +++ b/tests/SP/IntegrationTestCase.php @@ -0,0 +1,203 @@ +. + */ + +declare(strict_types=1); + +namespace SP\Tests; + +use DI\ContainerBuilder; +use Faker\Factory; +use Faker\Generator; +use Klein\Request; +use PHPUnit\Framework\MockObject\Exception; +use PHPUnit\Framework\MockObject\Stub; +use PHPUnit\Framework\TestCase; +use Psr\Container\ContainerInterface; +use SP\Core\Bootstrap\Path; +use SP\Core\Bootstrap\PathsContext; +use SP\Core\Definitions\CoreDefinitions; +use SP\Core\Definitions\DomainDefinitions; +use SP\Core\UI\ThemeContext; +use SP\Domain\Auth\Ports\LdapConnectionInterface; +use SP\Domain\Config\Ports\ConfigDataInterface; +use SP\Domain\Config\Ports\ConfigFileService; +use SP\Domain\Core\Bootstrap\UriContextInterface; +use SP\Domain\Core\Context\Context; +use SP\Domain\Core\Context\SessionContext; +use SP\Domain\Core\Exceptions\SPException; +use SP\Domain\Core\UI\ThemeContextInterface; +use SP\Domain\Database\Ports\DatabaseInterface; +use SP\Domain\Database\Ports\DbStorageHandler; +use SP\Domain\Notification\Ports\MailService; +use SP\Domain\User\Dtos\UserDataDto; +use SP\Domain\User\Models\ProfileData; +use SP\Infrastructure\Database\QueryResult; +use SP\Infrastructure\File\ArchiveHandler; +use SP\Tests\Generators\UserDataGenerator; +use SP\Tests\Generators\UserProfileDataGenerator; + +use function DI\autowire; +use function DI\factory; + +/** + * Class IntegrationTestCase + */ +abstract class IntegrationTestCase extends TestCase +{ + protected static Generator $faker; + + public static function setUpBeforeClass(): void + { + parent::setUpBeforeClass(); + + self::$faker = Factory::create(); + } + + /** + * @throws Exception + * @throws \Exception + */ + protected function buildContainer(array $definitions = [], Request $request = null): ContainerInterface + { + $configData = $this->getConfigData(); + + $configFileService = $this->createStub(ConfigFileService::class); + $configFileService->method('getConfigData')->willReturn($configData); + + $databaseUtil = self::createStub(\SP\Infrastructure\Database\DatabaseUtil::class); + $databaseUtil->method('checkDatabaseConnection')->willReturn(true); + $databaseUtil->method('checkDatabaseTables')->willReturn(true); + + $database = self::createStub(DatabaseInterface::class); + $database->method('runQuery')->willReturn($this->getQueryResult()); + + $mockedDefinitions = [ + ConfigFileService::class => $configFileService, + LdapConnectionInterface::class => self::createStub(LdapConnectionInterface::class), + 'backup.dbArchiveHandler' => self::createStub(ArchiveHandler::class), + 'backup.appArchiveHandler' => self::createStub(ArchiveHandler::class), + \SP\Infrastructure\Database\DatabaseUtil::class => $databaseUtil, + Context::class => $this->getContext(), + MailService::class => self::createStub(MailService::class), + DbStorageHandler::class => self::createStub(DbStorageHandler::class), + DatabaseInterface::class => $database, + ThemeContextInterface::class => autowire(ThemeContext::class) + ->constructorParameter( + 'basePath', + factory(static fn(PathsContext $p) => $p[Path::VIEW]) + ) + ->constructorParameter('baseUri', factory([UriContextInterface::class, 'getWebRoot'])) + ->constructorParameter('module', 'web') + ->constructorParameter('name', 'material-blue') + ]; + + + if ($request) { + $definitions += [Request::class => $request]; + } + + $containerBuilder = new ContainerBuilder(); + $containerBuilder->addDefinitions( + DomainDefinitions::getDefinitions(), + CoreDefinitions::getDefinitions(REAL_APP_ROOT, 'web'), + $definitions, + $mockedDefinitions + ); + + return $containerBuilder->build(); + } + + /** + * @throws Exception + */ + protected function getConfigData(): ConfigDataInterface|Stub + { + $configData = self::createStub(ConfigDataInterface::class); + $configData->method('isInstalled')->willReturn(true); + $configData->method('isMaintenance')->willReturn(false); + $configData->method('getDbName')->willReturn(self::$faker->colorName()); + $configData->method('getPasswordSalt')->willReturn(self::$faker->sha1()); + + return $configData; + } + + protected function getQueryResult(): QueryResult + { + return new QueryResult(); + } + + /** + * @throws Exception + * @throws SPException + */ + protected function getContext(): Context|Stub + { + $context = self::createStub(SessionContext::class); + $context->method('isLoggedIn')->willReturn(true); + $context->method('getAuthCompleted')->willReturn(true); + $context->method('getUserData')->willReturn($this->getUserDataDto()); + $context->method('getUserProfile')->willReturn($this->getUserProfile()); + + return $context; + } + + /** + * @return UserDataDto + * @throws SPException + */ + protected function getUserDataDto(): UserDataDto + { + return new UserDataDto(UserDataGenerator::factory()->buildUserData()); + } + + /** + * @return ProfileData + */ + protected function getUserProfile(): ProfileData + { + return UserProfileDataGenerator::factory()->buildProfileData(); + } + + protected function buildRequest(string $method, string $uri, array $params): Request + { + $server = array_merge( + $_SERVER, + [ + 'REQUEST_METHOD' => strtoupper($method), + 'REQUEST_URI' => $uri, + 'HTTP_USER_AGENT' => self::$faker->userAgent() + //'QUERY_STRING' => $query + ] + ); + + return new Request( + array_merge($_GET, $params), + array_merge($_POST, $params), + $_COOKIE, + $server, + $_FILES, + null + ); + } +} diff --git a/tests/SP/Modules/Api/ApiTestCase.php b/tests/SP/Modules/Api/ApiTestCase.php index b3aef3ad..923f2047 100644 --- a/tests/SP/Modules/Api/ApiTestCase.php +++ b/tests/SP/Modules/Api/ApiTestCase.php @@ -38,10 +38,8 @@ use Klein\Response; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; use RuntimeException; -use SP\Core\Bootstrap\BootstrapApi; use SP\Domain\Api\Services\ApiRequest; use SP\Domain\Auth\Models\AuthToken; -use SP\Domain\Auth\Services\AuthToken; use SP\Domain\Config\Ports\ConfigDataInterface; use SP\Domain\Config\Ports\ConfigFileService; use SP\Domain\Core\Acl\AclActionsInterface; @@ -57,8 +55,6 @@ use stdClass; use function DI\create; -use const SP\Tests\APP_DEFINITIONS_FILE; - define('APP_MODULE', 'api'); /** diff --git a/tests/SP/Modules/Web/Controllers/AccessManager/IndexControllerTest.php b/tests/SP/Modules/Web/Controllers/AccessManager/IndexControllerTest.php new file mode 100644 index 00000000..920d9ba4 --- /dev/null +++ b/tests/SP/Modules/Web/Controllers/AccessManager/IndexControllerTest.php @@ -0,0 +1,111 @@ +. + */ + +declare(strict_types=1); + +namespace SP\Tests\Modules\Web\Controllers\AccessManager; + +use PHPUnit\Framework\Attributes\Group; +use PHPUnit\Framework\MockObject\Exception; +use PHPUnit\Framework\MockObject\Stub; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; +use SP\Domain\Config\Ports\ConfigDataInterface; +use SP\Domain\Core\Bootstrap\BootstrapInterface; +use SP\Domain\Core\Bootstrap\ModuleInterface; +use SP\Domain\Core\Exceptions\InvalidClassException; +use SP\Domain\User\Models\ProfileData; +use SP\Infrastructure\File\FileException; +use SP\Infrastructure\File\FileSystem; +use SP\Modules\Web\Bootstrap; +use SP\Mvc\View\OutputHandlerInterface; +use SP\Tests\IntegrationTestCase; +use Symfony\Component\DomCrawler\Crawler; + +/** + * Class IndexControllerTest + */ +#[Group('integration')] +class IndexControllerTest extends IntegrationTestCase +{ + /** + * @throws Exception + * @throws FileException + * @throws InvalidClassException + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function testIndexAction() + { + $outputHandler = $this->createMock(OutputHandlerInterface::class); + + $definitions = FileSystem::require(FileSystem::buildPath(REAL_APP_ROOT, 'app', 'modules', 'web', 'module.php')); + $definitions[OutputHandlerInterface::class] = $outputHandler; + + $outputHandler->expects($this->once()) + ->method('bufferedContent') + ->with( + self::callback(static function (callable $callback) { + ob_start(); + $callback(); + $output = ob_get_clean(); + + $crawler = new Crawler($output); + $filter = $crawler->filterXPath( + '//div[contains(@id, \'tabs-\')]//form' + )->extract(['id']); + + return !empty($output) && count($filter) === 5; + }) + ); + + $container = $this->buildContainer( + $definitions, + $this->buildRequest('get', 'index.php', ['r' => 'accessManager/index']) + ); + + Bootstrap::run($container->get(BootstrapInterface::class), $container->get(ModuleInterface::class)); + } + + protected function getUserProfile(): ProfileData + { + return new ProfileData( + [ + 'mgmUsers' => true, + 'mgmGroups' => true, + 'mgmProfiles' => true, + 'mgmApiTokens' => true, + 'mgmPublicLinks' => true + ] + ); + } + + protected function getConfigData(): ConfigDataInterface|Stub + { + $configData = parent::getConfigData(); + $configData->method('isPublinksEnabled')->willReturn(true); + + return $configData; + } +} diff --git a/tests/SP/PHPUnitHelper.php b/tests/SP/PHPUnitHelper.php index 2b91e9f3..1d1bcf94 100644 --- a/tests/SP/PHPUnitHelper.php +++ b/tests/SP/PHPUnitHelper.php @@ -1,4 +1,5 @@ $method != 'transactionAware' ); } + + /** + * @return PathsContext + */ + protected function getPathsContext(): PathsContext + { + $pathsContext = new PathsContext(); + $pathsContext->addPath(Path::TMP, TMP_PATH); + $pathsContext->addPath(Path::APP, APP_PATH); + $pathsContext->addPath(Path::RESOURCES, RESOURCE_PATH); + $pathsContext->addPath(Path::CACHE, FileSystem::buildPath(RESOURCE_PATH, 'cache')); + $pathsContext->addPath(Path::SQL, FileSystem::buildPath(TEST_ROOT, 'schemas')); + $pathsContext->addPath(Path::CONFIG, FileSystem::buildPath(RESOURCE_PATH, 'config')); + $pathsContext->addPath(Path::XML_SCHEMA, FileSystem::buildPath(TEST_ROOT, 'schemas', 'syspass.xsd')); + + $this->pathsContext = $pathsContext; + + return $pathsContext; + } } diff --git a/tests/SP/UnitaryTestCase.php b/tests/SP/UnitaryTestCase.php index 4985e1db..ba741f72 100644 --- a/tests/SP/UnitaryTestCase.php +++ b/tests/SP/UnitaryTestCase.php @@ -54,11 +54,13 @@ use PHPUnit\Framework\MockObject\Exception; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use SP\Core\Application; +use SP\Core\Bootstrap\PathsContext; use SP\Core\Context\ContextException; use SP\Core\Context\Stateless; use SP\Domain\Config\Ports\ConfigFileService; use SP\Domain\Core\Context\Context; use SP\Domain\Core\Events\EventDispatcherInterface; +use SP\Domain\Core\Exceptions\SPException; use SP\Domain\User\Dtos\UserDataDto; use SP\Domain\User\Models\ProfileData; use SP\Domain\User\Models\User; @@ -76,6 +78,7 @@ abstract class UnitaryTestCase extends TestCase protected readonly ConfigFileService|MockObject $config; protected readonly Application $application; protected readonly Context $context; + protected readonly PathsContext $pathsContext; public static function setUpBeforeClass(): void { @@ -94,7 +97,7 @@ abstract class UnitaryTestCase extends TestCase setlocale(LC_MESSAGES, $lang); setlocale(LC_ALL, $lang); - bindtextdomain('messages', LOCALES_PATH); + bindtextdomain('messages', APP_PATH . DIRECTORY_SEPARATOR . 'locales'); textdomain('messages'); bind_textdomain_codeset('messages', 'UTF-8'); } @@ -107,18 +110,22 @@ abstract class UnitaryTestCase extends TestCase /** * @throws Exception * @throws ContextException + * @throws SPException */ protected function setUp(): void { parent::setUp(); $this->application = $this->buildApplication(); + + $this->getPathsContext(); } /** * @return Application * @throws Exception * @throws ContextException + * @throws SPException */ private function buildApplication(): Application { @@ -134,6 +141,7 @@ abstract class UnitaryTestCase extends TestCase /** * @throws ContextException + * @throws SPException */ protected function buildContext(): Context { @@ -147,6 +155,7 @@ abstract class UnitaryTestCase extends TestCase /** * @return UserDataDto + * @throws SPException */ private function buildUserDataDto(): UserDataDto { diff --git a/tests/SP/bootstrap.php b/tests/SP/bootstrap.php index f958d4da..1403cb52 100644 --- a/tests/SP/bootstrap.php +++ b/tests/SP/bootstrap.php @@ -37,13 +37,13 @@ use SP\Infrastructure\File\FileSystem; use function SP\logger; -define('DEBUG', true); -define('IS_TESTING', true); +define('DEBUG', false); define('REAL_APP_ROOT', dirname(__DIR__, 2)); +define('APP_ROOT', REAL_APP_ROOT); $testDirectory = vfsStream::setup( 'test', - 755, + 750, [ 'res' => [ 'cache' => [ @@ -59,35 +59,35 @@ $testDirectory = vfsStream::setup( 'app' => [ 'locales' => [], 'modules' => [], - 'resources' => [] + 'resources' => [], + 'config' => [], + 'cache' => [ + 'secure_session' => [] + ] ] ] ); -vfsStream::copyFromFileSystem(dirname(__DIR__) . '/res', $testDirectory->getChild('res')); +$testResources = vfsStream::copyFromFileSystem(dirname(__DIR__) . '/res', $testDirectory->getChild('res')); vfsStream::copyFromFileSystem(REAL_APP_ROOT . '/schemas', $testDirectory->getChild('schemas')); -vfsStream::copyFromFileSystem(REAL_APP_ROOT . '/app/resources', $testDirectory->getChild('app/resources')); +$appResources = vfsStream::copyFromFileSystem( + REAL_APP_ROOT . '/app/resources', + $testDirectory->getChild('app/resources') +); +vfsStream::copyFromFileSystem( + REAL_APP_ROOT . '/app/config', + $testDirectory->getChild('app/config') +); +vfsStream::copyFromFileSystem( + REAL_APP_ROOT . '/app/locales', + $testDirectory->getChild('app/locales') +); define('TEST_ROOT', $testDirectory->url()); -define('APP_ROOT', $testDirectory->getChild('app')->url()); -define('RESOURCE_PATH', $testDirectory->getChild('res')->url()); +define('APP_PATH', $testDirectory->getChild('app')->url()); +define('RESOURCE_PATH', $testResources->url()); define('TMP_PATH', $testDirectory->getChild('tmp')->url()); -define('VIEW_PATH', RESOURCE_PATH . DIRECTORY_SEPARATOR . 'view'); -define('CACHE_PATH', RESOURCE_PATH . DIRECTORY_SEPARATOR . 'cache'); -define('CONFIG_PATH', RESOURCE_PATH . DIRECTORY_SEPARATOR . 'config'); -define('LOCALES_PATH', APP_ROOT . DIRECTORY_SEPARATOR . 'locales'); -define('MODULES_PATH', APP_ROOT . DIRECTORY_SEPARATOR . 'modules'); -define('BACKUP_PATH', TMP_PATH); -define('PLUGINS_PATH', TMP_PATH); - -define('CONFIG_FILE', CONFIG_PATH . DIRECTORY_SEPARATOR . 'config.xml'); -define('ACTIONS_FILE', CONFIG_PATH . DIRECTORY_SEPARATOR . 'actions.xml'); -define('MIMETYPES_FILE', CONFIG_PATH . DIRECTORY_SEPARATOR . 'mime.xml'); -define('SQL_PATH', TEST_ROOT . DIRECTORY_SEPARATOR . 'schemas'); -define('PUBLIC_PATH', TEST_ROOT . DIRECTORY_SEPARATOR . 'public'); -define('XML_SCHEMA', TEST_ROOT . DIRECTORY_SEPARATOR . 'schemas' . DIRECTORY_SEPARATOR . 'syspass.xsd'); -define('LOG_FILE', TMP_PATH . DIRECTORY_SEPARATOR . 'test.log'); define('FIXTURE_FILES', [ RESOURCE_PATH . DIRECTORY_SEPARATOR . 'datasets' . DIRECTORY_SEPARATOR . 'truncate.sql', RESOURCE_PATH . DIRECTORY_SEPARATOR . 'datasets' . DIRECTORY_SEPARATOR . 'syspass.sql', @@ -98,18 +98,10 @@ define('SELF_HOSTNAME', gethostbyaddr(SELF_IP_ADDRESS)); require_once REAL_APP_ROOT . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php'; require_once REAL_APP_ROOT . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'BaseFunctions.php'; -logger('APP_ROOT=' . APP_ROOT); +logger('APP_PATH=' . APP_PATH); logger('TEST_ROOT=' . TEST_ROOT); logger('SELF_IP_ADDRESS=' . SELF_IP_ADDRESS); -if (is_dir(CONFIG_PATH) - && decoct(fileperms(CONFIG_PATH) & 0777) !== '750' -) { - print 'Setting permissions for ' . CONFIG_PATH . PHP_EOL; - - chmod(CONFIG_PATH, 0750); -} - /** * Función para llamadas a gettext */ diff --git a/tests/phpunit.xml b/tests/phpunit.xml index b1be2891..d8737e8b 100644 --- a/tests/phpunit.xml +++ b/tests/phpunit.xml @@ -48,11 +48,12 @@ ./SP/Domain/Account/Services/Builders/AccountSearchTokenizerDataTrait.php ./SP/Domain/Export/Services/XmlTrait.php - + + ./SP/Modules/Web ./SP/Modules/Api - - ./SP/Modules/Cli + ./SP/Modules/Api + ./SP/Modules/Cli diff --git a/tests/res/config/actions.xml b/tests/res/config/actions.xml deleted file mode 100644 index c472d2e1..00000000 --- a/tests/res/config/actions.xml +++ /dev/null @@ -1,868 +0,0 @@ - - - - - 2 - ACCOUNT_SEARCH - Buscar Cuentas - account/search - - - 1 - ACCOUNT - Cuentas - account/index - - - 20 - ACCOUNT_FILE - Archivos - account/listFile - - - 12 - ACCOUNT_REQUEST - Peticiones - account/requestAccess - - - 30 - ACCOUNT_FAVORITE - Favoritos - favorite/index - - - 1201 - WIKI - Wiki - wiki/index - - - 5001 - ITEMS_MANAGE - Elementos y Personalización - itemManager/index - - - 101 - CATEGORY - Gestión Categorías - category/index - - - 301 - CLIENT - Gestión Clientes - client/index - - - 1001 - AUTHTOKEN - Gestión Autorizaciones API - authToken/index - - - 401 - CUSTOMFIELD - Gestión Campos Personalizados - customField/index - - - 501 - PUBLICLINK - Enlaces Públicos - publicLink/index - - - 601 - FILE - Gestión de Archivos - file/index - - - 1301 - ACCOUNTMGR - Gestión de Cuentas - accountManager/index - - - 201 - TAG - Gestión de Etiquetas - tag/index - - - 1101 - PLUGIN - Gestión Plugins - plugin/index - - - 5002 - ACCESS_MANAGE - Usuarios y Accesos - accessManager/index - - - 701 - USER - Gestión Usuarios - user/index - - - 801 - GROUP - Gestión Grupos - group/index - - - 901 - PROFILE - Gestión Perfiles - profile/index - - - 1701 - EVENTLOG - Registro de Eventos - eventlog/index - - - 1702 - EVENTLOG_SEARCH - Buscar Eventos - eventlog/search - - - 1703 - EVENTLOG_CLEAR - Limpiar Eventos - eventlog/clear - - - 3 - ACCOUNT_VIEW - Ver Cuenta - account/view - - - 4 - ACCOUNT_CREATE - Nueva Cuenta - account/create - - - 5 - ACCOUNT_EDIT - Editar Cuenta - account/edit - - - 6 - ACCOUNT_DELETE - Eliminar Cuenta - account/delete - - - 7 - ACCOUNT_VIEW_PASS - Ver Clave - account/viewPass - - - 8 - ACCOUNT_EDIT_PASS - Editar Clave de Cuenta - account/editPass - - - 9 - ACCOUNT_EDIT_RESTORE - Restaurar Cuenta - account/restore - - - 10 - ACCOUNT_COPY - Copiar Cuenta - account/copy - - - 11 - ACCOUNT_COPY_PASS - Copiar Clave - account/copyPass - - - 21 - ACCOUNT_FILE_VIEW - Ver Archivo - accountFile/view - - - 22 - ACCOUNT_FILE_UPLOAD - Subir Archivo - accountFile/upload - - - 23 - ACCOUNT_FILE_DOWNLOAD - Descargar Archivo - accountFile/download - - - 24 - ACCOUNT_FILE_DELETE - Eliminar Archivo - accountFile/delete - - - 25 - ACCOUNT_FILE_SEARCH - Buscar Archivos - accountFile/search - - - 26 - ACCOUNT_FILE_LIST - Listar Archivos - accountFile/list - - - 31 - ACCOUNT_FAVORITE_VIEW - Ver Favoritos - favorite/view - - - 32 - ACCOUNT_FAVORITE_ADD - Añadir Favorito - accountFavorite/mark - - - 33 - ACCOUNT_FAVORITE_DELETE - Eliminar Favorito - accountFavorite/unmark - - - 40 - ACCOUNT_HISTORY_VIEW - Ver Historial - account/viewHistory - - - 41 - ACCOUNT_HISTORY_VIEW_PASS - Ver Clave - account/viewPassHistory - - - 42 - ACCOUNT_HISTORY_COPY_PASS - Copiar Clave - account/copyPassHistory - - - 1203 - WIKI_VIEW - Ver Wiki - wiki/view - - - 1204 - WIKI_CREATE - Añadir Wiki - wiki/create - - - 1205 - WIKI_EDIT - Editar Wiki - wiki/edit - - - 1206 - WIKI_DELETE - Eliminar Wiki - wiki/delete - - - 103 - CATEGORY_VIEW - Ver Categoría - category/view - - - 104 - CATEGORY_CREATE - Nueva Categoría - category/create - - - 105 - CATEGORY_EDIT - Editar Categoría - category/edit - - - 106 - CATEGORY_DELETE - Eliminar Categoría - category/delete - - - 102 - CATEGORY_SEARCH - Buscar Categoría - category/search - - - 303 - CLIENT_VIEW - Ver Cliente - client/view - - - 304 - CLIENT_CREATE - Nuevo Cliente - client/create - - - 305 - CLIENT_EDIT - Editar Cliente - client/edit - - - 306 - CLIENT_DELETE - Eliminar Cliente - client/delete - - - 302 - CLIENT_SEARCH - Buscar Cliente - client/search - - - 1004 - AUTHTOKEN_CREATE - Nuevo Token API - authToken/create - - - 1003 - AUTHTOKEN_VIEW - Ver Token API - authToken/view - - - 1005 - AUTHTOKEN_EDIT - Editar Token API - authToken/edit - - - 1006 - AUTHTOKEN_DELETE - Eliminar Token API - authToken/delete - - - 1002 - AUTHTOKEN_SEARCH - Buscar Token API - authToken/search - - - 404 - CUSTOMFIELD_CREATE - Nuevo Campo Personalizado - customField/create - - - 403 - CUSTOMFIELD_VIEW - Ver Campo Personalizado - customField/view - - - 405 - CUSTOMFIELD_EDIT - Editar Campo Personalizado - customField/edit - - - 406 - CUSTOMFIELD_DELETE - Eliminar Campo Personalizado - customField/delete - - - 402 - CUSTOMFIELD_SEARCH - Buscar Campo Personalizado - customField/search - - - 504 - PUBLICLINK_CREATE - Crear Enlace Público - publicLink/create - - - 503 - PUBLICLINK_VIEW - Ver Enlace Público - publicLink/view - - - 506 - PUBLICLINK_DELETE - Eliminar Enlace Público - publicLink/delete - - - 507 - PUBLICLINK_REFRESH - Actualizar Enlace Público - publicLink/refresh - - - 502 - PUBLICLINK_SEARCH - Buscar Enlace Público - publicLink/search - - - 603 - FILE_VIEW - Ver Archivo - file/view - - - 605 - FILE_DOWNLOAD - Descargar Archivo - file/download - - - 606 - FILE_DELETE - Eliminar Archivo - file/delete - - - 604 - FILE_UPLOAD - Subir Archivo - file/upload - - - 602 - FILE_SEARCH - Buscar Archivo - file/search - - - 1303 - ACCOUNTMGR_VIEW - Ver Cuenta - accountManager/view - - - 1304 - ACCOUNTMGR_DELETE - Eliminar Cuenta - accountManager/delete - - - 1302 - ACCOUNTMGR_SEARCH - Buscar Cuenta - accountManager/search - - - 204 - TAG_CREATE - Nueva Etiqueta - tag/create - - - 203 - TAG_VIEW - Ver Etiqueta - tag/view - - - 205 - TAG_EDIT - Editar Etiqueta - tag/edit - - - 206 - TAG_DELETE - Eliminar Etiqueta - tag/delete - - - 202 - TAG_SEARCH - Buscar Etiqueta - tag/search - - - 1104 - PLUGIN_CREATE - Nuevo Plugin - plugin/create - - - 1103 - PLUGIN_VIEW - Ver Plugin - plugin/view - - - 1102 - PLUGIN_SEARCH - Buscar Plugin - plugin/search - - - 1105 - PLUGIN_ENABLE - Habilitar Plugin - plugin/enable - - - 1106 - PLUGIN_DISABLE - Deshabilitar Plugin - plugin/disable - - - 1107 - PLUGIN_RESET - Restablecer Plugin - plugin/reset - - - 703 - USER_VIEW - Ver Usuario - user/view - - - 704 - USER_CREATE - Nuevo Usuario - user/create - - - 705 - USER_EDIT - Editar Usuario - user/edit - - - 706 - USER_DELETE - Eliminar Usuario - user/delete - - - 707 - USER_EDIT_PASS - Editar Clave Usuario - user/editPass - - - 702 - USER_SEARCH - Buscar Usuario - user/search - - - 803 - GROUP_VIEW - Ver Grupo - userGroup/view - - - 804 - GROUP_CREATE - Nuevo Grupo - userGroup/create - - - 805 - GROUP_EDIT - Editar Grupo - userGroup/edit - - - 806 - GROUP_DELETE - Eliminar Grupo - userGroup/delete - - - 802 - GROUP_SEARCH - Buscar Grupo - userGroup/search - - - 903 - PROFILE_VIEW - Ver Perfil - userProfile/view - - - 904 - PROFILE_CREATE - Nuevo Perfil - userProfile/create - - - 905 - PROFILE_EDIT - Editar Perfil - userProfile/edit - - - 906 - PROFILE_DELETE - Eliminar Perfil - userProfile/delete - - - 902 - PROFILE_SEARCH - Buscar Perfil - userProfile/search - - - 5010 - USERSETTINGS - Configuración Usuario - userSettingsManager/index - - - 5011 - USERSETTINGS_GENERAL - Preferencias General - userSettings/general - - - 1401 - NOTIFICATION - Notificaciones - notification/index - - - 1501 - CONFIG - Configuración - configManager/index - - - 1502 - CONFIG_GENERAL - Configuración General - configManager/general - - - 1510 - CONFIG_ACCOUNT - Configuración Cuentas - account/config - - - 1520 - CONFIG_WIKI - Configuración Wiki - wiki/config - - - 1530 - CONFIG_CRYPT - Configuración Encriptación - encryption/config - - - 1531 - CONFIG_CRYPT_REFRESH - Actualizar Hash - encryption/updateHash - - - 1532 - CONFIG_CRYPT_TEMPPASS - Clave Maestra Temporal - encryption/createTempPass - - - 1540 - CONFIG_BACKUP - Configuración Copia de Seguridad - backup/config - - - 1541 - CONFIG_BACKUP_RUN - Copia de Seguridad - backup/backup - - - 1550 - CONFIG_IMPORT - Configuración Importación - import/config - - - 1551 - CONFIG_IMPORT_CSV - Importar CSV - import/csv - - - 1552 - CONFIG_IMPORT_XML - Importar XML - import/xml - - - 1560 - CONFIG_EXPORT - Configuración Exportación - export/config - - - 1561 - CONFIG_EXPORT_RUN - Exportación - export/export - - - 1570 - CONFIG_MAIL - Configuración Email - mail/config - - - 1580 - CONFIG_LDAP - Configuración LDAP - ldap/config - - - 1581 - CONFIG_LDAP_SYNC - Sincronización LDAP - ldap/sync - - - 1311 - ACCOUNTMGR_HISTORY - Gestión de Cuenta (H) - accountHistoryManager/index - - - 1314 - ACCOUNTMGR_HISTORY_DELETE - Eliminar Cuenta - accountHistoryManager/delete - - - 1312 - ACCOUNTMGR_HISTORY_SEARCH - Buscar Cuenta - accountHistoryManager/search - - - 1315 - ACCOUNTMGR_HISTORY_RESTORE - Restaurar Cuenta - accountHistoryManager/restore - - - 1403 - NOTIFICATION_VIEW - Ver Notificación - notification/view - - - 1404 - NOTIFICATION_CREATE - Crear Notificación - notification/create - - - 1405 - NOTIFICATION_EDIT - Editar Notificación - notification/edit - - - 1406 - NOTIFICATION_DELETE - Eliminar Notificación - notification/delete - - - 1407 - NOTIFICATION_CHECK - Marcar Notificación - notification/check - - - 1402 - NOTIFICATION_SEARCH - Buscar Notificación - notification/search - - - 1801 - ITEMPRESET - Gestión Permisos - itemPreset/index - - - 1802 - ITEMPRESET_SEARCH - Buscar Permiso - itemPreset/search - - - 1803 - ITEMPRESET_VIEW - Ver Permiso - itemPreset/view - - - 1804 - ITEMPRESET_CREATE - Nuevo Permiso - itemPreset/create - - - 1805 - ITEMPRESET_EDIT - Editar Permiso - itemPreset/edit - - - 1806 - ITEMPRESET_DELETE - Eliminar Permiso - itemPreset/delete - - \ No newline at end of file diff --git a/tests/res/config/actions.yaml b/tests/res/config/actions.yaml new file mode 100644 index 00000000..2f5fd0d2 --- /dev/null +++ b/tests/res/config/actions.yaml @@ -0,0 +1,606 @@ +actions: + - id: 2 + name: ACCOUNT_SEARCH + text: Search for Accounts + route: account/search + - id: 1 + name: ACCOUNT + text: Accounts + route: account/index + - id: 20 + name: ACCOUNT_FILE + text: Files + route: account/listFile + - id: 12 + name: ACCOUNT_REQUEST + text: Requests + route: account/requestAccess + - id: 30 + name: ACCOUNT_FAVORITE + text: Favorites + route: favorite/index + - id: 1201 + name: WIKI + text: Wiki + route: wiki/index + - id: 5001 + name: ITEMS_MANAGE + text: Items and Customizations + route: itemManager/index + - id: 101 + name: CATEGORY + text: Categories Management + route: category/index + - id: 301 + name: CLIENT + text: Customers Management + route: client/index + - id: 1001 + name: AUTHTOKEN + text: API Authorizations Management + route: authToken/index + - id: 401 + name: CUSTOMFIELD + text: Custom Fields Management + route: customField/index + - id: 501 + name: PUBLICLINK + text: Public Links + route: publicLink/index + - id: 601 + name: FILE + text: Files Management + route: file/index + - id: 1301 + name: ACCOUNTMGR + text: Accounts Management + route: accountManager/index + - id: 201 + name: TAG + text: Tags Management + route: tag/index + - id: 1101 + name: PLUGIN + text: Plugins Management + route: plugin/index + - id: 5002 + name: ACCESS_MANAGE + text: Users and Accesses + route: accessManager/index + - id: 5003 + name: SECURITY_MANAGE + text: Security and Audit + route: securityManager/index + - id: 701 + name: USER + text: Users Management + route: user/index + - id: 801 + name: GROUP + text: Groups Management + route: group/index + - id: 901 + name: PROFILE + text: Profiles Management + route: profile/index + - id: 1701 + name: EVENTLOG + text: Event Log + route: eventlog/index + - id: 1702 + name: EVENTLOG_SEARCH + text: Search for Events + route: eventlog/search + - id: 1703 + name: EVENTLOG_CLEAR + text: Clear Events + route: eventlog/clear + - id: 3 + name: ACCOUNT_VIEW + text: View Account + route: account/view + - id: 4 + name: ACCOUNT_CREATE + text: New Account + route: account/create + - id: 5 + name: ACCOUNT_EDIT + text: Edit Account + route: account/edit + - id: 6 + name: ACCOUNT_DELETE + text: Remove Account + route: account/delete + - id: 7 + name: ACCOUNT_VIEW_PASS + text: View password + route: account/viewPass + - id: 8 + name: ACCOUNT_EDIT_PASS + text: Edit Account Password + route: account/editPass + - id: 9 + name: ACCOUNT_EDIT_RESTORE + text: Account Restore + route: account/restore + - id: 10 + name: ACCOUNT_COPY + text: Copy Account + route: account/copy + - id: 11 + name: ACCOUNT_COPY_PASS + text: Copy Password + route: account/copyPass + - id: 21 + name: ACCOUNT_FILE_VIEW + text: View File + route: accountFile/view + - id: 22 + name: ACCOUNT_FILE_UPLOAD + text: Upload File + route: accountFile/upload + - id: 23 + name: ACCOUNT_FILE_DOWNLOAD + text: Download File + route: accountFile/download + - id: 24 + name: ACCOUNT_FILE_DELETE + text: Delete File + route: accountFile/delete + - id: 25 + name: ACCOUNT_FILE_SEARCH + text: Search for Files + route: accountFile/search + - id: 26 + name: ACCOUNT_FILE_LIST + text: List Files + route: accountFile/list + - id: 31 + name: ACCOUNT_FAVORITE_VIEW + text: Show Favorites + route: favorite/view + - id: 32 + name: ACCOUNT_FAVORITE_ADD + text: Mark as Favorite + route: accountFavorite/mark + - id: 33 + name: ACCOUNT_FAVORITE_DELETE + text: Delete Favorite + route: accountFavorite/unmark + - id: 40 + name: ACCOUNT_HISTORY_VIEW + text: View History + route: account/viewHistory + - id: 41 + name: ACCOUNT_HISTORY_VIEW_PASS + text: View password + route: account/viewPassHistory + - id: 42 + name: ACCOUNT_HISTORY_COPY_PASS + text: Copy Password + route: account/copyPassHistory + - id: 1203 + name: WIKI_VIEW + text: View Wiki + route: wiki/view + - id: 1204 + name: WIKI_CREATE + text: Add Wiki + route: wiki/create + - id: 1205 + name: WIKI_EDIT + text: Edit Wiki + route: wiki/edit + - id: 1206 + name: WIKI_DELETE + text: Delete Wiki + route: wiki/delete + - id: 103 + name: CATEGORY_VIEW + text: View Category + route: category/view + - id: 104 + name: CATEGORY_CREATE + text: New Category + route: category/create + - id: 105 + name: CATEGORY_EDIT + text: Edit Category + route: category/edit + - id: 106 + name: CATEGORY_DELETE + text: Delete Category + route: category/delete + - id: 102 + name: CATEGORY_SEARCH + text: Search for Category + route: category/search + - id: 303 + name: CLIENT_VIEW + text: View Client + route: client/view + - id: 304 + name: CLIENT_CREATE + text: New Client + route: client/create + - id: 305 + name: CLIENT_EDIT + text: Edit Client + route: client/edit + - id: 306 + name: CLIENT_DELETE + text: Delete Client + route: client/delete + - id: 302 + name: CLIENT_SEARCH + text: Search for Client + route: client/search + - id: 1004 + name: AUTHTOKEN_CREATE + text: New API Token + route: authToken/create + - id: 1003 + name: AUTHTOKEN_VIEW + text: View API Token + route: authToken/view + - id: 1005 + name: AUTHTOKEN_EDIT + text: Edit API Token + route: authToken/edit + - id: 1006 + name: AUTHTOKEN_DELETE + text: Delete API Token + route: authToken/delete + - id: 1002 + name: AUTHTOKEN_SEARCH + text: Search for API Token + route: authToken/search + - id: 404 + name: CUSTOMFIELD_CREATE + text: New Custom Field + route: customField/create + - id: 403 + name: CUSTOMFIELD_VIEW + text: Show Custom Field + route: customField/view + - id: 405 + name: CUSTOMFIELD_EDIT + text: Edit Custom Field + route: customField/edit + - id: 406 + name: CUSTOMFIELD_DELETE + text: Delete Custom Field + route: customField/delete + - id: 402 + name: CUSTOMFIELD_SEARCH + text: Search for Custom Field + route: customField/search + - id: 504 + name: PUBLICLINK_CREATE + text: Create Public Link + route: publicLink/create + - id: 503 + name: PUBLICLINK_VIEW + text: Show Public Link + route: publicLink/view + - id: 506 + name: PUBLICLINK_DELETE + text: Delete Public Link + route: publicLink/delete + - id: 507 + name: PUBLICLINK_REFRESH + text: Update Public Link + route: publicLink/refresh + - id: 502 + name: PUBLICLINK_SEARCH + text: Search for Public Link + route: publicLink/search + - id: 603 + name: FILE_VIEW + text: View File + route: file/view + - id: 605 + name: FILE_DOWNLOAD + text: Download File + route: file/download + - id: 606 + name: FILE_DELETE + text: Delete File + route: file/delete + - id: 604 + name: FILE_UPLOAD + text: Upload File + route: file/upload + - id: 602 + name: FILE_SEARCH + text: Search for File + route: file/search + - id: 1303 + name: ACCOUNTMGR_VIEW + text: View Account + route: accountManager/view + - id: 1304 + name: ACCOUNTMGR_DELETE + text: Remove Account + route: accountManager/delete + - id: 1305 + name: ACCOUNTMGR_BULK_EDIT + text: Bulk Update + route: accountManager/bulkEdit + - id: 1302 + name: ACCOUNTMGR_SEARCH + text: Search for Account + route: accountManager/search + - id: 204 + name: TAG_CREATE + text: New Tag + route: tag/create + - id: 203 + name: TAG_VIEW + text: View Tag + route: tag/view + - id: 205 + name: TAG_EDIT + text: Edit Tag + route: tag/edit + - id: 206 + name: TAG_DELETE + text: Delete Tag + route: tag/delete + - id: 202 + name: TAG_SEARCH + text: Search for Tag + route: tag/search + - id: 1104 + name: PLUGIN_CREATE + text: New Plugin + route: plugin/create + - id: 1103 + name: PLUGIN_VIEW + text: View Plugin + route: plugin/view + - id: 1102 + name: PLUGIN_SEARCH + text: Search for Plugin + route: plugin/search + - id: 1105 + name: PLUGIN_ENABLE + text: Enable Plugin + route: plugin/enable + - id: 1106 + name: PLUGIN_DISABLE + text: Disable Plugin + route: plugin/disable + - id: 1107 + name: PLUGIN_RESET + text: Reset Plugin + route: plugin/reset + - id: 1108 + name: PLUGIN_DELETE + text: Delete Plugin + route: plugin/delete + - id: 703 + name: USER_VIEW + text: View User + route: user/view + - id: 704 + name: USER_CREATE + text: New User + route: user/create + - id: 705 + name: USER_EDIT + text: Edit User + route: user/edit + - id: 706 + name: USER_DELETE + text: Delete User + route: user/delete + - id: 707 + name: USER_EDIT_PASS + text: Edit User Password + route: user/editPass + - id: 702 + name: USER_SEARCH + text: Search for User + route: user/search + - id: 803 + name: GROUP_VIEW + text: View Group + route: userGroup/view + - id: 804 + name: GROUP_CREATE + text: New Group + route: userGroup/create + - id: 805 + name: GROUP_EDIT + text: Edit Group + route: userGroup/edit + - id: 806 + name: GROUP_DELETE + text: Delete Group + route: userGroup/delete + - id: 802 + name: GROUP_SEARCH + text: Search for Group + route: userGroup/search + - id: 903 + name: PROFILE_VIEW + text: View Profile + route: userProfile/view + - id: 904 + name: PROFILE_CREATE + text: New Profile + route: userProfile/create + - id: 905 + name: PROFILE_EDIT + text: Edit Profile + route: userProfile/edit + - id: 906 + name: PROFILE_DELETE + text: Delete Profile + route: userProfile/delete + - id: 902 + name: PROFILE_SEARCH + text: Search for Profile + route: userProfile/search + - id: 5010 + name: USERSETTINGS + text: User Configuration + route: userSettingsManager/index + - id: 5011 + name: USERSETTINGS_GENERAL + text: General Preferences + route: userSettings/general + - id: 1401 + name: NOTIFICATION + text: Notifications + route: notification/index + - id: 1501 + name: CONFIG + text: Configuration + route: configManager/index + - id: 1502 + name: CONFIG_GENERAL + text: General Configuration + route: configManager/general + - id: 1510 + name: CONFIG_ACCOUNT + text: Accounts Configuration + route: account/config + - id: 1520 + name: CONFIG_WIKI + text: Wiki Configuration + route: wiki/config + - id: 1530 + name: CONFIG_CRYPT + text: Encryption Configuration + route: encryption/config + - id: 1531 + name: CONFIG_CRYPT_REFRESH + text: Update Hash + route: encryption/updateHash + - id: 1532 + name: CONFIG_CRYPT_TEMPPASS + text: Temporary Master Password + route: encryption/createTempPass + - id: 1540 + name: CONFIG_BACKUP + text: Backup Configuration + route: backup/config + - id: 1541 + name: CONFIG_BACKUP_RUN + text: Backup + route: backup/backup + - id: 1550 + name: CONFIG_IMPORT + text: Import Configuration + route: import/config + - id: 1551 + name: CONFIG_IMPORT_CSV + text: CSV Import + route: import/csv + - id: 1552 + name: CONFIG_IMPORT_XML + text: XML Import + route: import/xml + - id: 1560 + name: CONFIG_EXPORT + text: Export Configuration + route: export/config + - id: 1561 + name: CONFIG_EXPORT_RUN + text: Export + route: export/export + - id: 1570 + name: CONFIG_MAIL + text: Email Configuration + route: mail/config + - id: 1580 + name: CONFIG_LDAP + text: LDAP Configuration + route: ldap/config + - id: 1581 + name: CONFIG_LDAP_SYNC + text: LDAP synchronization + route: ldap/sync + - id: 1311 + name: ACCOUNTMGR_HISTORY + text: Account Management (H) + route: accountHistoryManager/index + - id: 1314 + name: ACCOUNTMGR_HISTORY_DELETE + text: Remove Account + route: accountHistoryManager/delete + - id: 1312 + name: ACCOUNTMGR_HISTORY_SEARCH + text: Search for Account + route: accountHistoryManager/search + - id: 1315 + name: ACCOUNTMGR_HISTORY_RESTORE + text: Account Restore + route: accountHistoryManager/restore + - id: 1403 + name: NOTIFICATION_VIEW + text: View Notification + route: notification/view + - id: 1404 + name: NOTIFICATION_CREATE + text: Create Notification + route: notification/create + - id: 1405 + name: NOTIFICATION_EDIT + text: Edit Notification + route: notification/edit + - id: 1406 + name: NOTIFICATION_DELETE + text: Delete Notification + route: notification/delete + - id: 1407 + name: NOTIFICATION_CHECK + text: Checkout Notification + route: notification/check + - id: 1402 + name: NOTIFICATION_SEARCH + text: Search for Notification + route: notification/search + - id: 1801 + name: ITEMPRESET + text: Preset Values Management + route: itemPreset/index + - id: 1802 + name: ITEMPRESET_SEARCH + text: Search for Value + route: itemPreset/search + - id: 1803 + name: ITEMPRESET_VIEW + text: Display Value + route: itemPreset/view + - id: 1804 + name: ITEMPRESET_CREATE + text: New Value + route: itemPreset/create + - id: 1805 + name: ITEMPRESET_EDIT + text: Edit Value + route: itemPreset/edit + - id: 1806 + name: ITEMPRESET_DELETE + text: Delete Value + route: itemPreset/delete + - id: 1901 + name: TRACK + text: Tracks Management + route: track/index + - id: 1902 + name: TRACK_SEARCH + text: Search for track + route: track/search + - id: 1903 + name: TRACK_UNLOCK + text: Unlock track + route: track/unlock + - id: 1904 + name: TRACK_CLEAR + text: Clear the tracks out + route: track/clear + diff --git a/tests/res/config/mime.xml b/tests/res/config/mime.xml deleted file mode 100644 index 3de9734c..00000000 --- a/tests/res/config/mime.xml +++ /dev/null @@ -1,209 +0,0 @@ - - - - - application/x-abiword - AbiWord document - abw - - - application/octet-stream - Archive document (multiple files embedded) - arc - - - application/vnd.amazon.ebook - Amazon Kindle eBook format - azw - - - application/octet-stream - Any kind of binary data - bin - - - image/bmp - Windows OS/2 Bitmap Graphics - bmp - - - application/x-bzip - BZip archive - bz - - - application/x-bzip2 - BZip2 archive - bz2 - - - application/x-csh - C-Shell script - csh - - - text/csv - Comma-separated values (CSV) - csv - - - application/msword - Microsoft Word - doc - - - application/vnd.openxmlformats-officedocument.wordprocessingml.document - Microsoft Word (OpenXML) - docx - - - application/vnd.ms-fontobject - MS Embedded OpenType fonts - eot - - - application/epub+zip - Electronic publication (EPUB) - epub - - - image/gif - Graphics Interchange Format (GIF) - gif - - - text/html - HyperText Markup Language (HTML) - html - - - text/calendar - iCalendar format - ics - - - application/java-archive - Java Archive (JAR) - jar - - - image/jpeg - JPEG images - jpg - - - application/json - JSON format - json - - - application/vnd.apple.installer+xml - Apple Installer Package - mpkg - - - application/vnd.oasis.opendocument.presentation - OpenDocument presentation document - odp - - - application/vnd.oasis.opendocument.spreadsheet - OpenDocument spreadsheet document - ods - - - application/vnd.oasis.opendocument.text - OpenDocument text document - odt - - - image/png - Portable Network Graphics - png - - - application/pdf - Adobe Portable Document Format (PDF) - pdf - - - application/vnd.ms-powerpoint - Microsoft PowerPoint - ppt - - - application/vnd.openxmlformats-officedocument.presentationml.presentation - Microsoft PowerPoint (OpenXML) - pptx - - - application/x-rar-compressed - RAR archive - rar - - - application/rtf - Rich Text Format (RTF) - rtf - - - application/x-sh - Bourne shell script - sh - - - image/svg+xml - Scalable Vector Graphics (SVG) - svg - - - application/x-tar - Tape Archive (TAR) - tar - - - text/plain - Text, (generally ASCII or ISO 8859-n) - txt - - - application/vnd.visio - Microsoft Visio - vsd - - - application/xhtml+xml - XHTML - xhtml - - - application/vnd.ms-excel - Microsoft Excel - xls - - - application/vnd.openxmlformats-officedocument.spreadsheetml.sheet - Microsoft Excel (OpenXML) - xlsx - - - application/xml - XML - xml - - - application/vnd.mozilla.xul+xml - XUL - xul - - - application/zip - ZIP archive - zip - - - application/x-7z-compressed - 7-zip archive - 7z - - diff --git a/tests/res/config/mimetypes.yaml b/tests/res/config/mimetypes.yaml new file mode 100644 index 00000000..560e2d62 --- /dev/null +++ b/tests/res/config/mimetypes.yaml @@ -0,0 +1,126 @@ +mimetypes: + - type: application/x-abiword + description: AbiWord document + extension: abw + - type: application/octet-stream + description: Archive document (multiple files embedded) + extension: arc + - type: application/vnd.amazon.ebook + description: Amazon Kindle eBook format + extension: azw + - type: application/octet-stream + description: Any kind of binary data + extension: bin + - type: image/bmp + description: Windows OS/2 Bitmap Graphics + extension: bmp + - type: application/x-bzip + description: BZip archive + extension: bz + - type: application/x-bzip2 + description: BZip2 archive + extension: bz2 + - type: application/x-csh + description: C-Shell script + extension: csh + - type: text/csv + description: Comma-separated values (CSV) + extension: csv + - type: application/msword + description: Microsoft Word + extension: doc + - type: application/vnd.openxmlformats-officedocument.wordprocessingml.document + description: Microsoft Word (OpenXML) + extension: docx + - type: application/vnd.ms-fontobject + description: MS Embedded OpenType fonts + extension: eot + - type: application/epub+zip + description: Electronic publication (EPUB) + extension: epub + - type: image/gif + description: Graphics Interchange Format (GIF) + extension: gif + - type: text/html + description: HyperText Markup Language (HTML) + extension: html + - type: text/calendar + description: iCalendar format + extension: ics + - type: application/java-archive + description: Java Archive (JAR) + extension: jar + - type: image/jpeg + description: JPEG images + extension: jpg + - type: application/json + description: JSON format + extension: json + - type: application/vnd.apple.installer+xml + description: Apple Installer Package + extension: mpkg + - type: application/vnd.oasis.opendocument.presentation + description: OpenDocument presentation document + extension: odp + - type: application/vnd.oasis.opendocument.spreadsheet + description: OpenDocument spreadsheet document + extension: ods + - type: application/vnd.oasis.opendocument.text + description: OpenDocument text document + extension: odt + - type: image/png + description: Portable Network Graphics + extension: png + - type: application/pdf + description: Adobe Portable Document Format (PDF) + extension: pdf + - type: application/vnd.ms-powerpoint + description: Microsoft PowerPoint + extension: ppt + - type: >- + application/vnd.openxmlformats-officedocument.presentationml.presentation + description: Microsoft PowerPoint (OpenXML) + extension: pptx + - type: application/x-rar-compressed + description: RAR archive + extension: rar + - type: application/rtf + description: Rich Text Format (RTF) + extension: rtf + - type: application/x-sh + description: Bourne shell script + extension: sh + - type: image/svg+xml + description: Scalable Vector Graphics (SVG) + extension: svg + - type: application/x-tar + description: Tape Archive (TAR) + extension: tar + - type: text/plain + description: 'Text, (generally ASCII or ISO 8859-n)' + extension: txt + - type: application/vnd.visio + description: Microsoft Visio + extension: vsd + - type: application/xhtml+xml + description: XHTML + extension: xhtml + - type: application/vnd.ms-excel + description: Microsoft Excel + extension: xls + - type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet + description: Microsoft Excel (OpenXML) + extension: xlsx + - type: application/xml + description: XML + extension: xml + - type: application/vnd.mozilla.xul+xml + description: XUL + extension: xul + - type: application/zip + description: ZIP archive + extension: zip + - type: application/x-7z-compressed + description: 7-zip archive + extension: 7z +