From c6a1637dee2aea3b56587f0048d627d5a0718e53 Mon Sep 17 00:00:00 2001 From: Bye Date: Sat, 17 Feb 2024 12:04:47 +0000 Subject: [PATCH] Upload a lot of changes --- .idea/dataSources.local.xml | 2 +- .idea/dataSources.xml | 2 +- .../5bc27beb-c8ab-420d-bdbc-055b37ae9e39.xml | 205 +---------- .idea/id.iml | 4 + .idea/php.xml | 4 + account.php | 2 +- accounts_handler.php | 65 +++- admin_apps_create.php | 7 +- admin_initdatabase.php | 67 +++- admin_purge.php | 29 ++ api_handler.php | 117 +++++++ assets/bcid.svg | 6 + assets/default.png | Bin 0 -> 1228 bytes composer.json | 3 +- composer.lock | 320 +++++++++++++++++- credits.html => credits.php | 0 docs/hosting/errors.md | 7 + forgot_password.php | 34 +- index.php | 103 ++++-- landing.php | 2 +- login_external_basic.php | 147 ++++++++ signin.php | 44 ++- signout.php | 1 + styles/colours.css | 5 + styles/design.css | 5 + styles/layout.css | 5 + styles/types.css | 6 + 27 files changed, 913 insertions(+), 279 deletions(-) create mode 100644 admin_purge.php create mode 100644 api_handler.php create mode 100644 assets/bcid.svg create mode 100644 assets/default.png rename credits.html => credits.php (100%) create mode 100644 docs/hosting/errors.md create mode 100644 login_external_basic.php diff --git a/.idea/dataSources.local.xml b/.idea/dataSources.local.xml index 92eddc1..9c2db00 100644 --- a/.idea/dataSources.local.xml +++ b/.idea/dataSources.local.xml @@ -1,6 +1,6 @@ - + #@ diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml index b7c12c5..dfaf86d 100644 --- a/.idea/dataSources.xml +++ b/.idea/dataSources.xml @@ -5,7 +5,7 @@ mariadb true org.mariadb.jdbc.Driver - jdbc:mariadb://id:3306/id + jdbc:mariadb://id.local:3306/id.local $ProjectFileDir$ diff --git a/.idea/dataSources/5bc27beb-c8ab-420d-bdbc-055b37ae9e39.xml b/.idea/dataSources/5bc27beb-c8ab-420d-bdbc-055b37ae9e39.xml index f35c051..627b796 100644 --- a/.idea/dataSources/5bc27beb-c8ab-420d-bdbc-055b37ae9e39.xml +++ b/.idea/dataSources/5bc27beb-c8ab-420d-bdbc-055b37ae9e39.xml @@ -1,205 +1,7 @@ - - - exact - InnoDB - |root||bye||ALTER|G -|root||bye|100.12.43.1|ALTER|G -|root||mysql|localhost|ALTER|G -|root||root|localhost|ALTER|G -|root||bye||ALTER ROUTINE|G -|root||bye|100.12.43.1|ALTER ROUTINE|G -|root||mysql|localhost|ALTER ROUTINE|G -|root||root|localhost|ALTER ROUTINE|G -|root||bye||BINLOG ADMIN|G -|root||bye|100.12.43.1|BINLOG ADMIN|G -|root||mysql|localhost|BINLOG ADMIN|G -|root||root|localhost|BINLOG ADMIN|G -|root||bye||BINLOG MONITOR|G -|root||bye|100.12.43.1|BINLOG MONITOR|G -|root||mysql|localhost|BINLOG MONITOR|G -|root||root|localhost|BINLOG MONITOR|G -|root||bye||BINLOG REPLAY|G -|root||bye|100.12.43.1|BINLOG REPLAY|G -|root||mysql|localhost|BINLOG REPLAY|G -|root||root|localhost|BINLOG REPLAY|G -|root||bye||CONNECTION ADMIN|G -|root||bye|100.12.43.1|CONNECTION ADMIN|G -|root||mysql|localhost|CONNECTION ADMIN|G -|root||root|localhost|CONNECTION ADMIN|G -|root||bye||CREATE|G -|root||bye|100.12.43.1|CREATE|G -|root||mysql|localhost|CREATE|G -|root||root|localhost|CREATE|G -|root||bye||CREATE ROUTINE|G -|root||bye|100.12.43.1|CREATE ROUTINE|G -|root||mysql|localhost|CREATE ROUTINE|G -|root||root|localhost|CREATE ROUTINE|G -|root||bye||CREATE TABLESPACE|G -|root||bye|100.12.43.1|CREATE TABLESPACE|G -|root||mysql|localhost|CREATE TABLESPACE|G -|root||root|localhost|CREATE TABLESPACE|G -|root||bye||CREATE TEMPORARY TABLES|G -|root||bye|100.12.43.1|CREATE TEMPORARY TABLES|G -|root||mysql|localhost|CREATE TEMPORARY TABLES|G -|root||root|localhost|CREATE TEMPORARY TABLES|G -|root||bye||CREATE USER|G -|root||bye|100.12.43.1|CREATE USER|G -|root||mysql|localhost|CREATE USER|G -|root||root|localhost|CREATE USER|G -|root||bye||CREATE VIEW|G -|root||bye|100.12.43.1|CREATE VIEW|G -|root||mysql|localhost|CREATE VIEW|G -|root||root|localhost|CREATE VIEW|G -|root||bye||DELETE|G -|root||bye|100.12.43.1|DELETE|G -|root||mysql|localhost|DELETE|G -|root||root|localhost|DELETE|G -|root||bye||DELETE HISTORY|G -|root||bye|100.12.43.1|DELETE HISTORY|G -|root||mysql|localhost|DELETE HISTORY|G -|root||root|localhost|DELETE HISTORY|G -|root||bye||DROP|G -|root||bye|100.12.43.1|DROP|G -|root||mysql|localhost|DROP|G -|root||root|localhost|DROP|G -|root||bye||EVENT|G -|root||bye|100.12.43.1|EVENT|G -|root||mysql|localhost|EVENT|G -|root||root|localhost|EVENT|G -|root||bye||EXECUTE|G -|root||bye|100.12.43.1|EXECUTE|G -|root||mysql|localhost|EXECUTE|G -|root||root|localhost|EXECUTE|G -|root||bye||FEDERATED ADMIN|G -|root||bye|100.12.43.1|FEDERATED ADMIN|G -|root||mysql|localhost|FEDERATED ADMIN|G -|root||root|localhost|FEDERATED ADMIN|G -|root||bye||FILE|G -|root||bye|100.12.43.1|FILE|G -|root||mysql|localhost|FILE|G -|root||root|localhost|FILE|G -|root||bye||INDEX|G -|root||bye|100.12.43.1|INDEX|G -|root||mysql|localhost|INDEX|G -|root||root|localhost|INDEX|G -|root||bye||INSERT|G -|root||bye|100.12.43.1|INSERT|G -|root||mysql|localhost|INSERT|G -|root||root|localhost|INSERT|G -|root||bye||LOCK TABLES|G -|root||bye|100.12.43.1|LOCK TABLES|G -|root||mysql|localhost|LOCK TABLES|G -|root||root|localhost|LOCK TABLES|G -|root||bye||PROCESS|G -|root||bye|100.12.43.1|PROCESS|G -|root||mysql|localhost|PROCESS|G -|root||root|localhost|PROCESS|G -|root||bye||READ_ONLY ADMIN|G -|root||bye|100.12.43.1|READ_ONLY ADMIN|G -|root||mysql|localhost|READ_ONLY ADMIN|G -|root||root|localhost|READ_ONLY ADMIN|G -|root||bye||REFERENCES|G -|root||bye|100.12.43.1|REFERENCES|G -|root||mysql|localhost|REFERENCES|G -|root||root|localhost|REFERENCES|G -|root||bye||RELOAD|G -|root||bye|100.12.43.1|RELOAD|G -|root||mysql|localhost|RELOAD|G -|root||root|localhost|RELOAD|G -|root||bye||REPLICATION MASTER ADMIN|G -|root||bye|100.12.43.1|REPLICATION MASTER ADMIN|G -|root||mysql|localhost|REPLICATION MASTER ADMIN|G -|root||root|localhost|REPLICATION MASTER ADMIN|G -|root||bye||REPLICATION SLAVE|G -|root||bye|100.12.43.1|REPLICATION SLAVE|G -|root||mysql|localhost|REPLICATION SLAVE|G -|root||root|localhost|REPLICATION SLAVE|G -|root||bye||REPLICATION SLAVE ADMIN|G -|root||bye|100.12.43.1|REPLICATION SLAVE ADMIN|G -|root||mysql|localhost|REPLICATION SLAVE ADMIN|G -|root||root|localhost|REPLICATION SLAVE ADMIN|G -|root||bye||SELECT|G -|root||bye|100.12.43.1|SELECT|G -|root||mysql|localhost|SELECT|G -|root||root|localhost|SELECT|G -|root||bye||SET USER|G -|root||bye|100.12.43.1|SET USER|G -|root||mysql|localhost|SET USER|G -|root||root|localhost|SET USER|G -|root||bye||SHOW DATABASES|G -|root||bye|100.12.43.1|SHOW DATABASES|G -|root||mysql|localhost|SHOW DATABASES|G -|root||root|localhost|SHOW DATABASES|G -|root||bye||SHOW VIEW|G -|root||bye|100.12.43.1|SHOW VIEW|G -|root||mysql|localhost|SHOW VIEW|G -|root||root|localhost|SHOW VIEW|G -|root||bye||SHUTDOWN|G -|root||bye|100.12.43.1|SHUTDOWN|G -|root||mysql|localhost|SHUTDOWN|G -|root||root|localhost|SHUTDOWN|G -|root||bye||SLAVE MONITOR|G -|root||bye|100.12.43.1|SLAVE MONITOR|G -|root||mysql|localhost|SLAVE MONITOR|G -|root||root|localhost|SLAVE MONITOR|G -|root||bye||SUPER|G -|root||bye|100.12.43.1|SUPER|G -|root||mysql|localhost|SUPER|G -|root||root|localhost|SUPER|G -|root||bye||TRIGGER|G -|root||bye|100.12.43.1|TRIGGER|G -|root||mysql|localhost|TRIGGER|G -|root||root|localhost|TRIGGER|G -|root||bye||UPDATE|G -|root||bye|100.12.43.1|UPDATE|G -|root||mysql|localhost|UPDATE|G -|root||root|localhost|UPDATE|G -|root||bye||grant option|G -|root||bye|100.12.43.1|grant option|G -|root||mysql|localhost|grant option|G -|root||root|localhost|grant option|G -id|schema||id||ALTER|G -id|schema||id||ALTER ROUTINE|G -id|schema||id||CREATE|G -id|schema||id||CREATE ROUTINE|G -id|schema||id||CREATE TEMPORARY TABLES|G -id|schema||id||CREATE VIEW|G -id|schema||id||DELETE|G -id|schema||id||DELETE HISTORY|G -id|schema||id||DROP|G -id|schema||id||EVENT|G -id|schema||id||EXECUTE|G -id|schema||id||INDEX|G -id|schema||id||INSERT|G -id|schema||id||LOCK TABLES|G -id|schema||id||REFERENCES|G -id|schema||id||SELECT|G -id|schema||id||SHOW VIEW|G -id|schema||id||TRIGGER|G -id|schema||id||UPDATE|G -phpmyadmin|schema||phpmyadmin|localhost|ALTER|G -phpmyadmin|schema||phpmyadmin|localhost|ALTER ROUTINE|G -phpmyadmin|schema||phpmyadmin|localhost|CREATE|G -phpmyadmin|schema||phpmyadmin|localhost|CREATE ROUTINE|G -phpmyadmin|schema||phpmyadmin|localhost|CREATE TEMPORARY TABLES|G -phpmyadmin|schema||phpmyadmin|localhost|CREATE VIEW|G -phpmyadmin|schema||phpmyadmin|localhost|DELETE|G -phpmyadmin|schema||phpmyadmin|localhost|DELETE HISTORY|G -phpmyadmin|schema||phpmyadmin|localhost|DROP|G -phpmyadmin|schema||phpmyadmin|localhost|EVENT|G -phpmyadmin|schema||phpmyadmin|localhost|EXECUTE|G -phpmyadmin|schema||phpmyadmin|localhost|INDEX|G -phpmyadmin|schema||phpmyadmin|localhost|INSERT|G -phpmyadmin|schema||phpmyadmin|localhost|LOCK TABLES|G -phpmyadmin|schema||phpmyadmin|localhost|REFERENCES|G -phpmyadmin|schema||phpmyadmin|localhost|SELECT|G -phpmyadmin|schema||phpmyadmin|localhost|SHOW VIEW|G -phpmyadmin|schema||phpmyadmin|localhost|TRIGGER|G -phpmyadmin|schema||phpmyadmin|localhost|UPDATE|G - 10.6.12 - + + big5 1 @@ -1217,8 +1019,7 @@ phpmyadmin|schema||phpmyadmin|localhost|UPDATE|G 1 - 2023-11-16.19:58:39 - 2023-11-16.19:58:50 + 2023-11-16.19:58:50 utf8mb4_general_ci diff --git a/.idea/id.iml b/.idea/id.iml index 21a8ff4..7267852 100644 --- a/.idea/id.iml +++ b/.idea/id.iml @@ -19,6 +19,10 @@ + + + + diff --git a/.idea/php.xml b/.idea/php.xml index 4c1495a..a30690c 100644 --- a/.idea/php.xml +++ b/.idea/php.xml @@ -26,6 +26,10 @@ + + + + diff --git a/account.php b/account.php index d4408c1..30fa20f 100644 --- a/account.php +++ b/account.php @@ -78,7 +78,7 @@ if (isset($message )) {
- +
diff --git a/accounts_handler.php b/accounts_handler.php index c262cac..9add2f5 100644 --- a/accounts_handler.php +++ b/accounts_handler.php @@ -25,9 +25,12 @@ function get_avatar_url($bcid):string { } -function get_display_name($bcid, $use_bcid_fallback=true):string { +function get_display_name($bcid, $use_bcid_fallback=true, $put_bcid_in_parenthesis=false):string { $display_name = db_execute("SELECT display_name FROM accounts WHERE id = ?", [$bcid])['display_name']; if (!empty($display_name)) { + if ($put_bcid_in_parenthesis) { + return $display_name . " ($bcid)"; + } return $display_name; } @@ -38,6 +41,66 @@ function get_display_name($bcid, $use_bcid_fallback=true):string { return ""; } +// Tokens so apps can get VERY BASIC information + +function generate_basic_access_token($bcid): array +{ + // Returns an access token, a refresh token and an expiry timestamp. + + $access_token = md5(uniqid(more_entropy: true).rand(1000000, 9999999)); + $refresh_token = md5(uniqid("rfish").rand(1000000, 9999999)); + + $valid_time = 12; // in hours + $expiry = time() + ($valid_time * 60 * 60); + +// echo $access_token . ":" . $refresh_token; + + db_execute( + "INSERT INTO tokens (access_token, refresh_token, expiry, owner_id) VALUES (?,?,?,?)", + [$access_token, $refresh_token, $expiry, $bcid] + ); + + return [ + "access" => $access_token, + "refresh" => $refresh_token, + "expiry" => $expiry, + "id" => $bcid + ]; +} + +function generate_cookie_access_token($bcid) { + $access_token = md5(uniqid(prefix: "COOKIECOOKIECOOKIE", more_entropy: true).rand(1000000, 9999999)); + + $valid_time = 365 * 24; // 1 year + $expiry = time() + ($valid_time * 60 * 60); + +// echo $access_token . ":" . $refresh_token; + + db_execute( + "INSERT INTO tokens (access_token, expiry, owner_id, type) VALUES (?,?,?,'cookie')", + [$access_token, $expiry, $bcid] + ); + + return [ + "access" => $access_token, + "expiry" => $expiry, + "id" => $bcid + ]; +} + +function validate_access_token($access_token): bool +{ + $token_details = db_execute("SELECT * FROM tokens WHERE access_token = ?", [$access_token]); + if (null == $token_details) { + return false; + } + if (time() > $token_details['expiry']) { + db_execute("DELETE FROM tokens where access_token = ?", [$access_token]); + return false; + } + return true; +} + // Password resets const PASSWORD_RESET_VALIDITY = 300; // in seconds. function create_password_reset($bcid):string { diff --git a/admin_apps_create.php b/admin_apps_create.php index bc3bec9..0de29ff 100644 --- a/admin_apps_create.php +++ b/admin_apps_create.php @@ -13,7 +13,7 @@ function check_app_id($app_id): bool if ($_SERVER['REQUEST_METHOD'] == "POST") { $app_id = generate_app_id(); - db_execute("INSERT INTO apps (id, owner_id, title, description) VALUES (?, ?, ?, ?)", [$app_id, $_POST['owner'], $_POST['title'], $_POST['description']]); + db_execute("INSERT INTO apps (id, owner_id, title, description, type) VALUES (?, ?, ?, ?, ?)", [$app_id, $_POST['owner'], $_POST['title'], $_POST['description'], $_POST['type']]); die(); } @@ -35,5 +35,10 @@ if ($_SERVER['REQUEST_METHOD'] == "POST") { } ?> + + \ No newline at end of file diff --git a/admin_initdatabase.php b/admin_initdatabase.php index 2a61acc..fec3bb9 100644 --- a/admin_initdatabase.php +++ b/admin_initdatabase.php @@ -12,7 +12,9 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") { created_date date default current_timestamp() not null, display_name text null, password text not null, - verified tinyint(1) not null, + verified tinyint(1) default 0 not null, + has_pfp tinyint(1) default 0 not null, + is_admin tinyint(1) default 0 not null, constraint email unique (email) using hash );'); @@ -23,7 +25,7 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") { echo('

An error occurred: '. $e->getMessage() .'. Will skip. (Most likely the table already exists.)'); } - echo '

Create the `password_resets` table

'; + echo '

Create the `password_resets` table'; $stmt = $pdo->prepare('create table password_resets ( id int auto_increment @@ -33,11 +35,7 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") { expiration int not null, constraint password_resets_ibfk_1 foreign key (owner_id) references accounts (id) -); - -create index owner_id - on password_resets (owner_id); -'); +);'); try { $stmt->execute(); @@ -45,13 +43,66 @@ create index owner_id echo('

An error occurred: '. $e->getMessage() .'. Most likely this is already set.'); } + echo '

Create the `apps` table'; + + try { + db_execute('create table apps ( + id int auto_increment + primary key, + owner_id varchar(7) not null, + title text not null, + description text, + image text default "https://id.byecorps.com/assets/default.png" not null, + type text null, + callback text null, + constraint apps_ibfk_1 + foreign key (owner_id) references accounts (id) + );'); + } catch (PDOException $e) { + echo('

An error occurred: '. $e->getMessage() .'. Most likely this is already set.'); + } + + + echo '

Create the `badges` table'; + + try { + db_execute('create table badges ( + id int auto_increment + primary key, + app_id int not null, + title text not null, + description text, + image text default "https://id.byecorps.com/assets/default.png" not null, + constraint badges_ibfk_1 + foreign key (app_id) references apps (id) + );'); + } catch (PDOException $e) { + echo('

An error occurred: '. $e->getMessage() .'. Most likely this is already set.'); + } + + echo '

Create the `profiles` table'; + + try { + db_execute('create table profiles ( + id varchar(7) + primary key, + description text null, + public_avatar tinyint(1) default 0, + public_display_name tinyint(1) default 0, + constraint profiles_ibfk_1 + foreign key (id) references accounts (id) + );'); + } catch (PDOException $e) { + echo('

An error occurred: '. $e->getMessage() .'. Most likely this is already set.'); + } + + echo "

Database initialised.

"; } } ?> -

Admin

Init database

Assuming you have the database config configured, you can click this button to create the tables required for this thing to function.

diff --git a/admin_purge.php b/admin_purge.php new file mode 100644 index 0000000..691e757 --- /dev/null +++ b/admin_purge.php @@ -0,0 +1,29 @@ + + + + +

Purge

+
+

+ +

+
+ +

Expired password resets

+
+ +

Expired Login tokens

+
diff --git a/api_handler.php b/api_handler.php new file mode 100644 index 0000000..64e3c59 --- /dev/null +++ b/api_handler.php @@ -0,0 +1,117 @@ + 1, + default => 0, + }; +} + +// Misc (unauthorised) + +function redirect_to_documentation(): void +{ + header('Location: /docs/api'); +} + +// Health check + +function api_health_check(): array +{ + return ["message" => "Science compels us to explode the sun!", "time" => time(), "response_code" => 200]; +} + +// User (REQUIRES AUTHORISATION) + +function api_user_info() { + global $access_token, $token_owner; + // Authorisation levels: + // `display_name` = 1 (basic) + // `id` = 1 (basic) + // `email` = 1 (basic) + + $level = check_authorisation($access_token); + + $data = null; + + if ($level == 1) { + $data = db_execute("SELECT id, email, display_name FROM accounts WHERE id = ? LIMIT 1", [$token_owner]); + } + + if (null != $data) { + return [ + "response_code" => 200, + "id" => $data['id'], + "email" => $data['email'], + "display_name" => $data['display_name'] + ]; + } + + http_response_code(401); + return [ + "response_code" => 401, + "message" => "Unauthorized." + ]; + +} + +$api_routes = [ // base url is base_url.'/api' + // "/path" => "function_name" + // Misc + "" => "redirect_to_documentation", + "/status" => "api_health_check", + + // Account stuff + "/account/me" => "api_user_info" +]; + +$path = str_replace("/api", "", $path); + +if (isset($api_routes[$path])) { + if (isset($invalid_token)) { + http_response_code(498); + echo (json_encode([ + "response_code" => "498", + "message" => "Token expired or invalid." + ])); + } + echo json_encode($api_routes[$path]()); +} else { + http_response_code(404); + echo (json_encode([ + "response_code" => "404", + "message" => "Route not found." + ])); +} diff --git a/assets/bcid.svg b/assets/bcid.svg new file mode 100644 index 0000000..8911001 --- /dev/null +++ b/assets/bcid.svg @@ -0,0 +1,6 @@ + + Made with Pixels to Svg https://codepen.io/shshaw/pen/XbxvNj + + + + \ No newline at end of file diff --git a/assets/default.png b/assets/default.png new file mode 100644 index 0000000000000000000000000000000000000000..a1d6ae44f844f01c7b4191bf3bff9c6d05f59555 GIT binary patch literal 1228 zcmeAS@N?(olHy`uVBq!ia0y~yU~~Xs4mP03*$GQm0V&4fAa^H*b?0PWGBB{TdAc}; zRLpsM_bhLtql8;v{Zb9b|GXC%mkL~)mXxCQ&XTpJQnko6Dg?awbY3%&M;l|1*5SMTPDebug = SMTP::DEBUG_SERVER; Verbose output - $mail->isSMTP(); //Send using SMTP - $mail->Host = MAIL_HOST; //Set the SMTP server to send through - $mail->SMTPAuth = true; //Enable SMTP authentication - $mail->Username = MAIL_USERNAME; //SMTP username - $mail->Password = MAIL_PASSWORD; //SMTP password - $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS; //Enable implicit TLS encryption - $mail->Port = 465; - - $mail->setFrom('id@byecorps.com', 'ByeCorps ID'); - $mail->addAddress($user['email'], $safe_display_name); - $mail->addReplyTo('hello@byecorps.com', 'ByeCorps Support'); - - $mail->Subject = 'Reset your password'; - $mail->Body = 'Hey there '.$safe_display_name.'! Here is that password reset you requested. Just click the following link and you\'ll be sorted: + $resend->emails->send([ + 'from' => 'ByeCorps ID ', + 'to' => [$safe_display_name . "<" . $user['email']. ">"], + 'subject' => 'Reset your password', + 'text' => 'Hey there '.$safe_display_name.'! Here is that password reset you requested. Just click the following link and you\'ll be sorted: '.$password_reset_link.' -This link expires in 5 minutes.'; - $mail->send(); +This link expires in 5 minutes. + +If you did not request this password reset, please ignore it (or tighten your account\'s security)']); + +// echo("This is a security issue."); } catch (Exception $e) { echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}"; } @@ -65,7 +53,7 @@ This link expires in 5 minutes.'; ".$message."

"; ?> -

Forgot your password? We'll send you an email to reset it.

+

Forgot your password? We'll email you to reset it.

diff --git a/index.php b/index.php index 843ce30..3c9f9b9 100644 --- a/index.php +++ b/index.php @@ -3,37 +3,45 @@ require_once __DIR__ . '/vendor/autoload.php'; session_start(); -use kornrunner\Blurhash\Blurhash; - if (empty($_SESSION)) { $_SESSION['auth'] = false; } -include("config.php"); +include "config.php"; +// MySQL $pdo = new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD, PDO_OPTIONS); +// Email +if (defined("RESEND_API_KEY")) { + $resend = Resend::client(RESEND_API_KEY); +} -include("time_handler.php"); require "misc_functions.php"; require "database.php"; +include("time_handler.php"); include("id_handler.php"); include("accounts_handler.php"); -if ($_SESSION['auth']) { - $user = db_execute("SELECT * FROM `accounts` WHERE id = ? LIMIT 1", [$_SESSION['id']]); +// Attempt to log the user in using their cookie if auth isn't set. +if (!$_SESSION['auth']) { + if (key_exists('keep_me_logged_in', $_COOKIE)) { + if (validate_access_token($_COOKIE['keep_me_logged_in'])) { + // Work out who the key belongs to + $cookie_owner = db_execute("SELECT * FROM tokens WHERE access_token = ?", [$_COOKIE['keep_me_logged_in']]); + if ($cookie_owner['type'] != "cookie") { + setcookie('keep_me_logged_in', '', time()-3600); + goto skip_cookie; + } + $_SESSION['auth'] = true; + $_SESSION['id'] = $cookie_owner['owner_id']; + + } else { + setcookie('keep_me_logged_in', '', time()-3600); + } + } } -\Sentry\init([ - 'dsn' => SENTRY_DSN, - // Specify a fixed sample rate - 'traces_sample_rate' => 1.0, - // Set a sampling rate for profiling - this is relative to traces_sample_rate - 'profiles_sample_rate' => 1.0, -]); - -function does_variable_exists( $variable ) { - return (isset($$variable)) ? "true" : "false"; -} +skip_cookie: $host_string = $_SERVER['HTTP_HOST']; $host = explode('.', $host_string); @@ -45,6 +53,45 @@ if (str_ends_with($path,'/') && $path != "/") { exit; } $uri = array_values(array_filter(explode('/', $uri_string))); +try { + if ($_SESSION['auth']) { + $user = db_execute("SELECT * FROM `accounts` WHERE id = ? LIMIT 1", [$_SESSION['id']]); + if (!$user) { + // Account doesn't exist. Log the user out. + + // We won't redirect to the logout endpoint because if this is going off there's something + // broken anyway. + session_destroy(); + die("Your session was invalid so we've logged you out."); + } + } +} +catch (Exception) { + echo('
Database is broken. Please tell an admin.
'); + if ($uri_string == "/admin/init/database") { // Allows access to this page even if user doesn't have admin rights + // because you can't check the rights. + echo "
"; + include "admin_initdatabase.php"; + die ("
"); + + } +} + + +if (defined("SENTRY_DSN")) { + \Sentry\init([ + 'dsn' => SENTRY_DSN, + // Specify a fixed sample rate + 'traces_sample_rate' => 1.0, + // Set a sampling rate for profiling - this is relative to traces_sample_rate + 'profiles_sample_rate' => 1.0, + ]); +} + + +function does_variable_exists( $variable ) { + return (isset($$variable)) ? "true" : "false"; +} if(isset($query_string[1])) { $uri_string = $query_string[0]; @@ -65,11 +112,13 @@ $include = "404.html"; $paths = array( "/" => ["landing.php"], + "/admin" => ['admin.php'], "/admin/init/database" => ["admin_initdatabase.php"], "/admin/list/accounts" => ["admin_accounts.php"], "/admin/list/apps" => ["admin_apps.php"], "/admin/create/app" => ["admin_apps_create.php"], + "/admin/purge" => ["admin_purge.php"], "/account" => ["account.php", "Your account"], "/signin" => ["signin.php", "Sign in"], @@ -79,10 +128,19 @@ $paths = array( "/admin/signinas" => ["signinas.php"], "/reset/password" => ["reset_password.php", "Reset password"], "/docs" => ["docs.php", "Docs"], - "/credits" => ["credits.html", "Credits"], + "/credits" => ["credits.php", "Credits"], "/profile" => ["profile.php", "Profile"], + + "/signin/external/basic" => ["login_external_basic.php"] ); +if (!empty($uri) ) { // Go to jail. Go directly to jail. Do not pass Go. + if ($uri[0] == "api") { + include("api_handler.php"); + exit(); // fuck this shit i'm out + } +} + if (isset($paths[$path])) { $include = $paths[$path][0]; if (isset($paths[$path][1])) { @@ -95,6 +153,10 @@ else { http_response_code(404); } +if ($include == "login_external_basic.php") { + goto skip_formalities; +} + ?> @@ -116,14 +178,15 @@ else { if ($uri[0] == "admin" && !$user['is_admin']) { http_response_code(401); - die(""); + die("A cat standing in front of a door with a No Cats Allowed sign on it."); } + if ($uri[0] == "docs") { $include = "docs.php"; } } - + skip_formalities: include($include); ?> diff --git a/landing.php b/landing.php index 6e59f94..a4ea89b 100644 --- a/landing.php +++ b/landing.php @@ -1,6 +1,6 @@
- +

ByeCorps ID

Log into ByeCorps and beyond with a single ID.

diff --git a/login_external_basic.php b/login_external_basic.php new file mode 100644 index 0000000..9169211 --- /dev/null +++ b/login_external_basic.php @@ -0,0 +1,147 @@ + +401 Unauthorised

You are not permitted to view this content.

"; + exit(401); + } + + // Now let's determine if we're logged in or not. We can use the session for this, and verify using the + // `bcid` value (which only appears if youre logged in!!!) + if ($_SESSION['auth']) { + if (null == $_POST['bcid'] || $_SESSION['id'] != $_POST['bcid']) { + // Both of these suggest tampering, + // let's log the user out and throw an error. + $_SESSION['auth'] = false; + $_SESSION['id'] = null; + + $flash = "Sorry, something went wrong. Please sign in again."; + + goto login; + } + } + else { // of course, there's also the case that you WERENT logged in. Let's verify if you're logged in or not. + $user_db_version = db_execute("SELECT * FROM accounts WHERE email = ?", [$_POST['email']]); + if (!password_verify($_POST['password'], $user_db_version['password']) || null == $user_db_version) { + // INCORRECT PASSWORD!!!! + // or the account doesn't exist. we don't care either way. + + $flash = "Incorrect email or password."; + } else { + // if it's correct, we'll still force them to click log in again anyway. I'll also be nice and set the + // cookies properly. + + $_SESSION['id'] = $user_db_version['id']; + $_SESSION['auth'] = true; + $user = $user_db_version; + goto login; + } + } + + // The following gets run assuming we know the client is the one CLICKING the button. + $tokens = generate_basic_access_token($_POST['bcid']); + + header('Location: '. $_POST['callback'].'?access_token='.$tokens['access'].'&refresh='.$tokens['refresh'] + .'&expiry='.$tokens['expiry']); + exit(); + +} + +login: + +?> + + + + + + + + +
+
+ +

Sign into

+

Owned by

+

+ + +

Something went wrong!

+

Server returned error:
$error[0] (HTTP response code $error[1])

+
+"; + goto dont_show_form; + } + ?> +

uses ByeCorps ID for authentication.

+

Please double-check the information and avoid signing in with your BCID if you do not trust this app.

+

Please confirm that you'd like to sign into .

+ $flash

"; + } else { + echo "
"; + } + ?> + + + "; + echo "

You are signed in as ". get_display_name($_SESSION['id'], + put_bcid_in_parenthesis: true) . ". Not you?."; + goto signedin; } ?> +

You will need to sign in first.

+ + + + + +

+ You will be brought to . +
will be able to see your email and display name. +

+ + + + +
diff --git a/signin.php b/signin.php index 6de8f74..a1904f5 100644 --- a/signin.php +++ b/signin.php @@ -25,14 +25,20 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { if (password_verify($password, $user["password"])) { $_SESSION["id"] = $user["id"]; $_SESSION["auth"] = true; +// +// print_r($_POST); +// echo(is_string($_POST['keep_logged_in'])); + + if ($_POST['keep_logged_in'] == "on") { + $token = generate_cookie_access_token($user['id']); +// print_r($token); + setcookie("keep_me_logged_in", $token['access']); + } +// if (isset($query['callback'])) { header("Location: ".$query['callback']); } else { header("Location: /profile"); -// echo "
";
-//            var_dump($user);
-//            var_dump($_SESSION);
-//            die();
         }
 
         exit;
@@ -44,17 +50,21 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
 ?>
 
 
-

Sign in to ByeCorps ID

-$message
"; -}?> -
- - - -
+
+

Sign in to ByeCorps ID

+ $message
"; + }?> + -

- Forgot password? • New? Register for a ByeCorps ID. -

\ No newline at end of file +

+ Forgot password? • New? Register for a ByeCorps ID. +

+
\ No newline at end of file diff --git a/signout.php b/signout.php index c128d18..03f7dbe 100644 --- a/signout.php +++ b/signout.php @@ -2,6 +2,7 @@ $_SESSION['id'] = null; $_SESSION['auth'] = false; +setcookie('keep_me_logged_in', '', time()-3600); session_destroy(); ?> diff --git a/styles/colours.css b/styles/colours.css index f11cb97..287d9f0 100644 --- a/styles/colours.css +++ b/styles/colours.css @@ -101,6 +101,11 @@ input[data-com-onepassword-filled="dark"] { margin: 0; } +.flash { + background: var(--red-5); + color: black; +} + @media screen and (prefers-color-scheme: dark) { html { background: var(--background-dark, #121212); diff --git a/styles/design.css b/styles/design.css index acdac55..c6748d9 100644 --- a/styles/design.css +++ b/styles/design.css @@ -46,6 +46,11 @@ input:disabled { cursor: not-allowed; } +.flash { + padding: 1rem; + border-radius: 1rem; +} + table { background-color: var(--grey-2); width: 100%; diff --git a/styles/layout.css b/styles/layout.css index 03d20f2..9e89277 100644 --- a/styles/layout.css +++ b/styles/layout.css @@ -148,3 +148,8 @@ form { display: flex; } +#loginform { + max-width: 500px; + margin: auto; +} + diff --git a/styles/types.css b/styles/types.css index 7b09f26..10cea60 100644 --- a/styles/types.css +++ b/styles/types.css @@ -42,6 +42,12 @@ h2.subheading + h1 { font-family: 'Courier Prime', monospace; } +p.subtitle { + font-size: 0.9rem; + margin: 0; + opacity: 0.8; +} + .center { text-align: center; }