Daniel J. Summers 610ab67475 Move domain items up to lib
- WIP on converting more complex queries
2024-05-31 22:57:24 -04:00

235 lines
6.8 KiB
PHP

<?php
use BitBadger\Documents\DocumentException;
use BitBadger\Documents\Field;
use BitBadger\Documents\SQLite\Count;
use BitBadger\Documents\SQLite\Delete;
use BitBadger\Documents\SQLite\Patch;
use FeedReaderCentral\Data;
use FeedReaderCentral\Security;
use FeedReaderCentral\Table;
use FeedReaderCentral\User;
require __DIR__ . '/../cli-start.php';
cli_title('USER MAINTENANCE');
if ($argc < 2) display_help();
switch ($argv[1]) {
case 'add-user':
if ($argc < 4) {
printfn('Missing parameters: add-user requires e-mail and password');
exit(-1);
}
add_user();
break;
case 'set-password':
if ($argc < 4) {
printfn('Missing parameters: set-password requires e-mail and password');
exit(-1);
}
set_password($argv[2], $argv[3]);
break;
case 'delete-user':
if ($argc < 3) {
printfn('Missing parameters: delete-user requires e-mail address');
exit(-1);
}
delete_user($argv[2]);
break;
case 'set-single-password':
if ($argc < 3) {
printfn('Missing parameters: set-single-password requires a new password');
exit(-1);
}
set_password(Security::SINGLE_USER_EMAIL, $argv[2]);
break;
case 'reset-single-password':
set_password(Security::SINGLE_USER_EMAIL, Security::SINGLE_USER_PASSWORD);
break;
case 'migrate-single-user':
if ($argc < 4) {
printfn('Missing parameters: migrate-single-user requires e-mail and password');
exit(-1);
}
migrate_single_user();
break;
case 'remove-single-user':
delete_user(Security::SINGLE_USER_EMAIL);
break;
default:
printfn('Unrecognized option "%s"', $argv[1]);
display_help();
}
/**
* Display the options for this utility and exit
*/
function display_help(): never
{
printfn('Options:');
printfn(' - add-user [e-mail] [password]');
printfn(' Adds a new user to this instance');
printfn(' - set-password [e-mail] [password]');
printfn(' Sets the password for the given user');
printfn(' - delete-user [e-mail]');
printfn(' Deletes a user and all their data' . PHP_EOL);
printfn('To assist with changing from single-user to single-user-with-password mode:');
printfn(' - set-single-password [password]');
printfn(' Sets the password for the single-user mode user');
printfn(' - reset-single-password');
printfn(' Resets the single-user mode user\'s password to its default' . PHP_EOL);
printfn('To assist with changing from single-user to multi-user mode:');
printfn(' - migrate-single-user [e-mail] [password]');
printfn(' Changes the e-mail address and password for the single-user mode user');
printfn(' - remove-single-user');
printfn(' Removes the single-user mode user and its data');
exit(0);
}
/**
* Add a new user
*/
function add_user(): void
{
global $argv;
$db = Data::getConnection();
try {
// Ensure there is not already a user with this e-mail address
$user = User::findByEmail($argv[2]);
if ($user) {
printfn('A user with e-mail address "%s" already exists', $argv[2]);
return;
}
User::add($argv[2], $argv[3], $db);
printfn('User "%s" with password "%s" added successfully', $argv[2], $argv[3]);
} catch (DocumentException $ex) {
printfn("$ex");
} finally {
$db->close();
}
}
/**
* Get the way we will refer to the user against whom action is being taken
*
* @param string $email The e-mail address of the user
* @return string The string to use when displaying results
*/
function display_user(string $email): string
{
return $email == Security::SINGLE_USER_EMAIL ? 'single-user mode user' : "user \"$email\"";
}
/**
* Set a user's password
*/
function set_password(string $email, string $password): void
{
$db = Data::getConnection();
try {
$displayUser = display_user($email);
// Ensure this user exists
$user = User::findByEmail($email);
if (!$user) {
printfn('No %s exists', $displayUser);
return;
}
Security::updatePassword($email, $password, $db);
$msg = $email == Security::SINGLE_USER_EMAIL && $password == Security::SINGLE_USER_PASSWORD
? 'reset' : sprintf('set to "%s"', $password);
printfn('%s password %s successfully', init_cap($displayUser), $msg);
} catch (DocumentException $ex) {
printfn("$ex");
} finally {
$db->close();
}
}
/**
* Delete a user
*
* @param string $email The e-mail address of the user to be deleted
*/
function delete_user(string $email): void
{
$db = Data::getConnection();
try {
$displayUser = display_user($email);
// Get the user for the provided e-mail address
$user = User::findByEmail($email);
if (!$user) {
printfn('No %s exists', $displayUser);
return;
}
try {
$feedCount = Count::byFields(Table::FEED, [Field::EQ('user_id', $user->id)], $db);
} catch (DocumentException $ex) {
printfn("$ex");
return;
}
$proceed = readline("Delete the $displayUser and their $feedCount feed(s)? (y/N)" . PHP_EOL);
if (!$proceed || !str_starts_with(strtolower($proceed), 'y')) {
printfn('Deletion canceled');
return;
}
try {
// TODO: convert query
$itemDelete = $db->prepare('DELETE FROM item WHERE feed_id IN (SELECT id FROM feed WHERE user_id = :user)');
$itemDelete->bindValue(':user', $user->id);
$itemDelete->execute();
Delete::byFields(Table::FEED, [Field::EQ('user_id', $user->id)], $db);
Delete::byId(Table::USER, $user->id, $db);
printfn('%s deleted successfully', init_cap($displayUser));
} catch (DocumentException $ex) {
printfn("$ex");
}
} catch (DocumentException $ex) {
printfn("$ex");
} finally {
$db->close();
}
}
/**
* Change the single-user mode user to a different e-mail address and password
*/
function migrate_single_user(): void
{
global $argv;
$db = Data::getConnection();
try {
if (!$single = User::findByEmail(Security::SINGLE_USER_EMAIL)) {
printfn('There is no single-user mode user to be migrated');
return;
}
Patch::byId(Table::USER, $single->id,
['email' => $argv[2], 'password' => password_hash($argv[3], Security::PW_ALGORITHM)], $db);
printfn('The single user has been moved to "%s", with password "%s"', $argv[2], $argv[3]);
} catch (DocumentException $ex) {
printfn("$ex");
} finally {
$db->close();
}
}