web-base/Core/Configuration/Settings.class.php

221 lines
7.6 KiB
PHP
Raw Normal View History

2020-06-25 16:54:58 +02:00
<?php
/**
* Do not change settings here, they are dynamically loaded from database.
*/
2022-11-18 18:06:46 +01:00
namespace Core\Configuration;
2020-06-25 16:54:58 +02:00
2022-11-18 18:06:46 +01:00
use Core\Driver\Logger\Logger;
use Core\Driver\SQL\Query\Insert;
use Core\Objects\Context;
2020-06-25 16:54:58 +02:00
class Settings {
2021-04-02 21:58:06 +02:00
//
private bool $installationComplete;
// settings
2020-06-25 16:54:58 +02:00
private string $siteName;
private string $baseUrl;
2022-11-18 18:06:46 +01:00
private ?string $jwtPublicKey;
private ?string $jwtSecretKey;
2022-10-23 21:26:27 +02:00
private string $jwtAlgorithm;
2020-06-25 16:54:58 +02:00
private bool $registrationAllowed;
2020-06-26 23:32:45 +02:00
private bool $recaptchaEnabled;
2021-04-02 21:58:06 +02:00
private bool $mailEnabled;
2020-06-26 23:32:45 +02:00
private string $recaptchaPublicKey;
private string $recaptchaPrivateKey;
2022-02-20 16:53:26 +01:00
private string $mailSender;
private string $mailFooter;
private array $allowedExtensions;
2020-06-25 16:54:58 +02:00
2022-10-23 21:26:27 +02:00
//
private Logger $logger;
public function __construct() {
$this->logger = new Logger("Settings");
}
2022-11-18 18:06:46 +01:00
public function getJwtPublicKey(bool $allowPrivate = true): ?\Firebase\JWT\Key {
if (empty($this->jwtPublicKey)) {
// we might have a symmetric key, should we instead return the private key?
return $allowPrivate ? new \Firebase\JWT\Key($this->jwtSecretKey, $this->jwtAlgorithm) : null;
} else {
return new \Firebase\JWT\Key($this->jwtPublicKey, $this->jwtAlgorithm);
}
2022-10-23 21:26:27 +02:00
}
public function getJwtSecretKey(): \Firebase\JWT\Key {
return new \Firebase\JWT\Key($this->jwtSecretKey, $this->jwtAlgorithm);
2020-06-25 16:54:58 +02:00
}
2021-04-02 21:58:06 +02:00
public function isInstalled(): bool {
2020-06-25 16:54:58 +02:00
return $this->installationComplete;
}
2021-04-02 21:58:06 +02:00
public static function loadDefaults(): Settings {
2021-04-07 00:03:14 +02:00
$hostname = $_SERVER["SERVER_NAME"] ?? "localhost";
2020-06-25 16:54:58 +02:00
$protocol = getProtocol();
$settings = new Settings();
2022-10-23 21:26:27 +02:00
// General
2020-06-25 16:54:58 +02:00
$settings->siteName = "WebBase";
$settings->baseUrl = "$protocol://$hostname";
2022-10-23 21:26:27 +02:00
$settings->allowedExtensions = ['png', 'jpg', 'jpeg', 'gif', 'htm', 'html'];
2020-06-25 16:54:58 +02:00
$settings->installationComplete = false;
$settings->registrationAllowed = false;
2022-10-23 21:26:27 +02:00
// JWT
$settings->jwtSecretKey = null;
$settings->jwtPublicKey = null;
$settings->jwtAlgorithm = "HS256";
// Recaptcha
$settings->recaptchaEnabled = false;
2020-06-26 23:32:45 +02:00
$settings->recaptchaPublicKey = "";
$settings->recaptchaPrivateKey = "";
2022-10-23 21:26:27 +02:00
// Mail
2021-04-02 21:58:06 +02:00
$settings->mailEnabled = false;
2022-02-20 16:53:26 +01:00
$settings->mailSender = "webmaster@localhost";
$settings->mailFooter = "";
2022-10-23 21:26:27 +02:00
2022-02-20 16:53:26 +01:00
2020-06-25 16:54:58 +02:00
return $settings;
}
2022-10-23 21:26:27 +02:00
public function generateJwtKey(string $algorithm = null): bool {
$this->jwtAlgorithm = $algorithm ?? $this->jwtAlgorithm;
// TODO: key encryption necessary?
if (in_array($this->jwtAlgorithm, ["HS256", "HS384", "HS512"])) {
$this->jwtSecretKey = generateRandomString(32);
$this->jwtPublicKey = null;
} else if (in_array($this->jwtAlgorithm, ["RS256", "RS384", "RS512"])) {
$bits = intval(substr($this->jwtAlgorithm, 2));
$private_key = openssl_pkey_new(["private_key_bits" => $bits]);
$this->jwtPublicKey = openssl_pkey_get_details($private_key)['key'];
openssl_pkey_export($private_key, $this->jwtSecretKey);
} else if (in_array($this->jwtAlgorithm, ["ES256", "ES384"])) {
// $ec = new \Elliptic\EC('secp256k1'); ??
$this->logger->error("JWT algorithm: '$this->jwtAlgorithm' is currently not supported.");
return false;
} else if ($this->jwtAlgorithm == "EdDSA") {
$keyPair = sodium_crypto_sign_keypair();
$this->jwtSecretKey = base64_encode(sodium_crypto_sign_secretkey($keyPair));
$this->jwtPublicKey = base64_encode(sodium_crypto_sign_publickey($keyPair));
} else {
$this->logger->error("Invalid JWT algorithm: '$this->jwtAlgorithm', expected one of: " .
implode(",", array_keys(\Firebase\JWT\JWT::$supported_algs)));
return false;
}
return true;
}
2022-11-18 18:06:46 +01:00
public static function isJwtAlgorithmSupported(string $algorithm): bool {
return in_array(strtoupper($algorithm), ["HS256", "HS384", "HS512", "RS256", "RS384", "RS512", "EDDSA"]);
}
2022-10-23 21:26:27 +02:00
public function saveJwtKey(Context $context) {
2022-11-18 18:06:46 +01:00
$req = new \Core\API\Settings\Set($context);
2022-10-23 21:26:27 +02:00
$req->execute(array("settings" => array(
"jwt_secret_key" => $this->jwtSecretKey,
"jwt_public_key" => $this->jwtSecretKey,
"jwt_algorithm" => $this->jwtAlgorithm,
)));
2022-11-18 18:06:46 +01:00
return $req;
2022-10-23 21:26:27 +02:00
}
2022-06-20 19:52:31 +02:00
public function loadFromDatabase(Context $context): bool {
2022-10-23 21:26:27 +02:00
$this->logger = new Logger("Settings", $context->getSQL());
2022-11-18 18:06:46 +01:00
$req = new \Core\API\Settings\Get($context);
2020-06-25 16:54:58 +02:00
$success = $req->execute();
if ($success) {
$result = $req->getResult()["settings"];
$this->siteName = $result["site_name"] ?? $this->siteName;
2021-12-08 16:53:43 +01:00
$this->baseUrl = $result["base_url"] ?? $this->baseUrl;
2020-06-25 16:54:58 +02:00
$this->registrationAllowed = $result["user_registration_enabled"] ?? $this->registrationAllowed;
$this->installationComplete = $result["installation_completed"] ?? $this->installationComplete;
2022-10-23 21:26:27 +02:00
$this->jwtSecretKey = $result["jwt_secret_key"] ?? $this->jwtSecretKey;
$this->jwtPublicKey = $result["jwt_public_key"] ?? $this->jwtPublicKey;
$this->jwtAlgorithm = $result["jwt_algorithm"] ?? $this->jwtAlgorithm;
2020-06-26 23:32:45 +02:00
$this->recaptchaEnabled = $result["recaptcha_enabled"] ?? $this->recaptchaEnabled;
$this->recaptchaPublicKey = $result["recaptcha_public_key"] ?? $this->recaptchaPublicKey;
$this->recaptchaPrivateKey = $result["recaptcha_private_key"] ?? $this->recaptchaPrivateKey;
2021-04-02 21:58:06 +02:00
$this->mailEnabled = $result["mail_enabled"] ?? $this->mailEnabled;
2022-02-20 16:53:26 +01:00
$this->mailSender = $result["mail_from"] ?? $this->mailSender;
$this->mailFooter = $result["mail_footer"] ?? $this->mailFooter;
$this->allowedExtensions = explode(",", $result["allowed_extensions"] ?? strtolower(implode(",", $this->allowedExtensions)));
2020-06-25 16:54:58 +02:00
2022-10-23 21:26:27 +02:00
if (!isset($result["jwt_secret_key"])) {
if ($this->generateJwtKey()) {
$this->saveJwtKey($context);
}
2020-06-25 16:54:58 +02:00
}
}
return false;
}
public function addRows(Insert $query) {
2020-06-26 19:31:31 +02:00
$query->addRow("site_name", $this->siteName, false, false)
->addRow("base_url", $this->baseUrl, false, false)
->addRow("user_registration_enabled", $this->registrationAllowed ? "1" : "0", false, false)
->addRow("installation_completed", $this->installationComplete ? "1" : "0", true, true)
2022-10-23 21:26:27 +02:00
->addRow("jwt_secret_key", $this->jwtSecretKey, true, false)
->addRow("jwt_public_key", $this->jwtPublicKey, false, false)
->addRow("jwt_algorithm", $this->jwtAlgorithm, false, false)
2020-06-26 23:32:45 +02:00
->addRow("recaptcha_enabled", $this->recaptchaEnabled ? "1" : "0", false, false)
->addRow("recaptcha_public_key", $this->recaptchaPublicKey, false, false)
->addRow("recaptcha_private_key", $this->recaptchaPrivateKey, true, false)
->addRow("allowed_extensions", implode(",", $this->allowedExtensions), true, false);
2020-06-25 16:54:58 +02:00
}
2020-06-26 18:24:23 +02:00
2021-04-02 21:58:06 +02:00
public function getSiteName(): string {
2020-06-26 18:24:23 +02:00
return $this->siteName;
}
2021-04-02 21:58:06 +02:00
public function getBaseUrl(): string {
2020-06-26 18:24:23 +02:00
return $this->baseUrl;
}
2020-06-26 23:32:45 +02:00
2021-04-02 21:58:06 +02:00
public function isRecaptchaEnabled(): bool {
2020-06-26 23:32:45 +02:00
return $this->recaptchaEnabled;
}
2021-04-02 21:58:06 +02:00
public function getRecaptchaSiteKey(): string {
2020-06-26 23:32:45 +02:00
return $this->recaptchaPublicKey;
}
2021-04-02 21:58:06 +02:00
public function getRecaptchaSecretKey(): string {
2020-06-26 23:32:45 +02:00
return $this->recaptchaPrivateKey;
}
2020-06-27 22:47:12 +02:00
2021-04-02 21:58:06 +02:00
public function isRegistrationAllowed(): bool {
2020-06-27 22:47:12 +02:00
return $this->registrationAllowed;
}
2021-04-09 16:05:36 +02:00
public function isMailEnabled(): bool {
return $this->mailEnabled;
}
2022-02-20 16:53:26 +01:00
public function getMailSender(): string {
return $this->mailSender;
}
public function isExtensionAllowed(string $ext): bool {
return empty($this->allowedExtensions) || in_array(strtolower(trim($ext)), $this->allowedExtensions);
}
2022-06-20 19:52:31 +02:00
public function getDomain(): string {
return parse_url($this->getBaseUrl(), PHP_URL_HOST);
}
2022-11-18 18:06:46 +01:00
public function getLogger(): Logger {
return $this->logger;
}
2020-06-25 16:54:58 +02:00
}