430 lines
15 KiB
PHP
430 lines
15 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
ini_set('display_errors', '1');
|
|
error_reporting(E_ALL);
|
|
session_start();
|
|
|
|
if (!isset($_SESSION['user_id'])) {
|
|
header('Location: login.php');
|
|
exit;
|
|
}
|
|
|
|
$config = require __DIR__ . '/../config/database.php';
|
|
|
|
$dsn = sprintf(
|
|
'mysql:host=%s;dbname=%s;charset=%s',
|
|
$config['host'],
|
|
$config['dbname'],
|
|
$config['charset'] ?? 'utf8mb4'
|
|
);
|
|
|
|
$pdo = new PDO(
|
|
$dsn,
|
|
$config['user'],
|
|
$config['pass'],
|
|
[
|
|
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
|
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
|
]
|
|
);
|
|
|
|
$userId = (int) $_SESSION['user_id'];
|
|
$errors = [];
|
|
$successMessage = '';
|
|
$telegramConfig = require __DIR__ . '/../config/telegram.php';
|
|
|
|
function h(?string $value): string
|
|
{
|
|
return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8');
|
|
}
|
|
|
|
function generateTelegramLinkToken(int $length = 32): string
|
|
{
|
|
return bin2hex(random_bytes(max(16, (int) ceil($length / 2))));
|
|
}
|
|
|
|
$stmtUser = $pdo->prepare("
|
|
SELECT
|
|
`id`,
|
|
`username`,
|
|
`email`,
|
|
`display_name`,
|
|
`telegram_username`,
|
|
`telegram_chat_id`,
|
|
`telegram_tcrb_v_enabled`,
|
|
`telegram_link_token`,
|
|
`telegram_link_token_expires_at`,
|
|
`telegram_connected_at`,
|
|
`role`,
|
|
`is_active`
|
|
FROM `app_users`
|
|
WHERE `id` = :id
|
|
LIMIT 1
|
|
");
|
|
$stmtUser->execute([':id' => $userId]);
|
|
$user = $stmtUser->fetch();
|
|
|
|
if (!$user) {
|
|
$_SESSION = [];
|
|
session_destroy();
|
|
header('Location: login.php');
|
|
exit;
|
|
}
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$action = $_POST['action'] ?? '';
|
|
|
|
if ($action === 'update_profile') {
|
|
$displayName = trim($_POST['display_name'] ?? '');
|
|
$email = trim($_POST['email'] ?? '');
|
|
|
|
if ($email === '' || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
|
$errors[] = 'Bitte eine gültige E-Mail-Adresse eingeben.';
|
|
}
|
|
|
|
if ($displayName !== '' && mb_strlen($displayName) > 100) {
|
|
$errors[] = 'Der Anzeigename darf maximal 100 Zeichen lang sein.';
|
|
}
|
|
|
|
if (empty($errors)) {
|
|
$stmtCheck = $pdo->prepare("
|
|
SELECT `id`
|
|
FROM `app_users`
|
|
WHERE `email` = :email
|
|
AND `id` <> :id
|
|
LIMIT 1
|
|
");
|
|
$stmtCheck->execute([
|
|
':email' => $email,
|
|
':id' => $userId,
|
|
]);
|
|
|
|
if ($stmtCheck->fetch()) {
|
|
$errors[] = 'Die E-Mail-Adresse ist bereits vergeben.';
|
|
}
|
|
}
|
|
|
|
if (empty($errors)) {
|
|
$stmtUpdate = $pdo->prepare("
|
|
UPDATE `app_users`
|
|
SET
|
|
`display_name` = :display_name,
|
|
`email` = :email,
|
|
`updated_at` = NOW()
|
|
WHERE `id` = :id
|
|
");
|
|
$stmtUpdate->execute([
|
|
':display_name' => $displayName !== '' ? $displayName : null,
|
|
':email' => $email,
|
|
':id' => $userId,
|
|
]);
|
|
|
|
$_SESSION['display_name'] = $displayName !== '' ? $displayName : null;
|
|
$successMessage = 'Die Kontodaten wurden gespeichert.';
|
|
}
|
|
}
|
|
|
|
if ($action === 'generate_telegram_link') {
|
|
$token = generateTelegramLinkToken(32);
|
|
$expiresAt = (new DateTimeImmutable('now'))->modify('+30 minutes')->format('Y-m-d H:i:s');
|
|
|
|
$stmtLink = $pdo->prepare("
|
|
UPDATE `app_users`
|
|
SET
|
|
`telegram_link_token` = :token,
|
|
`telegram_link_token_expires_at` = :expires_at,
|
|
`updated_at` = NOW()
|
|
WHERE `id` = :id
|
|
");
|
|
$stmtLink->execute([
|
|
':token' => $token,
|
|
':expires_at' => $expiresAt,
|
|
':id' => $userId,
|
|
]);
|
|
|
|
$successMessage = 'Ein neuer Telegram-Verbindungscode wurde erzeugt.';
|
|
}
|
|
|
|
if ($action === 'disconnect_telegram') {
|
|
$stmtDisconnect = $pdo->prepare("
|
|
UPDATE `app_users`
|
|
SET
|
|
`telegram_username` = NULL,
|
|
`telegram_chat_id` = NULL,
|
|
`telegram_tcrb_v_enabled` = 0,
|
|
`telegram_link_token` = NULL,
|
|
`telegram_link_token_expires_at` = NULL,
|
|
`telegram_connected_at` = NULL,
|
|
`updated_at` = NOW()
|
|
WHERE `id` = :id
|
|
");
|
|
$stmtDisconnect->execute([
|
|
':id' => $userId,
|
|
]);
|
|
|
|
$successMessage = 'Die Telegram-Verknüpfung wurde entfernt.';
|
|
}
|
|
|
|
if ($action === 'update_tcrb_telegram_notifications') {
|
|
$enabled = isset($_POST['telegram_tcrb_v_enabled']) ? 1 : 0;
|
|
|
|
if ($enabled === 1 && empty($user['telegram_chat_id'])) {
|
|
$errors[] = 'Bitte zuerst Telegram verbinden, bevor du T-CrB-Nachrichten aktivierst.';
|
|
}
|
|
|
|
if (empty($errors)) {
|
|
$stmtNotification = $pdo->prepare("
|
|
UPDATE `app_users`
|
|
SET
|
|
`telegram_tcrb_v_enabled` = :enabled,
|
|
`updated_at` = NOW()
|
|
WHERE `id` = :id
|
|
");
|
|
$stmtNotification->execute([
|
|
':enabled' => $enabled,
|
|
':id' => $userId,
|
|
]);
|
|
|
|
$successMessage = $enabled === 1
|
|
? 'T-CrB-Telegram-Nachrichten wurden aktiviert.'
|
|
: 'T-CrB-Telegram-Nachrichten wurden deaktiviert.';
|
|
}
|
|
}
|
|
|
|
if ($action === 'change_password') {
|
|
$currentPassword = $_POST['current_password'] ?? '';
|
|
$newPassword = $_POST['new_password'] ?? '';
|
|
$newPasswordRepeat = $_POST['new_password_repeat'] ?? '';
|
|
|
|
$stmtPassword = $pdo->prepare("
|
|
SELECT `password_hash`
|
|
FROM `app_users`
|
|
WHERE `id` = :id
|
|
LIMIT 1
|
|
");
|
|
$stmtPassword->execute([':id' => $userId]);
|
|
$passwordRow = $stmtPassword->fetch();
|
|
|
|
if (!$passwordRow || !password_verify($currentPassword, $passwordRow['password_hash'])) {
|
|
$errors[] = 'Das aktuelle Passwort ist nicht korrekt.';
|
|
}
|
|
|
|
if ($newPassword === '') {
|
|
$errors[] = 'Bitte ein neues Passwort eingeben.';
|
|
} elseif (strlen($newPassword) < 8) {
|
|
$errors[] = 'Das neue Passwort muss mindestens 8 Zeichen lang sein.';
|
|
}
|
|
|
|
if ($newPassword !== $newPasswordRepeat) {
|
|
$errors[] = 'Die neuen Passwörter stimmen nicht überein.';
|
|
}
|
|
|
|
if (empty($errors)) {
|
|
$newHash = password_hash($newPassword, PASSWORD_DEFAULT);
|
|
|
|
$stmtUpdatePassword = $pdo->prepare("
|
|
UPDATE `app_users`
|
|
SET
|
|
`password_hash` = :password_hash,
|
|
`updated_at` = NOW()
|
|
WHERE `id` = :id
|
|
");
|
|
$stmtUpdatePassword->execute([
|
|
':password_hash' => $newHash,
|
|
':id' => $userId,
|
|
]);
|
|
|
|
$successMessage = 'Das Passwort wurde geaendert.';
|
|
}
|
|
}
|
|
|
|
$stmtUser->execute([':id' => $userId]);
|
|
$user = $stmtUser->fetch();
|
|
}
|
|
|
|
$loggedIn = true;
|
|
$publicBasePath = './';
|
|
$telegramBotUsername = trim((string) ($telegramConfig['bot_username'] ?? ''));
|
|
$telegramHasConnection = !empty($user['telegram_chat_id']);
|
|
$telegramTcrbVEnabled = !empty($user['telegram_tcrb_v_enabled']);
|
|
$telegramLinkToken = trim((string) ($user['telegram_link_token'] ?? ''));
|
|
$telegramLinkExpiresAt = !empty($user['telegram_link_token_expires_at'])
|
|
? new DateTimeImmutable((string) $user['telegram_link_token_expires_at'])
|
|
: null;
|
|
$telegramLinkIsActive = $telegramLinkToken !== ''
|
|
&& $telegramLinkExpiresAt instanceof DateTimeImmutable
|
|
&& $telegramLinkExpiresAt > new DateTimeImmutable('now');
|
|
$telegramDeepLink = $telegramLinkIsActive && $telegramBotUsername !== ''
|
|
? 'https://t.me/' . $telegramBotUsername . '?start=connect_' . $telegramLinkToken
|
|
: null;
|
|
?>
|
|
<?php require __DIR__ . '/header.php'; ?>
|
|
|
|
<?php if ($successMessage !== ''): ?>
|
|
<p class="msg-success"><?= h($successMessage) ?></p>
|
|
<?php endif; ?>
|
|
|
|
<?php if (!empty($errors)): ?>
|
|
<ul class="msg-error">
|
|
<?php foreach ($errors as $error): ?>
|
|
<li><?= h($error) ?></li>
|
|
<?php endforeach; ?>
|
|
</ul>
|
|
<?php endif; ?>
|
|
|
|
<div class="grid-2">
|
|
<div class="card">
|
|
<h2>Kontodaten</h2>
|
|
<table class="data-table mb-lg">
|
|
<tr><td>Benutzername</td><td><?= h($user['username']) ?></td></tr>
|
|
<tr><td>Rolle</td><td><?= h($user['role']) ?></td></tr>
|
|
</table>
|
|
<form method="post" action="" class="form-stack">
|
|
<input type="hidden" name="action" value="update_profile">
|
|
<div class="form-group">
|
|
<label for="display_name">Anzeigename <span class="form-optional">(optional)</span></label>
|
|
<input
|
|
type="text"
|
|
id="display_name"
|
|
name="display_name"
|
|
maxlength="100"
|
|
value="<?= h($user['display_name'] ?? '') ?>"
|
|
>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="email">E-Mail-Adresse</label>
|
|
<input
|
|
type="email"
|
|
id="email"
|
|
name="email"
|
|
required
|
|
maxlength="190"
|
|
value="<?= h($user['email']) ?>"
|
|
>
|
|
</div>
|
|
<button type="submit" class="btn btn-primary btn-full">Speichern</button>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h2>Telegram verbinden</h2>
|
|
<div class="form-stack">
|
|
<p class="hint">
|
|
Spätere Bot-Nachrichten funktionieren nur mit einer verknüpften Chat-ID. Der Telegram-Username allein reicht Telegram für aktive Nachrichten an einen Nutzer nicht aus.
|
|
</p>
|
|
<table class="data-table mb-lg">
|
|
<tr><td>Status</td><td><?= $telegramHasConnection ? 'Verbunden' : 'Nicht verbunden' ?></td></tr>
|
|
<tr><td>Telegram-Username</td><td><?= h(($user['telegram_username'] ?? '') !== '' ? '@' . ltrim((string) $user['telegram_username'], '@') : '—') ?></td></tr>
|
|
<tr><td>Chat-ID</td><td><?= h($user['telegram_chat_id'] ?? '—') ?></td></tr>
|
|
<tr><td>Verbunden seit</td><td><?= h($user['telegram_connected_at'] ?? '—') ?></td></tr>
|
|
</table>
|
|
|
|
<p class="hint"><strong>T CrB letzter V-Wert:</strong> <?= $telegramTcrbVEnabled ? 'Aktiv' : 'Aus' ?></p>
|
|
|
|
<?php if ($telegramLinkIsActive): ?>
|
|
<p class="hint">
|
|
Aktiver Verbindungscode bis <?= h($telegramLinkExpiresAt?->format('d.m.Y H:i')) ?>:
|
|
<strong><?= h($telegramLinkToken) ?></strong>
|
|
</p>
|
|
<?php endif; ?>
|
|
|
|
<div class="input-row">
|
|
<form method="post" action="">
|
|
<input type="hidden" name="action" value="generate_telegram_link">
|
|
<button type="submit" class="btn btn-primary"><?= $telegramLinkIsActive ? 'Neuen Verbindungscode erzeugen' : 'Telegram verbinden' ?></button>
|
|
</form>
|
|
|
|
<?php if ($telegramHasConnection): ?>
|
|
<form method="post" action="" onsubmit="return confirm('Telegram-Verknüpfung wirklich entfernen?');">
|
|
<input type="hidden" name="action" value="disconnect_telegram">
|
|
<button type="submit" class="btn btn-danger">Verknüpfung lösen</button>
|
|
</form>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<?php if ($telegramLinkIsActive): ?>
|
|
<?php if ($telegramDeepLink !== null): ?>
|
|
<div class="telegram-qr-block">
|
|
<div class="telegram-qr-image" id="telegramConnectQr" data-telegram-link="<?= h($telegramDeepLink) ?>"></div>
|
|
<p class="hint">QR-Code mit dem Handy in Telegram scannen und dann im Bot nur noch auf <strong>Start</strong> tippen.</p>
|
|
</div>
|
|
<?php endif; ?>
|
|
<p class="hint">
|
|
Verbindung starten: <a href="<?= h($publicBasePath . 'telegram/connect.php') ?>">Telegram-Verknüpfung öffnen</a>
|
|
<?php if ($telegramDeepLink !== null): ?>
|
|
oder direkt im Bot:
|
|
<a href="<?= h($telegramDeepLink) ?>" target="_blank" rel="noopener">@<?= h($telegramBotUsername) ?></a>
|
|
<?php endif; ?>
|
|
</p>
|
|
<?php endif; ?>
|
|
|
|
<form method="post" action="" class="form-stack">
|
|
<input type="hidden" name="action" value="update_tcrb_telegram_notifications">
|
|
<label class="checkbox-row">
|
|
<input
|
|
type="checkbox"
|
|
name="telegram_tcrb_v_enabled"
|
|
value="1"
|
|
<?= $telegramTcrbVEnabled ? 'checked' : '' ?>
|
|
<?= !$telegramHasConnection ? 'disabled' : '' ?>
|
|
>
|
|
<span>Letzten T CrB-Wert im Filter V per Telegram erhalten</span>
|
|
</label>
|
|
<?php if (!$telegramHasConnection): ?>
|
|
<p class="hint">Die Auswahl wird erst aktiv, nachdem dein Telegram-Konto verbunden ist.</p>
|
|
<?php endif; ?>
|
|
<button type="submit" class="btn btn-primary" <?= !$telegramHasConnection ? 'disabled' : '' ?>>Benachrichtigung speichern</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="grid-2">
|
|
<div class="card">
|
|
<h2>Passwort aendern</h2>
|
|
<form method="post" action="" class="form-stack">
|
|
<input type="hidden" name="action" value="change_password">
|
|
<div class="form-group">
|
|
<label for="current_password">Aktuelles Passwort</label>
|
|
<input type="password" id="current_password" name="current_password" required>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="new_password">Neues Passwort</label>
|
|
<input type="password" id="new_password" name="new_password" required>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="new_password_repeat">Neues Passwort wiederholen</label>
|
|
<input type="password" id="new_password_repeat" name="new_password_repeat" required>
|
|
</div>
|
|
<button type="submit" class="btn btn-primary btn-full">Passwort aendern</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<?php if ($telegramDeepLink !== null): ?>
|
|
<script src="<?= h($publicBasePath . 'js/qrcode.min.js') ?>"></script>
|
|
<script>
|
|
(function () {
|
|
const qrEl = document.getElementById('telegramConnectQr');
|
|
if (!qrEl || typeof QRCode === 'undefined') {
|
|
return;
|
|
}
|
|
|
|
const qrLink = qrEl.getAttribute('data-telegram-link');
|
|
if (!qrLink) {
|
|
return;
|
|
}
|
|
|
|
new QRCode(qrEl, {
|
|
text: qrLink,
|
|
width: 220,
|
|
height: 220,
|
|
correctLevel: QRCode.CorrectLevel.M
|
|
});
|
|
})();
|
|
</script>
|
|
<?php endif; ?>
|
|
|
|
<?php require __DIR__ . '/footer.php'; ?>
|