diff --git a/config/services.yaml b/config/services.yaml index f69af332..b2eaae3a 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -90,7 +90,7 @@ services: # # Workflows # - + OpenDxp\Bundle\AdminBundle\Service\Workflow\ActionsButtonService: ~ OpenDxp\Bundle\AdminBundle\Resolver\Workflow\WorkflowElementResolver: ~ @@ -160,6 +160,7 @@ services: OpenDxp\Bundle\AdminBundle\Service\Admin\AdminSettingsService: ~ OpenDxp\Bundle\AdminBundle\Service\Admin\AdminStatisticsService: ~ + OpenDxp\Bundle\AdminBundle\Service\Admin\InstanceIdentityService: ~ # # Repositories diff --git a/public/js/opendxp/startup.js b/public/js/opendxp/startup.js index 6e8c5c6a..30e3c7c8 100644 --- a/public/js/opendxp/startup.js +++ b/public/js/opendxp/startup.js @@ -496,11 +496,16 @@ Ext.onReady(function () { const sitesStore = new Ext.data.Store({ model: 'opendxp.model.sites' }); - sitesStore.load(); opendxp.globalmanager.add('sites', sitesStore); // check for updates - window.setTimeout(function () { + sitesStore.load({ + callback: function () { + window.setTimeout(sendMetricsCheck, 5000); + } + }); + + function sendMetricsCheck() { const domains = []; opendxp.globalmanager.get('sites').each(function (rec) { if (rec.get('rootId') !== 1) { @@ -515,6 +520,7 @@ Ext.onReady(function () { const data = { instance_id: opendxp.settings.instanceId, + system_uuid: opendxp.settings.systemUuid, revision: opendxp.settings.build, version: opendxp.settings.version, debug: opendxp.settings.debug, @@ -597,7 +603,7 @@ Ext.onReady(function () { .catch(error => { console.error('Metrics fetch error', error); }); - }, 5000); + } Ext.get('opendxp_logout')?.on('click', function () { document.getElementById('opendxp_logout_form').submit(); @@ -959,4 +965,4 @@ opendxp.helpers.unload = function () { if (!opendxp.wysiwyg) { opendxp.wysiwyg = {}; opendxp.wysiwyg.editors = []; -} \ No newline at end of file +} diff --git a/src/Dto/Admin/AdminSettingsDto.php b/src/Dto/Admin/AdminSettingsDto.php index 14782169..ceb95ebe 100644 --- a/src/Dto/Admin/AdminSettingsDto.php +++ b/src/Dto/Admin/AdminSettingsDto.php @@ -21,6 +21,7 @@ public function __construct( // Core identity public string $instanceId, + public string $systemUuid, public string $version, public string $build, public bool $debug, @@ -103,6 +104,7 @@ public function asSettingsArray(): array { return [ 'instanceId' => $this->instanceId, + 'systemUuid' => $this->systemUuid, 'version' => $this->version, 'build' => $this->build, 'debug' => $this->debug, diff --git a/src/Dto/Admin/StatisticsDto.php b/src/Dto/Admin/StatisticsDto.php index 02bcee07..b8cddc02 100644 --- a/src/Dto/Admin/StatisticsDto.php +++ b/src/Dto/Admin/StatisticsDto.php @@ -20,12 +20,14 @@ { public function __construct( public string $instanceId, + public string $systemUuid, public string $revision, public string $version, public int $majorVersion, public string $phpVersion, public ?string $dbVersion, public array $bundles, + public string $environment, ) { } @@ -33,12 +35,14 @@ public function asStatisticsArray(): array { return [ 'instance_id' => $this->instanceId, + 'system_uuid' => $this->systemUuid, 'revision' => $this->revision, 'version' => $this->version, 'major_version' => $this->majorVersion, 'php_version' => $this->phpVersion, 'db_version' => $this->dbVersion, 'bundles' => $this->bundles, + 'environment' => $this->environment, ]; } } diff --git a/src/Service/Admin/AdminSettingsService.php b/src/Service/Admin/AdminSettingsService.php index cf73c8e1..3c188d6f 100644 --- a/src/Service/Admin/AdminSettingsService.php +++ b/src/Service/Admin/AdminSettingsService.php @@ -58,10 +58,9 @@ public function __construct( private readonly KernelInterface $kernel, private readonly RequestStack $requestStack, private readonly SessionIdentityInterface $sessionIdentity, + private readonly InstanceIdentityService $instanceIdentity, #[Autowire('%opendxp_admin.custom_admin_route_name%')] private readonly string $customAdminRouteName, - #[Autowire('%secret%')] - private readonly string $secret, ) { } @@ -110,15 +109,17 @@ public function createSettings(string $locale, User $user): AdminSettingsDto } $notificationsEnabled = (bool) $config['notifications']['enabled']; + $environment = $this->kernel->getEnvironment(); return new AdminSettingsDto( - instanceId: $this->buildInstanceId(), + instanceId: $this->instanceIdentity->getInstanceId(), + systemUuid: $this->instanceIdentity->getSystemUuid($environment), version: Version::getVersion(), build: Version::getRevision(), debug: OpenDxp::inDebugMode(), devMode: OpenDxp::inDevMode(), disableMinifyJs: OpenDxp::disableMinifyJs(), - environment: $this->kernel->getEnvironment(), + environment: $environment, sessionId: htmlentities($this->sessionIdentity->getId(), ENT_QUOTES, 'UTF-8'), language: $locale, @@ -191,15 +192,6 @@ classDefinitionWriteable: !isset($_SERVER['OPENDXP_CLASS_DEFINITION_WRITABLE']) ); } - private function buildInstanceId(): string - { - try { - return sha1(substr($this->secret, 3, -3)); - } catch (Exception) { - return 'not-set'; - } - } - private function buildCustomViews(): array { $cvData = []; diff --git a/src/Service/Admin/AdminStatisticsService.php b/src/Service/Admin/AdminStatisticsService.php index 5de4ddde..3d50ae22 100644 --- a/src/Service/Admin/AdminStatisticsService.php +++ b/src/Service/Admin/AdminStatisticsService.php @@ -17,10 +17,8 @@ namespace OpenDxp\Bundle\AdminBundle\Service\Admin; use Doctrine\DBAL\Connection; -use Exception; use OpenDxp\Bundle\AdminBundle\Dto\Admin\StatisticsDto; use OpenDxp\Version; -use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\HttpKernel\KernelInterface; use Throwable; @@ -29,8 +27,7 @@ final class AdminStatisticsService public function __construct( private readonly Connection $db, private readonly KernelInterface $kernel, - #[Autowire('%secret%')] - private readonly string $secret, + private readonly InstanceIdentityService $instanceIdentity, ) { } @@ -43,22 +40,15 @@ public function createStatistics(): StatisticsDto } return new StatisticsDto( - instanceId: $this->buildInstanceId(), + instanceId: $this->instanceIdentity->getInstanceId(), + systemUuid: $this->instanceIdentity->getSystemUuid($this->kernel->getEnvironment()), revision: Version::getRevision(), version: Version::getVersion(), majorVersion: Version::getMajorVersion(), phpVersion: PHP_VERSION, dbVersion: is_string($dbVersion) ? $dbVersion : null, bundles: array_keys($this->kernel->getBundles()), + environment: $this->kernel->getEnvironment(), ); } - - private function buildInstanceId(): string - { - try { - return sha1(substr($this->secret, 3, -3)); - } catch (Exception) { - return 'not-set'; - } - } } diff --git a/src/Service/Admin/InstanceIdentityService.php b/src/Service/Admin/InstanceIdentityService.php new file mode 100644 index 00000000..2be5f10d --- /dev/null +++ b/src/Service/Admin/InstanceIdentityService.php @@ -0,0 +1,65 @@ +secret, 3, -3)); + } catch (Exception) { + return 'not-set'; + } + } + + public function getSystemUuid(string $environment): string + { + try { + $rootUuid = $this->getOrCreateRootUuid(); + + return Uuid::v5(Uuid::fromString($rootUuid), $environment)->toRfc4122(); + } catch (Exception) { + // fall back to a random, non-colliding, non-persisted value + return bin2hex(random_bytes(16)); + } + } + + /** + * @throws Exception + */ + private function getOrCreateRootUuid(): string + { + $existing = SettingsStore::get(self::SETTINGS_STORE_KEY, self::SETTINGS_STORE_SCOPE); + if ($existing !== null) { + return (string) $existing->getData(); + } + + $rootUuid = Uuid::v4()->toRfc4122(); + SettingsStore::set(self::SETTINGS_STORE_KEY, $rootUuid, SettingsStore::TYPE_STRING, self::SETTINGS_STORE_SCOPE); + + return $rootUuid; + } +}