Updated dependencies, improved config

* Configuration now key-value map with friendly accessors.
* Configuration file maps 1:1
This commit is contained in:
Chris 2024-03-12 00:28:31 +01:00
parent c810876aa4
commit da450b510a
5 changed files with 62 additions and 76 deletions

View File

@ -31,8 +31,9 @@ if (isset($opts['C'])) {
exit(1); exit(1);
} }
file_put_contents($file, <<<DEFAULTS file_put_contents($file, <<<DEFAULTS
listeners: server:
- address: 0.0.0.0:9000 public_url: https://example.com
address: 0.0.0.0:9000
cors: cors:
allow_origin: '*' allow_origin: '*'
csp: "default-src * 'self' http: 'unsafe-eval' 'unsafe-inline'; connect-src * 'self'" csp: "default-src * 'self' http: 'unsafe-eval' 'unsafe-inline'; connect-src * 'self'"
@ -62,20 +63,12 @@ if (isset($opts['c'])) {
$config = Configuration::fromFile($opts['c']); $config = Configuration::fromFile($opts['c']);
} else { } else {
$config = Configuration::createDefault() $config = Configuration::createDefault()
->addListener([ ->setListenAddress('127.0.0.1:8888')
'address' => '127.0.0.1:8888', ->setAllowOriginHeader("*")
'subscribe' => [ ->setContentSecurityPolicyHeader("default-src * 'self' http: 'unsafe-eval' 'unsafe-inline'; connect-src * 'self'")
'anonymous' => true
]
])
->setAllowAnonymousSubscribe(true) ->setAllowAnonymousSubscribe(true)
->setJwtSecret("!ChangeThisMercureHubJWTSecretKey!"); ->setJwtSecret("!ChangeThisMercureHubJWTSecretKey!");
} }
if (count($config->getListeners()) == 0) {
fwrite(STDERR, "No listeners available\n");
exit(1);
}
$daemon = new Daemon($config); $daemon = new Daemon($config);
$daemon->start(); $daemon->start();

8
composer.lock generated
View File

@ -249,11 +249,11 @@
}, },
{ {
"name": "noccylabs/simple-jwt", "name": "noccylabs/simple-jwt",
"version": "0.2.1", "version": "0.2.2",
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://dev.noccylabs.info/api/packages/noccy/composer/files/noccylabs%2Fsimple-jwt/0.2.1/noccylabs-simple-jwt.0.2.1.zip", "url": "https://dev.noccylabs.info/api/packages/noccy/composer/files/noccylabs%2Fsimple-jwt/0.2.2/noccylabs-simple-jwt.0.2.2.zip",
"shasum": "d55b26f9c8dbe8be4b49786492818085982a5089" "shasum": "57d3fd6f5c3bebb62f15477beffc5425f6f5b7d9"
}, },
"require": { "require": {
"ext-json": "*", "ext-json": "*",
@ -279,7 +279,7 @@
} }
], ],
"description": "Simple library for generating and verifying JWT tokens", "description": "Simple library for generating and verifying JWT tokens",
"time": "2023-04-10T00:31:31+00:00" "time": "2024-03-11T22:37:17+00:00"
}, },
{ {
"name": "psr/http-message", "name": "psr/http-message",

View File

@ -1,20 +1,20 @@
# Mercureact default configuration file # Mercureact default configuration file
# Please make a copy of me before editing # Please make a copy of me before editing
listeners: server:
- address: 0.0.0.0:9000 address: 0.0.0.0:9000
# Setup CORS headers # Setup CORS headers
cors: cors:
# Access-Control-Allow-Origin # Access-Control-Allow-Origin
allow_origin: '*' allow_origin: '*'
# Content-Security-Policy # Content-Security-Policy
csp: "default-src * 'self' http: 'unsafe-eval' 'unsafe-inline'; connect-src * 'self'" csp: "default-src * 'self' http: 'unsafe-eval' 'unsafe-inline'; connect-src * 'self'"
# Setup encryption # Setup encryption
encryption: encryption:
cert: foo.pem cert: foo.pem
key: foo.key key: foo.key
# Enable websockets # Enable websockets
websocket: websocket:

View File

@ -6,13 +6,8 @@ use Symfony\Component\Yaml\Yaml;
class Configuration class Configuration
{ {
private ?string $publicUrl = null; private array $config = [];
private ?string $jwtSecret = null;
private bool $allowAnonymousSubscribe = false;
private array $listeners = [];
public static function createDefault(): Configuration public static function createDefault(): Configuration
{ {
@ -30,81 +25,77 @@ class Configuration
$data = file_get_contents($file); $data = file_get_contents($file);
$yaml = Yaml::parse($data); $yaml = Yaml::parse($data);
if (isset($yaml['security'])) { $unwrap = null; // mute IDE complains about $unwrap not defined
$security = $yaml['security']; $unwrap = function (array $array, Configuration $target, array $path=[]) use (&$unwrap) {
if (isset($security['jwt_secret'])) foreach ($array as $key=>$value) {
$config->setJwtSecret($security['jwt_secret']); if (is_array($value)) {
} $unwrap($value, $target, [ ...$path, $key ]);
} else {
if (isset($yaml['subscribe'])) { $key = join(".", [ ...$path, $key ]);
$subscribe = $yaml['subscribe']; $target->config[$key] = $value;
if (isset($subscribe['allow_anonymous']))
$config->setAllowAnonymousSubscribe(boolval($subscribe['allow_anonymous']));
}
if (isset($yaml['listeners'])) {
foreach ($yaml['listeners'] as $listener) {
if (!is_array($listener)) {
throw new \Exception("Bad listener config");
} }
$config->addListener($listener);
} }
} };
$unwrap($yaml, $config);
return $config; return $config;
} }
public function setPublicUrl(string $publicUrl): self public function setPublicUrl(string $publicUrl): self
{ {
$this->publicUrl = $publicUrl; $this->config['server.public_url'] = $publicUrl;
return $this; return $this;
} }
public function getPublicUrl(): ?string public function getPublicUrl(): ?string
{ {
return $this->publicUrl; return $this->config['server.public_url']??null;
} }
public function setJwtSecret(string $secret): self public function setJwtSecret(string $secret): self
{ {
$this->jwtSecret = $secret; $this->config['security.jwt_secret'] = $secret;
return $this; return $this;
} }
public function getJwtSecret(): ?string public function getJwtSecret(): ?string
{ {
return $this->jwtSecret; return $this->config['security.jwt_secret']??null;
} }
function getAllowAnonymousSubscribe():bool function getAllowAnonymousSubscribe():bool
{ {
return $this->allowAnonymousSubscribe; return $this->config['subscribe.allow_anonymous']??false;
} }
function setAllowAnonymousSubscribe(bool $allowAnonymousSubscribe): self function setAllowAnonymousSubscribe(bool $allowAnonymousSubscribe): self
{ {
$this->allowAnonymousSubscribe = $allowAnonymousSubscribe; $this->config['subscribe.allow_anonymous'] = $allowAnonymousSubscribe;
return $this; return $this;
} }
function addListener(array $config): self public function setListenAddress(string $address): self
{ {
$this->listeners[] = [ $this->config['server.address'] = $address;
'address' => $config['address']??throw new \Exception("Address can't be empty"),
'cors' => isset($config['cors'])?[
'allow_origin' => $config['cors']['allow_origin']??'*',
'csp' => $config['cors']['csp']??'default-src * \'self\'',
]:[
'allow_origin' => '*',
'csp' => 'default-src * \'self\'',
],
];
return $this; return $this;
} }
public function getListeners(): array public function getListenAddress(): ?string
{ {
return $this->listeners; return $this->config['server.address']??null;
} }
public function setAllowOriginHeader(string $value): self
{
$this->config['headers.allow_origin'] = $value;
return $this;
}
public function setContentSecurityPolicyHeader(string $value): self
{
$this->config['headers.csp'] = $value;
return $this;
}
} }

View File

@ -25,11 +25,13 @@ class Daemon
{ {
$this->server = new Server($this->config, $this->loop); $this->server = new Server($this->config, $this->loop);
$listeners = $this->config->getListeners(); $listenAddress = $this->config->getListenAddress();
foreach ($listeners as $listener) { if (!$listenAddress) {
$socket = new SocketServer("tcp://".$listener['address']); fwrite(STDERR, "Warning: Empty listening address. You won't make it far.\n");
$this->server->listen($socket); return;
} }
$socket = new SocketServer("tcp://".$listenAddress);
$this->server->listen($socket);
} }
public function stop(): void public function stop(): void