Use bcrypt hash for CLI secret

This commit is contained in:
Florine W. Dekker 2022-12-06 18:00:18 +01:00
parent 9591c5ecd2
commit 685bf47b30
Signed by: FWDekker
GPG Key ID: D3DCFAA8A4560BE0
11 changed files with 50 additions and 46 deletions

View File

@ -1,7 +1,7 @@
{
"name": "fwdekker/death-notifier",
"description": "Get notified when a famous person dies.",
"version": "0.17.0", "_comment_version": "Also update version in `package.json`!",
"version": "0.17.1", "_comment_version": "Also update version in `package.json`!",
"type": "project",
"license": "MIT",
"homepage": "https://git.fwdekker.com/tools/death-notifier",

BIN
composer.lock generated

Binary file not shown.

BIN
package-lock.json generated

Binary file not shown.

View File

@ -1,6 +1,6 @@
{
"name": "death-notifier",
"version": "0.17.0", "_comment_version": "Also update version in `composer.json`!",
"version": "0.17.1", "_comment_version": "Also update version in `composer.json`!",
"description": "Get notified when a famous person dies.",
"author": "Florine W. Dekker",
"browser": "dist/bundle.js",

View File

@ -43,13 +43,7 @@ $logger = LoggerUtil::with_name();
// Wrap everything in try-catch to always return *something* to user
try {
// Preamble
$config = Config::get();
if (hash_equals($config["admin"]["cli_secret"], "REPLACE THIS WITH A SECRET VALUE"))
throw new IllegalArgumentError(
"You must set a CLI secret in the configuration file before running Death Notifier."
);
$db = new Database($config["database"]["filename"]);
$db = new Database(Config::get()["database"]["filename"]);
$wikipedia = new Wikipedia();
$email_queue = new EmailQueue($db);
@ -118,10 +112,7 @@ try {
$response = new Response(satisfied: true, payload: null);
} catch (Throwable $exception) {
$logger->error("An unhandled error occurred. Please try again later.", ["cause" => $exception]);
$response = new Response(
satisfied: false,
payload: ["message" => "An unhandled error occurred. Please try again later.", "target" => null]
);
$response = Response::unsatisfied("An unhandled error occurred. Please try again later.");
}

View File

@ -3,8 +3,7 @@
# TODO: Add i18n
[admin]
# TODO: Replace stored password with hash of password
# Password to use the CLI of `api.php`. Until this value is changed from its default, the feature 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]

View File

@ -47,7 +47,6 @@ class EmulateCronAction extends Action
{
// @phpstan-ignore-next-line
while (true) {
print("Emulating cron jobs.\n");
foreach ($this->actions as $action)
$action->handle($inputs);
print("Done.\n");

View File

@ -4,7 +4,7 @@ namespace com\fwdekker\deathnotifier\mailer;
use com\fwdekker\deathnotifier\Action;
use com\fwdekker\deathnotifier\Config;
use com\fwdekker\deathnotifier\validator\IsCliPasswordRule;
use com\fwdekker\deathnotifier\validator\EqualsCliSecretRule;
use com\fwdekker\deathnotifier\UnexpectedException;
use com\fwdekker\deathnotifier\validator\InvalidInputException;
use com\fwdekker\deathnotifier\validator\RuleSet;
@ -45,7 +45,7 @@ class ProcessEmailQueueAction extends Action
*/
public function handle(array $inputs): mixed
{
(new RuleSet(["password" => [new IsCliPasswordRule()]]))->check($inputs);
(new RuleSet(["password" => [new EqualsCliSecretRule()]]))->check($inputs);
$mailer = $this->create_mailer();
$emails = $this->email_queue->get_queue();

View File

@ -12,7 +12,7 @@ use com\fwdekker\deathnotifier\validator\InvalidInputException;
use com\fwdekker\deathnotifier\validator\RuleSet;
use com\fwdekker\deathnotifier\wikipedia\Wikipedia;
use com\fwdekker\deathnotifier\wikipedia\WikipediaException;
use com\fwdekker\deathnotifier\validator\IsCliPasswordRule;
use com\fwdekker\deathnotifier\validator\EqualsCliSecretRule;
use Monolog\Logger;
@ -70,7 +70,7 @@ class UpdateTrackingsAction extends Action
*/
public function handle(array $inputs): mixed
{
(new RuleSet(["password" => [new IsCliPasswordRule()]]))->check($inputs);
(new RuleSet(["password" => [new EqualsCliSecretRule()]]))->check($inputs);
// Process changes
$new_deletions = [];

View File

@ -0,0 +1,41 @@
<?php
namespace com\fwdekker\deathnotifier\validator;
use com\fwdekker\deathnotifier\Config;
/**
* Validates that the input equals the CLI secret.
*/
class EqualsCliSecretRule extends Rule
{
/**
* The default value of the CLI secret.
*/
private const CLI_SECRET_DEFAULT = "REPLACE THIS WITH A SECRET VALUE";
/**
* Validates that the input equals the CLI secret.
*
* @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 equals the CLI secret
* @throws InvalidInputException if the checked input is not set, the CLI secret is a blank string, the CLI secret
* is at its default value, or if the checked input does not equal the CLI secret
*/
public function check(array $inputs, string $key): void
{
$cli_password = Config::get()["admin"]["cli_secret"];
if (trim($cli_password) === "" || $cli_password === self::CLI_SECRET_DEFAULT)
throw new InvalidInputException(
$this->override_message ?? "The CLI is disabled because the CLI secret is not set.",
$key
);
if (!isset($inputs[$key]) || !password_verify($inputs[$key], Config::get()["admin"]["cli_secret"]))
throw new InvalidInputException($this->override_message ?? "Incorrect password.", $key);
}
}

View File

@ -1,26 +0,0 @@
<?php
namespace com\fwdekker\deathnotifier\validator;
use com\fwdekker\deathnotifier\Config;
/**
* Validates that the input equals the CLI password.
*/
class IsCliPasswordRule extends Rule
{
/**
* Validates that the input equals the CLI password.
*
* @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 equals the CLI password
* @throws InvalidInputException if the checked input is does not equal the CLI password
*/
public function check(array $inputs, string $key): void
{
if (!isset($inputs[$key]) || !hash_equals(Config::get()["admin"]["cli_secret"], $inputs[$key]))
throw new InvalidInputException($this->override_message ?? "Incorrect password.", $key);
}
}