Skip to content

Commit

Permalink
feat!: allow registration of multiple users (#340)
Browse files Browse the repository at this point in the history
feat: administration area
feat: add reset password functionality
  • Loading branch information
ellite authored May 26, 2024
1 parent 57b5c3d commit e1006e5
Show file tree
Hide file tree
Showing 90 changed files with 3,093 additions and 829 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ See instructions to run Wallos below.
0 1 * * * php /var/www/html/endpoints/cronjobs/updatenextpayment.php >> /var/log/cron/updatenextpayment.log 2>&1
0 2 * * * php /var/www/html/endpoints/cronjobs/updateexchange.php >> /var/log/cron/updateexchange.log 2>&1
0 9 * * * php /var/www/html/endpoints/cronjobs/sendnotifications.php >> /var/log/cron/sendnotifications.log 2>&1
*/2 * * * * php /var/www/html/endpoints/cronjobs/sendverificationemails.php >> /var/log/cron/sendverificationemail.log 2>&1
*/2 * * * * php /var/www/html/endpoints/cronjobs/sendresetpasswordemails.php >> /var/log/cron/sendresetpasswordemails.log 2>&1
```

5. If your web root is not `/var/www/html/` adjust the cronjobs above accordingly.
Expand Down
175 changes: 173 additions & 2 deletions admin.php
Original file line number Diff line number Diff line change
@@ -1,12 +1,183 @@
<?php
require_once 'includes/header.php';

$settings = [];
$settings['registrations'] = false;
if ($isAdmin != 1) {
header('Location: index.php');
exit;
}

// get admin settings from admin table
$stmt = $db->prepare('SELECT * FROM admin');
$result = $stmt->execute();
$settings = $result->fetchArray(SQLITE3_ASSOC);

// get user accounts where id is not 1
$stmt = $db->prepare('SELECT id, username, email FROM user ORDER BY id ASC');
$result = $stmt->execute();

$users = [];
while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
$users[] = $row;
}
$userCount = is_array($users) ? count($users) : 0;

?>

<section class="contain settings">

<section class="account-section">
<header>
<h2><?= translate('registrations', $i18n) ?></h2>
</header>
<div class="admin-form">
<div class="form-group-inline">
<input type="checkbox" id="registrations" <?= $settings['registrations_open'] ? 'checked' : '' ?> />
<label for="registrations"><?= translate('enable_user_registrations', $i18n) ?></label>
</div>
<div class="form-group">
<label for="maxUsers"><?= translate('maximum_number_users', $i18n) ?></label>
<input type="number" id="maxUsers" value="<?= $settings['max_users'] ?>" />
</div>
<div class="settings-notes">
<p>
<i class="fa-solid fa-circle-info"></i>
<?= translate('max_users_info', $i18n) ?>
</p>
</div>
<div class="form-group-inline">
<input type="checkbox" id="requireEmail" <?= $settings['require_email_verification'] ? 'checked' : '' ?> <?= empty($settings['smtp_address']) ? 'disabled' : '' ?>/>
<label for="requireEmail">
<?= translate('require_email_verification', $i18n) ?>
</label>
</div>
<?php
if (empty($settings['smtp_address'])) {
?>
<div class="settings-notes">
<p>
<i class="fa-solid fa-circle-info"></i>
<?= translate('configure_smtp_settings_to_enable', $i18n) ?>
</p>
</div>
<?php
}
?>
<div class="form-group">
<label for="serverUrl"><?= translate('server_url', $i18n) ?></label>
<input type="text" id="serverUrl" value="<?= $settings['server_url'] ?>" />
</div>
<div class="settings-notes">
<p>
<i class="fa-solid fa-circle-info"></i>
<?= translate('server_url_info', $i18n) ?>
</p>
<p>
<i class="fa-solid fa-circle-info"></i>
<?= translate('server_url_password_reset', $i18n) ?>
</p>
</div>
<div class="buttons">
<input type="submit" class="thin" value="<?= translate('save', $i18n) ?>" id="saveAccountRegistrations" onClick="saveAccountRegistrationsButton()"/>
</div>
</div>
</section>

<?php
if ($userCount >= 0) {
?>

<section class="account-section">
<header>
<h2><?= translate('user_management', $i18n) ?></h2>
</header>
<div class="user-list">
<?php
foreach ($users as $user) {
$userIcon = $user['id'] == 1 ? 'fa-user-tie' : 'fa-id-badge';
?>
<div class="form-group-inline" data-userid="<?= $user['id'] ?>">
<div class="user-list-row">
<div title="<?= translate('username', $i18n) ?>"><i class="fa-solid <?= $userIcon ?>"></i><?= $user['username'] ?></div>
<div title="<?= translate('email', $i18n) ?>"><i class="fa-solid fa-envelope"></i>
<a href="mailto:<?= $user['email']?>"><?= $user['email']?></a>
</div>
</div>
<div>
<?php
if ($user['id'] != 1) {
?>
<button class="image-button medium" onClick="removeUser(<?= $user['id'] ?>)">
<img src="images/siteicons/<?= $colorTheme ?>/delete.png" title="<?= translate('delete_user', $i18n) ?>">
</button>
<?php
} else {
?>
<button class="image-button medium disabled" disabled>
<img src="images/siteicons/<?= $colorTheme ?>/delete.png" title="<?= translate('delete_user', $i18n) ?>">
</button>
<?php
}
?>

</div>
</div>
<?php
}
?>
</div>
<div class="settings-notes">
<p>
<i class="fa-solid fa-circle-info"></i>
<?= translate('delete_user_info', $i18n) ?>
</p>
</div>
</section>

<?php
}
?>

<section class="account-section">
<header>
<h2><?= translate('smtp_settings', $i18n) ?></h2>
</header>
<div class="admin-form">
<div class="form-group-inline">
<input type="text" name="smtpaddress" id="smtpaddress" placeholder="<?= translate('smtp_address', $i18n) ?>" value="<?= $settings['smtp_address'] ?>" />
<input type="text" name="smtpport" id="smtpport" placeholder="<?= translate('port', $i18n) ?>" class="one-third" value="<?= $settings['smtp_port'] ?>" />
</div>
<div class="form-group-inline">
<input type="radio" name="encryption" id="encryptiontls" value="tls" <?= empty($settings['encryption']) || $settings['encryption'] == "tls" ? "checked" : "" ?> />
<label for="encryptiontls"><?= translate('tls', $i18n) ?></label>
<input type="radio" name="encryption" id="encryptionssl" value="ssl" <?= $settings['encryption'] == "ssl" ? "checked" : "" ?> />
<label for="encryptionssl"><?= translate('ssl', $i18n) ?></label>
</div>
<div class="form-group-inline">
<input type="text" name="smtpusername" id="smtpusername" placeholder="<?= translate('smtp_username', $i18n) ?>" value="<?= $settings['smtp_username'] ?>" />
</div>
<div class="form-group-inline">
<input type="password" name="smtppassword" id="smtppassword" placeholder="<?= translate('smtp_password', $i18n) ?>" value="<?= $settings['smtp_password'] ?>" />
</div>
<div class="form-group-inline">
<input type="text" name="fromemail" id="fromemail" placeholder="<?= translate('from_email', $i18n) ?>" value="<?= $settings['from_email'] ?>" />
</div>
<div class="settings-notes">
<p>
<i class="fa-solid fa-circle-info"></i> <?= translate('smtp_info', $i18n) ?>
</p>
<p>
<i class="fa-solid fa-circle-info"></i>
<?= translate('smtp_usage_info', $i18n) ?>
</p>
</div>
<div class="buttons">
<input type="button" class="secondary-button thin" value="<?= translate('test', $i18n) ?>" id="testSmtpSettingsButton" onClick="testSmtpSettingsButton()"/>
<input type="submit" class="thin" value="<?= translate('save', $i18n) ?>" id="saveSmtpSettingsButton" onClick="saveSmtpSettingsButton()"/>
</div>
</div>
</section>


<section class="account-section">
<header>
<h2><?= translate('backup_and_restore', $i18n) ?></h2>
Expand Down
2 changes: 2 additions & 0 deletions cronjobs
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
0 1 * * * /usr/local/bin/php /var/www/html/endpoints/cronjobs/updatenextpayment.php >> /var/log/cron/updatenextpayment.log 2>&1
0 2 * * * /usr/local/bin/php /var/www/html/endpoints/cronjobs/updateexchange.php >> /var/log/cron/updateexchange.log 2>&1
0 9 * * * /usr/local/bin/php /var/www/html/endpoints/cronjobs/sendnotifications.php >> /var/log/cron/sendnotifications.log 2>&1
*/2 * * * * /usr/local/bin/php /var/www/html/endpoints/cronjobs/sendverificationemails.php >> /var/log/cron/sendverificationemails.log 2>&1
*/2 * * * * /usr/local/bin/php /var/www/html/endpoints/cronjobs/sendresetpasswordemails.php >> /var/log/cron/sendresetpasswordemails.log 2>&1
132 changes: 132 additions & 0 deletions endpoints/admin/deleteuser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
<?php

require_once '../../includes/connect_endpoint.php';

if (!isset($_SESSION['loggedin']) || $_SESSION['loggedin'] !== true) {
die(json_encode([
"success" => false,
"message" => translate('session_expired', $i18n)
]));
}

// Check that user is an admin
if ($userId !== 1) {
die(json_encode([
"success" => false,
"message" => translate('error', $i18n)
]));
}

if ($_SERVER["REQUEST_METHOD"] === "POST") {

$postData = file_get_contents("php://input");
$data = json_decode($postData, true);

$userId = $data['userId'];

if ($userId == 1) {
die(json_encode([
"success" => false,
"message" => translate('error', $i18n)
]));
} else {
// Delete user
$stmt = $db->prepare('DELETE FROM user WHERE id = :id');
$stmt->bindValue(':id', $userId, SQLITE3_INTEGER);
$result = $stmt->execute();

// Delete subscriptions
$stmt = $db->prepare('DELETE FROM subscriptions WHERE user_id = :id');
$stmt->bindValue(':id', $userId, SQLITE3_INTEGER);
$result = $stmt->execute();

// Delete settings
$stmt = $db->prepare('DELETE FROM settings WHERE user_id = :id');
$stmt->bindValue(':id', $userId, SQLITE3_INTEGER);
$result = $stmt->execute();

// Delete fixer
$stmt = $db->prepare('DELETE FROM fixer WHERE user_id = :id');
$stmt->bindValue(':id', $userId, SQLITE3_INTEGER);
$result = $stmt->execute();

// Delete custom colors
$stmt = $db->prepare('DELETE FROM custom_colors WHERE user_id = :id');
$stmt->bindValue(':id', $userId, SQLITE3_INTEGER);
$result = $stmt->execute();

// Delete currencies
$stmt = $db->prepare('DELETE FROM currencies WHERE user_id = :id');
$stmt->bindValue(':id', $userId, SQLITE3_INTEGER);
$result = $stmt->execute();

// Delete categories
$stmt = $db->prepare('DELETE FROM categories WHERE user_id = :id');
$stmt->bindValue(':id', $userId, SQLITE3_INTEGER);
$result = $stmt->execute();

// Delete household
$stmt = $db->prepare('DELETE FROM household WHERE user_id = :id');
$stmt->bindValue(':id', $userId, SQLITE3_INTEGER);
$result = $stmt->execute();

// Delete payment methods
$stmt = $db->prepare('DELETE FROM payment_methods WHERE user_id = :id');
$stmt->bindValue(':id', $userId, SQLITE3_INTEGER);
$result = $stmt->execute();

// Delete email notifications
$stmt = $db->prepare('DELETE FROM email_notifications WHERE user_id = :id');
$stmt->bindValue(':id', $userId, SQLITE3_INTEGER);
$result = $stmt->execute();

// Delete telegram notifications
$stmt = $db->prepare('DELETE FROM telegram_notifications WHERE user_id = :id');
$stmt->bindValue(':id', $userId, SQLITE3_INTEGER);
$result = $stmt->execute();

// Delete webhook notifications
$stmt = $db->prepare('DELETE FROM webhook_notifications WHERE user_id = :id');
$stmt->bindValue(':id', $userId, SQLITE3_INTEGER);
$result = $stmt->execute();

// Delete gotify notifications
$stmt = $db->prepare('DELETE FROM gotify_notifications WHERE user_id = :id');
$stmt->bindValue(':id', $userId, SQLITE3_INTEGER);
$result = $stmt->execute();

// Delete pushover notifications
$stmt = $db->prepare('DELETE FROM pushover_notifications WHERE user_id = :id');
$stmt->bindValue(':id', $userId, SQLITE3_INTEGER);
$result = $stmt->execute();

// Dele notification settings
$stmt = $db->prepare('DELETE FROM notification_settings WHERE user_id = :id');
$stmt->bindValue(':id', $userId, SQLITE3_INTEGER);
$result = $stmt->execute();

// Delete last exchange update
$stmt = $db->prepare('DELETE FROM last_exchange_update WHERE user_id = :id');
$stmt->bindValue(':id', $userId, SQLITE3_INTEGER);
$result = $stmt->execute();

// Delete email verification
$stmt = $db->prepare('DELETE FROM email_verification WHERE user_id = :id');
$stmt->bindValue(':id', $userId, SQLITE3_INTEGER);
$result = $stmt->execute();

die(json_encode([
"success" => true,
"message" => translate('success', $i18n)
]));

}

} else {
die(json_encode([
"success" => false,
"message" => translate('error', $i18n)
]));
}

?>
59 changes: 59 additions & 0 deletions endpoints/admin/saveopenregistrations.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

require_once '../../includes/connect_endpoint.php';

if (!isset($_SESSION['loggedin']) || $_SESSION['loggedin'] !== true) {
die(json_encode([
"success" => false,
"message" => translate('session_expired', $i18n)
]));
}

// Check that user is an admin
if ($userId !== 1) {
die(json_encode([
"success" => false,
"message" => translate('error', $i18n)
]));
}

if ($_SERVER["REQUEST_METHOD"] === "POST") {

$postData = file_get_contents("php://input");
$data = json_decode($postData, true);

$openRegistrations = $data['open_registrations'];
$maxUsers = $data['max_users'];
$requireEmailVerification = $data['require_email_validation'];
$serverUrl = $data['server_url'];

if ($requireEmailVerification == 1 && $serverUrl == "") {
echo json_encode([
"success" => false,
"message" => translate('fill_all_fields', $i18n)
]);
die();
}

$sql = "UPDATE admin SET registrations_open = :openRegistrations, max_users = :maxUsers, require_email_verification = :requireEmailVerification, server_url = :serverUrl";
$stmt = $db->prepare($sql);
$stmt->bindParam(':openRegistrations', $openRegistrations, SQLITE3_INTEGER);
$stmt->bindParam(':maxUsers', $maxUsers, SQLITE3_INTEGER);
$stmt->bindParam(':requireEmailVerification', $requireEmailVerification, SQLITE3_INTEGER);
$stmt->bindParam(':serverUrl', $serverUrl, SQLITE3_TEXT);
$result = $stmt->execute();

if ($result) {
echo json_encode([
"success" => true,
"message" => translate('success', $i18n)
]);
} else {
echo json_encode([
"success" => false,
"message" => translate('error', $i18n)
]);
}
}

?>
Loading

0 comments on commit e1006e5

Please sign in to comment.