Add telegram linking

- Add init script
- Apply error toggle from config file
This commit is contained in:
schism 2021-03-05 14:42:31 +05:30
parent e8d9d89b7a
commit 33b13af1dc
18 changed files with 615 additions and 74 deletions

View File

@ -10,28 +10,24 @@ This project has two parts the web server which gives the UI to enter new users
Requires
- php >= 7
- php-sqlite3
- curl
- php-curl
- mysql/postgres
- web server (only needed in production)
- mysql/postgres (recommended)
Run copy the configuration file from `web/php/config.sample.php` to `web/php/config.php` and change the values accordingly.
```sh
cp web/php/config.sample.json web/php/config.json
```
Run the intialization script to check and initialize the configuration.
```sh
php web/php/init.php
```
In production hide the folder `php` from the webserver. For development use,
```sh
php -S localhost:8001 -t web
```
All is well.
#### More configuration
The default database is `sqlite`. If you are using any other database engine, specify the configuration in `web/php/config.json`. For a starting reference see `web/php/config.sample.json`.
```json
{
"DBPATH": "mysql:host=localhost;dbname=myDb",
"DBUSERNAME": "user",
"DBPASSWORD": "pass"
}
```
The configuration can also be read from enviroment variables but the `config.json` is given precedence.

View File

@ -1,8 +1,4 @@
<?php
ini_set("display_errors", "1");
ini_set("display_startup_errors", "1");
error_reporting(E_ALL);
session_start();
require_once(__DIR__ ."/php/helpers.php");

BIN
web/assets/telegram-sc.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

View File

@ -40,7 +40,7 @@
<?php
if ($user->active) {
echo'
<div id="indicator" class="inactive"></div>
<div class="indicator inactive"></div>
<div id="bro_activity" class="info_entry">
Bro on Duty
<span>Your attendance is being checked and marked</span>
@ -48,7 +48,7 @@
';
} else {
echo'
<div id="indicator" class="active"></div>
<div class="indicator active"></div>
<div id="bro_activity" class="info_entry">
Bro is chilling
<span>Account is inactive</span>
@ -61,18 +61,25 @@
<?php
if ($user->active) {
echo '<a href="/toggle_activation.php">
<div id="btn_acountstatus" class="active">
<div id="btn_acountstatus" class="button small error">
Deactivate
</div>
</a>';
} else {
echo '<a href="/toggle_activation.php">
<div id="btn_acountstatus" class="inactive">
<div id="btn_acountstatus" class="button small accent">
Activate
</div>
</a>';
}
?>
<a href="/notifications.php">
<div class="button ic <?php echo ($user->telegramId) ? "accent" : "error"; ?>">
<svg class="icon sm" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
<path d="M10 2a6 6 0 00-6 6v3.586l-.707.707A1 1 0 004 14h12a1 1 0 00.707-1.707L16 11.586V8a6 6 0 00-6-6zM10 18a3 3 0 01-3-3h6a3 3 0 01-3 3z" />
</svg>
</div>
</a>
</div>
</div>
<div id="schedule">

View File

@ -0,0 +1,26 @@
<?php
session_start();
require_once(__DIR__ ."/php/helpers.php");
add_dependancies();
redirect_unauthenticated();
$db = connect_db();
$user = get_user_from_session($db);
$error = "";
try {
$user->telegramId = 0;
$user->update($db);
} catch (Exception $e) {
$error = $e->getMessage();
} finally {
if ($error !== "") {
header("location: /notifications.php?deactivation_notification_error={$error}");
}
header("location: /notifications.php");
}
?>

View File

@ -3,7 +3,8 @@
require_once(__DIR__ ."/php/helpers.php");
add_dependancies();
redirect_authenticated();
$redirect_url = $_GET["redirect"] ?? "/dashboard.php";
redirect_authenticated($redirect_url);
$db = connect_db();
$num_users = $db->getTotalCount("users");
@ -12,7 +13,7 @@
$error = $username = "";
if ($_SERVER["REQUEST_METHOD"] === "POST") {
$user = new User();
$username = $_POST["username"] ?? "";
$password = $_POST["password"] ?? "";
@ -20,24 +21,24 @@
try {
$user->find($db, $username);
try {
$user->login($db, $username, $password);
header("location: /dashboard.php");
$user->login($db, $username, $password);
header("location: {$redirect_url}");
} catch (Exception $e) {
$error = $e->getMessage();
}
} catch (Exception $e) {
try {
$user->username = $username;
$user->password = $password;
$user->save($db);
$_SESSION["username"] = $username;
header("location: /dashboard.php");
header("location: {$redirect_url}");
} catch (Exception $e) {
$error = $e->getMessage();
}
}
}
}
$isError = ($error !== "");
@ -67,7 +68,7 @@
<h2 class="heading">Signin or Signup</h2>
<span class="sub">Please note that we will be storing this password in a database as plain text. So please don't use your master or important passwords.</span>
</div>
<form id="form" method="post" action="/index.php">
<form id="form" method="post" action="/index.php?redirect=<?php echo $redirect_url; ?>">
<input autofocus class="input <?php echo $isError ? "error" : ""; ?>" id="username" type="text" name="username" value="<?php echo $username; ?>"placeholder="eduserver username" />
<input class="input <?php echo $isError ? "error" : ""; ?>" id="password" type="password" name="password" placeholder="eduserver password" />
<div class="error"><?php echo $error; ?></div>

