From d8c35856de53f9b9786fa6f8192d58329ea8e68f Mon Sep 17 00:00:00 2001 From: trinkey Date: Thu, 27 Mar 2025 13:06:13 -0400 Subject: [PATCH] admin page + invite codes --- TODO.md | 2 - admin.php | 72 +++++++++++++++++++++++++++++++ config.php | 6 ++- index.php | 11 ++++- lang/en-US.json | 16 ++++++- login.php | 4 +- logout.php | 5 +++ signup.php | 112 +++++++++++++++++++++++++++++++----------------- 8 files changed, 180 insertions(+), 48 deletions(-) create mode 100644 admin.php create mode 100644 logout.php diff --git a/TODO.md b/TODO.md index 902a136..c5965a3 100644 --- a/TODO.md +++ b/TODO.md @@ -1,3 +1 @@ - account deletion -- admin page - - invite codes diff --git a/admin.php b/admin.php new file mode 100644 index 0000000..2cb7f4d --- /dev/null +++ b/admin.php @@ -0,0 +1,72 @@ + generate_id()) + ); + } else { + $err = $lang["errors"]["intent"]; + } +} else if ($_GET["del"]) { + $del_type = explode("-", $_GET["del"])[0]; + $del_id = explode("-", $_GET["del"])[1]; + + if (strlen($del_id) === 64 && preg_match("/^[a-f0-9]{64}$/", $del_id) && $del_type === "invite") { + pg_delete( + $db, "invites", + array( + "id" => $del_id + ) + ); + } +} + +$title = $lang["admin"]["title"]; +include "boilerplate/head.php"; + +?> + +
+

+ {$lang['admin']['invite']['disabled']}"; + } + ?> + + +
+ + "> +
+
+ + diff --git a/config.php b/config.php index 190e1dd..a66f99d 100644 --- a/config.php +++ b/config.php @@ -5,7 +5,7 @@ $site_name = "Todo List Manager"; $signups = "invite"; // true, false, "invite" - treats it as true if no users currently exist, invite requires an admin to invite the user $language = "en-US"; // an item from the lang folder. exclude the ".json" -$admin_users = array( +$admin_users = array("trinkey" // "username1", "username2", ... ); @@ -39,4 +39,8 @@ $default_schema = array( ) ); +if ($signups !== true and pg_fetch_array(pg_query($db, "SELECT count(*) FROM users LIMIT 1;")) === "0") { + $signups = true; +} + ?> diff --git a/index.php b/index.php index 2f82807..a6d089f 100644 --- a/index.php +++ b/index.php @@ -12,7 +12,7 @@ if ($user === false) { $q = "SELECT count(*) FROM users LIMIT 1;"; - if ($signups !== false || ($signups === false && pg_fetch_array(pg_query($db, $q))["count"] !== 0)) { + if ($signups !== false) { echo " - {$lang['account']['sign_up']}"; } @@ -433,7 +433,14 @@ foreach ($sections as $section) { -

+

+ + {$lang['admin']['title']}"; + } + ?> +

diff --git a/lang/en-US.json b/lang/en-US.json index 4b65249..36e4e1d 100644 --- a/lang/en-US.json +++ b/lang/en-US.json @@ -12,13 +12,15 @@ "user_exists": "User '%u' already exists", "incorrect_password": "Incorrect password", "password_match": "Passwords don't match", - "password_changed": "Password changed" + "password_changed": "Password changed", + "invalid_invite": "Invalid invite code" }, "log_in": "Log In", "log_in_instead": "Log in instead?", "sign_up": "Sign Up", "sign_up_instead": "Sign up instead?", + "invite": "Invite code", "username": "Username", "password": "Password", "verify": "Verify password" @@ -114,5 +116,17 @@ "title": "More options...", "source_code": "Source code" + }, + + "admin": { + "invite": { + "title": "Invite Codes", + "disabled": "Invite codes are not required to sign up", + "delete": "Delete", + "none": "None", + "new": "Generate new code" + }, + + "title": "Admin Panel" } } diff --git a/login.php b/login.php index ac5c287..6d7b16b 100644 --- a/login.php +++ b/login.php @@ -55,9 +55,7 @@ {$lang['account']['sign_up_instead']}

