From 5a063e661c2fd6a9f91576bd044c3afcf227214b Mon Sep 17 00:00:00 2001
From: Bye
Date: Mon, 6 Nov 2023 16:38:18 +0000
Subject: [PATCH] forgot to push whoops
---
account.php | 132 ++++++++++++++++++++++++++++++++++++
admin_accounts.php | 36 ++++++++++
admin_initdatabase.php | 51 ++++++++++++++
db.php | 0
forgot_password.php | 31 +++++++++
header.php | 26 ++++++-
id.sql | 3 +-
id_handler.php | 22 +++---
index.php | 60 ++++++++++------
landing.html => landing.php | 8 ++-
register.php | 56 ---------------
signin.php | 56 +++++++++++++++
signinas.php | 12 ++++
signout.php | 8 +++
signup.php | 46 +++++++++++++
strings.php | 16 +++++
styles/colours.css | 77 +++++++++++++++++++++
styles/design.css | 17 +++++
styles/global.css | 4 +-
styles/layout.css | 63 ++++++++++++++++-
styles/types.css | 24 +++++++
time_handler.php | 47 +++++++++++++
22 files changed, 699 insertions(+), 96 deletions(-)
create mode 100644 account.php
create mode 100644 admin_accounts.php
create mode 100644 admin_initdatabase.php
create mode 100644 db.php
create mode 100644 forgot_password.php
rename landing.html => landing.php (55%)
delete mode 100644 register.php
create mode 100644 signin.php
create mode 100644 signinas.php
create mode 100644 signout.php
create mode 100644 signup.php
create mode 100644 strings.php
create mode 100644 time_handler.php
diff --git a/account.php b/account.php
new file mode 100644
index 0000000..4812057
--- /dev/null
+++ b/account.php
@@ -0,0 +1,132 @@
+prepare('SELECT * FROM accounts WHERE id = ? LIMIT 1');
+$stmt->execute([$_SESSION['id']]);
+$user = $stmt->fetch();
+
+
+if ($_SERVER['REQUEST_METHOD'] == "POST") {
+
+ if (isset($_POST["old_password"]) && $_POST["old_password"] != "") {
+ // means password reset is wanted.
+
+ if (!password_verify($_POST["old_password"], $user["password"])) {
+ $password_error = "Incorrect password. (Error 901)";
+ }
+
+ if (password_verify($_POST['new_password'], $user["password"])) {
+ $password_error = "New password may not be same as old password. (Error 902)";
+ }
+
+ if ($_POST['new_password'] != $_POST['repeat_new_password']) {
+ $password_error = "The passwords must match. (Error 900)";
+ }
+
+
+ if (isset($password_error)) {
+ $message = $password_error;
+ goto skip_submit;
+ }
+
+ $new_password = password_hash($_POST["new_password"], PASSWORD_DEFAULT);
+
+ $sql = "UPDATE accounts SET password = ? WHERE id = ?";
+ $pdo->prepare($sql)->execute([$new_password, $user["id"]]);
+ }
+
+ if (isset($_POST["display_name"])) {
+ $sql = "UPDATE accounts SET display_name = ? WHERE id = ?";
+ $pdo->prepare($sql)->execute([$_POST["display_name"], $user["id"]]);
+ }
+
+ $message = "Updated sucessfully. Changes might take a few minutes to take effect.";
+
+}
+
+skip_submit:
+
+?>
+
+Your account
+
+".$message."";
+ }
+?>
+
+
+
+
+ = $user['display_name'] ?>
+ = format_bcid($user['id']); ?>
+
+
+
+
+
+
+
+
diff --git a/admin_accounts.php b/admin_accounts.php
new file mode 100644
index 0000000..483fcf7
--- /dev/null
+++ b/admin_accounts.php
@@ -0,0 +1,36 @@
+");
+}
+
+$sql = "SELECT * FROM accounts";
+$result = $pdo-> query($sql);
+if (!$result) {
+ http_response_code(500);
+ die("");
+}
+
+
+$count_req = $pdo->query("SELECT COUNT(*) FROM accounts");
+$count = $count_req->fetchColumn();
+
+
+?>
+
+Admin
+Accounts
+
+There is currently = $count ?> accounts registered.
+
+
+";
+ print_r($row);
+ echo "
Sign in as ".$row['display_name']."";
+ }
+ ?>
+
diff --git a/admin_initdatabase.php b/admin_initdatabase.php
new file mode 100644
index 0000000..4ff1220
--- /dev/null
+++ b/admin_initdatabase.php
@@ -0,0 +1,51 @@
+");
+}
+
+if ($_SERVER["REQUEST_METHOD"] == "POST") {
+ if ($_POST['init'] == 'Init') {
+ echo("
Initialising DB...");
+ $pdo = new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD, PDO_OPTIONS);
+ echo "
Create table `accounts`";
+ $stmt = $pdo->prepare('CREATE TABLE `accounts` (
+ `id` tinytext NOT NULL,
+ `email` text NOT NULL,,
+ `display_name` text NULL,
+ `password` text NOT NULL,
+ `verified` tinyint(1) NOT NULL
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;');
+
+ try {
+ $stmt->execute();
+ } catch (PDOException $e) {
+ echo('
An error occurred: '. $e->getMessage() .'. Will skip. (Most likely the table already exists.)');
+ }
+
+ echo '
Set indexes for table `accounts`';
+ $stmt = $pdo->prepare('ALTER TABLE `accounts`
+ ADD PRIMARY KEY (`id`(7)),
+ ADD UNIQUE KEY `email` (`email`) USING HASH;');
+
+ try {
+ $stmt->execute();
+ } 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/db.php b/db.php
new file mode 100644
index 0000000..e69de29
diff --git a/forgot_password.php b/forgot_password.php
new file mode 100644
index 0000000..15ced1a
--- /dev/null
+++ b/forgot_password.php
@@ -0,0 +1,31 @@
+
+prepare($sql);
+ $stmt->execute([$_POST['email']]);
+ $user = $stmt->fetch();
+
+ if ($user != null) { // account exists
+ mail($user['email'], "ByeCorps ID Password Reset Confirmation", "The email was sent!");
+ }
+}
+
+?>
+
+Forgot password
+
+".$message."
"; ?>
+
+Forgot your password? We'll send you an email to reset it.
+
+
\ No newline at end of file
diff --git a/header.php b/header.php
index c9ea57e..7cae72e 100644
--- a/header.php
+++ b/header.php
@@ -1,5 +1,25 @@
+prepare($sql);
+ $stmt->execute([$_SESSION['id']]);
+ $name = $stmt->fetchColumn();
+}
+
+if ($name == '') {
+ $name = ''.format_bcid($_SESSION['id']).'
';
+}
+
+skip_auth:
+
+?>
+
@@ -8,8 +28,12 @@
ByeCorps ID
\ No newline at end of file
diff --git a/id.sql b/id.sql
index c1a24cd..86a603a 100644
--- a/id.sql
+++ b/id.sql
@@ -30,7 +30,8 @@ SET time_zone = "+00:00";
CREATE TABLE `accounts` (
`id` tinytext NOT NULL COMMENT 'BCID',
`email` text NOT NULL,
- `password` text NOT NULL COMMENT 'Hashed!!!',
+ `display_name` text NULL,
+ `password` text NOT NULL,
`verified` tinyint(1) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
diff --git a/id_handler.php b/id_handler.php
index 01615cd..ac66b35 100644
--- a/id_handler.php
+++ b/id_handler.php
@@ -1,6 +1,6 @@
";
-echo "Random BCID (unformatted): $BCID
-";
-echo "Check if BCID is valid: ".validate_bcid($BCID)."
-";
+ if (!validate_bcid($stripped_bcid)) {
+ throw new Exception('Invalid BCID.');
+ }
-if ($query['bcid']) {
- echo "BCID provided in the query: ".$query['bcid']."
-";
- echo "Checking the BCID provided in the query: ".validate_bcid($query['bcid'])."
-";
+ return substr($stripped_bcid, 0, 3).'-'.substr($stripped_bcid, -4, 4);
}
+
+$BCID = generate_bcid();
?>
\ No newline at end of file
diff --git a/index.php b/index.php
index f2f3bed..5bb9cda 100644
--- a/index.php
+++ b/index.php
@@ -3,12 +3,22 @@
session_start();
include("config.php");
+include("id_handler.php");
+include("time_handler.php");
+
+function does_variable_exists( $variable ) {
+ return (isset($$variable)) ? "true" : "false";
+}
$host_string = $_SERVER['HTTP_HOST'];
$host = explode('.', $host_string);
$uri_string = $_SERVER['REQUEST_URI'];
$query_string = explode('?', $uri_string);
$path = $query_string[0];
+if (str_ends_with($path,'/') && $path != "/") {
+ header('Location: '.substr($path,0, -1));
+ exit;
+}
$uri = array_values(array_filter(explode('/', $uri_string)));
if(isset($query_string[1])) {
@@ -21,30 +31,33 @@ if(isset($query_string[1])) {
}
}
else {
- $query = array();
+ $query = array();
}
+$pdo = new PDO(DB_DSN, DB_USERNAME, DB_PASSWORD, PDO_OPTIONS);
+
$include = "404.html";
-
// routing
-if (!$uri) {
- // empty array means index
- $include = "landing.html";
-}
-else if ($path == "/signin") {
- $doc_title = "Sign in";
- include("signin.php");
- exit;
-}
-else if ($path == "/register") {
- $doc_title = "Register";
- include("register.php");
- exit;
-}
-else if ($path == "/tests/id") {
- include("id_handler.php");
- exit;
+
+$paths = array(
+ "/" => ["landing.php"],
+ "/admin/init/database" => ["admin_initdatabase.php"],
+ "/admin/accounts" => ["admin_accounts.php"],
+ "/account" => ["account.php", "Your account"],
+ "/signin" => ["signin.php", "Sign in"],
+ "/signup" => ["signup.php", "Sign up"],
+ "/signout" => ["signout.php", "Signed out"],
+ "/forgot_password" => ["forgot_password.php", "Forgot password"],
+ "/admin/signinas" => ["signinas.php"]
+);
+
+if (isset($paths[$path])) {
+ $include = $paths[$path][0];
+ if (isset($paths[$path][1])) {
+ $doc_title = $paths[$path][1];
+ }
}
+
else {
$doc_title = "404";
http_response_code(404);
@@ -60,7 +73,14 @@ else {
-
+ ");
+ }
+
+ include($include); ?>
diff --git a/landing.html b/landing.php
similarity index 55%
rename from landing.html
rename to landing.php
index 6ad7729..c60788c 100644
--- a/landing.html
+++ b/landing.php
@@ -3,7 +3,11 @@
ByeCorps ID
Log into ByeCorps and beyond with a single ID.
- Sign in
- Create an account
+
+ Manage account"; }
+ else { echo "Sign inCreate an account"; }
+ ?>
+
\ No newline at end of file
diff --git a/register.php b/register.php
deleted file mode 100644
index eb8ce98..0000000
--- a/register.php
+++ /dev/null
@@ -1,56 +0,0 @@
-setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
- $sql = "INSERT INTO `accounts` (`email`, `password`, `verified`) VALUES ('$email', '$password', '0')";
- try{
- $stmt = $conn->prepare($sql);
- $stmt->execute($query);
- $result = $stmt->fetch();
- echo "Failed successfully: $result";
- } catch (PDOException $e) {
- http_response_code(500);
- die("An error occured: $e");
- }
- }
- catch(PDOException $e) {
- die ("Connection failed: " . $e->getMessage());
- }
- echo '';
- print_r($_POST);
-
- exit;
-}
-
-?>
-
-
-
-
-
-
-
-
-
- Sign in
-
-
-
-
-
\ No newline at end of file
diff --git a/signin.php b/signin.php
new file mode 100644
index 0000000..03614f1
--- /dev/null
+++ b/signin.php
@@ -0,0 +1,56 @@
+prepare($sql);
+ $stmt->execute(array("email"=> $email));
+ $user = $stmt->fetch();
+ }
+ catch (PDOException $e) {
+ die ("Something happened: ". $e->getMessage());
+ }
+
+ if (password_verify($password, $user["password"])) {
+ $_SESSION["id"] = $user["id"];
+ $_SESSION["auth"] = true;
+ if (isset($query['callback'])) {
+ header("Location: ".$query['callback']);
+ } else {
+ header("Location: /account");
+ }
+
+ exit;
+ } else {
+ $message = "Email or password incorrect.";
+ }
+}
+
+?>
+
+
+Sign in to ByeCorps ID
+$message";
+}?>
+
+
+
+ New? Register for a ByeCorps ID.
+
\ No newline at end of file
diff --git a/signinas.php b/signinas.php
new file mode 100644
index 0000000..d31fbfc
--- /dev/null
+++ b/signinas.php
@@ -0,0 +1,12 @@
+");
+}
+
+$_SESSION['id'] = $query['id'];
+
+header ('Location: /account');
+
+?>
\ No newline at end of file
diff --git a/signout.php b/signout.php
new file mode 100644
index 0000000..fb565e5
--- /dev/null
+++ b/signout.php
@@ -0,0 +1,8 @@
+
+
+You've been signed out successfully. You may close the page.
+Sign back in ~ Go to home
diff --git a/signup.php b/signup.php
new file mode 100644
index 0000000..9d70fca
--- /dev/null
+++ b/signup.php
@@ -0,0 +1,46 @@
+prepare($sql);
+ $stmt->execute([$BCID, $email, $password, 0]);
+ $result = $stmt->fetch();
+ echo "Failed successfully: $result";
+ } catch (PDOException $e) {
+ http_response_code(500);
+ die("An error occured: $e");
+ }
+ }
+ catch(PDOException $e) {
+ die ("Connection failed: " . $e->getMessage());
+ }
+
+ $_SESSION["auth"] = true;
+ $_SESSION["id"] = $BCID;
+
+ exit;
+}
+
+?>
+
+Sign up for ByeCorps ID
+
\ No newline at end of file
diff --git a/strings.php b/strings.php
new file mode 100644
index 0000000..c0cc8c0
--- /dev/null
+++ b/strings.php
@@ -0,0 +1,16 @@
+ "Message"
+
+ // XX errors are generic messages
+
+ // 9XX errors are user error
+ "900" => "Sorry, those passwords don't match. Please try again.",
+ "901" => "Incorrect password. Please check your spelling and try again."
+
+]
+
+?>
\ No newline at end of file
diff --git a/styles/colours.css b/styles/colours.css
index 2d91167..61ee275 100644
--- a/styles/colours.css
+++ b/styles/colours.css
@@ -13,14 +13,31 @@
--flax: #efdd8d;
--mindaro: #f4fdaf;
+ /* open colors: used for debugging */
+ --red-5: #ff6b6b;
+ --red-5-transparent: #ff6b6b3a;
+ --red-8: #e03131;
+ --green-5: #51cf66;
+ --green-8: #2f9e44;
+
color-scheme: light dark;
}
+button, .button {
+ background-color: #1f302b40;
+ color: var(--white);
+}
+
button.primary, .button.primary {
color: var(--black-bean);
background-color: var(--flax);
}
+button.danger, .button.danger {
+ color: var(--white);
+ background-color: var(--red-5);
+}
+
header {
background-color: var(--flax);
color: var(--dark-slate-gray);
@@ -30,6 +47,49 @@ header a {
color: var(--dark-slate-gray);
}
+input {
+ all: unset;
+ padding: 1em;
+ text-align: start;
+
+ border-radius: 1em;
+
+ background-color: #c0c0c077;
+}
+
+input[data-com-onepassword-filled="light"] {
+ background-color: var(--byecorps-white) !important;
+}
+
+input[data-com-onepassword-filled="dark"] {
+ background-color: var(--byecorps-blue) !important;
+}
+
+.icon-true {
+ color: var(--green-8);
+}
+
+.icon-false {
+ color: var(--red-8);
+}
+
+.dangerzone {
+ background-color: var(--red-5-transparent);
+ color: var(--white);
+
+ padding: 0.5rem 1em;
+ border-radius: 1em;
+
+}
+
+.dangerzone h2 {
+ margin: 0;
+}
+
+.dangerzone p {
+ margin: 0;
+}
+
@media screen and (prefers-color-scheme: dark) {
button.primary, .button.primary {
color: var(--flax);
@@ -44,4 +104,21 @@ header a {
header a {
color: var(--flax);
}
+
+ input {
+
+ background-color: #2c2c2c77;
+ }
+
+ .icon-true {
+ color: var(--green-5);
+ }
+
+ .icon-false {
+ color: var(--red-5);
+ }
+
+ a, a:visited, a:link {
+ color: var(--flax);
+ }
}
\ No newline at end of file
diff --git a/styles/design.css b/styles/design.css
index 7de58d3..27cc92b 100644
--- a/styles/design.css
+++ b/styles/design.css
@@ -28,3 +28,20 @@ input {
border-radius: 1em;
}
+
+input[type="checkbox"] {
+ -webkit-appearance: checkbox;
+ -moz-appearance: checkbox;
+ -ms-appearance: checkbox;
+ -o-appearance: checkbox;
+ appearance: checkbox;
+
+ width: 1em;
+ height: 1em;
+ margin: 0 0.5em 0 0;
+}
+
+input:disabled {
+ opacity: 0.75;
+ cursor: not-allowed;
+}
diff --git a/styles/global.css b/styles/global.css
index 59f2674..379b764 100644
--- a/styles/global.css
+++ b/styles/global.css
@@ -3,10 +3,8 @@
@import url(./layout.css);
@import url(./colours.css);
-:root {
- color-scheme: light dark;
-}
* {
box-sizing: border-box;
+
}
diff --git a/styles/layout.css b/styles/layout.css
index 7d0829c..6e4f2b4 100644
--- a/styles/layout.css
+++ b/styles/layout.css
@@ -33,6 +33,7 @@ header .end {
}
main {
+ height: 100%;
flex: 1;
padding: 1rem 1rem;
}
@@ -47,10 +48,69 @@ footer {
gap: 1rem;
}
+fieldset {
+
+ border: #c0c0c0c0 1px solid;
+ border-radius: calc(1em + 10px);
+
+ padding: 10px 10px 5px 10px;
+}
+
+legend {
+ font-size: 1.25rem;
+ font-weight: 600;
+}
+
+form:has(fieldset) {
+
+ /* fit two fieldsets side by side */
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 1rem;
+
+
+}
+
+form:has(fieldset) > button[type="submit"] {
+ /* align the button to the right */
+ grid-column: span 2;
+}
+
+form .container {
+ /* contains a label and an input */
+ display: flex;
+ flex-direction: column;
+ gap: 0.25rem;
+ padding-bottom: 5px;
+}
+
+form .container:has(input[type="checkbox"]) {
+ flex-direction: row;
+}
+
+form .container label {
+ font-size: 0.9rem;
+ opacity: 0.5;
+}
+
+form .container:has(input[type="checkbox"]) label {
+ margin-left: 0.5em;
+ opacity: 1;
+ font-size: 1rem;
+}
+
footer h2 {
margin: 0;
}
+form {
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+}
+
+
+
.hero {
display: flex;
flex-direction: column;
@@ -66,4 +126,5 @@ footer h2 {
.accountnav {
display: flex;
gap: 1rem;
-}
\ No newline at end of file
+}
+
diff --git a/styles/types.css b/styles/types.css
index 6fce88f..83ae2a8 100644
--- a/styles/types.css
+++ b/styles/types.css
@@ -1,6 +1,8 @@
/* 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(/fontawesome/css/all.css);
html {
@@ -10,6 +12,16 @@ html {
-moz-osx-font-smoothing: grayscale;
}
+h2.subheading {
+ font-weight: 500;
+ font-size: 1.5rem;
+ margin-bottom: 0;
+}
+
+h2.subheading + h1 {
+ margin-top: 0;
+}
+
.bc-1 {
font-weight: 700;
}
@@ -22,6 +34,18 @@ html {
font-weight: 400;
}
+.bcid {
+ font-family: 'Courier Prime', monospace;
+}
+
.center {
text-align: center;
}
+
+.icon-true::before {
+ content: "\f00c";
+}
+
+.icon-false::before {
+ content: "\f00d";
+}
diff --git a/time_handler.php b/time_handler.php
new file mode 100644
index 0000000..cae9b56
--- /dev/null
+++ b/time_handler.php
@@ -0,0 +1,47 @@
+ 0)
+ {
+ $day_diff = floor($diff / 86400);
+ if($day_diff == 0)
+ {
+ if($diff < 60) return 'just now';
+ if($diff < 120) return '1 minute ago';
+ if($diff < 3600) return floor($diff / 60) . ' minutes ago';
+ if($diff < 7200) return '1 hour ago';
+ if($diff < 86400) return floor($diff / 3600) . ' hours ago';
+ }
+ if($day_diff == 1) return 'Yesterday';
+ if($day_diff < 7) return $day_diff . ' days ago';
+ if($day_diff < 31) return ceil($day_diff / 7) . ' weeks ago';
+ if($day_diff < 60) return 'last month';
+ return date('F Y', $ts);
+ }
+ else
+ {
+ $diff = abs($diff);
+ $day_diff = floor($diff / 86400);
+ if($day_diff == 0)
+ {
+ if($diff < 120) return 'in a minute';
+ if($diff < 3600) return 'in ' . floor($diff / 60) . ' minutes';
+ if($diff < 7200) return 'in an hour';
+ if($diff < 86400) return 'in ' . floor($diff / 3600) . ' hours';
+ }
+ if($day_diff == 1) return 'Tomorrow';
+ if($day_diff < 4) return date('l', $ts);
+ if($day_diff < 7 + (7 - date('w'))) return 'next week';
+ if(ceil($day_diff / 7) < 4) return 'in ' . ceil($day_diff / 7) . ' weeks';
+ if(date('n', $ts) == date('n') + 1) return 'next month';
+ return date('F Y', $ts);
+ }
+}
+
+?>
\ No newline at end of file