View File

@ -1,8 +1,4 @@
<?php
ini_set("display_errors", "1");
ini_set("display_startup_errors", "1");
error_reporting(E_ALL);
session_start();
$_SESSION = [];

50
web/notifications.php Normal file
View File

@ -0,0 +1,50 @@
<?php
session_start();
require_once(__DIR__ ."/php/helpers.php");
add_dependancies();
redirect_unauthenticated();
$db = connect_db();
$user = get_user_from_session($db);
?>
<?php
require_once(__DIR__. "/php/components/html_head.php");
html_head("Notifications");
?>
<body>
<div class="container">
<?php require(__DIR__."/php/components/header.php"); ?>
<main id="notifications">
<h1 class="heading">Activate Notifications</h1>
<section id="telegram" class="channel">
<div class="heading">
<div class="<?php echo ($user->telegramId) ? "indicator inactive" : "indicator active"; ?>"></div>
<h2>Telegram</h2>
<?php
if ($user->telegramId) {
echo '<a id="deactivate-btn" href="/deactivate_notification.php">
<div class="button xs error">Unlink</div>
</a>';
}
?>
</div>
<div class="steps">
<ol type="1">
<li>Send a <code>\start</code> message to the telegram bot <a href="https://t.me/proxybro_bot" target="_blank" rel="noopener">@proxybro_bot</a></li>
<li>The bot will send back a verification link.</li>
<li>Click on the link and login.</li>
</ol>
</div>
</section>
</main>
<?php require(__DIR__."/php/components/footer.php"); ?>
</div>
</body>
</html>

View File

