From 117dd8172793a239f71c91222606bf00677eeb33 Mon Sep 17 00:00:00 2001 From: Jack Anderson Date: Mon, 6 Nov 2023 16:03:39 +0000 Subject: [PATCH] SuiteCRM 8.4.2 Release --- README.md | 2 +- VERSION | 2 +- config/core_services.yaml | 6 ++ config/packages/api_platform.yaml | 4 +- config/packages/security.php | 51 +++++++++------ config/routes/api_platform.yaml | 2 +- .../graphql/graphql_allow_introspection.yaml | 2 + core/app/common/package.json | 2 +- core/app/core/package.json | 2 +- core/backend/Kernel.php | 11 ++++ .../Migrations/Version20231108164138.php | 56 ++++++++++++++++ .../Security/GraphqlIntrospectionManager.php | 64 +++++++++++++++++++ package.json | 2 +- public/index.php | 1 + .../AOP_Case_Updates/AOP_Case_Updates.php | 3 +- 15 files changed, 181 insertions(+), 29 deletions(-) create mode 100644 config/services/graphql/graphql_allow_introspection.yaml create mode 100644 core/backend/Migrations/Version20231108164138.php create mode 100644 core/backend/Security/GraphqlIntrospectionManager.php diff --git a/README.md b/README.md index 69081929ce..f786ee25c9 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ -# SuiteCRM 8.4.1 +# SuiteCRM 8.4.2 [![LICENSE](https://img.shields.io/github/license/suitecrm/suitecrm.svg)](https://github.com/salesagility/suitecrm/blob/hotfix/LICENSE.txt) [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/salesagility/SuiteCRM-Core/issues) diff --git a/VERSION b/VERSION index 6da4de57dc..e7fdef7e2e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.4.1 +8.4.2 diff --git a/config/core_services.yaml b/config/core_services.yaml index dc10c8e547..4ed6acc5a7 100644 --- a/config/core_services.yaml +++ b/config/core_services.yaml @@ -65,6 +65,8 @@ services: $adminOnlyModuleActions: '%system.admin_only_module_actions%' $navbarAdministrationOverrides: '%navbar.administration_override%' $quickActions: '%quick_actions%' + $graphqlShowDocs: '%graphql.graphql_show_docs%' + _instanceof: App\Process\Service\ProcessHandlerInterface: tags: [ 'app.process.handler' ] @@ -288,6 +290,10 @@ services: alias: App\Routes\Service\LegacyRouteHandler public: true + graphql.introspection_manager: + alias: App\Security\GraphqlIntrospectionManager + public: true + entity_manager: alias: doctrine.orm.entity_manager public: true diff --git a/config/packages/api_platform.yaml b/config/packages/api_platform.yaml index 5a6dcd4008..ca2b35669a 100644 --- a/config/packages/api_platform.yaml +++ b/config/packages/api_platform.yaml @@ -2,9 +2,9 @@ api_platform: graphql: default_ide: graphql-playground graphiql: - enabled: true - graphql_playground: enabled: false + graphql_playground: + enabled: true mapping: paths: ['%kernel.project_dir%/core'] patch_formats: diff --git a/config/packages/security.php b/config/packages/security.php index 45fb388f7c..1bf01261fb 100644 --- a/config/packages/security.php +++ b/config/packages/security.php @@ -97,10 +97,16 @@ ['path' => '^/$', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], ['path' => '^/api', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], ['path' => '^/api/graphql', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], - ['path' => '^/api/graphql/graphiql*', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], ['path' => '^/', 'roles' => 'IS_AUTHENTICATED_FULLY'] ]; + + $appEnv = $env['APP_ENV'] ?? 'prod'; + $showDocs = $env['GRAPHQL_SHOW_DOCS'] ?? ($appEnv === 'dev'); + if ($showDocs === 'false' || $showDocs === false) { + $baseAccessControl = array_merge([['path' => '^/docs', 'roles' => 'NO_ACCESS']], $baseAccessControl); + } + $containerConfig->parameters()->set('auth.logout.redirect', false); $containerConfig->parameters()->set('auth.logout.path', 'logout'); @@ -244,6 +250,29 @@ $samlMainFirewallConfig['saml']['user_factory'] = 'saml_user_factory'; } + $samlAccessControl = [ + ['path' => '^/login$', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], + ['path' => '^/session-status$', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], + ['path' => '^/logout$', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], + ['path' => '^/saml/login', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], + ['path' => '^/saml/metadata', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], + ['path' => '^/saml/acs', 'roles' => 'ROLE_USER'], + ['path' => '^/saml/logout', 'roles' => 'ROLE_USER'], + ['path' => '^/logged-out', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], + ['path' => '^/auth', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], + ['path' => '^/auth/login', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], + ['path' => '^/auth/session-status', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], + ['path' => '^/auth/logout', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], + ['path' => '^/$', 'roles' => 'ROLE_USER'], + ['path' => '^/api', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], + ['path' => '^/api/graphql', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], + ['path' => '^/', 'roles' => 'IS_AUTHENTICATED_FULLY'] + ]; + + if (!$showDocs) { + $samlAccessControl = array_merge([['path' => '^/docs', 'roles' => 'NO_ACCESS']], $samlAccessControl); + } + $containerConfig->extension('security', [ 'providers' => [ 'app_user_provider' => [ @@ -293,25 +322,7 @@ ] ], ]), - 'access_control' => [ - ['path' => '^/login$', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], - ['path' => '^/session-status$', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], - ['path' => '^/logout$', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], - ['path' => '^/saml/login', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], - ['path' => '^/saml/metadata', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], - ['path' => '^/saml/acs', 'roles' => 'ROLE_USER'], - ['path' => '^/saml/logout', 'roles' => 'ROLE_USER'], - ['path' => '^/logged-out', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], - ['path' => '^/auth', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], - ['path' => '^/auth/login', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], - ['path' => '^/auth/session-status', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], - ['path' => '^/auth/logout', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], - ['path' => '^/$', 'roles' => 'ROLE_USER'], - ['path' => '^/api', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], - ['path' => '^/api/graphql', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], - ['path' => '^/api/graphql/graphiql*', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], - ['path' => '^/', 'roles' => 'IS_AUTHENTICATED_FULLY'] - ] + 'access_control' => $samlAccessControl ]); diff --git a/config/routes/api_platform.yaml b/config/routes/api_platform.yaml index 24f9549ae7..e242a38bea 100644 --- a/config/routes/api_platform.yaml +++ b/config/routes/api_platform.yaml @@ -9,4 +9,4 @@ swagger_ui: graphiql: path: /docs/graphql - controller: api_platform.graphql.action.graphiql + controller: api_platform.graphql.action.graphql_playground diff --git a/config/services/graphql/graphql_allow_introspection.yaml b/config/services/graphql/graphql_allow_introspection.yaml new file mode 100644 index 0000000000..b94f324556 --- /dev/null +++ b/config/services/graphql/graphql_allow_introspection.yaml @@ -0,0 +1,2 @@ +parameters: + graphql.graphql_show_docs: '%env(default::bool:GRAPHQL_SHOW_DOCS)%' diff --git a/core/app/common/package.json b/core/app/common/package.json index 247a68c6a5..dda4518c6b 100644 --- a/core/app/common/package.json +++ b/core/app/common/package.json @@ -1,6 +1,6 @@ { "name": "common", - "version": "8.4.1", + "version": "8.4.2", "peerDependencies": { "@angular/common": "^12.1.0", "@angular/core": "^12.1.0", diff --git a/core/app/core/package.json b/core/app/core/package.json index f2d5ee4095..a845acafdb 100644 --- a/core/app/core/package.json +++ b/core/app/core/package.json @@ -1,6 +1,6 @@ { "name": "core", - "version": "8.4.1", + "version": "8.4.2", "peerDependencies": { "@angular/common": "^12.1.0", "@angular/core": "^12.1.0", diff --git a/core/backend/Kernel.php b/core/backend/Kernel.php index 660efb87c4..64a8eadaff 100644 --- a/core/backend/Kernel.php +++ b/core/backend/Kernel.php @@ -129,4 +129,15 @@ public function getLegacyRoute(Request $request): array return []; } + + /** + * Enable/disable graphql introspection + * @return void + */ + public function configureGraphqlIntrospection(): void + { + if ($this->container->has('graphql.introspection_manager')) { + $this->container->get('graphql.introspection_manager')->configure(); + } + } } diff --git a/core/backend/Migrations/Version20231108164138.php b/core/backend/Migrations/Version20231108164138.php new file mode 100644 index 0000000000..61a158c79b --- /dev/null +++ b/core/backend/Migrations/Version20231108164138.php @@ -0,0 +1,56 @@ +container->get('app.system-configs'); + $systemConfigs = $systemConfigsHandler->getConfigs(); + if (isset($systemConfigs['allowed_preview']) && in_array('pdf', $systemConfigs['allowed_preview'])) { + $key = array_search('pdf', $systemConfigs['allowed_preview']); + unset($systemConfigs['allowed_preview'][$key]); + $systemConfigsHandler->updateSystemConfig($systemConfigs); + $this->log('Removed PDF from allowed_preview inside config file.'); + return; + } + + $this->log('PDF was not found in allowed_preview config skipping...'); + + } + + public function down(Schema $schema) : void + { + // this down() migration is auto-generated, please modify it to your needs + + } +} diff --git a/core/backend/Security/GraphqlIntrospectionManager.php b/core/backend/Security/GraphqlIntrospectionManager.php new file mode 100644 index 0000000000..183f9fb571 --- /dev/null +++ b/core/backend/Security/GraphqlIntrospectionManager.php @@ -0,0 +1,64 @@ +. + * + * In accordance with Section 7(b) of the GNU Affero General Public License + * version 3, these Appropriate Legal Notices must retain the display of the + * "Supercharged by SuiteCRM" logo. If the display of the logos is not reasonably + * feasible for technical reasons, the Appropriate Legal Notices must display + * the words "Supercharged by SuiteCRM". + */ + +namespace App\Security; + +use GraphQL\Validator\DocumentValidator; +use GraphQL\Validator\Rules\DisableIntrospection; + +class GraphqlIntrospectionManager +{ + /** + * @var bool|null + */ + private $graphqlShowDocs; + + /** + * @param bool|null $graphqlShowDocs + */ + public function __construct( + ?bool $graphqlShowDocs + ) { + $this->graphqlShowDocs = $graphqlShowDocs; + } + + /** + * Enable/disable graphql introspection + * @return void + */ + public function configure(): void + { + $env = $_ENV ?? []; + $appEnv = $env['APP_ENV'] ?? 'prod'; + $showDocs = $this->graphqlShowDocs ?? ($appEnv === 'dev'); + + if ($showDocs === false) { + DocumentValidator::addRule(new DisableIntrospection()); + } + } + +} diff --git a/package.json b/package.json index 654b4e4846..e3c380c94b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "suitecrm", - "version": "8.4.1", + "version": "8.4.2", "scripts": { "ng": "ng", "start": "npm run start:shell", diff --git a/public/index.php b/public/index.php index b6935b7cc7..ee89f79aa1 100644 --- a/public/index.php +++ b/public/index.php @@ -59,6 +59,7 @@ } } else { + $kernel->configureGraphqlIntrospection(); $response = $kernel->handle($request); $response->send(); $kernel->terminate($request, $response); diff --git a/public/legacy/modules/AOP_Case_Updates/AOP_Case_Updates.php b/public/legacy/modules/AOP_Case_Updates/AOP_Case_Updates.php index 9bac0dcd2b..b12e3a7eb1 100755 --- a/public/legacy/modules/AOP_Case_Updates/AOP_Case_Updates.php +++ b/public/legacy/modules/AOP_Case_Updates/AOP_Case_Updates.php @@ -106,7 +106,8 @@ public function bean_implements($interface) */ public function save($check_notify = false) { - $this->name = SugarCleaner::cleanHtml($this->name); + + $this->name = SugarCleaner::cleanHtml($this->name ?? ''); $this->parseDescription(); parent::save($check_notify); if (file_exists('custom/modules/AOP_Case_Updates/CaseUpdatesHook.php')) {