"; } diff --git a/logout.php b/logout.php new file mode 100644 index 0000000..6fe1170 --- /dev/null +++ b/logout.php @@ -0,0 +1,5 @@ + diff --git a/signup.php b/signup.php index d24cdcd..10c40fb 100644 --- a/signup.php +++ b/signup.php @@ -2,6 +2,11 @@ include "config.php"; include "helper.php"; + if ($signups === false) { + http_response_code(404); + exit(); + } + if (is_logged_in()) { header("Location: index.php"); exit(); @@ -30,50 +35,74 @@ $c = pg_fetch_array($response)["count"]; if ($c === "0") { - $user_id = generate_id(); - $pw_hash = password_hash($p, PASSWORD_DEFAULT); - $user_parameters = array( - "id" => $user_id, - "username" => $u, - "password_hash" => $pw_hash, - "enable_colors" => true, - "yellow_threshold" => 2, - "gray_threshold" => 60 - ); + $allow_signup = true; + if ($signups === "invite") { + $invite_code = $_POST["invite"]; - pg_insert($db, "users", $user_parameters); + if (strlen($invite_code) !== 64 || !preg_match("/^[a-f0-9]{64}$/", $invite_code)) { + $allow_signup = false; + $err = $lang["account"]["errors"]["invalid_invite"]; + } else { + $q = "SELECT count(*) FROM invites WHERE id='$invite_code' LIMIT 1;"; + $invite_valid = pg_fetch_array(pg_query($db, $q))["count"] === "1"; + echo json_encode(pg_fetch_array(pg_query($db, $q))); - foreach ($default_schema as $section_id => $section_data) { - $section_id = generate_id(); - $section_parameters = array( - "id" => $section_id, - "users" => $user_id, - "name" => $section_data["name"], - "show_subtitle" => $section_data["show_subtitle"] - ); - - pg_insert($db, "section", $section_parameters); - - foreach ($section_data["items"] as $row_id => $row_data) { - $row_id = generate_id(); - $row_parameters = array( - "id" => $row_id, - "section" => $section_id, - "name" => $row_data["name"], - "display_format" => $row_data["display_format"] - ); - - pg_insert($db, "row", $row_parameters); + if (!$invite_valid) { + $allow_signup = false; + $err = $lang["account"]["errors"]["invalid_invite"]; + } else { + $q = "DELETE FROM invites WHERE id='$invite_code';"; + pg_query($db, $q); + } } } - $token = get_token($u, $pw_hash); - setcookie( - "token", $token, - time() + 60 * 60 * 24 * 365 // 1 year from now - ); - header("Location: index.php"); - exit(); + if ($allow_signup) { + $user_id = generate_id(); + $pw_hash = password_hash($p, PASSWORD_DEFAULT); + $user_parameters = array( + "id" => $user_id, + "username" => $u, + "password_hash" => $pw_hash, + "enable_colors" => true, + "yellow_threshold" => 2, + "gray_threshold" => 60 + ); + + pg_insert($db, "users", $user_parameters); + + foreach ($default_schema as $section_id => $section_data) { + $section_id = generate_id(); + $section_parameters = array( + "id" => $section_id, + "users" => $user_id, + "name" => $section_data["name"], + "show_subtitle" => $section_data["show_subtitle"] + ); + + pg_insert($db, "section", $section_parameters); + + foreach ($section_data["items"] as $row_id => $row_data) { + $row_id = generate_id(); + $row_parameters = array( + "id" => $row_id, + "section" => $section_id, + "name" => $row_data["name"], + "display_format" => $row_data["display_format"] + ); + + pg_insert($db, "row", $row_parameters); + } + } + + $token = get_token($u, $pw_hash); + setcookie( + "token", $token, + time() + 60 * 60 * 24 * 365 // 1 year from now + ); + header("Location: index.php"); + exit(); + } } else { $err = str_replace("%u", htmlspecialchars($u), $lang["account"]["errors"]["user_exists"]); } @@ -88,6 +117,11 @@
" name="username" value="" maxlength="64" required>
" name="password" type="password" value="" required>
" name="verify" type="password" required>
+ "; + } + ?>
">