Clean up the cleaning up

This commit is contained in:
Florine W. Dekker 2022-12-01 23:46:05 +01:00
parent f67873467e
commit 19922907c8
Signed by: FWDekker
GPG Key ID: D3DCFAA8A4560BE0
27 changed files with 86 additions and 113 deletions

View File

@ -1,7 +1,7 @@
{
"name": "fwdekker/death-notifier",
"description": "Get notified when a famous person dies.",
"version": "0.15.5", "_comment_version": "Also update version in `package.json`!",
"version": "0.15.6", "_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.15.5", "_comment_version": "Also update version in `composer.json`!",
"version": "0.15.6", "_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

@ -3,18 +3,19 @@
use com\fwdekker\deathnotifier\ActionDispatcher;
use com\fwdekker\deathnotifier\ActionMethod;
use com\fwdekker\deathnotifier\Database;
use com\fwdekker\deathnotifier\EmulateCronCliAction;
use com\fwdekker\deathnotifier\EmulateCronAction;
use com\fwdekker\deathnotifier\LoggerUtil;
use com\fwdekker\deathnotifier\mailer\MailManager;
use com\fwdekker\deathnotifier\mailer\ProcessEmailQueueCliAction;
use com\fwdekker\deathnotifier\mailer\ProcessEmailQueueAction;
use com\fwdekker\deathnotifier\mediawiki\MediaWiki;
use com\fwdekker\deathnotifier\ProtectedAction;
use com\fwdekker\deathnotifier\Response;
use com\fwdekker\deathnotifier\StartSessionAction;
use com\fwdekker\deathnotifier\tracking\AddTrackingAction;
use com\fwdekker\deathnotifier\tracking\ListTrackingsAction;
use com\fwdekker\deathnotifier\tracking\RemoveTrackingAction;
use com\fwdekker\deathnotifier\tracking\TrackingManager;
use com\fwdekker\deathnotifier\tracking\UpdateTrackingsCliAction;
use com\fwdekker\deathnotifier\tracking\UpdateTrackingsAction;
use com\fwdekker\deathnotifier\user\GetUserDataAction;
use com\fwdekker\deathnotifier\user\LoginAction;
use com\fwdekker\deathnotifier\user\LogoutAction;
@ -41,6 +42,11 @@ $config = Util::read_config();
LoggerUtil::configure($config["logger"]);
$logger = LoggerUtil::with_name();
if (hash_equals($config["admin"]["cli_secret"], "REPLACE THIS WITH A SECRET VALUE")) {
$logger->error("You must set a CLI secret in the configuration file before running Death Notifier.");
exit(1);
}
$db = new Database($config["database"]["filename"]);
$mediawiki = new MediaWiki();
@ -82,12 +88,12 @@ try {
$dispatcher->register_action(new RemoveTrackingAction($tracking_manager));
// CLI actions
$cli_actions = [
new UpdateTrackingsCliAction($config, $db->conn, $tracking_manager, $mediawiki, $mail_manager),
new ProcessEmailQueueCliAction($config, $mail_manager),
new UpdateTrackingsAction($db->conn, $tracking_manager, $mediawiki, $mail_manager, $config["admin"]["cli_secret"]),
new ProcessEmailQueueAction($config, $mail_manager, $config["admin"]["cli_secret"]),
];
$dispatcher->register_action($cli_actions[0]);
$dispatcher->register_action($cli_actions[1]);
$dispatcher->register_action(new EmulateCronCliAction($cli_actions));
$dispatcher->register_action(new EmulateCronAction($cli_actions));
// Dispatch
if (isset($_GET["action"]))
$response = $dispatcher->handle(ActionMethod::GET);

View File

@ -3,6 +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
cli_secret = REPLACE THIS WITH A SECRET VALUE

View File

@ -6,6 +6,7 @@ use com\fwdekker\deathnotifier\validator\IsEqualToRule;
use com\fwdekker\deathnotifier\validator\IsNotSetRule;
use com\fwdekker\deathnotifier\validator\IsSetRule;
use com\fwdekker\deathnotifier\validator\Rule;
use com\fwdekker\deathnotifier\validator\ValidationException;
use InvalidArgumentException;
@ -66,6 +67,7 @@ abstract class Action
$this->method = $method;
$this->name = $name;
// TODO: Move authorisation-related validation to `dispatch` method?
$this->require_logged_in = $require_logged_in;
$this->require_logged_out = $require_logged_out;
$this->require_valid_csrf_token = $require_valid_csrf_token;

View File

@ -2,6 +2,7 @@
namespace com\fwdekker\deathnotifier;
use com\fwdekker\deathnotifier\validator\ValidationException;
use InvalidArgumentException;

View File

@ -1,54 +0,0 @@
<?php
namespace com\fwdekker\deathnotifier;
use com\fwdekker\deathnotifier\validator\Rule;
/**
* An action for the CLI, which requires a valid password to be executed.
*/
abstract class CliAction extends Action
{
/**
* @var array<string, mixed> the application's configuration
*/
protected mixed $config;
/**
* Constructs a new CLI action.
*
* @param array<string, mixed> $config the application's configuration
* @param string $name the name of the action that this action handles
* @param array<string, Rule[]> $rule_lists maps input keys to {@see Rule}s that should be validated before this
* action is handled
*/
public function __construct(mixed $config, string $name, array $rule_lists = [])
{
parent::__construct(ActionMethod::CLI, $name, rule_lists: $rule_lists);
$this->config = $config;
}
/**
* Validates the admin password, and then validates remaining inputs as with any {@see Action}.
*
* @return void
* @throws ValidationException if the input is invalid
*/
public function validate_inputs(): void
{
$inputs = $this->method->get_inputs();
if (hash_equals($this->config["admin"]["cli_secret"], "REPLACE THIS WITH A SECRET VALUE"))
throw new ValidationException("Default config value for 'cli_secret' detected. CLI access disabled.");
if (!isset($inputs["password"]))
throw new ValidationException("Password required. Specify a password using `password=...`.");
// TODO: Read input password from file specified as an input argument in `$argv` (= `$inputs`)
if (!hash_equals($this->config["admin"]["cli_secret"], $inputs["password"]))
throw new ValidationException("Incorrect password.");
parent::validate_inputs();
}
}

View File

@ -37,7 +37,7 @@ class Database
*/
public function __construct(string $filename)
{
$this->logger = LoggerUtil::with_name("Database");
$this->logger = LoggerUtil::with_name($this::class);
$this->conn = new PDO("sqlite:$filename", options: array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
$this->conn->exec("PRAGMA foreign_keys = ON;");

View File

@ -3,12 +3,14 @@
namespace com\fwdekker\deathnotifier;
use com\fwdekker\deathnotifier\validator\ValidationException;
/**
* Periodically executes several other actions, as if cron jobs have been set up to do so.
*
* Intended for local development only.
*/
class EmulateCronCliAction extends Action
class EmulateCronAction extends Action
{
/**
* The number of seconds between executing tasks.
@ -57,7 +59,7 @@ class EmulateCronCliAction extends Action
print("Emulating cron jobs.\n");
foreach ($this->actions as $action)
$action->handle();
print("Done\n");
print("Done.\n");
sleep(self::INTERVAL);
}

View File

@ -24,7 +24,7 @@ class LoggerUtil
/**
* Configures the main logger.
*
* @param array $config the logger configuration
* @param array<string, mixed> $config the logger configuration
* @return void
*/
public static function configure(array $config): void

View File

@ -2,9 +2,11 @@
namespace com\fwdekker\deathnotifier\mailer;
use com\fwdekker\deathnotifier\Action;
use com\fwdekker\deathnotifier\ActionException;
use com\fwdekker\deathnotifier\CliAction;
use com\fwdekker\deathnotifier\ActionMethod;
use com\fwdekker\deathnotifier\LoggerUtil;
use com\fwdekker\deathnotifier\validator\IsEqualToRule;
use Monolog\Logger;
use PHPMailer\PHPMailer\Exception as PHPMailerException;
use PHPMailer\PHPMailer\PHPMailer;
@ -14,12 +16,16 @@ use PHPMailer\PHPMailer\SMTP;
/**
* Processes the queue of emails to send.
*/
class ProcessEmailQueueCliAction extends CliAction
class ProcessEmailQueueAction extends Action
{
/**
* @var Logger the logger to log with
*/
private readonly Logger $logger;
/**
* @var array<string, mixed> the application's configuration
*/
private readonly array $config;
/**
* @var MailManager the manager to process the queue with
*/
@ -29,14 +35,20 @@ class ProcessEmailQueueCliAction extends CliAction
/**
* Constructs a new `ProcessEmailQueueAction`.
*
* @param mixed $config the application's configuration
* @param array<string, mixed> $config the application's configuration
* @param MailManager $mail_manager the manager to process the queue with
* @param string $password the admin password required to perform this function
*/
public function __construct(mixed $config, MailManager $mail_manager)
public function __construct(array $config, MailManager $mail_manager, string $password)
{
parent::__construct($config, "process-email-queue");
parent::__construct(
ActionMethod::CLI,
"process-email-queue",
rule_lists: ["password" => [new IsEqualToRule($password, "Incorrect password.")]],
);
$this->logger = LoggerUtil::with_name("ProcessEmailQueueCliAction");
$this->logger = LoggerUtil::with_name($this::class);
$this->config = $config;
$this->mail_manager = $mail_manager;
}

View File

@ -2,8 +2,10 @@
namespace com\fwdekker\deathnotifier\mediawiki;
use com\fwdekker\deathnotifier\ValidationException;
use com\fwdekker\deathnotifier\LoggerUtil;
use com\fwdekker\deathnotifier\validator\Rule;
use com\fwdekker\deathnotifier\validator\ValidationException;
use Monolog\Logger;
/**
@ -11,6 +13,10 @@ use com\fwdekker\deathnotifier\validator\Rule;
*/
class IsPersonPageRule extends Rule
{
/**
* @var Logger the logger to log with
*/
private Logger $logger;
/**
* @var MediaWiki the instance to connect to Wikipedia with
*/
@ -28,6 +34,7 @@ class IsPersonPageRule extends Rule
{
parent::__construct($override_message);
$this->logger = LoggerUtil::with_name($this::class);
$this->mediawiki = $mediawiki;
}
@ -47,16 +54,14 @@ class IsPersonPageRule extends Rule
$person_name = $inputs[$key];
try {
$info = $this->mediawiki->query_person_info([$person_name]);
} catch (MediaWikiException) {
// TODO: Log this exception!
// $this->logger->error("Failed to query page info.", ["cause" => $exception, "name" => $person_name]);
} catch (MediaWikiException $exception) {
$this->logger->error("Failed to query page info.", ["cause" => $exception, "name" => $person_name]);
throw new ValidationException(
$this->override_message ?? "Could not reach Wikipedia. Maybe the website is down?"
);
}
$normalized_name = $info->redirects[$person_name];
$status = $info->results[$normalized_name]["status"];
$type = $info->results[$normalized_name]["type"];
if (in_array($normalized_name, $info->missing))

View File

@ -44,7 +44,7 @@ class MediaWiki
*/
public function __construct()
{
$this->logger = LoggerUtil::with_name("MediaWiki");
$this->logger = LoggerUtil::with_name($this::class);
}

View File

@ -6,12 +6,14 @@ use com\fwdekker\deathnotifier\Action;
use com\fwdekker\deathnotifier\ActionException;
use com\fwdekker\deathnotifier\ActionMethod;
use com\fwdekker\deathnotifier\IllegalStateException;
use com\fwdekker\deathnotifier\LoggerUtil;
use com\fwdekker\deathnotifier\mediawiki\IsPersonPageRule;
use com\fwdekker\deathnotifier\mediawiki\MediaWiki;
use com\fwdekker\deathnotifier\mediawiki\MediaWikiException;
use com\fwdekker\deathnotifier\ValidationException;
use com\fwdekker\deathnotifier\validator\HasLengthRule;
use com\fwdekker\deathnotifier\validator\IsNotBlankRule;
use com\fwdekker\deathnotifier\validator\ValidationException;
use Monolog\Logger;
/**
@ -19,6 +21,10 @@ use com\fwdekker\deathnotifier\validator\IsNotBlankRule;
*/
class AddTrackingAction extends Action
{
/**
* @var Logger the logger to log with
*/
private Logger $logger;
/**
* @var TrackingManager the manager to add the tracking to
*/
@ -51,6 +57,7 @@ class AddTrackingAction extends Action
],
);
$this->logger = LoggerUtil::with_name($this::class);
$this->tracking_manager = $tracking_manager;
$this->mediawiki = $mediawiki;
}
@ -72,8 +79,7 @@ class AddTrackingAction extends Action
try {
$info = $this->mediawiki->query_person_info([$person_name]);
} catch (MediaWikiException $exception) {
// TODO: Log this?
// $this->logger->error("Failed to query page info.", ["cause" => $exception, "name" => $person_name]);
$this->logger->error("Failed to query page info.", ["cause" => $exception, "name" => $person_name]);
throw new ActionException("Could not reach Wikipedia. Maybe the website is down?");
}

View File

@ -24,10 +24,6 @@ class TrackingManager
*/
public const MAX_TITLE_LENGTH = 255;
/**
* @var Logger the logger to log with
*/
private Logger $logger;
/**
* @var PDO the database connection to interact with
*/
@ -41,7 +37,6 @@ class TrackingManager
*/
public function __construct(PDO $conn)
{
$this->logger = LoggerUtil::with_name("TrackingManager");
$this->conn = $conn;
}

View File

@ -2,20 +2,28 @@
namespace com\fwdekker\deathnotifier\tracking;
use com\fwdekker\deathnotifier\Action;
use com\fwdekker\deathnotifier\ActionException;
use com\fwdekker\deathnotifier\CliAction;
use com\fwdekker\deathnotifier\ActionMethod;
use com\fwdekker\deathnotifier\Database;
use com\fwdekker\deathnotifier\LoggerUtil;
use com\fwdekker\deathnotifier\mailer\MailManager;
use com\fwdekker\deathnotifier\mediawiki\MediaWiki;
use com\fwdekker\deathnotifier\mediawiki\MediaWikiException;
use com\fwdekker\deathnotifier\validator\IsEqualToRule;
use Monolog\Logger;
use PDO;
/**
* Updates all trackings that users have added.
*/
class UpdateTrackingsCliAction extends CliAction
class UpdateTrackingsAction extends Action
{
/**
* @var Logger the logger to log with
*/
private Logger $logger;
/**
* @var PDO the database connection to interact with
*/
@ -37,17 +45,22 @@ class UpdateTrackingsCliAction extends CliAction
/**
* Constructs a new `UpdateTrackingsAction`.
*
* @param mixed $config the application's configuration
* @param PDO $conn the database connection to interact with
* @param TrackingManager $tracking_manager the manager through which trackings should be updated
* @param MediaWiki $mediawiki the instance to connect to Wikipedia with
* @param MailManager $mailer the mailer to send emails with
* @param string $password the admin password required to perform this function
*/
public function __construct(mixed $config, PDO $conn, TrackingManager $tracking_manager, MediaWiki $mediawiki,
MailManager $mailer)
public function __construct(PDO $conn, TrackingManager $tracking_manager, MediaWiki $mediawiki, MailManager $mailer,
string $password)
{
parent::__construct($config, "update-trackings");
parent::__construct(
ActionMethod::CLI,
"update-trackings",
rule_lists: ["password" => [new IsEqualToRule($password, "Incorrect password.")]],
);
$this->logger = LoggerUtil::with_name($this::class);
$this->conn = $conn;
$this->tracking_manager = $tracking_manager;
$this->mediawiki = $mediawiki;
@ -64,15 +77,14 @@ class UpdateTrackingsCliAction extends CliAction
public function handle(): mixed
{
$names = $this->tracking_manager->list_all_unique_person_names();
if (empty($names)) return;
if (empty($names)) return null;
// Fetch changes
try {
$people_statuses = $this->mediawiki->query_person_info($names);
} catch (MediaWikiException) {
} catch (MediaWikiException $exception) {
$this->logger->error("Failed to query page info.", ["cause" => $exception, "pages" => $names]);
throw new ActionException("Could not reach Wikipedia. Maybe the website is down?");
// TODO: Log this exception
// $this->logger->error("Failed to retrieve page information.", ["cause" => $exception, "pages" => $names]);
}
// Process changes

View File

@ -63,7 +63,7 @@ class UserManager
*/
public function __construct(PDO $conn, MailManager $mailer)
{
$this->logger = LoggerUtil::with_name("UserManager");
$this->logger = LoggerUtil::with_name($this::class);
$this->conn = $conn;
$this->mailer = $mailer;
}

View File

@ -2,8 +2,6 @@
namespace com\fwdekker\deathnotifier\validator;
use com\fwdekker\deathnotifier\ValidationException;
/**
* Verifies that the input is of the specific length.

View File

@ -2,8 +2,6 @@
namespace com\fwdekker\deathnotifier\validator;
use com\fwdekker\deathnotifier\ValidationException;
/**
* Verifies that the input is an email address.

View File

@ -2,8 +2,6 @@
namespace com\fwdekker\deathnotifier\validator;
use com\fwdekker\deathnotifier\ValidationException;
/**
* Verifies that the input has the specified value.

View File

@ -2,8 +2,6 @@
namespace com\fwdekker\deathnotifier\validator;
use com\fwdekker\deathnotifier\ValidationException;
/**
* Verifies that the input is not blank.

View File

@ -2,8 +2,6 @@
namespace com\fwdekker\deathnotifier\validator;
use com\fwdekker\deathnotifier\ValidationException;
/**
* Verifies that the input is not set.

View File

@ -2,8 +2,6 @@
namespace com\fwdekker\deathnotifier\validator;
use com\fwdekker\deathnotifier\ValidationException;
/**
* Verifies that the input is set.

View File

@ -2,9 +2,6 @@
namespace com\fwdekker\deathnotifier\validator;
use com\fwdekker\deathnotifier\Response;
use com\fwdekker\deathnotifier\ValidationException;
/**
* A rule/constraint/assertion that should hold over an input.

View File

@ -1,6 +1,6 @@
<?php
namespace com\fwdekker\deathnotifier;
namespace com\fwdekker\deathnotifier\validator;
use Exception;