mirror of
https://github.com/nextcloud/server.git
synced 2026-02-03 20:41:22 -05:00
feat(config): add serverid configuration and use it for Snowflakes
Signed-off-by: Benjamin Gaussorgues <benjamin.gaussorgues@nextcloud.com>
This commit is contained in:
parent
69ec2ce26b
commit
1f74ed9239
7 changed files with 99 additions and 3 deletions
|
|
@ -132,6 +132,7 @@ return array(
|
|||
'OCA\\Settings\\SetupChecks\\ReadOnlyConfig' => $baseDir . '/../lib/SetupChecks/ReadOnlyConfig.php',
|
||||
'OCA\\Settings\\SetupChecks\\SchedulingTableSize' => $baseDir . '/../lib/SetupChecks/SchedulingTableSize.php',
|
||||
'OCA\\Settings\\SetupChecks\\SecurityHeaders' => $baseDir . '/../lib/SetupChecks/SecurityHeaders.php',
|
||||
'OCA\\Settings\\SetupChecks\\ServerIdConfig' => $baseDir . '/../lib/SetupChecks/ServerIdConfig.php',
|
||||
'OCA\\Settings\\SetupChecks\\SupportedDatabase' => $baseDir . '/../lib/SetupChecks/SupportedDatabase.php',
|
||||
'OCA\\Settings\\SetupChecks\\SystemIs64bit' => $baseDir . '/../lib/SetupChecks/SystemIs64bit.php',
|
||||
'OCA\\Settings\\SetupChecks\\TaskProcessingPickupSpeed' => $baseDir . '/../lib/SetupChecks/TaskProcessingPickupSpeed.php',
|
||||
|
|
|
|||
|
|
@ -147,6 +147,7 @@ class ComposerStaticInitSettings
|
|||
'OCA\\Settings\\SetupChecks\\ReadOnlyConfig' => __DIR__ . '/..' . '/../lib/SetupChecks/ReadOnlyConfig.php',
|
||||
'OCA\\Settings\\SetupChecks\\SchedulingTableSize' => __DIR__ . '/..' . '/../lib/SetupChecks/SchedulingTableSize.php',
|
||||
'OCA\\Settings\\SetupChecks\\SecurityHeaders' => __DIR__ . '/..' . '/../lib/SetupChecks/SecurityHeaders.php',
|
||||
'OCA\\Settings\\SetupChecks\\ServerIdConfig' => __DIR__ . '/..' . '/../lib/SetupChecks/ServerIdConfig.php',
|
||||
'OCA\\Settings\\SetupChecks\\SupportedDatabase' => __DIR__ . '/..' . '/../lib/SetupChecks/SupportedDatabase.php',
|
||||
'OCA\\Settings\\SetupChecks\\SystemIs64bit' => __DIR__ . '/..' . '/../lib/SetupChecks/SystemIs64bit.php',
|
||||
'OCA\\Settings\\SetupChecks\\TaskProcessingPickupSpeed' => __DIR__ . '/..' . '/../lib/SetupChecks/TaskProcessingPickupSpeed.php',
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ use OCA\Settings\SetupChecks\RandomnessSecure;
|
|||
use OCA\Settings\SetupChecks\ReadOnlyConfig;
|
||||
use OCA\Settings\SetupChecks\SchedulingTableSize;
|
||||
use OCA\Settings\SetupChecks\SecurityHeaders;
|
||||
use OCA\Settings\SetupChecks\ServerIdConfig;
|
||||
use OCA\Settings\SetupChecks\SupportedDatabase;
|
||||
use OCA\Settings\SetupChecks\SystemIs64bit;
|
||||
use OCA\Settings\SetupChecks\TaskProcessingPickupSpeed;
|
||||
|
|
@ -207,6 +208,7 @@ class Application extends App implements IBootstrap {
|
|||
$context->registerSetupCheck(RandomnessSecure::class);
|
||||
$context->registerSetupCheck(ReadOnlyConfig::class);
|
||||
$context->registerSetupCheck(SecurityHeaders::class);
|
||||
$context->registerSetupCheck(ServerIdConfig::class);
|
||||
$context->registerSetupCheck(SchedulingTableSize::class);
|
||||
$context->registerSetupCheck(SupportedDatabase::class);
|
||||
$context->registerSetupCheck(SystemIs64bit::class);
|
||||
|
|
|
|||
57
apps/settings/lib/SetupChecks/ServerIdConfig.php
Normal file
57
apps/settings/lib/SetupChecks/ServerIdConfig.php
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace OCA\Settings\SetupChecks;
|
||||
|
||||
use OCP\IConfig;
|
||||
use OCP\IL10N;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\SetupCheck\ISetupCheck;
|
||||
use OCP\SetupCheck\SetupResult;
|
||||
use Override;
|
||||
|
||||
final class ServerIdConfig implements ISetupCheck {
|
||||
public function __construct(
|
||||
private readonly IL10N $l10n,
|
||||
private readonly IConfig $config,
|
||||
private readonly IURLGenerator $urlGenerator,
|
||||
) {
|
||||
}
|
||||
|
||||
#[Override]
|
||||
public function getName(): string {
|
||||
return $this->l10n->t('Configuration server ID');
|
||||
}
|
||||
|
||||
#[Override]
|
||||
public function getCategory(): string {
|
||||
return 'config';
|
||||
}
|
||||
|
||||
#[Override]
|
||||
public function run(): SetupResult {
|
||||
$serverid = $this->config->getSystemValueInt('serverid', PHP_INT_MIN);
|
||||
$linkToDoc = $this->urlGenerator->linkToDocs('admin-update');
|
||||
|
||||
if ($serverid === PHP_INT_MIN) {
|
||||
return SetupResult::info(
|
||||
$this->l10n->t('server identifier isn’t configured. It is recommended if your Nextcloud instance is running on several PHP servers. Add a serverid in your configuration.'),
|
||||
$linkToDoc,
|
||||
);
|
||||
}
|
||||
|
||||
if ($serverid < 0 || $serverid > 1023) {
|
||||
return SetupResult::error(
|
||||
$this->l10n->t('"%d" is not a valid server identifier. It must be between 0 and 1023.', [$serverid]),
|
||||
$linkToDoc,
|
||||
);
|
||||
}
|
||||
|
||||
return SetupResult::success($this->l10n->t('server identifier is configured and valid.'));
|
||||
}
|
||||
}
|
||||
|
|
@ -45,6 +45,20 @@ $CONFIG = [
|
|||
*/
|
||||
'instanceid' => '',
|
||||
|
||||
/**
|
||||
* This is a unique identifier for your server.
|
||||
* It is useful when your Nextcloud instance is using different PHP servers.
|
||||
* Once it's set it shouldn't be changed.
|
||||
*
|
||||
* Value must be an integer, comprised between 0 and 1023.
|
||||
*
|
||||
* When config.php is shared between different servers, this value should be overriden with "NC_serverid=<int>" on each server.
|
||||
* Note that it must be overriden for CLI and for your webserver.
|
||||
*
|
||||
* Example for CLI: NC_serverid=42 occ config:list system
|
||||
*/
|
||||
'serverid' => -1,
|
||||
|
||||
/**
|
||||
* The salt used to hash all passwords, auto-generated by the Nextcloud
|
||||
* installer. (There are also per-user salts.) If you lose this salt, you lose
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ declare(strict_types=1);
|
|||
namespace OC\Snowflake;
|
||||
|
||||
use OCP\AppFramework\Utility\ITimeFactory;
|
||||
use OCP\IConfig;
|
||||
use OCP\Snowflake\IGenerator;
|
||||
use Override;
|
||||
|
||||
|
|
@ -23,6 +24,7 @@ use Override;
|
|||
final class Generator implements IGenerator {
|
||||
public function __construct(
|
||||
private readonly ITimeFactory $timeFactory,
|
||||
private readonly IConfig $config,
|
||||
private readonly ISequence $sequenceGenerator,
|
||||
) {
|
||||
}
|
||||
|
|
@ -100,8 +102,14 @@ final class Generator implements IGenerator {
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return configured serverid or generate one if not set
|
||||
*/
|
||||
private function getServerId(): int {
|
||||
return crc32(gethostname() ?: random_bytes(8));
|
||||
$serverid = $this->config->getSystemValueInt('serverid', -1);
|
||||
return $serverid > 0
|
||||
? $serverid
|
||||
: crc32(gethostname() ?: random_bytes(8));
|
||||
}
|
||||
|
||||
private function isCli(): bool {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ use OC\Snowflake\Decoder;
|
|||
use OC\Snowflake\Generator;
|
||||
use OC\Snowflake\ISequence;
|
||||
use OCP\AppFramework\Utility\ITimeFactory;
|
||||
use OCP\IConfig;
|
||||
use OCP\Snowflake\IGenerator;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
|
|
@ -24,17 +25,25 @@ use Test\TestCase;
|
|||
*/
|
||||
class GeneratorTest extends TestCase {
|
||||
private Decoder $decoder;
|
||||
private IConfig&MockObject $config;
|
||||
private ISequence&MockObject $sequence;
|
||||
|
||||
public function setUp():void {
|
||||
$this->decoder = new Decoder();
|
||||
|
||||
$this->config = $this->createMock(IConfig::class);
|
||||
$this->config->method('getSystemValueInt')
|
||||
->with('serverid')
|
||||
->willReturn(42);
|
||||
|
||||
$this->sequence = $this->createMock(ISequence::class);
|
||||
$this->sequence->method('isAvailable')->willReturn(true);
|
||||
$this->sequence->method('nextId')->willReturn(421);
|
||||
|
||||
}
|
||||
|
||||
public function testGenerator(): void {
|
||||
$generator = new Generator(new TimeFactory(), $this->sequence);
|
||||
$generator = new Generator(new TimeFactory(), $this->config, $this->sequence);
|
||||
$snowflakeId = $generator->nextId();
|
||||
$data = $this->decoder->decode($generator->nextId());
|
||||
|
||||
|
|
@ -52,6 +61,9 @@ class GeneratorTest extends TestCase {
|
|||
|
||||
// Check CLI
|
||||
$this->assertTrue($data['isCli']);
|
||||
|
||||
// Check serverId
|
||||
$this->assertEquals(42, $data['serverId']);
|
||||
}
|
||||
|
||||
#[DataProvider('provideSnowflakeData')]
|
||||
|
|
@ -60,11 +72,12 @@ class GeneratorTest extends TestCase {
|
|||
$timeFactory = $this->createMock(ITimeFactory::class);
|
||||
$timeFactory->method('now')->willReturn($dt);
|
||||
|
||||
$generator = new Generator($timeFactory, $this->sequence);
|
||||
$generator = new Generator($timeFactory, $this->config, $this->sequence);
|
||||
$data = $this->decoder->decode($generator->nextId());
|
||||
|
||||
$this->assertEquals($expectedSeconds, ($data['createdAt']->format('U') - IGenerator::TS_OFFSET));
|
||||
$this->assertEquals($expectedMilliseconds, (int)$data['createdAt']->format('v'));
|
||||
$this->assertEquals(42, $data['serverId']);
|
||||
}
|
||||
|
||||
public static function provideSnowflakeData(): array {
|
||||
|
|
|
|||
Loading…
Reference in a new issue