Check config perms, validate boolean inputs
This commit is contained in:
parent
5a99441a0c
commit
fbce900475
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "fwdekker/death-notifier",
|
||||
"description": "Get notified when a famous person dies.",
|
||||
"version": "0.17.2", "_comment_version": "Also update version in `package.json`!",
|
||||
"version": "0.17.3", "_comment_version": "Also update version in `package.json`!",
|
||||
"type": "project",
|
||||
"license": "MIT",
|
||||
"homepage": "https://git.fwdekker.com/tools/death-notifier",
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "death-notifier",
|
||||
"version": "0.17.2", "_comment_version": "Also update version in `composer.json`!",
|
||||
"version": "0.17.3", "_comment_version": "Also update version in `composer.json`!",
|
||||
"description": "Get notified when a famous person dies.",
|
||||
"author": "Florine W. Dekker",
|
||||
"browser": "dist/bundle.js",
|
||||
|
|
|
@ -3,33 +3,37 @@
|
|||
# TODO: Add i18n
|
||||
|
||||
[admin]
|
||||
# bcrypt hash of password to use the CLI of `api.php`. If set to its default value, or if empty, the CLI is disabled
|
||||
# bcrypt hash of password to use the CLI of `api.php`. If set to its default value, or if empty, the CLI is disabled.
|
||||
cli_secret = REPLACE THIS WITH A SECRET VALUE
|
||||
|
||||
[database]
|
||||
# Relative path to SQLite database
|
||||
# Relative path to SQLite database.
|
||||
filename = .death-notifier.db
|
||||
|
||||
[logger]
|
||||
# File to store logs in
|
||||
# File to store logs in.
|
||||
file = .death-notifier.log
|
||||
# Log level. See https://seldaek.github.io/monolog/doc/01-usage.html#log-levels
|
||||
level = 200
|
||||
|
||||
[mail]
|
||||
# Host name of SMTP server to send mail through
|
||||
# Host name of SMTP server to send mail through.
|
||||
host = TODO
|
||||
# Port of SMTP server to send mail through
|
||||
# Port of SMTP server to send mail through.
|
||||
port = TODO
|
||||
# Username to authenticate with at SMTP server
|
||||
# Username to authenticate with at SMTP server.
|
||||
username = TODO
|
||||
# Password to authenticate with at SMTP server
|
||||
# Password to authenticate with at SMTP server.
|
||||
password = TODO
|
||||
# Name to show to recipient
|
||||
# Name to show to recipient.
|
||||
from_name = TODO
|
||||
|
||||
[security]
|
||||
# `true` if and only if insecure file permissions for config files should be tolerated.
|
||||
allow_config_insecure_permissions = false
|
||||
|
||||
[server]
|
||||
# The path to the main page. Going to this path in your browser should show the contents of `index.html`
|
||||
# The path to the directory containing the site's main page.
|
||||
base_path = https://example.com/death-notifier/
|
||||
# The message to display at the top of all pages. An empty string hides the message
|
||||
# The message to display at the top of all pages. A blank string hides the message.
|
||||
global_message =
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace com\fwdekker\deathnotifier;
|
||||
|
||||
use Error;
|
||||
use InvalidArgumentException;
|
||||
|
||||
|
||||
|
@ -40,7 +41,6 @@ class Config
|
|||
*/
|
||||
private static function read_config(): array
|
||||
{
|
||||
// TODO: Check permissions, return `null` if too permissive
|
||||
$config = parse_ini_file("config.default.ini.php", process_sections: true, scanner_mode: INI_SCANNER_TYPED);
|
||||
if ($config === false) throw new InvalidArgumentException("Invalid `config.default.ini.php` file.");
|
||||
|
||||
|
@ -49,6 +49,20 @@ class Config
|
|||
if ($config_custom === false) throw new InvalidArgumentException("Invalid `config.ini.php` file.");
|
||||
|
||||
$config = array_replace_recursive($config, $config_custom);
|
||||
|
||||
// Check file permissions
|
||||
if (!$config["security"]["allow_config_insecure_permissions"]) {
|
||||
$perms = fileperms("config.ini.php");
|
||||
if ($perms === false)
|
||||
throw new Error("Failed to read file permissions for `config.ini.php` even though the file exists.");
|
||||
|
||||
$perms = substr(decoct($perms), 3);
|
||||
if ($perms !== "600")
|
||||
throw new InvalidArgumentException(
|
||||
"Insecure file permissions for `config.ini.php`. " .
|
||||
"Should be 600 but was $perms."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $config;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace com\fwdekker\deathnotifier\user;
|
||||
|
||||
use com\fwdekker\deathnotifier\Action;
|
||||
use com\fwdekker\deathnotifier\validator\IsBooleanRule;
|
||||
use com\fwdekker\deathnotifier\validator\IsValidCsrfTokenRule;
|
||||
use com\fwdekker\deathnotifier\UnexpectedException;
|
||||
use com\fwdekker\deathnotifier\validator\IsSetRule;
|
||||
|
@ -51,18 +52,17 @@ class ToggleNotificationsAction extends Action
|
|||
(new SessionRuleSet(validate_logged_in: true))->check($_SESSION);
|
||||
(new RuleSet([
|
||||
"token" => [new IsValidCsrfTokenRule()],
|
||||
// TODO: Do we need an IsBooleanRule? (check the `== true` below)
|
||||
"enable_notifications" => [new IsSetRule()],
|
||||
"enable_notifications" => [new IsBooleanRule()],
|
||||
]))->check($inputs);
|
||||
|
||||
$this->user_list->transaction(function () use ($inputs) {
|
||||
$user_data = $this->user_list->get_user_by_uuid($_SESSION["uuid"]);
|
||||
if ($user_data === null)
|
||||
throw new UnexpectedException("Failed to retrieve user data. Refresh the page and try again.");
|
||||
if ($user_data["email_verification_token"] === null)
|
||||
throw new InvalidInputException("Please verify your email address before enabling notifications.");
|
||||
if ($inputs["enable_notifications"] && $user_data["email_verification_token"] !== null)
|
||||
throw new InvalidInputException("Please verify your email address before toggling notifications.");
|
||||
|
||||
$this->user_list->set_notifications_enabled($_SESSION["uuid"], $inputs["enable_notifications"] == true);
|
||||
$this->user_list->set_notifications_enabled($_SESSION["uuid"], $inputs["enable_notifications"]);
|
||||
});
|
||||
|
||||
return null;
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace com\fwdekker\deathnotifier\validator;
|
||||
|
||||
|
||||
/**
|
||||
* Validates that the input is a boolean.
|
||||
*/
|
||||
class IsBooleanRule extends Rule
|
||||
{
|
||||
/**
|
||||
* Validates that the input is a boolean.
|
||||
*
|
||||
* @param array<int|string, mixed> $inputs the list of inputs in which the value at {@see $key} should be checked
|
||||
* @param string $key the key in {@see $inputs} of the input to check
|
||||
* @return void if the checked input is a boolean
|
||||
* @throws InvalidInputException if the checked input is not a boolean
|
||||
*/
|
||||
public function check(array $inputs, string $key): void
|
||||
{
|
||||
if (!isset($inputs[$key]) || !is_bool($inputs[$key]))
|
||||
throw new InvalidInputException(
|
||||
$this->override_message ?? "Field '" . htmlentities($key) . "' must be a boolean.",
|
||||
$key
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue