From c6a1637dee2aea3b56587f0048d627d5a0718e53 Mon Sep 17 00:00:00 2001 From: Bye Date: Sat, 17 Feb 2024 12:04:47 +0000 Subject: [PATCH 01/12] 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; } From d7a64844c46c3421beb6902bcdf9ac4a4b0fbd5a Mon Sep 17 00:00:00 2001 From: bye Date: Tue, 20 Feb 2024 19:49:42 +0000 Subject: [PATCH 02/12] yo waht's up --- .gitignore | 3 +- .idea/.gitignore | 5 - .idea/codeStyles/codeStyleConfig.xml | 5 - .idea/dataSources.local.xml | 19 - .idea/dataSources.xml | 12 - .../5bc27beb-c8ab-420d-bdbc-055b37ae9e39.xml | 1288 ----------------- .../storage_v2/_src_/schema/id.Gw0AAA.meta | 2 - .../schema/information_schema.FNRwLQ.meta | 2 - .../storage_v2/_src_/schema/mysql.osA4Bg.meta | 2 - .../schema/performance_schema.kIw0nw.meta | 2 - .idea/id.iml | 30 - .idea/modules.xml | 8 - .idea/php.xml | 47 - .idea/sqldialects.xml | 6 - .idea/vcs.xml | 6 - accounts_handler.php | 2 +- admin_apps_create.php | 6 +- admin_initdatabase.php | 39 +- forgot_password.php | 12 +- index.php | 8 +- profile.php | 2 +- 21 files changed, 45 insertions(+), 1461 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/codeStyles/codeStyleConfig.xml delete mode 100644 .idea/dataSources.local.xml delete mode 100644 .idea/dataSources.xml delete mode 100644 .idea/dataSources/5bc27beb-c8ab-420d-bdbc-055b37ae9e39.xml delete mode 100644 .idea/dataSources/5bc27beb-c8ab-420d-bdbc-055b37ae9e39/storage_v2/_src_/schema/id.Gw0AAA.meta delete mode 100644 .idea/dataSources/5bc27beb-c8ab-420d-bdbc-055b37ae9e39/storage_v2/_src_/schema/information_schema.FNRwLQ.meta delete mode 100644 .idea/dataSources/5bc27beb-c8ab-420d-bdbc-055b37ae9e39/storage_v2/_src_/schema/mysql.osA4Bg.meta delete mode 100644 .idea/dataSources/5bc27beb-c8ab-420d-bdbc-055b37ae9e39/storage_v2/_src_/schema/performance_schema.kIw0nw.meta delete mode 100644 .idea/id.iml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/php.xml delete mode 100644 .idea/sqldialects.xml delete mode 100644 .idea/vcs.xml diff --git a/.gitignore b/.gitignore index a078a68..cf76f7b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ config.php -vendor/ \ No newline at end of file +vendor/ +.idea/ \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index b58b603..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index a55e7a1..0000000 --- a/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/dataSources.local.xml b/.idea/dataSources.local.xml deleted file mode 100644 index 9c2db00..0000000 --- a/.idea/dataSources.local.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - #@ - ` - - - master_key - bye - - - - - - - - \ No newline at end of file diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml deleted file mode 100644 index dfaf86d..0000000 --- a/.idea/dataSources.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - mariadb - true - org.mariadb.jdbc.Driver - jdbc:mariadb://id.local:3306/id.local - $ProjectFileDir$ - - - \ No newline at end of file diff --git a/.idea/dataSources/5bc27beb-c8ab-420d-bdbc-055b37ae9e39.xml b/.idea/dataSources/5bc27beb-c8ab-420d-bdbc-055b37ae9e39.xml deleted file mode 100644 index 627b796..0000000 --- a/.idea/dataSources/5bc27beb-c8ab-420d-bdbc-055b37ae9e39.xml +++ /dev/null @@ -1,1288 +0,0 @@ - - - - - - big5 - 1 - - - big5 - - - big5 - - - big5 - - - dec8 - 1 - - - dec8 - - - dec8 - - - dec8 - - - cp850 - 1 - - - cp850 - - - cp850 - - - cp850 - - - hp8 - 1 - - - hp8 - - - hp8 - - - hp8 - - - koi8r - 1 - - - koi8r - - - koi8r - - - koi8r - - - latin1 - - - latin1 - 1 - - - latin1 - - - latin1 - - - latin1 - - - latin1 - - - latin1 - - - latin1 - - - latin1 - - - latin1 - - - latin2 - - - latin2 - 1 - - - latin2 - - - latin2 - - - latin2 - - - latin2 - - - latin2 - - - swe7 - 1 - - - swe7 - - - swe7 - - - swe7 - - - ascii - 1 - - - ascii - - - ascii - - - ascii - - - ujis - 1 - - - ujis - - - ujis - - - ujis - - - sjis - 1 - - - sjis - - - sjis - - - sjis - - - hebrew - 1 - - - hebrew - - - hebrew - - - hebrew - - - tis620 - 1 - - - tis620 - - - tis620 - - - tis620 - - - euckr - 1 - - - euckr - - - euckr - - - euckr - - - koi8u - 1 - - - koi8u - - - koi8u - - - koi8u - - - gb2312 - 1 - - - gb2312 - - - gb2312 - - - gb2312 - - - greek - 1 - - - greek - - - greek - - - greek - - - cp1250 - 1 - - - cp1250 - - - cp1250 - - - cp1250 - - - cp1250 - - - cp1250 - - - cp1250 - - - gbk - 1 - - - gbk - - - gbk - - - gbk - - - latin5 - 1 - - - latin5 - - - latin5 - - - latin5 - - - armscii8 - 1 - - - armscii8 - - - armscii8 - - - armscii8 - - - utf8mb3 - 1 - - - utf8mb3 - - - utf8mb3 - - - utf8mb3 - - - utf8mb3 - - - utf8mb3 - - - utf8mb3 - - - utf8mb3 - - - utf8mb3 - - - utf8mb3 - - - utf8mb3 - - - utf8mb3 - - - utf8mb3 - - - utf8mb3 - - - utf8mb3 - - - utf8mb3 - - - utf8mb3 - - - utf8mb3 - - - utf8mb3 - - - utf8mb3 - - - utf8mb3 - - - utf8mb3 - - - utf8mb3 - - - utf8mb3 - - - utf8mb3 - - - utf8mb3 - - - utf8mb3 - - - utf8mb3 - - - utf8mb3 - - - utf8mb3 - - - utf8mb3 - - - utf8mb3 - - - utf8mb3 - - - utf8mb3 - - - ucs2 - 1 - - - ucs2 - - - ucs2 - - - ucs2 - - - ucs2 - - - ucs2 - - - ucs2 - - - ucs2 - - - ucs2 - - - ucs2 - - - ucs2 - - - ucs2 - - - ucs2 - - - ucs2 - - - ucs2 - - - ucs2 - - - ucs2 - - - ucs2 - - - ucs2 - - - ucs2 - - - ucs2 - - - ucs2 - - - ucs2 - - - ucs2 - - - ucs2 - - - ucs2 - - - ucs2 - - - ucs2 - - - ucs2 - - - ucs2 - - - ucs2 - - - ucs2 - - - ucs2 - - - ucs2 - - - cp866 - 1 - - - cp866 - - - cp866 - - - cp866 - - - keybcs2 - 1 - - - keybcs2 - - - keybcs2 - - - keybcs2 - - - macce - 1 - - - macce - - - macce - - - macce - - - macroman - 1 - - - macroman - - - macroman - - - macroman - - - cp852 - 1 - - - cp852 - - - cp852 - - - cp852 - - - latin7 - - - latin7 - 1 - - - latin7 - - - latin7 - - - latin7 - - - latin7 - - - utf8mb4 - 1 - - - utf8mb4 - - - utf8mb4 - - - utf8mb4 - - - utf8mb4 - - - utf8mb4 - - - utf8mb4 - - - utf8mb4 - - - utf8mb4 - - - utf8mb4 - - - utf8mb4 - - - utf8mb4 - - - utf8mb4 - - - utf8mb4 - - - utf8mb4 - - - utf8mb4 - - - utf8mb4 - - - utf8mb4 - - - utf8mb4 - - - utf8mb4 - - - utf8mb4 - - - utf8mb4 - - - utf8mb4 - - - utf8mb4 - - - utf8mb4 - - - utf8mb4 - - - utf8mb4 - - - utf8mb4 - - - utf8mb4 - - - utf8mb4 - - - utf8mb4 - - - utf8mb4 - - - utf8mb4 - - - cp1251 - - - cp1251 - - - cp1251 - - - cp1251 - 1 - - - cp1251 - - - cp1251 - - - cp1251 - - - utf16 - 1 - - - utf16 - - - utf16 - - - utf16 - - - utf16 - - - utf16 - - - utf16 - - - utf16 - - - utf16 - - - utf16 - - - utf16 - - - utf16 - - - utf16 - - - utf16 - - - utf16 - - - utf16 - - - utf16 - - - utf16 - - - utf16 - - - utf16 - - - utf16 - - - utf16 - - - utf16 - - - utf16 - - - utf16 - - - utf16 - - - utf16 - - - utf16 - - - utf16 - - - utf16 - - - utf16 - - - utf16 - - - utf16 - - - utf16le - 1 - - - utf16le - - - utf16le - - - utf16le - - - cp1256 - 1 - - - cp1256 - - - cp1256 - - - cp1256 - - - cp1257 - - - cp1257 - - - cp1257 - 1 - - - cp1257 - - - cp1257 - - - utf32 - 1 - - - utf32 - - - utf32 - - - utf32 - - - utf32 - - - utf32 - - - utf32 - - - utf32 - - - utf32 - - - utf32 - - - utf32 - - - utf32 - - - utf32 - - - utf32 - - - utf32 - - - utf32 - - - utf32 - - - utf32 - - - utf32 - - - utf32 - - - utf32 - - - utf32 - - - utf32 - - - utf32 - - - utf32 - - - utf32 - - - utf32 - - - utf32 - - - utf32 - - - utf32 - - - utf32 - - - utf32 - - - utf32 - - - binary - 1 - - - geostd8 - 1 - - - geostd8 - - - geostd8 - - - geostd8 - - - cp932 - 1 - - - cp932 - - - cp932 - - - cp932 - - - eucjpms - 1 - - - eucjpms - - - eucjpms - - - eucjpms - - - utf8mb3_general_ci - - - utf8mb4_general_ci - - - utf8mb3_general_ci - - - 1 - 2023-11-16.19:58:50 - utf8mb4_general_ci - - - utf8mb4_general_ci - - - utf8mb3_general_ci - - - localhost - - - localhost - - - localhost - - - - localhost - - - - 100.12.43.1 - - - InnoDB - utf8mb4_general_ci -
- - InnoDB - utf8mb4_general_ci -
- - InnoDB - utf8mb4_general_ci -
- - InnoDB - utf8mb4_general_ci -
- - InnoDB - utf8mb4_general_ci -
- - varchar(7)|0s - 1 - 1 - - - text|0s - 1 - 2 - - - date|0s - current_timestamp() - 1 - 3 - - - text|0s - 4 - - - text|0s - 1 - 5 - - - tinyint(1)|0s - 1 - 6 - - - tinyint(1)|0s - 0 - 1 - 7 - - - tinyint(1)|0s - 0 - 1 - 8 - - - id - btree - 1 - - - email - hash - 1 - - - 1 - 1 - PRIMARY - - - email - - - int(10)|0s - 1 - 1 - - - varchar(7)|0s - 2 - - - text|0s - 1 - 3 - - - text|0s - 4 - - - owner_id - set-null - cascade - id - accounts - - - id - btree - 1 - - - owner_id - btree - - - 1 - 1 - PRIMARY - - - 1 - int(11)|0s - 1 - 1 - - - int(11)|0s - 1 - 2 - - - text|0s - 1 - 3 - - - text|0s - 4 - - - text|0s - 1 - 5 - - - app_id - id - apps - - - id - btree - 1 - - - app_id - btree - - - 1 - 1 - PRIMARY - - - 8 - int(11)|0s - 1 - 1 - - - tinytext|0s - 1 - 2 - - - varchar(7)|0s - 1 - 3 - - - int(11)|0s - 1 - 4 - - - owner_id - id - accounts - - - id - btree - 1 - - - owner_id - btree - - - 1 - 1 - PRIMARY - - - varchar(7)|0s - 1 - 1 - - - text|0s - 2 - - - tinyint(1)|0s - 0 - 1 - 3 - - - tinyint(1)|0s - 0 - 1 - 4 - - - id - id - accounts - - - id - btree - 1 - - - 1 - 1 - PRIMARY - -
-
\ No newline at end of file diff --git a/.idea/dataSources/5bc27beb-c8ab-420d-bdbc-055b37ae9e39/storage_v2/_src_/schema/id.Gw0AAA.meta b/.idea/dataSources/5bc27beb-c8ab-420d-bdbc-055b37ae9e39/storage_v2/_src_/schema/id.Gw0AAA.meta deleted file mode 100644 index d4880e4..0000000 --- a/.idea/dataSources/5bc27beb-c8ab-420d-bdbc-055b37ae9e39/storage_v2/_src_/schema/id.Gw0AAA.meta +++ /dev/null @@ -1,2 +0,0 @@ -#n:id -! [1700164719000, 0, null, null, -2147483648, -2147483648] diff --git a/.idea/dataSources/5bc27beb-c8ab-420d-bdbc-055b37ae9e39/storage_v2/_src_/schema/information_schema.FNRwLQ.meta b/.idea/dataSources/5bc27beb-c8ab-420d-bdbc-055b37ae9e39/storage_v2/_src_/schema/information_schema.FNRwLQ.meta deleted file mode 100644 index 1ff3db2..0000000 --- a/.idea/dataSources/5bc27beb-c8ab-420d-bdbc-055b37ae9e39/storage_v2/_src_/schema/information_schema.FNRwLQ.meta +++ /dev/null @@ -1,2 +0,0 @@ -#n:information_schema -! [null, 0, null, null, -2147483648, -2147483648] diff --git a/.idea/dataSources/5bc27beb-c8ab-420d-bdbc-055b37ae9e39/storage_v2/_src_/schema/mysql.osA4Bg.meta b/.idea/dataSources/5bc27beb-c8ab-420d-bdbc-055b37ae9e39/storage_v2/_src_/schema/mysql.osA4Bg.meta deleted file mode 100644 index 86a53f1..0000000 --- a/.idea/dataSources/5bc27beb-c8ab-420d-bdbc-055b37ae9e39/storage_v2/_src_/schema/mysql.osA4Bg.meta +++ /dev/null @@ -1,2 +0,0 @@ -#n:mysql -! [null, 0, null, null, -2147483648, -2147483648] diff --git a/.idea/dataSources/5bc27beb-c8ab-420d-bdbc-055b37ae9e39/storage_v2/_src_/schema/performance_schema.kIw0nw.meta b/.idea/dataSources/5bc27beb-c8ab-420d-bdbc-055b37ae9e39/storage_v2/_src_/schema/performance_schema.kIw0nw.meta deleted file mode 100644 index 9394db1..0000000 --- a/.idea/dataSources/5bc27beb-c8ab-420d-bdbc-055b37ae9e39/storage_v2/_src_/schema/performance_schema.kIw0nw.meta +++ /dev/null @@ -1,2 +0,0 @@ -#n:performance_schema -! [null, 0, null, null, -2147483648, -2147483648] diff --git a/.idea/id.iml b/.idea/id.iml deleted file mode 100644 index 7267852..0000000 --- a/.idea/id.iml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 9367315..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/php.xml b/.idea/php.xml deleted file mode 100644 index a30690c..0000000 --- a/.idea/php.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/sqldialects.xml b/.idea/sqldialects.xml deleted file mode 100644 index 63772a3..0000000 --- a/.idea/sqldialects.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1dd..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/accounts_handler.php b/accounts_handler.php index 9add2f5..5d862b9 100644 --- a/accounts_handler.php +++ b/accounts_handler.php @@ -25,7 +25,7 @@ function get_avatar_url($bcid):string { } -function get_display_name($bcid, $use_bcid_fallback=true, $put_bcid_in_parenthesis=false):string { +function get_display_name($bcid, $use_bcid_fallback=true, $put_bcid_in_parenthesis=false, $format_bcid=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) { diff --git a/admin_apps_create.php b/admin_apps_create.php index 0de29ff..1e495fb 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, type) VALUES (?, ?, ?, ?, ?)", [$app_id, $_POST['owner'], $_POST['title'], $_POST['description'], $_POST['type']]); + db_execute("INSERT INTO apps (id, owner_id, title, description, type, callback) VALUES (?, ?, ?, ?, ?, ?)", [$app_id, $_POST['owner'], $_POST['title'], $_POST['description'], $_POST['type'], $_POST['callback']]); die(); } @@ -40,5 +40,7 @@ if ($_SERVER['REQUEST_METHOD'] == "POST") { - + + + \ No newline at end of file diff --git a/admin_initdatabase.php b/admin_initdatabase.php index fec3bb9..838580c 100644 --- a/admin_initdatabase.php +++ b/admin_initdatabase.php @@ -6,15 +6,15 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") { echo "

Create table `accounts`"; $stmt = $pdo->prepare('create table accounts ( - id varchar(7) not null + id varchar(7) not null primary key, - email text not null, - created_date date default current_timestamp() not null, - display_name text null, - password text 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, + email text not null, + created_date datetime default current_timestamp() not null, + display_name text null, + password text 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 );'); @@ -73,6 +73,8 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") { 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 badges_ibfk_1 foreign key (app_id) references apps (id) );'); @@ -89,6 +91,7 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") { 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) );'); @@ -96,6 +99,26 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") { echo('

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

Create the `tokens` table'; + + try { + db_execute('create table tokens ( + id int auto_increment primary key, + access_token text unique, + refresh_token text null, + expiry int not null, + owner_id varchar(7), + application_id int(10) null, + + constraint tokens_application_id + foreign key (application_id) references apps (id), + constraint tokens_owner_id + foreign key (owner_id) references accounts (id) + );'); + } catch (PDOException $e) { + echo('

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

Database initialised.

"; } diff --git a/forgot_password.php b/forgot_password.php index f8180ea..bd02325 100644 --- a/forgot_password.php +++ b/forgot_password.php @@ -16,15 +16,7 @@ if ($_SERVER['REQUEST_METHOD'] == "POST") { // create a password reset $password_reset_link = create_password_reset($user['id']); - try { - $safe_display_name = format_bcid($user['id']); - } catch (Exception $e) { - die("Bad BCID."); - } - - if ($user['display_name'] != '') { - $safe_display_name = $user['display_name']; - } + $safe_display_name = get_display_name($user['id'], use_bcid_fallback: true); try { @@ -41,7 +33,7 @@ If you did not request this password reset, please ignore it (or tighten your ac // echo("This is a security issue."); } catch (Exception $e) { - echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}"; + echo "Message could not be sent. Mailer Error: $e"; } } diff --git a/index.php b/index.php index 3c9f9b9..7a6bd0b 100644 --- a/index.php +++ b/index.php @@ -176,10 +176,10 @@ if ($include == "login_external_basic.php") { echo "

Admin

"; } - if ($uri[0] == "admin" && !$user['is_admin']) { - http_response_code(401); - die("A cat standing in front of a door with a No Cats Allowed sign on it."); - } +// if ($uri[0] == "admin" && !$user['is_admin']) { +// http_response_code(401); +// die("A cat standing in front of a door with a No Cats Allowed sign on it."); +// } if ($uri[0] == "docs") { $include = "docs.php"; diff --git a/profile.php b/profile.php index 0c38e6c..9b365d2 100644 --- a/profile.php +++ b/profile.php @@ -11,7 +11,7 @@ $profile = db_execute("SELECT * FROM `profiles` WHERE id = ? LIMIT 1", [$user['i if (empty($profile)) { $profile = [ - "id" => "0000000", + "id" => "9999999", "public_display_name" => false, "public_avatar" => false, "description" => null, From e0df5a8c097cdb7ffc1fbd36d8bc64a47e3661bd Mon Sep 17 00:00:00 2001 From: Bye Date: Sat, 2 Mar 2024 12:41:57 +0000 Subject: [PATCH 03/12] Commit --- accounts_handler.php | 23 ++------ admin_apps_create.php | 10 ++-- admin_initdatabase.php | 17 ++++++ api_handler.php | 24 ++++++++- assets/icons/apple-icon-180.png | Bin 0 -> 698 bytes assets/icons/apple-splash-1125-2436.png | Bin 0 -> 16356 bytes assets/icons/apple-splash-1136-640.png | Bin 0 -> 4561 bytes assets/icons/apple-splash-1170-2532.png | Bin 0 -> 17311 bytes assets/icons/apple-splash-1179-2556.png | Bin 0 -> 17783 bytes assets/icons/apple-splash-1242-2208.png | Bin 0 -> 15967 bytes assets/icons/apple-splash-1242-2688.png | Bin 0 -> 19355 bytes assets/icons/apple-splash-1284-2778.png | Bin 0 -> 20320 bytes assets/icons/apple-splash-1290-2796.png | Bin 0 -> 19153 bytes assets/icons/apple-splash-1334-750.png | Bin 0 -> 5868 bytes assets/icons/apple-splash-1488-2266.png | Bin 0 -> 18170 bytes assets/icons/apple-splash-1536-2048.png | Bin 0 -> 17136 bytes assets/icons/apple-splash-1620-2160.png | Bin 0 -> 18407 bytes assets/icons/apple-splash-1640-2360.png | Bin 0 -> 20641 bytes assets/icons/apple-splash-1668-2224.png | Bin 0 -> 19755 bytes assets/icons/apple-splash-1668-2388.png | Bin 0 -> 21173 bytes assets/icons/apple-splash-1792-828.png | Bin 0 -> 7886 bytes assets/icons/apple-splash-2048-1536.png | Bin 0 -> 16264 bytes assets/icons/apple-splash-2048-2732.png | Bin 0 -> 28653 bytes assets/icons/apple-splash-2160-1620.png | Bin 0 -> 17730 bytes assets/icons/apple-splash-2208-1242.png | Bin 0 -> 13787 bytes assets/icons/apple-splash-2224-1668.png | Bin 0 -> 18647 bytes assets/icons/apple-splash-2266-1488.png | Bin 0 -> 16890 bytes assets/icons/apple-splash-2360-1640.png | Bin 0 -> 19371 bytes assets/icons/apple-splash-2388-1668.png | Bin 0 -> 19070 bytes assets/icons/apple-splash-2436-1125.png | Bin 0 -> 13640 bytes assets/icons/apple-splash-2532-1170.png | Bin 0 -> 14600 bytes assets/icons/apple-splash-2556-1179.png | Bin 0 -> 14863 bytes assets/icons/apple-splash-2688-1242.png | Bin 0 -> 16322 bytes assets/icons/apple-splash-2732-2048.png | Bin 0 -> 26953 bytes assets/icons/apple-splash-2778-1284.png | Bin 0 -> 17014 bytes assets/icons/apple-splash-2796-1290.png | Bin 0 -> 17412 bytes assets/icons/apple-splash-640-1136.png | Bin 0 -> 5494 bytes assets/icons/apple-splash-750-1334.png | Bin 0 -> 7083 bytes assets/icons/apple-splash-828-1792.png | Bin 0 -> 9836 bytes assets/icons/manifest-icon-192.maskable.png | Bin 0 -> 721 bytes assets/icons/manifest-icon-512.maskable.png | Bin 0 -> 2331 bytes dashboard.php | 12 +++++ database.php | 9 ++++ head.php | 56 +++++++++++++++++--- image_grabber.php | 17 ++++++ index.php | 26 ++++++--- login_external_basic.php | 9 +++- manifest.json | 34 ++++++++++++ profile.php | 37 ++++++++++--- signin.php | 17 +++--- signup.php | 4 +- styles/design.css | 23 ++++++-- styles/global.css | 6 +-- styles/profiles.css | 30 +++++++++++ styles/types.css | 31 +++++++++-- 55 files changed, 322 insertions(+), 63 deletions(-) create mode 100644 assets/icons/apple-icon-180.png create mode 100644 assets/icons/apple-splash-1125-2436.png create mode 100644 assets/icons/apple-splash-1136-640.png create mode 100644 assets/icons/apple-splash-1170-2532.png create mode 100644 assets/icons/apple-splash-1179-2556.png create mode 100644 assets/icons/apple-splash-1242-2208.png create mode 100644 assets/icons/apple-splash-1242-2688.png create mode 100644 assets/icons/apple-splash-1284-2778.png create mode 100644 assets/icons/apple-splash-1290-2796.png create mode 100644 assets/icons/apple-splash-1334-750.png create mode 100644 assets/icons/apple-splash-1488-2266.png create mode 100644 assets/icons/apple-splash-1536-2048.png create mode 100644 assets/icons/apple-splash-1620-2160.png create mode 100644 assets/icons/apple-splash-1640-2360.png create mode 100644 assets/icons/apple-splash-1668-2224.png create mode 100644 assets/icons/apple-splash-1668-2388.png create mode 100644 assets/icons/apple-splash-1792-828.png create mode 100644 assets/icons/apple-splash-2048-1536.png create mode 100644 assets/icons/apple-splash-2048-2732.png create mode 100644 assets/icons/apple-splash-2160-1620.png create mode 100644 assets/icons/apple-splash-2208-1242.png create mode 100644 assets/icons/apple-splash-2224-1668.png create mode 100644 assets/icons/apple-splash-2266-1488.png create mode 100644 assets/icons/apple-splash-2360-1640.png create mode 100644 assets/icons/apple-splash-2388-1668.png create mode 100644 assets/icons/apple-splash-2436-1125.png create mode 100644 assets/icons/apple-splash-2532-1170.png create mode 100644 assets/icons/apple-splash-2556-1179.png create mode 100644 assets/icons/apple-splash-2688-1242.png create mode 100644 assets/icons/apple-splash-2732-2048.png create mode 100644 assets/icons/apple-splash-2778-1284.png create mode 100644 assets/icons/apple-splash-2796-1290.png create mode 100644 assets/icons/apple-splash-640-1136.png create mode 100644 assets/icons/apple-splash-750-1334.png create mode 100644 assets/icons/apple-splash-828-1792.png create mode 100644 assets/icons/manifest-icon-192.maskable.png create mode 100644 assets/icons/manifest-icon-512.maskable.png create mode 100644 dashboard.php create mode 100644 image_grabber.php mode change 100644 => 100755 index.php create mode 100644 manifest.json diff --git a/accounts_handler.php b/accounts_handler.php index 5d862b9..34e6c0a 100644 --- a/accounts_handler.php +++ b/accounts_handler.php @@ -2,27 +2,14 @@ // This file carries functions related to accounts. function get_avatar_url($bcid):string { - global $pdo; - $sql = "SELECT has_pfp FROM `accounts` WHERE id = ?"; + $exists = db_execute('SELECT public FROM avatars WHERE id = ? LIMIT 1', [$bcid]); - try { - $stmt = $pdo -> prepare($sql); - $stmt->execute([$bcid]); - $has_pfp = $stmt->fetch(); - } catch (PDOException $e) { - http_response_code(500); - die($e); - } - - $appendix = "default.png"; - - if ($has_pfp['has_pfp']) { - $appendix = $bcid; - } - - return 'https://cdn.byecorps.com/id/profile/'.$appendix; + if (empty($exists)) { + return '/assets/default.png'; + } + return '/public/avatars/' . $bcid; } function get_display_name($bcid, $use_bcid_fallback=true, $put_bcid_in_parenthesis=false, $format_bcid=false):string { diff --git a/admin_apps_create.php b/admin_apps_create.php index 1e495fb..c769a22 100644 --- a/admin_apps_create.php +++ b/admin_apps_create.php @@ -23,11 +23,11 @@ if ($_SERVER['REQUEST_METHOD'] == "POST") {
- + - - + + + + diff --git a/admin_initdatabase.php b/admin_initdatabase.php index 838580c..fb860c9 100644 --- a/admin_initdatabase.php +++ b/admin_initdatabase.php @@ -119,6 +119,23 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") { echo('

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

Create the `tokens` table'; + + try { + db_query('CREATE TABLE `badge_owners` ( + `badge_id` int(11) NOT NULL, + `owner_id` varchar(7) NOT NULL, + `earned` timestamp NULL DEFAULT current_timestamp(), + `info` text DEFAULT NULL COMMENT \'App may attach more info about how the badge was won (Killed "CoolGamer69 in battle!")\', + + constraint badges_owners_badge + foreign key (badge_id) references badges (id), + constraint badges_owners_owner + foreign key (owner_id) references accounts (id) +);'); + } catch (PDOException $e) { + echo('

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

Database initialised.

"; } diff --git a/api_handler.php b/api_handler.php index 64e3c59..34c5c5a 100644 --- a/api_handler.php +++ b/api_handler.php @@ -53,6 +53,19 @@ function api_health_check(): array return ["message" => "Science compels us to explode the sun!", "time" => time(), "response_code" => 200]; } +// Potentially authenticated image endpoints + +function get_avatar(): array +{ + if (!array_key_exists('id', $query)) { + return [ + 'response_code' => 404, + 'message' => 'ID not assigned/found' + ]; + } + $user_id = $query['id']; +} + // User (REQUIRES AUTHORISATION) function api_user_info() { @@ -94,7 +107,10 @@ $api_routes = [ // base url is base_url.'/api' "/status" => "api_health_check", // Account stuff - "/account/me" => "api_user_info" + "/account/me" => "api_user_info", + + // Get avatar + "/avatars/get" => "get_avatar" ]; $path = str_replace("/api", "", $path); @@ -107,7 +123,11 @@ if (isset($api_routes[$path])) { "message" => "Token expired or invalid." ])); } - echo json_encode($api_routes[$path]()); + $response = $api_routes[$path](); + if (array_key_exists('response_code', $response)) { + http_response_code($response['response_code']); + } + echo json_encode($response); } else { http_response_code(404); echo (json_encode([ diff --git a/assets/icons/apple-icon-180.png b/assets/icons/apple-icon-180.png new file mode 100644 index 0000000000000000000000000000000000000000..f07b87c89f135d2996cc9bca2cbc94c5493f5cc7 GIT binary patch literal 698 zcmeAS@N?(olHy`uVBq!ia0vp^TR@nD4M^IaWitX&jKx9jP7LeL$-HD>U@Gx+aSW-L z^Y-q;%tHV8dSMC2ED^`aN&_WWv$u-z`;UJ=_x}1>8JqX--L&leg-fzu z-;O$bFZ<{E^#9`h2~Nna3w~Gh<|gZmkAAi57q2TkpLa>a2ifVVr(*kT&zs2n{B!t3 z`S16qTFCR^GMle&x0ps_7@fX^#$l&Sf=d#Wzp$PzV C`w3V8 literal 0 HcmV?d00001 diff --git a/assets/icons/apple-splash-1125-2436.png b/assets/icons/apple-splash-1125-2436.png new file mode 100644 index 0000000000000000000000000000000000000000..50920b97b8336200fa3538251b3e401f13f82176 GIT binary patch literal 16356 zcmeI3Ur19?9LIn6da1c7%-KUp>0ZJjVQaI8Al;Ig4u>_XN9SH@1x7_Z457HWE7d~@ z(L+YvhaiJo8i?2*iA$wXX(dBZgCYjShNu)PLB!6v_ceP;80-78!#!~B#`pft_xCy9 zZI=%;))ksd%tTb^ulF?(Nk@qC71KI46W^M6%m(31Q(X=9zT2E4vXkGp_fYiK?9@&{ zvy8xgoFGY?BO^3 zLJDkRud=*7j}2BQ7C{J91hxh|0%nP>f%XX`02=`kLCfrL03-ks011EuKms5EkN`*k zBwz{v34jEDLV}^$nepQ+&z2_4=YX}@UeI8|h|8hQI2 zJ*4*PauT3O6`8DUCJIohdNX+JTyuqS8AS%1Ye+$6A-e3KrKAgyt2d*sL zFK3h*c>VwQm1g6uizw=Lrtsy33yG^+ES&!ez7Lj;sLxFs>-9|Wf_{9%1raoW2K;X;r~_z#IzV3_85%$X n)(}t!&;YCqECLn*i?Rj@qHi6&7>k44ofy`glX=O&AlU8c z;uumf=k2Y)+}92wt{1l%F(w@Zq5AeV=? zUokS+T&|lFe1G?P!>@a9{!W|yxALdt{q%qB_w^apKVV`9s#fqjzzC!|gn@-P1H&U0 z86eqU!AK9OZC9BYDwh403ci24zxY-4=I;k5|ET@b^Iw}G?jY*`7xTHR*%?0g{4QKK z@59<(`*!`7TCL8&@JCaR{-H$A7#X#ToV<`1ZOhP*zH9x)DkcU7n>KDbW+7}5b~}up z;la#rk7H~b#UYM5F#pkD$my1B12eyr_-MrqEN=%(#l3y49I$PD zx^B*D^*>qPO~d>d9yG>006K60o7i`L*Y=*jstj_(5A)IFGTQ9{CWO&W-~&*880`{| hjsk$v0nypvJ8P!Ak=U=0drv^xJYD@<);T3K0RTFQ`v?F4 literal 0 HcmV?d00001 diff --git a/assets/icons/apple-splash-1170-2532.png b/assets/icons/apple-splash-1170-2532.png new file mode 100644 index 0000000000000000000000000000000000000000..c6cd4a14d981cb7e3f5c66917698e312042b608c GIT binary patch literal 17311 zcmeI4Ur1AN6vxlH!?xiX4zrLTn~R7dx2G_QwzcI(G>15|m$shlKgGyQu`c1mWYU%v z1gU#03|#nNfe&6uh=>*;BGS5?_BtYEH<3D}Dq?pUtcN&e6oI-L8x6)crHLxYWw+M1^k%26THZv0 zV9xghi;O09CLEdB{%K??5WB=4Az^H3k7)U;CiXreXO~el`bsss^5f1m%v6}M1aBZV zkPavgsE1Go2qN$RL5 zjBOoQck5nxy)79#pvvkV_l=+Sp5NHk^{TitqGU;FF&GuhL{u(zC8JF*8Z5yZEDR7E zNQV_%9EJ|-sAYKn^|abIGgZCs-JO^56OJ8M&Mj!}zsawkPn>E}#)jtFxn$1<8Kt}A zm1f_^Tu0TnCuYejDn9z-`3G;qV(r|BcK%tYu*w z_~m%;$fH=Gm38i;5jn+$>^R`2r)}HsvjC7fIg;P&9Pv%xFS=_P>%3iiOnxBzMz?n&ouU>qAyPt}We*QVjC_zEIAVUFMt-_A)lC~iJ!nf|Tt*qcJ zdBwOFHeX;UsN}<8U6q7*L0Nb#HQU}7ovdVTpvEXD4}%~U2y!GK%r{o>d_#5}+yC#< zp5~jg7Ev`UkK=D+p}HWu_s literal 0 HcmV?d00001 diff --git a/assets/icons/apple-splash-1179-2556.png b/assets/icons/apple-splash-1179-2556.png new file mode 100644 index 0000000000000000000000000000000000000000..5f90799a900db4524bee7e853a59e7aa7c9e28b3 GIT binary patch literal 17783 zcmeI4-Aj{U7{>3dO`0~h%0A3wMz+XfruT9f%G9_S(@F?`v&ZNQ^{LB0K=ZIe2DG{Y&%qmLe`Hi9^_Z#@r z-x|?z$sciRxul&tEY{yVfMt*bU4o4RD1eh}2(S*=B9emG2nbIs0`eq_fUL|S017Mu zpdds56j%g6fkglm#C||hU=aWX76DLT5dZ}i0Z(zUBs}YpP#H zb+Z>oBWx}5T>#2Q9N|d0QXWXMibJam1>qz7 z(k0U~wMB9F_!^pww0V5m#SGyYL{mppC&HhD#Xw9WJzvUtyqku~>r6S{4&`ddZ>d%8 zGl7brqIwRXOhwK{RU#}&*S()E`m|EQZFNp0#_mT4f4SON51KltRy1M^#g|wynd5uC z@Im&YLl8<_&gxt3qEM2G zE{qyWyDSL`O|O;&1?6Z2DV8LNrcFZHS1pU`J${q&Dt99a&((ns-hJcjInVQZ54*g- zti+JAK81)3_EKv(k#3MkAJ8X@Cll8kt)gg7m6u4=5!yIGludT4<)Hi4=Tb13 z_xt*#g-CrnC3Vs5Qy1NObk-HF1JjaRW5&f_s*pL{V*{fy( z&BvyXz@;?prGF3RUXSQr8=mf-od0=;d7oY`D q0R{nH05k#}A`Ov-NJFIIB1l7Hh2M0j*_&~gzl+^gX6=xi7ybb7<&fwA literal 0 HcmV?d00001 diff --git a/assets/icons/apple-splash-1242-2688.png b/assets/icons/apple-splash-1242-2688.png new file mode 100644 index 0000000000000000000000000000000000000000..45c72d46c48e015edf310793b4ba6d92755a33fb GIT binary patch literal 19355 zcmeHPT}V@57=AaGt=U4+*7}iz0xt^FgaYSm9;VY94eO$)Xd!7BqENEw`Z=aWq9hev z6gm9qqKlHi(ClhiP+*RBQHmuArdgAaT(#`?dv_Xm6-A*L&(%8)eCOMFzvq3P=Y82u z-PSytUbjL=MEcwuYXOmFkVq$MBgK`Bex)>z`QGP7D$CC%2?&DN6U+AGz; z#Izgr8@JtAYUr#8$nqm)UfrS$x+P`MU8@YbwaTD7S{ZaFD1&ax52J#G%umrs4v@n- zh3Wux2pm{IkI)W*ga1ZY*S9UCXZwcU`(lq(G~FLxw7PHlVbSKPVqN~lkDm&kI1Y~$ zN9JF87r!95ZrQxB3y*s}I|W~dehVNDinO!ga(c&Af>zT8a1OZqDt++w|F%SbD_7?Fr@7o%jy-`VJSULNnP#5y3=>62x>jB}7A38ihs? zS;+(`5h{(SEJQg-F$vNL`e8(73Ni@{kxDYx_nuRCN>^Ky&(*u_aLxx0@Ap1G=VNC} zONvrW>r6zH>T$cuh?0y%rih#@e(`>^Y!yZFmlZjwdw6}6NFk4_(0jb?(_6cwDx}`E z$K0+JYg^CN?%4ODucGHfy10RqvHmo!G#|Ez$5Ftt%ferss|&fvcB3SU@&p$F0y+WP z0W$%E5$phpgia8X5Fh{qC}Y?IcqAA_F$nJ!QoE8bcjb6Hs!CHlk`xP8w)+onc{DVX-Iyd>bvfwz6`2?6VS!Q4({WMAB!B=A zupP*WnIN-mvYap8D>hT>?7KI! z!7E?J+d`jTPK}rY59ZR!FUAfyuC4+#|ACbrMkTtWA@@43pp*Mh9F2J24B)_IV6u2I zSwd;%pEU0ms_RL;F*(q=Nl={H4gy?~=rsbozhQFL_+e$}`?Zk3t0sI}5d}hF5fFy5 z^Xc0t6CTZ12%VLuGu}WgB-V15lF-v}Hx<15h>k>B{Pl+Nk(0%H$u{nU&R9ZcOpHJ7 z8HrkXim9W=79CJCPn**;`zO!zrcVsIHA|>A>3O|Xzh$G2@SdQ;PdYDap2%j^Ok`H3 zmhk&rxDnupHbduNcZiJ;!05nuDhsbQ;{{=|=>R1ti5Q&+>1OPz@LCAd&Z$VfUUc*Q5$vAh=TvyH?Aw3{H y{)Y4b`GfpH{t6FckUz+u`yk%r&ubuoUNnK0LW9m{y%o==86(f`5?8m=*YFdOHsi(s literal 0 HcmV?d00001 diff --git a/assets/icons/apple-splash-1290-2796.png b/assets/icons/apple-splash-1290-2796.png new file mode 100644 index 0000000000000000000000000000000000000000..cee06dbbb8b2de6722bfbc0d2f5f7e9201eac4fa GIT binary patch literal 19153 zcmeHPUr19?96obS=Wr<_C~ejXA?cyNP!A%`vD#hKv>`qCbS)uR^bjMFsX2xQ_F#)7 z%xW$l7X7n5^iYsvSkOz%2b0AnX%Ddsn+vBEi`F^!C_M;+STAzFr*qG}cMs>|`+dLf z_d92|zsY9NYAQ8^5Uo`(+X+$8Yt4eXh~61ezurp+h0|^^k+Fz=o)81Enj4xs?kv1N zpa>gCICwBCn3cLKrJHoB@!FN)9{N5BPle(N>7x7CPBx003)sLX-cxEeY2)`Q`q;#X zM-oCn1KdD3Kpdcl$PO$oB3Hs5Fdo1xNj?(cfN(%Kpj?6;qFzS541Y)n8YXC%&^X9Z zFNa&B1CBP;XwB7RS*c&q|Jk^!GMLh*4&9nL^Pxp!d#F6wzUN*!vlT*3AsciW*1UB0 zn%KmEM?iz}0Ng-0Fg<`cKq@H>kR6aKnH<0#Y%H_nj|Ga!W3fImU-HzK8TO?d%S##0 zbkEtLmA>z9zf6AH5-ATn`K?#}I($T08R7n~d}A&1Khn~1dpikw5~0BEm$7S3*Tkdg z$+CFEyZdWr0o=NzFvltVgl+6K?<;xS+~5nEr}v z;aoAx=M~X!@_XFVxig0 zbRbv#4#O#(q(w0zwJP8oHk5M+&kj`a-R9Vc>-vOR$NldpKcmDqNBa4}HU6*jYQB$e z=Br#i!-5~>0mMZ|mq5Q5;AGzg0Q}xOkOX=_&kbdQL>rK+khBH37uYyhf*h7$+B9fN Tw*1H*XC=P%sLecP5F1{9g{!1D``Vk{1FcVbv~PUa;8gV-`p z7srr_Id5+r%zf-2!s>WCfvKla(WsAeqM-rH?``F}HgcvBq6Z#0PAJLvbN;u~eR-e> z3=E3#tJ%SfJzh6hK#ZamUl66>KFS>pjnTv~niockg3*$2sFj52(Y6c>^D^wuW#-?% zKI7ZBGj}(i{Sy60T5tIF z?O%)Kdu@x&KUDt-yZ+%nH$(mDqiP_JOi<2Y0@0R-1||3QD@KM7F24)c&HE6)YWM4R z*=yzj9h-lANH~6Q2I;7)1~S=iUMt7I;9nA-{1w=2ZZHv_4a$5DeH%DI^b?Lj$;|<_ z^$!TYJ-)MwN%6aBm_N|r+aC|Pa|p%5PuHO&xq zqA6I|n0F@vO;X6i~oxpGy?SX<)!{}(t l=-AX~UKkyj9O^|u9mB>GMxQ!c-7bJiHBVPRmvv4FO#s<@3bgmWNFGXCI+rAxsa-@= zQ_KsyP&6w_C~4-!Kx!Df*r+TpJZt>LECoA!-?pHO$dopUp546v4&TMz?|q-=d7uB| zuRWNV5fT&|L_{Il{ps060YgNp7b+$D{YW+;<;G7TovlR>Q@KyXw8bKPdGJxUcS7}sGI_tcjE7qA>MPovkjl;T3Vz;n>oJM zmRBwiSzHg$W8299j?s}ip zIJt`Hn2|^DLtrH_iw|Cqzaa46b0FtWI6@ClwIBwqKVk{iY^#ZQrdK3L4TI5U?d@?Z zn}?SAPh-#dsnz+b$A>jpMn|(Xg$+?*5}?P|&|@!~aZE&TkwenHOcctk~-vEy? Bu@3+M literal 0 HcmV?d00001 diff --git a/assets/icons/apple-splash-1536-2048.png b/assets/icons/apple-splash-1536-2048.png new file mode 100644 index 0000000000000000000000000000000000000000..c313eec3775251e5d3334bcdf6937cf53be6848e GIT binary patch literal 17136 zcmeI4Ur1AN6vvOdt4&b~qsSp`l48)vB_vT?bGC9CS&RyTC?TOJ%ZI&`Y2FqDickna z^yi@->>->FVI_!NeF{o#3}PnepkhoS3tC&Gv-`W})Esux_>b)Kx(Ms*oN>*W_p;VP-a{Ru!S_)1S$B7(N?{OcxaQEYsyFhi2 zs%~BKdZfZzU1g=?_X6pi-)_fpw675PW~TW|R06k~~ z5Em>1Z~zBE0Otkk035(U5I`NpIsgZ75Cl**vkt%k95ezbn^^|n01kox%4XI9IDms7 zu*_w1D)LkcH{9RU{lMI!+MJ;s&XCPn5*~AP_P(4B9v*d9S6mriA@)&d_`}OqaqzsD z0%pE}1zE`9^qmc)_AG9HSl<4AXds?zKf3s1;Cy0s)$r8Zd~9xha&Fc>(~?M9l+Jf1 z-aq`AIS%Zu*hpV_d-JXdc9*1fFD!l-Us%fj+_;6e=0FVUATq+?Nj!&MMXvkX#vXl7 z4^R0|gx6@BIX)_qr1mlAvRz%uw&n&~avSl51q=inz(Ei|T(Az7k;BO5V%x9(0w5jf zxU(WHzpj!=DVprqe?aUhY8hfBptQ~)hqrwea-9^#m%2|*Zj-exC%X0+ZzwB7^S=i0 zxv)e>2JNx0W~Hn@eYx83&A_t^iUmEf4j-*QYY-g3K@j*oLJ@}vk=iQSMN`kkPiNaq zB;hd8Rg%#LxkFASWSKki)N^4}3( literal 0 HcmV?d00001 diff --git a/assets/icons/apple-splash-1620-2160.png b/assets/icons/apple-splash-1620-2160.png new file mode 100644 index 0000000000000000000000000000000000000000..7e08f6d724ade8c556a3c48c08137261c8fde802 GIT binary patch literal 18407 zcmeI4ZAep57{{O0Hm`3usX(Kxg_WR!i|mE8(z!B2=Mp7D&`IQn3^dk<878+8rW8cP z3dHOM3O|UMLL%l`N*I(14m6R#3X!3ysECke=ic3Y3_r!L_P<~5;cmMep7Xr?&i_2D z&SK6857`+)MB$ldOu0nrJR+`wQ?n<9VV)1{rm*E^7^!7omzPLSnWnTnd&BhTfk@s! zZg=jQvsS&=qUyeDSc(7GIMq3l%znbIqxHo>zR}9#XIsRPCTxdz=dDe?Pn78@aiEWi z^F4TPQHTSsMwk&%s)5Z$xEy!|Y{488enE&4LcSnE?j+O^BGgpC0plaU0pLL3WWWL7 zfVlzS0C2$E0B`^}U~T|7030wk02~nC@6t9L4l|wG-fs+VQahWD@NwF5c>>oGH8BQ`mfMfBc1s1=ZV9XP5m&SDEvmqNsgnRpm}dL}KG)p5)(n z71aEr^OZNayj@(=0&f=avn#{tg%j^q`)<#sxRbDqv>}%9;>iJTaMic0@k4_*vU3=l zjo(`^f*epSH$=6JIqNF$_W}qT3t%!~%fM7e@ct&|{VSfWRM2ND_G}YEe*C=M-;x8o z4-nq3%d4%~5oFc=x@yj$<@=Mam$7W&=K3nJaH%rYaRkI)`&!+=V(fQ!{>*o2%@RI^ zLS_og7JA(n+w90%)m9#~kBkb9DKf#Tj;ZghEnSXG>fs+H&KEhlBSKO2i8gW7m#K_B zH7zs>yOYPNKR42oBQ3TiB~|zM+lgg5>Hj{L5S2uaR1WHVP2O{tbU0?go(b8LWip(R zuuhGDoRJ_YL%w5LCXfLj50Gb-2&IVG0HuiJDv?2LhIg`-R+$R8@J<pS}RhjuvqGv)YF{)vY=!QPpt%%&Ej)$s?Ig+Oiq literal 0 HcmV?d00001 diff --git a/assets/icons/apple-splash-1640-2360.png b/assets/icons/apple-splash-1640-2360.png new file mode 100644 index 0000000000000000000000000000000000000000..b400cd308b32ad1d04bb18a3348f3e3a9d1b4270 GIT binary patch literal 20641 zcmeI4-%C?r7{{OE?9f>)t#y%-Z5NR@LM|l&9Zs9L#n6<{FetGfWa*9laH!;(AXdwp zqE?!VAR!7R5<`(TQtCoe3$)ZEA!ukCGfP=U^`5hx`UfVl@jW-^<-p#thv)sg-{*J+?&6%l?2C*ra1TjILVC@i4K)@rm3<3&(0s;yMC;$owC;$prp@;$j zssJbe3V;F@0iYnPP*6KJng5{AusQp+YfEE;$}a%Y-oc#Im^*t zm&Q9Q{OlX|RJE=Y>)ELZTV^jrd}srWN&wq`#BTpE1$5!Gr-N+$l3<@(Te*ymIDH>ndaMK#mW99vahD(deMB|xK zf+rx7)xmSKcp!#_5DzH~$d5n|2i*8HhoogrqTTj)e*_!y*hz3<|{uONOSFwZuh554}_t zTZBY`;U5gqqVz`@Lr9Gbrlq(UB<94Ce-MJ~-n;EJ@?kLBcQ3pAcK6%%{e8|k_ndq7 zyLr@*7ZtH1f{3CD^7TbTVa-H}E=3qSvVBFD$)04!qC6dSjKt3osi{Dpd%Vu#n#hfk z)Fesi>-qZ7Z7sLVPhKATc-2A-fuVVS#t~}JAcxQJV}6J z%FI=Wf!YugA_g~9tPso}n8H-D&pixT(FHaw)z|Ii+t?t_f3EMj4R0>>UfGx{i6x z)0D}|snt1UZ<{rmF6={}o7e!V z9wd@vZ2y{*EpvRuGpIV(7CH3BJ1+V?(uaStNQx&)7h^ZM2Uf^ptYd%0vP;h z=>Mp0`-^Zklcu{DY%Zny z@A+uerR6tfD7!PTlHLEw)3Mv4@-}W6b)Exd25&9>gVNg$l;yp>LRyNqxbwZ))8i#s zyd5Pt2|*JRIDzdDTmf7G!4(i(0bBvW6$GOzi0u5FQ#&*{Jk67zg2M)Vhpw#Y50Z1A A%m4rY literal 0 HcmV?d00001 diff --git a/assets/icons/apple-splash-1668-2388.png b/assets/icons/apple-splash-1668-2388.png new file mode 100644 index 0000000000000000000000000000000000000000..41f4ca6780f387ab26cb46b3839cfb4423c5b609 GIT binary patch literal 21173 zcmeI4-%C?r7{?!fU{hNhG|HrMiZBRE7hM=@rgQ#++WfJSO2nuTtP~Mzn&uL-^2Xh@ zXxdHcmFp(cMCD}Cph5$&@JBHs6v=8ZiO9sx`|j*Nn9=aNo4ssjhw<=vzt8i2pNDg= z(3q!;ijN{9WkJ57m?)x+DAKHmkUq&M72>3~khsCOI96t}l%k46 zQL~Y62#c|I+31}G-q3P=+y41fVJAUARbkQ-ST00Uqk*V5mp}eojvO4GywEt_ zU$s(TR*K$aBBy&JFFWoqZ1i|WKGXf@P*1Kg!0ARSgDK6UZ2BpiPW_Z za9qqeJ$C;rKwu($u6G-G%04ulFb&NNf18f2KBY|{cg9V%xb&xnDmr$fDrJY-V6VOo zPKS}jSwG*W_OyF%{U}?~=-5a|`3Uwc#0nxVF@Ve^1pyfyWz1Hu-G(kT5>3^2xmLMD zX9-V5NgKq%Q2k&(iFN(+8M+X6rPFKgW-^yrzPYZen6P%Oa6F9+MK=9*Lw0g*UUF`B z^3z?RJt+-cMIO_QhATl|QU>_!8CW}G;joUZYwxc<>L&5zz{6&FH;=iqabQKQ18XAi z)9jW1GmraH)7<&wh_6w!*ycOriVnGvZjY4*ChGJ)r?J8)|FyS~vh8$Ke&#}& zT5c@hCRW4*oDlX7K?)!R1SxpgtWBNk2kY=wCS)D-B6)j7eY&i@(o~JHjtdrbUQ}N(>ZSQ+=pb0=Q z;Y0pc2#euCEsFz$$sx$V2xcj`FtC6b4FZe;5ILt&MWaE$Fd77-LBKE?1fxL!tQ1De zg3%xtO$8_!;bs^=14F~|Z;$5`ovZEDe14{CUSwKrUX9-Vz^pyj85n-#-WeGUs|mTF z)@8-3eaEI0gF|D@b4I(_9&`yG?85fZ5jn z?)3;;P!IV*@=nI#Q%d0rircS%{{3*JZq91;5AJuM-j^$89vPzo+paP*Fub_YU;LG& zVs+&Gm%pWg&jG{ZL4Lsq34qZ-pJCa{fi%w;9(=t8O4|P(?>qL26PV3Aq#J;R8xRc7 z))>5;`&1hLxcV!!0DoXh_cr;T%=3IHpm1jU8GZk;b}xv@z>weqZ2}+YfOQfCVYQ4h z6STl}V^IJrX6WH?fG{Kk8z2k=CFtnws6h&l5E%_4=qUbZIvUL)pb!`>Mj-QBqa~yQ lBtwjrkfS9eC?!zbh+x^(ZQQ5)GQSjLny0Iu%Q~loCIEAYGLZlP literal 0 HcmV?d00001 diff --git a/assets/icons/apple-splash-2048-1536.png b/assets/icons/apple-splash-2048-1536.png new file mode 100644 index 0000000000000000000000000000000000000000..a53ba1c6cf49be2e67de301f6eec55585a6a4d0b GIT binary patch literal 16264 zcmeHOQAkr^6h3#3>$Jp6P(~S!dho$8%*tk)-r2+?QL&&zjDZA^M1p8*8D5q|f~36+ z3tK(S9>R>oq9j)@5`hvC5gRmok)g4InZj&!?#;XRg2;{Uf4KK>$1Xqr{r+>l^PThe zH`dqWWbeo(qMX`ejwT`#n37oyt{nphPZd+T6^)#^_c-rLH2!D zv+7<`#kY7P4295Q`Cufgvia#%_v;2xdokPQRzJObXOo6!zCd9{8p$w#A4q3EVAgj#6ca$5u>i#+r4^IFey+eP zS6UZJY#QfRDm(t3`?vI44-*v}QhNay8bXp9qSUgn^_0{8OzyyV)D;{pqim`-i~_n-IR`OC+Y&xqaYNv5o*#3R5O!SNE+%eI&E+R=5V%n!7o2+3l*XlO06 TY%432cB#MAR@Xbms+^u*kXIZt literal 0 HcmV?d00001 diff --git a/assets/icons/apple-splash-2048-2732.png b/assets/icons/apple-splash-2048-2732.png new file mode 100644 index 0000000000000000000000000000000000000000..75dcd5f3ae0de1f09db1e13167367bab02147c34 GIT binary patch literal 28653 zcmeHQTS!z<6y4*DIt*iuM)tD2NMIjf(+he@qfI_~*n=VoD$9>P>|qFDBjv5JD3SUI zD#_>tTBPPrnjh)tM+(sc0+UFbFdRawDI~LLn$Ef2Gx;sbT$*)0?%5yrUJm=Lz4qGs z9%e3X%gu^0%`p*COis3a2a%DPraEI3n>GzhuVj<1ct=(SHM~sxL?ls;J$+|M_0YTY zIN3_B#wCF(7orwe<4TK$<0EIh9&CBLhCRZEy#L1j=rNPXV-}VrUsy8fg=v^2EXgG- z((yGY!)O(jP1XrB03lNCO4~NCSd2 zfHYu{0BHbez`NMW2UQu8O*L2oju58NA}pIMEWDBkzGSQf5FvU9v;n?k znE{D{6)eb*P#cg2ykOCiG}!5FYGUeHISare6c`0YwT4mPQpuett2D-)z$I|0c;NrT zWy#I?L_gaG{j1VCwzqvf|@mp}SMeOuX}ugw4Z%-%s?5+#fV)eNMAR;5Ep zPs_b{Sch@CYopCP?*q7xU*jTx*=UBZVx_tJz7m;B@Wj!_QAZuUgmqJI!egDeZ zl*&E+Q9ac?^Ci_iA9>Wbj=KAU{arM$(7Z#Xduab{Kv1{%L-1}v{_D3HS<35> zc2uv@gxv~1G7mt>3LJr{!PF`iKq(?9G^b=OmdzPQ3$hDu^A+Z7$h9|Q88ZlKg>nz zrIU=npn5X|VW5&+P*#x3La>tZ)c%wxINsS8{CKA{qCOM z^RP>Y%1h&7(qf1xu57>2LKNLZq^XG32uIHOY@37+Rg0yxggn0V1)@wUGw!WuyY~52 zu8PYf&cGEVK4Z^s?SGgUl{8_0`b#`7xVew4mzzKOI@d|>6T^j9u=r*sYZ zzW(b?PPgy4ez0SdJz*Vk+J;B01v-SQ1&WxSd*7+y|4Fpyb@JPpG@2lm9w_QO7IEsr%<1(@Z#c9%m<F*5F^O>V9+^g zECa)6AOO?CXdsLR!f2T=S}-z<)(*gIFd7J>fdDBDM^nORN*GNEqkRX4(GC zjH6=`gSX#&8Z>%z;Pag0c2$R>Uw@ObeYiOCJWoS*rF_BC$p6wi*%=rL{P&HHB{2-z z0kuh~Ux2ysLFKi#rd5aDS{Sb@lKcIF6DaiI_&M3jZal1kBB3h625inIe9k6p&K_M? zGQWAvd~@ECBhK{dRR-=)qxo}mTnm_7Mgw6q5WpcYni3$vFgn&v@075~mmg^5wa<61 ze_;W~LES|D(WxnhK|4Qpa~ZIC$ng4Re{mJlhvw(|mZ^hcZG(dR=+q*^pq*cZWU{!; z^3T7pJmCHN^!7(sc8hz$JUX*6fP?xj)lK&q7(_ckYXL@Q>_?X^0L#+RK%ikDKuSUe zhJA03TiQ0(KiRqdC9vOoz^P_*z0BZEcqfk+$Irj43~FeAKt;UW0x$ze4B9GpbOF|A zNd``&L#sHCe|u{q$k_)J>R&s)(d}z+g%^wog77AO1PgrHPYf}XII46s1V%$(Gz3ON uU^E0qLtr!nMnhmU1V%$(Gz5lH2&kTaWp?WBA`8%@6oaR$pUXO@geCwPQ<%H} literal 0 HcmV?d00001 diff --git a/assets/icons/apple-splash-2224-1668.png b/assets/icons/apple-splash-2224-1668.png new file mode 100644 index 0000000000000000000000000000000000000000..24d1b32565d5304d4d697dec113b95a8840c87cb GIT binary patch literal 18647 zcmeI4T}V@57{{M&>NZn~l~J;CK_-$H3ojgIm@;vSXo-lH;JgSz2?CMa2sUM9yT}SE zEYb@FTUdVNS5e|Y0&gS}{GgN2AVN(?N|<$F^q%u>vzsAAQpx|^>|vZU&iU>4JntvR zeJVdYIx;qrh@x{W=0YM(H&KL36T!Y&D5$y5J`~l3*_qV&TE9SKpd52XQSE~z@t8s| zkYE(jbrVk4p|(+7c+4By_z&qi`7jqB2!z7${*pj!K`5gD2W|v7fCE7SNB{}A1KQ6sb`%kk8iY-+7GwI)ByOqp-E zUS=7;=gm0WcTsy&$7Ub-fe;+%cO{5jW$>ELy}Mx_DO#(U-rau2ce%JvOi`x|ip@jf z`hfVIhD&{oD)KsPb>V*HoVT3_84GaWLWJNj=}{92NwQbs*R~epROOtC#y(t9rp-B2 zL>A<=tVfo6Jy7#j)r3KQZ&Y4=&DH#Ncw5(Ey z;siRNv*l_iCTwkiy#VMgpwB3^PbfSnJbzY#U;5b`t@@>)lp~^(xdWDuKy}@HSVvV|bUawv;>RnCs zako<49lOS=%AZK>yCL4H;HHHN`=^*{^Gl;_xaMtlym(vHXqSss`78Ba|CLmzL@2QU z2W|v7fCG|&I{*&<5{I)V6$6O$otaXj=c- z&eY+@_(v6%LnIX2zh5o?;do5$Jve{^a-KT?4&ZlH$7a4OLnAKdQPtqYE)O0-D=B$ry>;%EjvZY5r_=^x`*W7vR ztpPUay#R2S2#L&!7a#xvZ^K{$On?dK=FwL5bz}O&Qx7IR%)2I8mXnol?##5-{{%j{ B)3E>m literal 0 HcmV?d00001 diff --git a/assets/icons/apple-splash-2266-1488.png b/assets/icons/apple-splash-2266-1488.png new file mode 100644 index 0000000000000000000000000000000000000000..fa7ff4ee0aa9e55aa9a7317dc916cb5b4dcdc0ff GIT binary patch literal 16890 zcmeAS@N?(olHy`uVBq!ia0y~y;JC%Wz3 z#WAE}&YN3~ybT5n2M!qipWMNwV!-ZQ-}1!Ik@ZW}yRUpeJz(%4qfQpaW~fit!U*Lw z9LQjXi8o#Z*#rhmi+N#87B^`alcUEB#uSjqg)tQjfX;*fhf#w^g8~u)qp4yvgFy4b zXjw5@Y(kU5Xbm!2nL?AoXuD#xi3Lpxqpi)+hBq`RjP^lByJL`~FxoR6?W98sh0$S! z(GeDCQW%ND3JIHw+0FZy0!3V_9hr_ebR2Q)IO4#ycV1*{q{n{4=Pn;YHl2=(5f$J- zj5r7&5{v?(7;!)v>$`wxax6qNM4b@blNLm$6}!P3eE5Np@@{+H?=LO=vCj={A1eFX zeO_MmDxLM-qm|zuO@2RZ`8>-#2PeN5V_!CxhU~2)G$ZW|Ey)+H&dz8;T{)Gh`8$YZ@`xhfSV?z5EYj4}xGX8M7Ug_fx z3Xg`s(R48a)5Wxxzy(eprh^m1gYy-i=2pN;ihT{@^c^M{dWGw#i$_w9c`$vhwHBiQ zSA#-F0;93SMHx4fX2C6o>NNZd)DE&nKvocP5F8C0O*A7Z(Lnq<%u_{zoGsX&Kh~$- zb@OkyKKHm?6%(*p5$Gp0G(MUchFxYjSR(h^v@StVEFz@4!(6tD6 z-ri~iMR0>c{cBM+jXr2(Gb9MWTOXrLNT7^{!)Q1Rk$hom@$ee(jDR_ya{)#(GC0`| cw%p6HVyVS8-nm;rhdD5Ky85}Sb4q9e02N#AfB*mh literal 0 HcmV?d00001 diff --git a/assets/icons/apple-splash-2360-1640.png b/assets/icons/apple-splash-2360-1640.png new file mode 100644 index 0000000000000000000000000000000000000000..74192f744471ed19a0b948dc4128faac759c707c GIT binary patch literal 19371 zcmeHPT}V@582+|&Ytvy^5JkmqN-qpj!&YidS#F|jWfGZThKU)0f{A9$PTGatGzot) zGzGzKLP|>wMUEh7W#=-`C?--Vn>uiW1ZL-K-`94l6n5;{&E6e2=j^=i^Zq=~_i^r@ zwwiU?-C9D3F5P0vB1B^#M0ItmN<1>uXgDW+Dax|Usia%jGe?M?q?=N*D_h-Du?k*K z_~)^!7SooU_kmL1u~vAm@u@eKbbWpSRFggc>%Vn6inoFUA9@i>Em**Um4a|PT2v`{P{iBMZ86i{-}EGQJvLor%VC}85kAWES? zFhYY_P%MCOfrnBkfSyCOpiqFY0AYbbVST~^=V(hjc6pnsBl^dTQgGG@({+MV+t!gk z@;Jj#RHH6Ft8JEUkfRLbTt?7jn(9a`-$R93FgGk2V7Ul|L zlWfuQA+Ab%3eRx)N3*SRqI_RxRMNGs-j+Al+vAgS5Kv005Hr{C_qXMTSpf$+)ItJ6o~SJa*rHQ{azp>{I| zqou9489yuZicWOeU44!x{7yktT_%A}@+;qdGiWgoy^LW^#=T6wUHCuy=c5X@IHUXb z0!X-9YXd>HB3u0)z!U~nOLIXFvLD#cv=K7J!A`Xpip4>p!0X?i#pPm#-`J3B3e78c zh9{mnS5lhIm-0U+{uwobi%6^}t<@9LnL`H-8+8qqy$u#!Lr2BTqu+`I?%rAn)VWi?qIRbyeF zdIM|kScj%ikTIFU3OXxpU`$|43=3dPU`!MXJ$ds}FC?4S-*FYYqaTF)o`CW*0y9=0 z4*MJipHSS$2@rYFM0`m=*eU6~00^KA1Bjp@XoSeA5y zG)Q_d%53%!UQyC8d=VK82_b6O91dJDFtC4j-re=0CPFQ~`|$6-m;0t zIPIO9#QecTt|)pYdy_G}efCrpyTgBIzq*7iS^Bj`iEuVluuj-+JiJ-hrf(<~wxq+w zKm*($L<*#UAdCblfD{m<08&7Z0)iAk3J6jFDPZj~8U$1Ykb=J}1r3i{diGIFc zFFN2cq64lEvdc3>yF3CH1C1bV+^aM*uDO$JH**br6V7)AwpKX8X>xcr!rQi>AmUD! zA=@DLu0?SXENt#*M|l6+v9o5rl5t-K$wEDCp(w=@q$Ok`VZ4~tEB;vkf5Sp3*HNyA ze7O$YgYGS*duyn57stbiEawAd6LIl-(ekaJr=4JSo90YBb!f8HksWGf=T2p(T4^7R zEzq1B-`6?S{=-wU_?)0eEJ+7BiAg-?s!FZ5%we4Eq(hg+kL2|o+zvl72qtuh!K7Ip zjZqJaH}5s)8-szS@)oZ5yqIfg<3q4!xB;d&Tz!;PD64);M9XUmEb z{}{S5m;I$Lw{WT&XWF2q$)9Ih#0e9vm~P551H&d hfSxZv1wgTKC`y|4rzBWDs-F68$vKj*@6If*{RQ%iImG|~ literal 0 HcmV?d00001 diff --git a/assets/icons/apple-splash-2436-1125.png b/assets/icons/apple-splash-2436-1125.png new file mode 100644 index 0000000000000000000000000000000000000000..d4b6f87215d890a45f561fd0949edcf8701bdd8e GIT binary patch literal 13640 zcmeAS@N?(olHy`uVBq!ia0y~y;A~-FU`gd*1Bx)m1&RSF#^NA%Cx&(BWL`2bC@^@s zIEGZrd2{Dr?jZ*T*MlmH7_UDNif#8U;nh>zsaU+FWy|d2KCJQF-4-@)zgNE59}hGE z0{&FnFJ^~v7(U1~8NfIV9F7t&wnK{o4~(tgBmi;;7zikGFvHj#0xgU%whPB07?VMX zB@xaR95tSSVKi`n>0vbG00Ut(TY*Z3(LwP_pX1@FCQ=Yl3xN&#dE^nZ!8a4gV;R1%iHkKj>9t%2fwernkbsOE+W>tr} zXP#qw5d7oq({(fd+5h;*G#Ycj#0vz2HRd+uEmrqAeY4;=C z!B&Qk*o3*!7u;|Rf4y%Rq|Q2U{S&n-Er!wgEKs7SWHt^KO}`8M{2N+I<1Y(?Ol)AZ z8*RxCy7u6ydWsFOBbiDF}`*5V7Zc`{)9s(II|NQWzcL2L{4m8{((wy1oOOW34BEnynH~@@xCo zTQqSZI)MpJh?Ryj1Q4qW)mjkc#i;VpkZBlA1fz*yG!Zb2CW6sKFq#M$MiaqkA{b2s d48uMVDBUnHebAYA(;U=u^mO%eS?83{1OV`$3F80& literal 0 HcmV?d00001 diff --git a/assets/icons/apple-splash-2532-1170.png b/assets/icons/apple-splash-2532-1170.png new file mode 100644 index 0000000000000000000000000000000000000000..b8ca512a0fabc881e1ab01a2fd4a59c854c078f6 GIT binary patch literal 14600 zcmeAS@N?(olHy`uVBq!ia0y~y;C#Zsz%q%04JdL;ujV+AVk{1FcVbv~PUa;8g93x6 zi(^Q|oHut4avpLJa0nEY-oWO)rEkg%si3BLt~Ngt*(=vKB~IqFtoc^+=Jsb6pneGW z^JG&MjLpFCgT2WH&g0mgb~JZaG1ajV>2*1V$pD* zd#?40UI~sx8Y?{15_sA&WZE)#+9u3tN|=9X^K31ac;&NiS28k;j@i+<&ds?D%G?R5 zzYG2RBj%Ye`f%s^7x1WS!}Ohm;uNTnv_vqffq{W=Rv8VY(NF?Tn_w$NN0Y{A(ilw| z4CFUM@MWOJT<{Fznm0SwzvKie1h#o+7buSO*8dP45<6gK3yQ(8ZSv2*u>268_j}en z5TD_Lk@)Bk*8mT3eZRbOD+7bXHqcrCaHJ477kB#$Nb!%YpcqX!k@f#SET0~bE*j0I zqy27hQUVc!z27}L&oV?Sm0=fgkRp|V;oq^kIhTch2%N9=^#^942G!BN{}Aea{iu5P zy1ELnR&I~=plstjSRQLF1}dK=p5)th&OIs!VuQc|2c$`cMx;?EW~6GJ%?UB8$kT$T z?Ibu5Ly`sph_+pV0%CY_)B;FA1If`Kf(ONDDuM^aXhwqt#b{9h3yIO9Vzk16q=kmj zIvJKJMq3rIkYE^Xc)^2Wv~3CtiqWD177`4jMFl)4MvDq~P>dE8u%H;CMTG*3l$llK SiEv|(KRjLiT-G@yGywo*1N8|2 literal 0 HcmV?d00001 diff --git a/assets/icons/apple-splash-2556-1179.png b/assets/icons/apple-splash-2556-1179.png new file mode 100644 index 0000000000000000000000000000000000000000..44a462f07bc14bc2fc2e6ca4c24abf548a97cedb GIT binary patch literal 14863 zcmeAS@N?(olHy`uVBq!ia0y~y;QYhDz%rYI4JdLl;*BtnVk{1FcVbv~PUa;8g93x6 zi(^Q|oHut4<{mZ>U~p6|U|x4nbr;{%6;dHipUnPv$T3x9p9v{g;L_C3y8m4A|C>M) zAfVymzHojRhk@ab?+11`kFm)f&gKyK!wBOzG(13PVPdI=i8BZ&{9uN08W;}B!`KWg z9RJ{K1&2{9Mgxk0VKhYn^Ym!GU>GexfTj6pNjq9!Fffc(tiZ<1X!BsS9R+MGjy4ZQ zn+Kpi!)Wthw0Qtb2BXb`(dGfDI2dgnFrYRM8g9P=4a__Uz9WDBs`4Jo{@Sk``fBSg zx?J8T9h3RU(xC9XZ;bkmQ%7t;13RK|qa!p!xMi{ZDrkJ|z;X*vEa$)LfBs4^&L>8h z;oot|bD_)b`foe?pBGq8w2KoMZfl4yd$+(WNuguW0;QP^h7yYkB^DX-w6r+#1#a1U zKDzZmHeYd77SO6899F}-OMSr178pGY^OEe(z2wY4Fa2@;wOU_)kPt(KCZXsDsTz&h z(e^bc9gMcGN88uHWH8#k9&KNPii6?azP_;x)C@ilyyo|;c_9BXFxbrC9-YA)S`!dC zmqE?o2b$j=&zZ*{pL+ND7Zy-VHcT&iIC3YZzfaqx!oVQ87qk`t6dFJcX4-UqR_F+d`@1w1EP!1n$y^prufyscv);n}CfuZ61cKPRDSmctRW$lTP zT%Urn7Z42LI<#i(?_cxe;LG+H{+w&2WI^BjvbPPOc9z41|JUDgl(aJ+LM-s(;Xt&Z z4HOVd1rIbJE%qDLFd9muNdvLIb~HbX=7-VzFq$90?FGj_OeF1mhe9OXn%TGcbWve519GbyqvcMR0DXr`njxgN@xNAfN3 z#WAE}&YL@qyiA4y4uJ|14$MLqHwuLx_F`Zzc(7^i{5{JPE~QoddinLn_V27f?GVt= zbNdw|jKje2qn|+p&Qow>0672x1e6&Nx;g|Km|zkNM>rf1CM2;efJ-nKG6ldn4HAqR zaE?RIs5PU3Hk#5#^9{U67%gl@i_X#dX0-MkZE`Gtmx-edsL@vEXd8O8<1yNe8tr?I z_M}ILAK(px(ZQ6VKLS-8Zwrb~gX52XM%f+;KfZ6R+{5K7)6MQav2NY$Q)j>I-HRv2 z&BnfW1A(d@#MD8Gzz2uV$zHMIa19iho4~;9;leI-v7uG!hws0R-(|a|H3?4=W3v_q znLG3YXtdtPS?`}Q1E-yc8_d`K%6(D}N&@eT7)OWL zM#d1^?JuARPmujx=;wdp%~dPq>jksL;o0K+hwRfZ;k{b`^i;Bev8e_41c_+dGk3Px8L zVXqfP3xeTR5I}1-`LcHl*c=oZ8WTJW8rW18F?VKIa3(a~-bdSPle`vHnG`i_#bf*%$VKBPyYIL*O=q&H(Ebr(n?_itd zwRwAskrP->H!S$S{hnt?t@Ikzf*1-I4KY|kVqh3e gFz|Lz16A`2r@E`zDW{3=7lO?9boFyt=akR{0EzNJ00000 literal 0 HcmV?d00001 diff --git a/assets/icons/apple-splash-2732-2048.png b/assets/icons/apple-splash-2732-2048.png new file mode 100644 index 0000000000000000000000000000000000000000..6d325da141e93fba0e7959687c6e32d2b0bfee56 GIT binary patch literal 26953 zcmeHQT}V?=96!@Cr(2mc8Tqvck?NrY3u{f&W_}>9Mv3*1SE2`zSz=nu$oY|whzS>9^ReMArkjBUHw!d%i}+f4=Cw7yqn@l*@ne^LLBEBPxwY!3lfvL0Yw6U00Sln@BkQq2Mhu502l}~fG0u=0uhjn z@Wf?%qWtjF5el2I7QkaCtJO~`^ES~h;Ha|Ml&bzto8^9%yk}v)cfvIvT&=5d>!#cj z1My>}P8VIs@atA|fyn!H3CR{?01UtbCWrt$h#d~5FL?gGqG)(~^MSM}`{pCMv>Ia2 zU3ObfyK26q5i*@thQIYn(uPA3nbz=-L4*22vpSg*$#%bJ>(V;fES6+X zq}*Hg$g{(4|9;S7XHoS`*{w)N|3^L_tQ41j1Mi7)-x3#fCHAm(2FYy|R1^W&8Al-!!vp z)p<5P*Kge@m*7_`nIrv{xD|^1R@NCC{4PRQ(C^pd+vT4bI1E4o)1Vue&7#>70_#NH zAU#oXpn&pSW(8FzYG_P6Fpa|86EkVwd7HJ`emGyGNTUB9Fvb2Oz&CF|V`asZ;>%*o7Gn=-h%-3 z#WAE}&YN3?f(-@?2Mz@NpW4Bua$#rr&BPz!0*pK7Rqtg6>VX1_GwYFf5Bhty!DJX1 z1V%ZdVE{}Hqv>EY3_zvAXgU}TgVA&V3W3pdFd7EnWH4GLj^+h$LKv+ZN6W;~GI6v_ zgoMCoUKq^_qj_P#^TL6&=X`l8tcx@_;tCj~4Fs(X1f>fS-)UT(F8g-R+J^#LW#9#9^&(-^r!|Ln8 z?d@l5`(?}nRQ9L-P6jt3ZX8EB3?nBD5@*YSqW;6TJJ-Lo^nZIiXWoa4ub#6Xxb>&s z;AFWNP-=se`7I`R@^BCs<&4xYxUq~Kln(a1J#K0HaJ8lVGTZN_wv6DUQP(P+3t@q{ z3LK-H(J&ZI2cvlbTsVxD2cu;oI3Wy^GI4tFy<*r}07wEKjbB3Xn{yew65`&x-?QdH z!z^zLymQFVpoGj(809n!>oC~h%MVHf6}S6~tC&8pBND~_L%qmrWLic!0wX63w!H*( zAr9Q%F8}-s%LDmszpS6_T>p|2TwK&}j`l(sKpoEm{MO|GObQ|ljv@z{(hL?^_GGll zJDxvuXa9q0PO}3Wz@Y^qM$Q<b8R6Z^P?}zopr0H3$V4gdfE literal 0 HcmV?d00001 diff --git a/assets/icons/apple-splash-2796-1290.png b/assets/icons/apple-splash-2796-1290.png new file mode 100644 index 0000000000000000000000000000000000000000..e906f5e324f8ef8943d0b0a47db4fab149682d06 GIT binary patch literal 17412 zcmeAS@N?(olHy`uVBq!ia0y~y;CjQrz{3 z#WAE}&YN3|yayB*4j3HxueyklbAMOslT1;c1J7=rw+8Bff`%izWMOO|U7vP?70zv# zkSGr4FgUfvA~+n9WsGp1LdvKnaA1rE1T;;I2E=GUFpQQF&_pmA5TgMxT75#(z-T~> z1_Z-s%MzLhMgw9rAQ(nl%g{tH8W5uaG1_f_rh(Cb7~BEzAo)38o-)fK4URaE1__Rd z790~LJPwA>4|5Cq-5e@<@ba1j%PpWGIxyhiL>@3xK^ZVhKptglLLOxs)kK@nyI^Ds zGWfx|(%Z|`Yf9!G|I*SwudXit!Q?a~Kp4>LEBSEQ4NC{F^(0oDBgCERL+)GY)n0r4xNESKgL!*=rj&a08{{?BStR zjf|F4G$^Ms_MLkyXNzcQF#J0;nk*nGZKyS~M)L;^^2d;Fc#o!t(G&qs1EWn`SWt{M zaiJkG8W5uaG2}**V7YiWjgV2r05Ym#n1Qnz)$^#zAt8_*!0>$ZQ(1Ai>G}VDZVKgy-Lt)q?1`!@v zK?VlqWuS8bz&-;J!^U@`K4KWH1VM>lcvR~mzvi23MaXhBfV|}C>gTe~DWM4f+S+H^ literal 0 HcmV?d00001 diff --git a/assets/icons/apple-splash-640-1136.png b/assets/icons/apple-splash-640-1136.png new file mode 100644 index 0000000000000000000000000000000000000000..1e8208d9a18f8aa37048edc74032e9fb8a988450 GIT binary patch literal 5494 zcmeAS@N?(olHy`uVBq!ia0y~yU}|7sU@72W1Bz7jKLwHujKx9jP7LeL$-HD>5H;|0 zaSW-L^Y%t#=A8f$*Mk--7_Tl63T^ia;ng~rd4Q#9|KB~9#;i5(4!tX?$Uk4Z_dgSZ z!sG8>fadI*&cMRZA=tpcV8|rEpy0;9#BhYefuTWyk%K`%nSqfZiA90Ip=VUlXb_C1 zg3*jHS{95Jhod#ZFs>9g`|>ZywLiD?z3um{U-n-89Txq!@~6!G^nb1Q^(V*Bs6B9V z8T*BAcdlRh{_SzhuY0d*KiGf#{X^z|xK9xyZ5k(Ov*jFa*Uh;s{O{HB_rG7x`#ozO z!vS_$d2h6Jg{6TxBe#kn_k69dKSP6zIE@;d+g>tmd3)T_wo(7fo$Fs%80;P}(WX^< z#>}?i`X>43Us&Q!yn27SINtj{^9oue-XYsY2j)741KGFwi>nTKSHH`yVoKDbQNLr4 z?f0*CwoD8S?;q1B#z(sYquqhg?!ahwV6;0h+8r3i-GN~_0{DkO8@`> literal 0 HcmV?d00001 diff --git a/assets/icons/apple-splash-750-1334.png b/assets/icons/apple-splash-750-1334.png new file mode 100644 index 0000000000000000000000000000000000000000..a9ae50458736d90a8ac0082dae5bd5653f009d65 GIT binary patch literal 7083 zcmeAS@N?(olHy`uVBq!ia0y~yV0y>Ez-q?91{67U-55kM76-XIF|0c$^OAujV(AW->kot;=s)6SNwUe=6vnuCu}0^%cc)9`*8gW< zXo!FN{|zGp!-3~5)(i|R9OVoQ90EXl1QhNtGAKCgU}kV=C}3x3V0g#}wC<2B&=sQ! zM}ucHQH*AV(UM}cd>pM6Mk~$Hrow0giPC0a!c1F+cU$s)Z`i*6v&6S=C+;rp{Sz}I z`OEi<`JL-O*&p6qP&g2cP_VN~<{sa${d%rE$XN%@e~g}c_`m-7Lr3Y{6h2^7&2T64 z?zfx5`Be{B<&-VYq?uzN=DJTN-^LFYneG{8p#d~^_Ubm(;;+WMnq&uG~*TK0^V eJ$TEW4{RqI%$p1|p_(ZOtT!7v-o;XNSZiVIR+{ec)b3a$5&1H&d3eg=jKsuc_j4LS#z85mMHN0p9- zz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#_BFx5D@vmfz|xK4tlR$Fe!b zuPf7Le%<+T-ygS?ALE+m7akrIo$uV$><5DHKAu%{u5M27xtU*W4pe{EtBC){{~-O& z;21u*{fhBJ$nU~+^F9P^eXhCl_|_^W2AgTpV!Z literal 0 HcmV?d00001 diff --git a/assets/icons/manifest-icon-192.maskable.png b/assets/icons/manifest-icon-192.maskable.png new file mode 100644 index 0000000000000000000000000000000000000000..f7735bce248c912588326cf1a2ae3c5fe9ecbe81 GIT binary patch literal 721 zcmeAS@N?(olHy`uVBq!ia0vp^2SAvE4M+yv$zcaljKx9jP7LeL$-HD>VCwdCaSW-L z^Y-q+%) + +

Hey there !

diff --git a/database.php b/database.php index bd1fcbd..9d794f9 100644 --- a/database.php +++ b/database.php @@ -10,6 +10,15 @@ function db_execute($sql, $variables=[]) { } +function db_execute_all($sql, $variables=[]) { + global $pdo; + + $stmt = $pdo->prepare($sql); + $stmt->execute($variables); + return $stmt->fetchAll(); + +} + function db_query($sql) { global $pdo; diff --git a/head.php b/head.php index 2d5c655..37e681a 100644 --- a/head.php +++ b/head.php @@ -1,13 +1,55 @@ - - - + -<?php if (isset($doc_title)) { echo $doc_title." | "; } ?>ByeCorps ID + - + - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/image_grabber.php b/image_grabber.php new file mode 100644 index 0000000..ed82256 --- /dev/null +++ b/image_grabber.php @@ -0,0 +1,17 @@ + ["admin_accounts.php"], "/admin/list/apps" => ["admin_apps.php"], "/admin/create/app" => ["admin_apps_create.php"], + "/admin/signinas" => ["signinas.php"], "/admin/purge" => ["admin_purge.php"], - "/account" => ["account.php", "Your account"], + // Settings + "/dashboard" => ["dashboard.php", "Dashboard", true], + + "/account" => ["account.php", "Your account", true], "/signin" => ["signin.php", "Sign in"], "/signup" => ["signup.php", "Sign up"], - "/signout" => ["signout.php", "Signed out"], + "/signout" => ["signout.php", "Signed out". false, true], "/forgot/password" => ["forgot_password.php", "Forgot password"], - "/admin/signinas" => ["signinas.php"], "/reset/password" => ["reset_password.php", "Reset password"], "/docs" => ["docs.php", "Docs"], "/credits" => ["credits.php", "Credits"], @@ -139,6 +142,10 @@ if (!empty($uri) ) { // Go to jail. Go directly to jail. Do not pass Go. include("api_handler.php"); exit(); // fuck this shit i'm out } + if ($uri[0] == "public" && $uri[1] == "avatars") { + include("image_grabber.php"); + exit(); + } } if (isset($paths[$path])) { @@ -146,6 +153,11 @@ if (isset($paths[$path])) { if (isset($paths[$path][1])) { $doc_title = $paths[$path][1]; } + if (array_key_exists(3, $paths[$path])) { + if ($paths[$path][3]) { + goto skip_formalities; + } + } } else { @@ -167,8 +179,7 @@ if ($include == "login_external_basic.php") {
- + include($include); + ?>
- \ No newline at end of file + diff --git a/login_external_basic.php b/login_external_basic.php index 9169211..5b3d55b 100644 --- a/login_external_basic.php +++ b/login_external_basic.php @@ -96,9 +96,14 @@ login:
-

Sign into

+
+ <?= htmlspecialchars($user['display_name']) ?>'s avatar + × + <?= htmlspecialchars($user['title']) ?>'s avatar +
+

Sign into

Owned by

-

+ $badges); + } +} ?>
Avatar
-
+
@@ -48,6 +52,23 @@ if ($_SESSION['id'] != $profile['id']) {

Badges

+ This profile has no badges :(

'; + } else { + foreach ($badges as $badge) { + echo "
+". htmlspecialchars($badge[ +
+" . htmlspecialchars($badge['title']) . " +

". htmlspecialchars($badge['description']) ."

+

". htmlspecialchars($badge['description']) ."

+

Earned " . $badge['earned'] . "

+
+
"; + } + } + ?>
@@ -58,6 +79,10 @@ if ($_SESSION['id'] != $profile['id']) { Joined + + Badges earned + +
diff --git a/signin.php b/signin.php index a1904f5..88f8619 100644 --- a/signin.php +++ b/signin.php @@ -29,11 +29,14 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { // print_r($_POST); // echo(is_string($_POST['keep_logged_in'])); - if ($_POST['keep_logged_in'] == "on") { - $token = generate_cookie_access_token($user['id']); + if (array_key_exists('keep_logged_in', $_POST)) { + if ($_POST['keep_logged_in'] == "on") { + $token = generate_cookie_access_token($user['id']); // print_r($token); - setcookie("keep_me_logged_in", $token['access']); + setcookie("keep_me_logged_in", $token['access']); + } } + // if (isset($query['callback'])) { header("Location: ".$query['callback']); @@ -57,14 +60,14 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { echo "
$message
"; }?> - - + +

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

-
\ No newline at end of file +
diff --git a/signup.php b/signup.php index 13fc42e..612426a 100644 --- a/signup.php +++ b/signup.php @@ -55,7 +55,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {

Sign up for ByeCorps ID

- - + +
\ No newline at end of file diff --git a/styles/design.css b/styles/design.css index c6748d9..0d5d2d8 100644 --- a/styles/design.css +++ b/styles/design.css @@ -15,9 +15,9 @@ button, .button { cursor: pointer; } -header a { - text-decoration: none; -} +/*header a {*/ +/* text-decoration: underline;*/ +/*}*/ /* inputs */ @@ -72,6 +72,23 @@ table > tbody > tr > td { padding: .5em; } +#connection_img { + display: flex; + gap: 1rem; + + justify-content: center; +} + +#connection_img img { + height:7.5rem; + border-radius: 50%; +} + +#connection_img .sep { + font-size: 4rem; + align-self: center; +} + @media screen and (prefers-color-scheme: dark) { table { background-color: var(--grey-9); diff --git a/styles/global.css b/styles/global.css index c689015..adf6fc5 100644 --- a/styles/global.css +++ b/styles/global.css @@ -9,10 +9,10 @@ } body::after { - content: "Development: Subject To Change"; + content: "BETA"; position: fixed; - top: 4.5rem; - right: -1rem; + top: 5rem; + right: 1rem; text-align: right; font-size: 2.5rem; diff --git a/styles/profiles.css b/styles/profiles.css index 147c159..01c8d67 100644 --- a/styles/profiles.css +++ b/styles/profiles.css @@ -32,6 +32,36 @@ grid-template-columns: 3fr 1fr; } +#badges { + display: grid; + grid-template-columns: repeat(auto-fit, 1fr); + gap: 0.5rem; +} + +#badges .badge { + display: flex; + align-items: center; + + gap: 1rem; +} + +.badge .details { + display: flex; + flex-direction: column; +} + +.badge img { + height: 7.5em; + width: 7.5em; + object-fit: contain; + border-radius: 1em; +} + +.badge .details .title { + font-size: 1.5rem; + font-weight: 700; +} + @media screen and (prefers-color-scheme: dark) { #profile { background: var(--grey-9); diff --git a/styles/types.css b/styles/types.css index 10cea60..2fec09e 100644 --- a/styles/types.css +++ b/styles/types.css @@ -1,7 +1,7 @@ /* This file deals with font types and font families. */ @import url(https://fonts.bunny.net/css?family=montserrat:400,400i,600,600i,700,700i,900,900i); -@import url(https://fonts.bunny.net/css2?family=courier+prime:wght@400;700&display=swap); /* for BCIDs */ +@import url(https://fonts.bunny.net/css2?family=Space+Mono:wght@400;700&display=swap); /* for BCIDs */ @import url(/fontawesome/css/all.css); @@ -39,10 +39,10 @@ h2.subheading + h1 { } .bcid { - font-family: 'Courier Prime', monospace; + font-family: 'Space Mono', monospace; } -p.subtitle { +.subtitle { font-size: 0.9rem; margin: 0; opacity: 0.8; @@ -59,3 +59,28 @@ p.subtitle { .icon-false::before { content: "\f00d"; } + +.space-mono-regular { + font-family: "Space Mono", monospace; + font-weight: 400; + font-style: normal; +} + +.space-mono-regular-italic { + font-family: "Space Mono", monospace; + font-weight: 400; + font-style: italic; +} + +.space-mono-bold { + font-family: "Space Mono", monospace; + font-weight: 700; + font-style: normal; +} + +.space-mono-bold-italic { + font-family: "Space Mono", monospace; + font-weight: 700; + font-style: italic; +} + From 74d351e9cd953dee861ff57a8d2bfc91c2dc02d1 Mon Sep 17 00:00:00 2001 From: Bye Date: Sun, 17 Mar 2024 15:48:32 +0000 Subject: [PATCH 04/12] I don't know if this is OK to publish. YOLO --- dashboard.php | 17 +++++++++++------ head.php | 42 ++++-------------------------------------- index.php | 29 ++++++++++++++++++----------- profile.php | 3 ++- signin.php | 2 +- 5 files changed, 36 insertions(+), 57 deletions(-) diff --git a/dashboard.php b/dashboard.php index 58d5592..9542481 100644 --- a/dashboard.php +++ b/dashboard.php @@ -1,12 +1,17 @@ +$doc_title = get_display_name($user['id']) . "'s Dashboard" ; -

Hey there !

+$output = $output . + "

Hey there ". $user['display_name'] ."!

"; diff --git a/head.php b/head.php index 37e681a..1998630 100644 --- a/head.php +++ b/head.php @@ -1,9 +1,11 @@ - + + + - +<?php if (isset($doc_title)) { echo $doc_title." | "; } ?>ByeCorps ID @@ -15,41 +17,5 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/index.php b/index.php index b5fde9e..354cb19 100755 --- a/index.php +++ b/index.php @@ -3,6 +3,8 @@ require_once __DIR__ . '/vendor/autoload.php'; session_start(); +error_reporting(E_ERROR | E_WARNING | E_PARSE); + if (empty($_SESSION)) { $_SESSION['auth'] = false; } @@ -124,10 +126,10 @@ $paths = array( // Settings "/dashboard" => ["dashboard.php", "Dashboard", true], - "/account" => ["account.php", "Your account", true], + "/account" => ["account.php", "Your account"], "/signin" => ["signin.php", "Sign in"], "/signup" => ["signup.php", "Sign up"], - "/signout" => ["signout.php", "Signed out". false, true], + "/signout" => ["signout.php", "Signed out"], "/forgot/password" => ["forgot_password.php", "Forgot password"], "/reset/password" => ["reset_password.php", "Reset password"], "/docs" => ["docs.php", "Docs"], @@ -148,15 +150,14 @@ if (!empty($uri) ) { // Go to jail. Go directly to jail. Do not pass Go. } } +$migrated = false; if (isset($paths[$path])) { $include = $paths[$path][0]; if (isset($paths[$path][1])) { $doc_title = $paths[$path][1]; } - if (array_key_exists(3, $paths[$path])) { - if ($paths[$path][3]) { - goto skip_formalities; - } + if (isset($paths[$path][2])) { + $migrated = $paths[$path][2]; } } @@ -165,10 +166,12 @@ else { http_response_code(404); } -if ($include == "login_external_basic.php") { - goto skip_formalities; -} +if ($migrated) { + $output = ""; + + include($include); +} ?> @@ -197,8 +200,12 @@ if ($include == "login_external_basic.php") { } } - skip_formalities: - include($include); + if ($migrated) { + echo $output; + } + else { + include ($include); + } ?>
diff --git a/profile.php b/profile.php index 75829b8..4f65db5 100644 --- a/profile.php +++ b/profile.php @@ -1,10 +1,11 @@ - + Date: Sun, 17 Mar 2024 16:01:42 +0000 Subject: [PATCH 05/12] Create FUNDING.yml --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..31686a3 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: byemc From 259970d8d518572b3737e65e0eec1beb91c7f81c Mon Sep 17 00:00:00 2001 From: Bye Date: Sun, 17 Mar 2024 18:01:45 +0000 Subject: [PATCH 06/12] Add PHP_SESSID support to api to allow JavaScript on the main website to do crazy auto-save shit --- api_handler.php | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/api_handler.php b/api_handler.php index 34c5c5a..d3fdc14 100644 --- a/api_handler.php +++ b/api_handler.php @@ -7,6 +7,8 @@ if (array_key_exists('HTTP_AUTHORIZATION', $_SERVER)) { $access_token = str_replace("Bearer ", "", $_SERVER['HTTP_AUTHORIZATION']); } + + if (!empty($access_token)) { // Check who the access token belongs to $token = db_execute("SELECT * FROM tokens WHERE access_token = ?", [$access_token]); @@ -30,12 +32,23 @@ function check_authorisation($token): int $token_row = db_execute("SELECT * FROM tokens WHERE access_token = ?", [$token]); if (null == $token_row) { - return 0; + if (array_key_exists('auth', $_SESSION)) { + if ($_SESSION['auth']) { + $token_row = [ + "type" => "dangerous" + ]; + } else { + return 0; + } + } else { + return 0; + } } return match ($token_row['type']) { - "basic" => 1, - default => 0, + "dangerous" => 22, + "basic" => 1, + default => 0, }; } @@ -64,11 +77,13 @@ function get_avatar(): array ]; } $user_id = $query['id']; + return []; } // User (REQUIRES AUTHORISATION) -function api_user_info() { +function api_user_info(): array +{ global $access_token, $token_owner; // Authorisation levels: // `display_name` = 1 (basic) @@ -86,9 +101,7 @@ function api_user_info() { if (null != $data) { return [ "response_code" => 200, - "id" => $data['id'], - "email" => $data['email'], - "display_name" => $data['display_name'] + "data" => $data ]; } From 3118befc0ec7887f1240007fa1cd62df6b39a6ca Mon Sep 17 00:00:00 2001 From: Bye Date: Mon, 18 Mar 2024 20:11:01 +0000 Subject: [PATCH 07/12] Dashboard --- account.php | 2 +- api_handler.php | 13 ++++++-- dashboard.php | 18 ++++++++++- index.php | 1 + login_external_basic.php | 9 +----- settings.php | 44 +++++++++++++++++++++++++ styles/colours.css | 13 ++++++-- styles/profiles.css | 10 +++--- styles/settings.css | 69 ++++++++++++++++++++++++++++++++++++++++ 9 files changed, 159 insertions(+), 20 deletions(-) create mode 100644 settings.php create mode 100644 styles/settings.css diff --git a/account.php b/account.php index 30fa20f..fe7931c 100644 --- a/account.php +++ b/account.php @@ -77,7 +77,7 @@ if (isset($message )) { ?>
-
+
diff --git a/api_handler.php b/api_handler.php index d3fdc14..2792cb1 100644 --- a/api_handler.php +++ b/api_handler.php @@ -14,6 +14,7 @@ if (!empty($access_token)) { $token = db_execute("SELECT * FROM tokens WHERE access_token = ?", [$access_token]); // if the token doesn't exist... if (empty($token)) { + $invalid_token = true; // We won't tell this to the end-user immediately because I'd prefer to tell them about // 404 first. } else { @@ -21,10 +22,12 @@ if (!empty($access_token)) { } } -function check_authorisation($token): int +function check_authorisation($token=""): int { + global $token_owner; // Validate token - if (!validate_access_token($token)) { + if (!validate_access_token($token) && "" != $token) { + echo "invalid"; return 0; // Unauthorised } @@ -37,6 +40,7 @@ function check_authorisation($token): int $token_row = [ "type" => "dangerous" ]; + $token_owner = $_SESSION['id']; } else { return 0; } @@ -94,8 +98,11 @@ function api_user_info(): array $data = null; - if ($level == 1) { + if ($level >= 1) { $data = db_execute("SELECT id, email, display_name FROM accounts WHERE id = ? LIMIT 1", [$token_owner]); + } if ($level == 22) { + $data = db_execute("SELECT * FROM accounts WHERE id = ? LIMIT 1", [$token_owner]); + unset($data['password']); } if (null != $data) { diff --git a/dashboard.php b/dashboard.php index 9542481..b5e630e 100644 --- a/dashboard.php +++ b/dashboard.php @@ -14,4 +14,20 @@ if (!$_SESSION['auth']) { $doc_title = get_display_name($user['id']) . "'s Dashboard" ; $output = $output . - "

Hey there ". $user['display_name'] ."!

"; + " + +
+
+
+ +
+
+ " . htmlspecialchars(get_display_name($user['id'], false)) . " + " . format_bcid($user['id']) . " +
+
+
+

". htmlspecialchars(get_display_name($user['id'], false)) ."'s Dashboard

+
+
+"; diff --git a/index.php b/index.php index 354cb19..dee8e31 100755 --- a/index.php +++ b/index.php @@ -125,6 +125,7 @@ $paths = array( // Settings "/dashboard" => ["dashboard.php", "Dashboard", true], + "/settings" => ["settings.php", "Settings"], "/account" => ["account.php", "Your account"], "/signin" => ["signin.php", "Sign in"], diff --git a/login_external_basic.php b/login_external_basic.php index 5b3d55b..15bfebe 100644 --- a/login_external_basic.php +++ b/login_external_basic.php @@ -86,14 +86,7 @@ login: ?> - - - - - - - -
+
diff --git a/settings.php b/settings.php new file mode 100644 index 0000000..13d3d3a --- /dev/null +++ b/settings.php @@ -0,0 +1,44 @@ + + + + +
+
+
+ /> +
+
+ + +
+
+ + +
diff --git a/styles/colours.css b/styles/colours.css index 287d9f0..aac47e3 100644 --- a/styles/colours.css +++ b/styles/colours.css @@ -27,6 +27,9 @@ --background: white; --background-dark: #121212; + --foreground: black; + --foreground-dark: white; + color-scheme: light dark; } @@ -107,8 +110,15 @@ input[data-com-onepassword-filled="dark"] { } @media screen and (prefers-color-scheme: dark) { + :root { + --background: #121212; + --foreground: white; + + color-scheme: light dark; + } + html { - background: var(--background-dark, #121212); + background: var(--background, #121212); } button.primary, .button.primary { @@ -126,7 +136,6 @@ input[data-com-onepassword-filled="dark"] { } input, textarea { - background-color: #2c2c2c77; } diff --git a/styles/profiles.css b/styles/profiles.css index 01c8d67..fb02a44 100644 --- a/styles/profiles.css +++ b/styles/profiles.css @@ -1,5 +1,5 @@ -#profile { +#mini_profile { display: flex; gap: 1rem; padding: 1rem; @@ -12,18 +12,18 @@ background: var(--grey-0); } -#profile > .avatar { +#mini_profile > .avatar { height: 150px; border-radius: 1em; } -#profile > .info > .displayname { +#mini_profile > .info > .displayname { font-size: 2.5rem; font-weight: bolder; } -#profile > .info > .bcid { +#mini_profile > .info > .bcid { font-size: 1.5rem; } @@ -63,7 +63,7 @@ } @media screen and (prefers-color-scheme: dark) { - #profile { + #mini_profile { background: var(--grey-9); } } diff --git a/styles/settings.css b/styles/settings.css new file mode 100644 index 0000000..86ad52f --- /dev/null +++ b/styles/settings.css @@ -0,0 +1,69 @@ + +#settings_split { + display: grid; + + grid-template-columns: 1fr 4fr; +} + +#mini_profile { + display: flex; + flex-direction: column; + + border-radius: 1.5rem; + overflow: clip; +} + +#mini_profile .image_container { + display: flex; + background: linear-gradient(to bottom, white, var(--background) 90%); +} + +#mini_profile .image_container img { + width: 50%; + margin: 0.5rem auto auto; + padding-top: 0.5rem; + border-radius: 1rem; +} + +#mini_profile .texts { + text-align: center; + display: flex; + flex-direction: column; + + padding-top: 1rem; +} + +#mini_profile .texts .displayname { + font-size: 2rem; + font-weight: bold; +} + +#settings_list { + list-style: none; +} + +#settings_list > h1 { + margin: 0 0 1rem 0; +} + +#settings_list li { + border-top: var(--foreground) 1px solid; +} + +#settings_list li:first-child { + border-top: none; +} + +#settings_list li > a { + display: block; + padding: 1rem 0; + + color: var(--foreground); + text-decoration: none; + + transition: color 0.2s ease-in-out; +} + +#settings_list li > a:hover { + color: var(--flax) +} From 004009ca51129b91d3e53a3a200e4e1d3f514dc9 Mon Sep 17 00:00:00 2001 From: Bye Date: Fri, 29 Mar 2024 22:02:39 +0000 Subject: [PATCH 08/12] Fix essential security bug --- index.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/index.php b/index.php index 354cb19..4751dc3 100755 --- a/index.php +++ b/index.php @@ -190,10 +190,10 @@ if ($migrated) { echo "

Admin

"; } -// if ($uri[0] == "admin" && !$user['is_admin']) { -// http_response_code(401); -// die("A cat standing in front of a door with a No Cats Allowed sign on it."); -// } + if ($uri[0] == "admin" && !$user['is_admin']) { + http_response_code(401); + die("A cat standing in front of a door with a No Cats Allowed sign on it."); + } if ($uri[0] == "docs") { $include = "docs.php"; From b007cff0d9998161520c613c5b9f451f09da5928 Mon Sep 17 00:00:00 2001 From: Bye Date: Fri, 29 Mar 2024 22:04:20 +0000 Subject: [PATCH 09/12] i don't render what this changed this might be a terrible idea --- dashboard.php | 36 ++++++++++++------- index.php | 2 +- styles/colours.css | 4 +++ styles/settings.css | 85 +++++++++++++++++++++++++++++++++++++++++---- styles/types.css | 2 +- 5 files changed, 107 insertions(+), 22 deletions(-) diff --git a/dashboard.php b/dashboard.php index b5e630e..e6d23f7 100644 --- a/dashboard.php +++ b/dashboard.php @@ -11,23 +11,33 @@ if (!$_SESSION['auth']) { exit; } -$doc_title = get_display_name($user['id']) . "'s Dashboard" ; +?> -$output = $output . - " + -
-
-
- +
+
+
+ ' />
-
- " . htmlspecialchars(get_display_name($user['id'], false)) . " - " . format_bcid($user['id']) . " +
+ +
-
-

". htmlspecialchars(get_display_name($user['id'], false)) ."'s Dashboard

+
-"; diff --git a/index.php b/index.php index dee8e31..90a06e1 100755 --- a/index.php +++ b/index.php @@ -124,7 +124,7 @@ $paths = array( "/admin/purge" => ["admin_purge.php"], // Settings - "/dashboard" => ["dashboard.php", "Dashboard", true], + "/dashboard" => ["dashboard.php", "Dashboard"], "/settings" => ["settings.php", "Settings"], "/account" => ["account.php", "Your account"], diff --git a/styles/colours.css b/styles/colours.css index aac47e3..fe71ae5 100644 --- a/styles/colours.css +++ b/styles/colours.css @@ -30,6 +30,8 @@ --foreground: black; --foreground-dark: white; + --chip-background: var(--grey-0); + color-scheme: light dark; } @@ -114,6 +116,8 @@ input[data-com-onepassword-filled="dark"] { --background: #121212; --foreground: white; + --chip-background: var(--grey-9); + color-scheme: light dark; } diff --git a/styles/settings.css b/styles/settings.css index 86ad52f..95d424e 100644 --- a/styles/settings.css +++ b/styles/settings.css @@ -1,8 +1,12 @@ +main { + display: flex; +} + #settings_split { display: grid; - - grid-template-columns: 1fr 4fr; + grid-template-columns: 1fr 3fr; + gap: 1rem; } #mini_profile { @@ -11,17 +15,20 @@ border-radius: 1.5rem; overflow: clip; + + padding-bottom: 1.5rem; + + background: var(--background); } #mini_profile .image_container { display: flex; - background: linear-gradient(to bottom, white, var(--background) 90%); + background: linear-gradient(to bottom, white, var(--background) 95%); } #mini_profile .image_container img { width: 50%; - margin: 0.5rem auto auto; - padding-top: 0.5rem; + margin: 0.5rem auto 0.5rem; border-radius: 1rem; } @@ -29,8 +36,6 @@ text-align: center; display: flex; flex-direction: column; - - padding-top: 1rem; } #mini_profile .texts .displayname { @@ -67,3 +72,69 @@ #settings_list li > a:hover { color: var(--flax) } + +.tiles { + display: grid; + gap: 1rem; + grid-template-columns: repeat(3, 1fr); + grid-template-rows: 150px; + grid-auto-flow: dense; +} + +.tiles .tile { + background: #343a40; + text-align: center; + display: flex; + text-decoration: none; + + font-size: 1.2rem; + font-weight: 500; + + border-radius: 1.5rem; + + transition: scale 0.2s ease-in-out; +} + +.tiles .tile:hover { + scale: 1.05; +} + +.tiles .tile div { + margin: auto; +} + +.tiles .tile span { + display: block; +} + +.tile.double-height { + grid-row: span 2; +} + +@media screen and (max-width: 960px) { + #settings_split { + grid-template-columns: none; + } + + #mini_profile { + flex-direction: row; + padding-bottom: 0; + } + + #mini_profile .image_container { + width: 40%; + background: linear-gradient(to right, white, var(--chip-background) 95%); + } + + #mini_profile .image_container img { + margin: 1rem; + border-radius: 1rem; + } + + #mini_profile .texts { + flex: 1; + margin: auto auto auto 0; + text-align: left; + } +} + diff --git a/styles/types.css b/styles/types.css index 2fec09e..26b27af 100644 --- a/styles/types.css +++ b/styles/types.css @@ -1,6 +1,6 @@ /* This file deals with font types and font families. */ -@import url(https://fonts.bunny.net/css?family=montserrat:400,400i,600,600i,700,700i,900,900i); +@import url(https://fonts.bunny.net/css?family=montserrat:400,400i,500,600,600i,700,700i,900,900i); @import url(https://fonts.bunny.net/css2?family=Space+Mono:wght@400;700&display=swap); /* for BCIDs */ @import url(/fontawesome/css/all.css); From dca42da4fc6807bc7357e4fad203f5d57d8bd14b Mon Sep 17 00:00:00 2001 From: Bye Date: Sun, 28 Apr 2024 14:44:19 +0100 Subject: [PATCH 10/12] Fix a minor issue in the login form (basic external) --- dashboard.php | 2 +- login_external_basic.php | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/dashboard.php b/dashboard.php index e6d23f7..61c814b 100644 --- a/dashboard.php +++ b/dashboard.php @@ -26,7 +26,7 @@ if (!$_SESSION['auth']) {
- +
Settings diff --git a/login_external_basic.php b/login_external_basic.php index 15bfebe..af0e93e 100644 --- a/login_external_basic.php +++ b/login_external_basic.php @@ -86,7 +86,6 @@ login: ?> -
From 10702cef414eec6611086117565d565f8c35e8ee Mon Sep 17 00:00:00 2001 From: bye Date: Wed, 29 May 2024 18:33:57 +0100 Subject: [PATCH 11/12] i dont know whats in this commit hopefully it's good --- accounts_handler.php | 34 ++++++++++++-- admin.php | 5 ++ admin_accounts.php | 6 +-- admin_create_token.php | 86 ++++++++++++++++++++++++++++++++++ api_handler.php | 65 +++++++++++++++++++++----- assets/buttons/signinwith.svg | 88 +++++++++++++++++++++++++++++++++++ head.php | 2 +- index.php | 2 + landing.php | 32 +++++++++++-- login_external_basic.php | 41 +++++++++++----- profile.php | 48 +------------------ settings_account.php | 79 +++++++++++++++++++++++++++++++ signin.php | 2 +- styles/colours.css | 6 +++ styles/profiles.css | 8 ++++ styles/types.css | 4 ++ 16 files changed, 426 insertions(+), 82 deletions(-) create mode 100644 admin_create_token.php create mode 100644 assets/buttons/signinwith.svg create mode 100644 settings_account.php diff --git a/accounts_handler.php b/accounts_handler.php index 34e6c0a..1ae09c3 100644 --- a/accounts_handler.php +++ b/accounts_handler.php @@ -30,7 +30,7 @@ function get_display_name($bcid, $use_bcid_fallback=true, $put_bcid_in_parenthes // Tokens so apps can get VERY BASIC information -function generate_basic_access_token($bcid): array +function generate_basic_access_token($bcid, $application_id=""): array { // Returns an access token, a refresh token and an expiry timestamp. @@ -42,14 +42,42 @@ function generate_basic_access_token($bcid): array // echo $access_token . ":" . $refresh_token; + if ($application_id) { + db_execute( + "INSERT INTO tokens (access_token, refresh_token, expiry, owner_id, application_id, permissions) VALUES (?,?,?,?,?, (1<<0 | 1<<1))", + [$access_token, $refresh_token, $expiry, $bcid, $application_id] + ); + } else { + db_execute( + "INSERT INTO tokens (access_token, refresh_token, expiry, owner_id, permissions) VALUES (?,?,?,?, (1<<0 | 1<<1))", + [$access_token, $refresh_token, $expiry, $bcid] + ); + } + + return [ + "access" => $access_token, + "refresh" => $refresh_token, + "expiry" => $expiry, + "id" => $bcid + ]; +} + +function generate_token($bcid, $application_id=null, $permissions=0): array { + $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); + db_execute( - "INSERT INTO tokens (access_token, refresh_token, expiry, owner_id) VALUES (?,?,?,?)", - [$access_token, $refresh_token, $expiry, $bcid] + "INSERT INTO tokens (access_token, refresh_token, expiry, owner_id, application_id, permissions, type) VALUES (?,?,?,?,?,?, 'oauth')", + [$access_token, $refresh_token, $expiry, $bcid, $application_id, $permissions] ); return [ "access" => $access_token, "refresh" => $refresh_token, + "permissions" => $permissions, "expiry" => $expiry, "id" => $bcid ]; diff --git a/admin.php b/admin.php index d92d029..efb0b73 100644 --- a/admin.php +++ b/admin.php @@ -18,6 +18,11 @@ +

API

+
+

Init

  • diff --git a/admin_accounts.php b/admin_accounts.php index 3a73e80..b353838 100644 --- a/admin_accounts.php +++ b/admin_accounts.php @@ -21,9 +21,9 @@ $count = $count_req->fetchColumn(); diff --git a/admin_create_token.php b/admin_create_token.php new file mode 100644 index 0000000..6456f05 --- /dev/null +++ b/admin_create_token.php @@ -0,0 +1,86 @@ +"; + print_r($_POST); + echo ""; + + $token = generate_token($_POST['owner'], $_POST['application'], $_POST['permissions']); + + echo "

    Created token. Access token: ". $token['access'] ."

    "; +} + +?> + +

    Token generator

    + +
    +
    + + +
    +
    + + +
    + + + +

    Permissions

    +

    Permission number:

    +
    + + +
    + + +
    + + + + diff --git a/api_handler.php b/api_handler.php index 2792cb1..164e5c0 100644 --- a/api_handler.php +++ b/api_handler.php @@ -7,8 +7,6 @@ if (array_key_exists('HTTP_AUTHORIZATION', $_SERVER)) { $access_token = str_replace("Bearer ", "", $_SERVER['HTTP_AUTHORIZATION']); } - - if (!empty($access_token)) { // Check who the access token belongs to $token = db_execute("SELECT * FROM tokens WHERE access_token = ?", [$access_token]); @@ -27,7 +25,6 @@ function check_authorisation($token=""): int global $token_owner; // Validate token if (!validate_access_token($token) && "" != $token) { - echo "invalid"; return 0; // Unauthorised } @@ -50,8 +47,9 @@ function check_authorisation($token=""): int } return match ($token_row['type']) { - "dangerous" => 22, - "basic" => 1, + "dangerous" => 1<<0 | 1<<1, // Everything + "basic" => 1<<1, // Basic + "oauth" => $token_row['permissions'], default => 0, }; } @@ -93,16 +91,12 @@ function api_user_info(): array // `display_name` = 1 (basic) // `id` = 1 (basic) // `email` = 1 (basic) - $level = check_authorisation($access_token); - $data = null; - - if ($level >= 1) { + if ($level & (1 << 0)) { $data = db_execute("SELECT id, email, display_name FROM accounts WHERE id = ? LIMIT 1", [$token_owner]); - } if ($level == 22) { - $data = db_execute("SELECT * FROM accounts WHERE id = ? LIMIT 1", [$token_owner]); - unset($data['password']); + } else { + $data = db_execute("SELECT id, display_name FROM accounts WHERE id = ? LIMIT 1", [$token_owner]); } if (null != $data) { @@ -117,7 +111,50 @@ function api_user_info(): array "response_code" => 401, "message" => "Unauthorized." ]; +} +function api_settings(): array +{ + // GET: Return all settings + // POST/PATCH: Update settings + + global $access_token, $token_owner; + + $level = check_authorisation($access_token); + + if (!($level & (1 << 1))) { // account.settings + http_response_code(401); + return [ + "response_code" => 401, + "message" => "Unauthorized." + ]; + } + + if ($_SERVER['REQUEST_METHOD'] === "POST") { + + // Now for the fucking worstest code ever + $settings_changed = json_decode(file_get_contents('php://input'), true); + + if (isset($settings_changed['account'])) { + if (isset($settings_changed['account']['display_name'])) { + $display_name = db_execute('UPDATE accounts SET display_name = ? WHERE id = ?', + [$settings_changed['account']['display_name'], $token_owner]); + } + } + } + + // Get account settings + $display_name = db_execute('SELECT display_name FROM accounts WHERE id = ?', [$token_owner])["display_name"]; + + + return [ + "response_code" => 200, + "settings" => [ + "account" => [ + "display_name" => $display_name, + ] + ] + ]; } $api_routes = [ // base url is base_url.'/api' @@ -129,6 +166,9 @@ $api_routes = [ // base url is base_url.'/api' // Account stuff "/account/me" => "api_user_info", + // Settings + "/settings" => "api_settings", + // Get avatar "/avatars/get" => "get_avatar" ]; @@ -142,6 +182,7 @@ if (isset($api_routes[$path])) { "response_code" => "498", "message" => "Token expired or invalid." ])); + exit(); } $response = $api_routes[$path](); if (array_key_exists('response_code', $response)) { diff --git a/assets/buttons/signinwith.svg b/assets/buttons/signinwith.svg new file mode 100644 index 0000000..ca72560 --- /dev/null +++ b/assets/buttons/signinwith.svg @@ -0,0 +1,88 @@ + + + + diff --git a/head.php b/head.php index 1998630..5ea88ad 100644 --- a/head.php +++ b/head.php @@ -7,7 +7,7 @@ > <?php if (isset($doc_title)) { echo $doc_title." | "; } ?>ByeCorps ID - + diff --git a/index.php b/index.php index 9f068c5..3d7a309 100755 --- a/index.php +++ b/index.php @@ -120,12 +120,14 @@ $paths = array( "/admin/list/accounts" => ["admin_accounts.php"], "/admin/list/apps" => ["admin_apps.php"], "/admin/create/app" => ["admin_apps_create.php"], + "/admin/create/token" => ["admin_create_token.php"], "/admin/signinas" => ["signinas.php"], "/admin/purge" => ["admin_purge.php"], // Settings "/dashboard" => ["dashboard.php", "Dashboard"], "/settings" => ["settings.php", "Settings"], + "/settings/account" => ["settings_account.php", "Settings -> Account"], "/account" => ["account.php", "Your account"], "/signin" => ["signin.php", "Sign in"], diff --git a/landing.php b/landing.php index a4ea89b..c4769b4 100644 --- a/landing.php +++ b/landing.php @@ -1,3 +1,11 @@ + +
    @@ -5,10 +13,26 @@

    Log into ByeCorps and beyond with a single ID.

    - Manage account"; } - else { echo "Sign inCreate an account"; } + Manage account"; } + else { echo "Sign inCreate an account"; } ?>
    -
    \ No newline at end of file +
+ + + +
+
+ +

ByeCorps ID

+

Log into ByeCorps and beyond with a single ID.

+
+ diff --git a/login_external_basic.php b/login_external_basic.php index af0e93e..2a1c68c 100644 --- a/login_external_basic.php +++ b/login_external_basic.php @@ -31,9 +31,29 @@ if ($query['callback'] != $app['callback']) { goto login; } +if ($_SESSION['auth'] && $_SERVER['REQUEST_METHOD'] == 'GET') { + // We can check if there's already a valid token of the same level and just pass that on instead. + $valid_tokens = db_execute_all("SELECT * FROM tokens WHERE owner_id = ? AND type = ? AND application_id = ? AND expiry > ?", + [$_SESSION['id'], "basic", $app_id, time()]); + + if (sizeof($valid_tokens) > 0) { + print_r($valid_tokens); + + $token = $valid_tokens[0]; + + header('Location: '. $_GET['callback'].'?access_token='.$token['access_token'].'&refresh='.$token['refresh_token'] + .'&expiry='.$token['expiry']); + exit(); + } + +// if (validate_access_token()) + + +} + if ($_SERVER['REQUEST_METHOD'] === 'POST') { // Here's a few easy steps to figure out if we should give the other party a token or not. - print_r($_POST); +// print_r($_POST); // First: match the session ids. If they aren't the same it's probably Not Ok. if (session_id() != $_POST['sessionid']) { @@ -74,7 +94,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { } // The following gets run assuming we know the client is the one CLICKING the button. - $tokens = generate_basic_access_token($_POST['bcid']); + $tokens = generate_basic_access_token($_POST['bcid'], $app_id); header('Location: '. $_POST['callback'].'?access_token='.$tokens['access'].'&refresh='.$tokens['refresh'] .'&expiry='.$tokens['expiry']); @@ -94,15 +114,15 @@ login: <?= htmlspecialchars($user['title']) ?>'s avatar

Sign into

-

Owned by

+

Owned by

- +
+

Something went wrong!

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

@@ -110,9 +130,9 @@ login: goto dont_show_form; } ?> -

uses ByeCorps ID for authentication.

+

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 .

+

Please confirm that you'd like to sign into .

$flash

"; @@ -131,11 +151,10 @@ login: - - +

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

diff --git a/profile.php b/profile.php index 4f65db5..1636266 100644 --- a/profile.php +++ b/profile.php @@ -33,7 +33,7 @@ if ($_SESSION['id'] != $profile['id']) { } // Get badges owned by this person -$badges = db_execute_all('SELECT * FROM badge_owners INNER JOIN badges b on badge_owners.badge_id = b.id; ', []); +$badges = db_execute_all('SELECT * FROM badge_owners INNER JOIN badges b on badge_owners.badge_id = b.id WHERE owner_id = ?; ', [$profile['id']]); if (!empty($badges)) { if (!array_is_list($badges)) { $badges = array (0 => $badges); @@ -42,49 +42,3 @@ if (!empty($badges)) { ?> -
- Avatar -
-
-
-
-
- -
-
-

Badges

- This profile has no badges :(

'; - } else { - foreach ($badges as $badge) { - echo "
-". htmlspecialchars($badge[ -
-" . htmlspecialchars($badge['title']) . " -

". htmlspecialchars($badge['description']) ."

-

". htmlspecialchars($badge['description']) ."

-

Earned " . $badge['earned'] . "

-
-
"; - } - } - ?> -
- -
-

Info

- - - - - - - - - - -
Joined
Badges earned
- -
-
diff --git a/settings_account.php b/settings_account.php new file mode 100644 index 0000000..08cf72f --- /dev/null +++ b/settings_account.php @@ -0,0 +1,79 @@ + + + + +
+
+
+ <?= htmlspecialchars(get_display_name($user['id'])) ?>'s avatar +
+
+ + +
+
+ +
+

Account

+
+
+ + +
+ + +
+
+
+ + + + diff --git a/signin.php b/signin.php index 7814a1a..0574d99 100644 --- a/signin.php +++ b/signin.php @@ -33,7 +33,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { if ($_POST['keep_logged_in'] == "on") { $token = generate_cookie_access_token($user['id']); // print_r($token); - setcookie("keep_me_logged_in", $token['access']); + setcookie("keep_me_logged_in", $token['access'], time()+606024*365); } } diff --git a/styles/colours.css b/styles/colours.css index fe71ae5..b346a2f 100644 --- a/styles/colours.css +++ b/styles/colours.css @@ -24,6 +24,8 @@ --grey-8: #343a40; --grey-9: #212529; + --error-color: var(--red-5); + --background: white; --background-dark: #121212; @@ -111,6 +113,10 @@ input[data-com-onepassword-filled="dark"] { color: black; } +.fg-error { + color: var(--error-color); +} + @media screen and (prefers-color-scheme: dark) { :root { --background: #121212; diff --git a/styles/profiles.css b/styles/profiles.css index fb02a44..d5b4f78 100644 --- a/styles/profiles.css +++ b/styles/profiles.css @@ -1,4 +1,12 @@ +#profile { + display: flex; +} + +#profile .avatar { + height: 150px; +} + #mini_profile { display: flex; gap: 1rem; diff --git a/styles/types.css b/styles/types.css index 26b27af..2861f85 100644 --- a/styles/types.css +++ b/styles/types.css @@ -52,6 +52,10 @@ h2.subheading + h1 { text-align: center; } +.vertical-center { + vertical-align: center; +} + .icon-true::before { content: "\f00c"; } From 75ae8e91dec8f08ee92859b890beb6a9bcaf3cbe Mon Sep 17 00:00:00 2001 From: bye Date: Fri, 31 May 2024 20:43:48 +0100 Subject: [PATCH 12/12] Clearing profile.php will remake soon --- profile.php | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/profile.php b/profile.php index 1636266..71ac284 100644 --- a/profile.php +++ b/profile.php @@ -19,26 +19,5 @@ if (empty($profile)) { ]; } -$avatar = "/assets/default.png"; -$display_name = ""; - -if ($_SESSION['id'] != $profile['id']) { - $avatar = get_avatar_url($profile['id']); - if ($profile['public_display_name']) { - $display_name = get_display_name($profile['id'], false); - } -} else { - $avatar = get_avatar_url($profile['id']); - $display_name = get_display_name($profile['id'], false); -} - -// Get badges owned by this person -$badges = db_execute_all('SELECT * FROM badge_owners INNER JOIN badges b on badge_owners.badge_id = b.id WHERE owner_id = ?; ', [$profile['id']]); -if (!empty($badges)) { - if (!array_is_list($badges)) { - $badges = array (0 => $badges); - } -} - ?>