@ -22,6 +22,7 @@ class Database {
username VARCHAR(10) NOT NULL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
password VARCHAR(255) NOT NULL,
telegramId VARCHAR(25) NULL DEFAULT NULL,
active INTEGER NOT NULL DEFAULT 1
)";
$this->dbh->exec($users_table_query);
@ -29,6 +30,19 @@ class Database {
if ($this->isError() !== false) {
throw new Exception("Couldn\"t create table: {$this->error}");
}
$verify_query = "CREATE TABLE IF NOT EXISTS alert_verify (
passkey VARCHAR(50) NOT NULL PRIMARY KEY,
chatId VARCHAR(25) NOT NULL,
channel VARCHAR(25) NOT NULL,
status INT NOT NULL DEFAULT 0,
time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP)";
$this->dbh->exec($verify_query);
if ($this->isError() !== false) {
echo $this->error;
throw new Exception("Couldn\"t create table: {$this->error}");
}
}
function isError() {

71
web/php/Telegram.php Normal file
View File

@ -0,0 +1,71 @@
<?php
class Telegram {
function __construct($token, $commands = []) {
$this->token = $token;
$this->commands = $commands;
}
function sendMessage($chatId, $text, $options = []) {
send_post("https://api.telegram.org/bot{$this->token}/sendMessage", [
"chat_id" => $chatId,
"text" => $text,
"parse_mode" => isset($options["parse_mode"])? $options["parse_mode"] : "MarkdownV2",
"disable_web_page_preview" => isset($options["disable_web_page_preview"])? $options["disable_web_page_preview"] : false,
]);
}
function setWebhook($url) {
send_post("https://api.telegram.org/bot{$this->token}/setWebhook", [
"url" => $url
]);
}
function recieveAndHandleMessage() {
$inputJSON = file_get_contents('php://input');
$input = json_decode($inputJSON);
$chatId = $input->message->chat->id;
$chatText = $input->message->text;
if ($this->executeCommandIfExist($input->message, $chatId, $chatText) === false) {
$this->sendGenericResponse($chatId);
}
}
function executeCommandIfExist($message, $chatId, $text) {
$isCommand = false;
if (@isset($message->entities)) {
foreach ($message->entities as $entity) {
if ($entity->type === "bot_command") {
$isCommand = true;
$commandName = substr($text, $entity->offset, $entity->length);
$arguments = explode(" ", substr($text, $entity->offset + $entity->length));
if (array_key_exists($commandName, $this->commands)) {
$commandFunction = $this->commands[$commandName]["function"];
$commandFunction($chatId, $arguments, $this);
return true;
}
break;
}
}
}
if ($isCommand) {
$this->sendMessage($chatId, "Command not recognised");
}
return false;
}
function sendGenericResponse($chatId) {
$helpString = "";
foreach ($this->commands as $command=>$config) {
$helpString .= "\n{$command} - {$config["description"]}";
}
$this->sendMessage($chatId, "Available commands are: ". $helpString);
}
}

View File

@ -24,11 +24,12 @@ class User {
// update all other than username and password
function update($db) {
// Prepare UPDATE statement.
$update = "UPDATE users SET active=:active WHERE username=:username";
$update = "UPDATE users SET active=:active, telegram_id=:telegramId WHERE username=:username";
$stmt = $db->dbh->prepare($update);
$stmt->bindParam(":username", $this->username, PDO::PARAM_STR);
$stmt->bindParam(":active", $this->active, PDO::PARAM_STR);
$stmt->bindParam(":telegramId", $this->telegramId, PDO::PARAM_STR);
$result = $stmt->execute();
if ($result === false) {
@ -41,7 +42,7 @@ class User {
function find($db, $username) {
// Prepare SELECT statement.
$select = "SELECT username, name, password, active FROM users WHERE username=?";
$select = "SELECT username, name, password, active, telegram_id FROM users WHERE username=?";
$stmt = $db->dbh->prepare($select);
if ($db->isError()) {
@ -61,6 +62,7 @@ class User {
$this->name = $results["name"];
$this->password = $results["password"];
$this->active = intval($results["active"]);
$this->telegramId = intval($results["telegram_id"]) === 0 ? null : $results["telegram_id"];
return true;
}

View File

@ -1,5 +1,10 @@
{
"DBPATH": "mysql:host=localhost;dbname=myDb",
"DBUSERNAME": "user",
"DBPASSWORD": "pass"
"DBPASSWORD": "pass",
"SHOW_ERROR": 1,
"SERVER_URL": "https://myproxybro.com",
"TELEGRAM_TOKEN": "telegram_bot_token",
"TELEGRAM_USERNAME": "my_proxybro_bot",
"TELEGRAM_ENDPOINT": "my_sample_endpoint"
}

View File

@ -1,39 +1,57 @@
<?php
function add_dependancies() {
require_once(__DIR__ ."/Config.php");
$config = new Config();
if (!is_null($config->SHOW_ERROR) && $config->SHOW_ERROR === 1) {
ini_set("display_errors", "1");
ini_set("display_startup_errors", "1");
error_reporting(E_ALL);
}
require_once(__DIR__ ."/Telegram.php");
require_once(__DIR__ ."/Database.php");
require_once(__DIR__ ."/User.php");
require_once(__DIR__ ."/Config.php");
require_once(__DIR__ ."/Schedule.php");
}
function redirect_authenticated() {
function redirect_authenticated($redirect_url = null) {
$redirect_url = $redirect_url ?? "/dashboard.php";
if (isset($_SESSION["username"])) {
header("location: /dashboard.php");
header("location: {$redirect_url}");
}
}
function redirect_unauthenticated() {
function redirect_unauthenticated($redirect_url = null) {
$redirect_url = $redirect_url ?? "/";
if (!isset($_SESSION["username"])) {
header("location: /");
header("location: {$redirect_url}");
}
}
function get_user_from_session($db, $show_error = true) {
function get_user_from_session($db, $display_error = true) {
try {
$user = new User();
$user->find($db, @$_SESSION["username"]);
return $user;
} catch (Exception $e) {
if ($show_error) {
if ($display_error) {
echo "User not found";
echo '<a href="logout.php">Logout</a>';
exit;
}
return null;
}
}
function flog($message, $file, $level) {
$message = is_string($message) ? $message : json_encode(($message));
file_put_contents("web.log", strtoupper($level) . "|" . substr($file, -20) ."|" . date("Y-m-d h:m:s") . "|" . session_id() . "|" . $message . "\n", FILE_APPEND);
}
function connect_db() {
try {
$config = new Config();
@ -44,7 +62,6 @@ function connect_db() {
$db = new Database($path);
$db->connect($username, $password);
$db->create_tables();
return $db;
} catch (Exception $e) {
echo "Error with database <br/>";

84
web/php/init.php Normal file
View File

@ -0,0 +1,84 @@
<?php
require_once(__DIR__ . "/helpers.php");
add_dependancies();
$config = new Config();
$BASE_URL = __DIR__ ."/..";
// check if the configuration variables exist
show("\nChecking configuration variables");
$config_keys = json_decode(file_get_contents("{$BASE_URL}/php/config.sample.json"), true);
$config_error_flag = false;
foreach ($config_keys as $key => $value) {
if (is_null($config->$key)) {
show_error("Configuration variable '{$key}' was not found.");
$config_error_flag = true;
}
}
if ($config_error_flag) {
show_error("Some configuration variables were not found.");
exit;
}
show_success("All configuration variables found.");
// check connection of mysql using configuration
show("\nChecking mysql connection");
try {
$config = new Config();
$path = $config->DBPATH;
$username = $config->DBUSERNAME;
$password = $config->DBPASSWORD;
$db = new Database($path);
$db->connect($username, $password);
$db->create_tables();
show_success("Connected to database and tables created.");
} catch (Exception $e) {
show_error("Couldn't connect to database.");
}
// move the telegram endpoint to a secret location
show("\nAdding telegram endpoint");
$original_file = "php/telegram_recieve";
if ((copy("{$BASE_URL}/{$original_file}.php", "{$BASE_URL}/{$config->TELEGRAM_ENDPOINT}.php")) === false) {
show_error("Couldn't move telegram recieving file");
exit;
} else {
show_success("Added telegram recieving endpoint({$config->TELEGRAM_ENDPOINT})");
}
// add telegram webhook
show("\nAdding telegram webhook");
$telegram = new Telegram($config->TELEGRAM_TOKEN);
try {
$telegram->setWebhook("{$config->SERVER_URL}/{$config->TELEGRAM_ENDPOINT}.php");
show_success("Webhook added");
} catch (Exception $e) {
show_success("Telegram webhook could not be added.");
show("Notifications will not be sent to the user");
}
function show_error($msg) {
show($msg, true, "ERROR");
}
function show_success($msg) {
show($msg, true, "INFO");
}
function show($msg, $newline = true, $prefix = "") {
$prefix = $prefix ? "{$prefix}: " : "";
echo "{$prefix}{$msg}";
if ($newline) {
echo PHP_EOL;
}
}

View File

@ -0,0 +1,82 @@
<?php
session_start();
require_once(__DIR__ ."/php/helpers.php");
add_dependancies();
$config = new Config();
$startCommand = function ($chatId, $arguments, $telegram) {
$config = new Config();
$db = connect_db();
$message = "";
try {
// check if chatId already exists in users table
$query = "SELECT COUNT(*) as count FROM users WHERE telegram_id=?";
$stmt = $db->dbh->prepare($query);
$stmt->execute([$chatId]);
$data = $stmt->fetch(PDO::FETCH_ASSOC);
if (intval($data["count"]) >= 1) {
// already a telegramId exists
$telegram->sendMessage($chatId, "A user with using this chat as notification already exists. Cannot duplicate notifications.");
return;
}
// check already active activation link exists
$query = "SELECT passkey, chatId, channel FROM alert_verify WHERE chatId=? and status=0 and channel='telegram'";
$stmt = $db->dbh->prepare($query);
$stmt->execute([$chatId]);
$data = $stmt->fetch(PDO::FETCH_ASSOC);
if (isset($data["chatId"])) {
// a link already exists
$pass = $data["passkey"];
} else {
// create a new activation link
$query = "INSERT INTO alert_verify (passkey, chatId, channel) VALUES (?, ?, ?)";
$stmt = $db->dbh->prepare($query);
if ($db->isError() !== false) {
throw new Exception($db->error);
}
$pass = bin2hex(random_bytes(12));
$stmt->execute([$pass, $chatId, "telegram"]);
if ($db->isError() !== false) {
throw new Exception("Couldn't create verification link");
}
}
$link = $config->SERVER_URL . "/verify_notification.php?key=". $pass;
$telegram->sendMessage($chatId, "Click the link to activiate notifivation\n{$link}");
} catch (Exception $e) {
$telegram->sendMessage($chatId, "Something went wrong at out end (token: ". session_id() ."). Please [report this issue](https://git.disroot.org/sQr00t/ProxyBro/issues).", [
"parse_mode" => "MarkdownV2",
"disable_web_page_preview" => true,
]);
flog($e->getMessage(), __FILE__, "ERROR");
}
};
$commands = [
"/start" => [
"name" => "Start",
"description" => "Start recieveing notifications from proxybro",
"function" => $startCommand,
]];
$telegram = new Telegram($config->TELEGRAM_TOKEN, $commands);
$telegram->recieveAndHandleMessage();

View File

@ -16,8 +16,9 @@
--color-primary: #131a26;
--color-primary-dark: #0c1018;
--color-accent: #3bd671;
--color-accent-dark: #199b46;
--color-accent-dark: #2abb5d;
--color-accent-error: #DF484A;
--color-accent-error-dark: #dd3b3e;
--color-accent-error-border: #9b2222;
--color-primary-light: #212937;
--color-body: #687790;
@ -34,6 +35,7 @@
/* --font-medium: 1.2rem; */
/* --font-large: 1.7rem; */
/* --font-xl: 2.2rem; */
--font-small: 16px;
--font-normal: 16px;
--font-medium: 18px;
--font-large: 24px;
@ -61,6 +63,10 @@ body {
padding: 0 50px;
}
.link {
color: var(--color-body);
}
.heading {
color: var(--color-heading);
}
@ -75,12 +81,21 @@ body {
color: var(--color-accent);
}
.row {
display: flex;
flex-direction: row;
}
h2,
.h2 {
font-size: var(--font-xl);
font-weight: 700;
}
a {
color: inherit;
}
header {
width: 100%;
/* margin: auto; */
@ -217,12 +232,27 @@ main#homepage .part.right #form {
}
.button {
display: block;
display: flex;
justify-content: center;
text-decoration: none;
align-items: center;
padding: 10px 25px;
font-size: var(--font-medium);
border: none;
border-radius: 5px;
font-weight: 500;
border-radius: 3px;
font-weight: 700;
cursor: pointer;
transition: background-color 200ms ease-in-out;
}
.button.small {
padding: 10px 15px;
}
.button.xs {
padding: 5px 5px;
font-size: var(--font-small);
}
.error {
@ -232,13 +262,21 @@ main#homepage .part.right #form {
.button.accent {
background-color: var(--color-accent);
color: var(--color-heading);
transition: background-color 200ms ease-in-out;
}
.button.accent:hover {
background-color: var(--color-accent-dark);
}
.button.error {
color: var(--color-heading);
background-color: var(--color-accent-error);
}
.button.error:hover {
background-color: var(--color-accent-error-dark);
}
form .bottom-container {
display: flex;
justify-content: flex-end;
@ -278,26 +316,29 @@ main#dashboard #stats {
background-color: var(--color-primary-light);
border-radius: 5px;
display: flex;
flex-direction: column-reverse;
justify-content: space-between;
align-items: center;
padding: 20px 30px;
color: #fff;
padding: 0 30px;
color: var(--color-heading);
text-align: center;
margin-bottom: 20px;
box-shadow: 0 20px 40px rgba(0,0,0,0.1)
}
main#dashboard #stats > div {
margin: 20px auto;
}
main#dashboard #stats_left {
display: flex;
justify-content: space-around;
width: 50%;
justify-content: space-around;
width: 100%;
}
main#dashboard #stats_left .seperator {
min-width: 3px;
height: 30px%;
background-color: var(--color-primary);
}
main#dashboard #stats_right {
width: 30%;
width: 100%;
margin: 0 20px;
}
main#dashboard .info_entry {
@ -319,28 +360,48 @@ main#dashboard #summary {
background-color: var(--color-primary-light);
border-radius: 5px;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
padding: 20px 50px;
color: #fff;
padding: 0 50px;
color: var(--color-heading);
text-align: center;
margin-bottom: 20px;
box-shadow: 0 20px 40px rgba(0,0,0,0.1)
}
main#dashboard #indicator {
.indicator {
min-width: 20px;
min-height: 20px;
height: 20px;
/* filter: drop-shadow(0px 0px 10px); */
box-shadow: 0 0px 19px;
}
main#dashboard .icon {
height: 30px;
width: 30px;
}
main#dashboard .icon.sm {
height: 22px;
width: 22px;
}
main#dashboard #summary > div {
padding: 20px 0;
}
main#dashboard #summary_left {
display: flex;
align-items: center;
}
main#dashboard #summary_right {
display: flex;
flex-direction: row;
}
main#dashboard #summary_right a {
text-decoration: none;
}
main#dashboard #summary_right a:first-child {
margin-right: 15px;
}
main#dashboard #bro_activity {
text-align: left;
margin-left: 35px;
@ -348,13 +409,13 @@ main#dashboard #bro_activity {
main#dashboard #btn_acountstatus {
padding: 10px 15px;
font-weight: 700;
color: #fff;
color: var(--color-heading);
}
main#dashboard .inactive {
main .inactive {
background-color: var(--color-accent);
color: var(--color-accent);
}
main#dashboard .active {
main .active {
background-color: var(--color-accent-error);
color: var(--color-accent-error);
}
@ -363,26 +424,29 @@ main#dashboard .active {
/* schedule styling */
main#dashboard #schedule {
width: 95%;
width: 100%;
margin: auto;
margin-top: 40px;
overflow: auto;
}
main#dashboard #schedule h2 {
color: #fff;
color: var(--color-heading);
margin-right: 15px;
}
main#dashboard table {
main#dashboard #schedule table {
overflow: auto;
background-color: var(--color-primary-light);
width: 100%;
border-collapse: collapse;
border-radius: 5px;
margin: 20px 0;
width: 100%;
/* filter: drop-shadow(10px 10px 30px var(--color-primary-dark)); */
box-shadow: 0 20px 40px rgba(0,0,0,0.2)
}
main#dashboard table thead {
background-color: #181F2C;
color: #fff;
color: var(--color-heading);
}
main#dashboard table th,td {
@ -395,7 +459,7 @@ main#dashboard table td {
}
main#dashboard table .course {
text-align: left;
color: #fff;
color: var(--color-heading);
}
main#dashboard table tbody>tr>:nth-child(4) {
font-weight: 500;
@ -409,3 +473,56 @@ main#dashboard table td.success {
main#dashboard table td.pending {
color: #F29030;
}
@media screen and (min-width: 1000px) {
main#dashboard #stats {
flex-direction: row;
}
main#dashboard #stats_right {
width: 30%;
}
main#dashboard #stats_left {
width: 50%;
}
main#dashboard #summary {
flex-direction: row;
}
}
/* Notifications page */
main#notifications .channel .heading {
display: flex;
align-items: center;
margin: 30px 0 10px 0;
}
main#notifications .channel .heading {
display: flex;
align-items: center;
margin: 30px 0 10px 0;
}
main#notifications .channel .heading > *:not(:last-child) {
margin-right: 20px;
}
main#notifications .channel .steps {
margin-top: 30px;
}
main#notifications .channel .steps li {
font-size: var(--font-medium);
margin: 15px 0;
}
main#notifications #deactivate-btn {
text-decoration: none;
}
/* Verify Notifications Page */
main#verify-notification {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
}
main#verify-notification .link {
padding: 10px;
margin-top: 15px;
}

View File

@ -1,8 +1,4 @@
<?php
ini_set("display_errors", "1");
ini_set("display_startup_errors", "1");
error_reporting(E_ALL);
session_start();
require_once(__DIR__ ."/php/helpers.php");

View File

@ -0,0 +1,81 @@
<?php
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);
session_start();
require_once(__DIR__ ."/php/helpers.php");
add_dependancies();
$config = new Config();
$db = connect_db();
$user = get_user_from_session($db, false);
$current_route = $_SERVER["REQUEST_URI"];
$key = $_GET["key"];
$telegram = new Telegram($config->TELEGRAM_TOKEN);
$message = "";
if ($user && $key) {
try {
// get telegram details from alert_verify
$query = "SELECT chatId FROM alert_verify WHERE passkey=? AND channel=? AND status=0";
$stmt = $db->dbh->prepare($query);
$stmt->execute([$key, "telegram"]);
$data = $stmt->fetch(PDO::FETCH_ASSOC);
if ($data === false) {
throw new Exception("Invalid or expired link");
}
$chatId = $data["chatId"];
// update telegramId in users table
$query = "UPDATE users SET telegram_id=? WHERE username=? LIMIT 1";
$stmt = $db->dbh->prepare($query);
$stmt->execute([$chatId, $user->username]);
// and change status to 1 in alert_verify
$query = "UPDATE alert_verify SET status=1 WHERE chatId=?";
$stmt = $db->dbh->prepare($query);
$stmt->execute([$chatId]);
$message = "Verification complete. You will now recieve attendance updates.";
$telegram->sendMessage($chatId, $message);
header("location: /dashboard.php");
} catch (Exception $e) {
$message = $e->getMessage();
}
} else if (isset($key)) {
header("location: /index.php?redirect={$current_route}");
} else {
header("location: /");
}
?>
<?php
require_once(__DIR__. "/php/components/html_head.php");
html_head("Dashboard");
?>
<body>
<div class="container">
<?php require(__DIR__."/php/components/header.php"); ?>
<main id="verify-notification">
<h2 class="heading"><?php echo $message; ?></h2>
<div class="link">
<a href="/">Go home</a>
</div>
</main>
<?php require(__DIR__."/php/components/footer.php"); ?>
</div>
</body>
</html>