From 10702cef414eec6611086117565d565f8c35e8ee Mon Sep 17 00:00:00 2001 From: bye <bye@byecorps.com> Date: Wed, 29 May 2024 18:33:57 +0100 Subject: [PATCH] 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 @@ </li> </ul> +<h2>API</h2> +<ul> + <li><a href="/admin/create/token">Token generator</a></li> +</ul> + <h2>Init</h2> <ul> <li> 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(); <ul> <?php foreach ($result as $row) { - echo "<li><pre>"; - print_r($row); - echo "</pre><p><a href='/admin/signinas?id=".$row['id']."'>Sign in as ".$row['display_name']."</a></li>"; + echo "<li>"; + echo $row['id']; + echo "<p><a href='/admin/signinas?id=".$row['id']."'>Sign in as ".htmlspecialchars($row['display_name'])."</a></li>"; } ?> </ul> 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 @@ +<?php + +if ($_SERVER["REQUEST_METHOD"] == "POST") { + echo "<pre>"; + print_r($_POST); + echo "</pre>"; + + $token = generate_token($_POST['owner'], $_POST['application'], $_POST['permissions']); + + echo "<p>Created token. Access token: <code>". $token['access'] ."</code></p>"; +} + +?> + +<h1>Token generator</h1> + +<form method="post"> + <div class="container"> + <label for="owner">Token owner</label> + <select name="owner" required id="owner"> + <?php + $users = db_query("SELECT * FROM accounts"); + foreach ($users as $row) { + echo "<option value='".$row['id']."'>".get_display_name($row['id'])." (".$row['id'].") </option>"; + } + ?> + </select> + </div> + <div class="container"> + <label for="app">Token app</label> + <select name="app" id="app"> + <option value="null">None</option> + <?php + $users = db_query("SELECT * FROM apps"); + foreach ($users as $row) { + echo "<option value='".$row['id']."'>". $row['title'] ."</option>"; + } + ?> + </select> + </div> + + <input type="hidden" id="permissions" name="permissions" value="0" /> + + <h2>Permissions</h2> + <p>Permission number: <span id="permissionnumber"></span></p> + <div class="checkboxes container"> + <input type="checkbox" id="account.email" value="1" /><label for="account.email"><code>account.email</code></label> + <input type="checkbox" id="account.settings" value="2" /><label for="account.settings"><code>account.settings</code></label> + </div> + + <button type="submit">Generate!</button> +</form> + +<style> + form .container { + display: unset; + } +</style> + +<script> + const displayNumber = document.getElementById("permissionnumber"); + const permissionsInput = document.getElementById("permissions"); + const checkboxes = document.querySelectorAll("input[type='checkbox']"); + + console.log(checkboxes); + + function updateCheckboxes() { + let permissions = 0; + + for (let checkbox of checkboxes) { + if (checkbox.checked) { + permissions += Number(checkbox.value); + } + } + + displayNumber.innerText = permissions.toString(); + permissionsInput.value = permissions; + } + + for (let checkbox of checkboxes) { + checkbox.onchange = updateCheckboxes; + } + + updateCheckboxes(); + +</script> 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 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + width="300.858" + height="50" + viewBox="0 0 79.602012 13.229167" + version="1.1" + id="svg1" + xml:space="preserve" + inkscape:export-filename="bitmap.png" + inkscape:export-xdpi="192" + inkscape:export-ydpi="192" + inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)" + sodipodi:docname="bcidsignin.svg" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview + id="namedview1" + pagecolor="#ffffff" + bordercolor="#000000" + borderopacity="0.25" + inkscape:showpageshadow="true" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="true" + inkscape:deskcolor="#d1d1d1" + inkscape:document-units="px" + showborder="false" + labelstyle="default" + inkscape:zoom="2.8649832" + inkscape:cx="165.446" + inkscape:cy="-36.300388" + inkscape:window-width="1920" + inkscape:window-height="1008" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + inkscape:current-layer="layer2" /><defs + id="defs1" /><g + inkscape:groupmode="layer" + id="layer2" + inkscape:label="Layer 2"><rect + style="display:inline;opacity:1;fill:#efdd8d;fill-opacity:1;stroke:#dcc455;stroke-width:0.261525;stroke-dasharray:none;stroke-opacity:1" + id="rect35" + width="79.340492" + height="12.967643" + x="0.13076229" + y="0.13076213" + ry="2.0748229" + rx="2.1097128" + inkscape:label="Background" /><g + style="shape-rendering:crispEdges" + id="g32" + transform="matrix(0.52916667,0,0,0.52916667,9.5250001,3.7041667)" + inkscape:label="BCID person"><g + id="layer1-5" + inkscape:label="BCID logo"><g + id="g27" + inkscape:label="Body" + style="opacity:1"><path + id="rect26" + style="opacity:1;fill:#000000;fill-opacity:1" + d="M 1.0058594,6.5 C 1.0026133,6.5 1,6.5026133 1,6.5058594 V 7.4941406 C 1,7.4973867 1.0026133,7.5 1.0058594,7.5 H 0.00585938 C 0.00261328,7.5 0,7.5026133 0,7.5058594 V 11.494141 C 0,11.497387 0.00261328,11.5 0.00585938,11.5 H 7.9941406 C 7.9973867,11.5 8,11.497387 8,11.494141 V 7.5058594 C 8,7.5026133 7.9973867,7.5 7.9941406,7.5 h -1 C 6.9973867,7.5 7,7.4973867 7,7.4941406 V 6.5058594 C 7,6.5026133 6.9973867,6.5 6.9941406,6.5 Z" + inkscape:label="Body" /></g><g + id="g31" + inkscape:label="Head"><path + id="rect28" + style="opacity:1;fill:#000000;fill-opacity:1" + d="M 1.0058594,-0.5 C 1.0026133,-0.5 1,-0.49738672 1,-0.49414062 V 0.49414062 C 1,0.49738672 1.0026133,0.5 1.0058594,0.5 H 1.9941406 C 1.9973867,0.5 2,0.49738672 2,0.49414062 V -0.49414062 C 2,-0.49738672 1.9973867,-0.5 1.9941406,-0.5 Z m 2,0 C 3.0026133,-0.5 3,-0.49738672 3,-0.49414062 V 0.49414062 C 3,0.49738672 3.0026133,0.5 3.0058594,0.5 H 4.9941406 C 4.9973867,0.5 5,0.49738672 5,0.49414062 V -0.49414062 C 5,-0.49738672 4.9973867,-0.5 4.9941406,-0.5 Z m -1,1 C 2.0026133,0.5 2,0.50261328 2,0.50585938 V 1.4941406 C 2,1.4973867 2.0026133,1.5 2.0058594,1.5 h -1 C 1.0026133,1.5 1,1.5026133 1,1.5058594 V 5.4941406 C 1,5.4973867 1.0026133,5.5 1.0058594,5.5 H 6.9941406 C 6.9973867,5.5 7,5.4973867 7,5.4941406 V 1.5058594 C 7,1.5026133 6.9973867,1.5 6.9941406,1.5 h -4 C 2.9973867,1.5 3,1.4973867 3,1.4941406 V 0.50585938 C 3,0.50261328 2.9973867,0.5 2.9941406,0.5 Z" + inkscape:label="Head" /></g></g></g><g + id="text32" + style="font-weight:500;font-size:4.58611px;font-family:Montserrat;-inkscape-font-specification:'Montserrat, Medium';letter-spacing:-0.079375px;word-spacing:0.0926042px;stroke-width:0;stroke-miterlimit:8.7" + inkscape:label="Sign in" + transform="scale(0.95030748,1.052291)" + aria-label="Sign in with ByeCorps ID"><path + style="font-weight:normal;-inkscape-font-specification:'Montserrat, Normal';opacity:1" + d="m 19.328294,7.9399255 c 0.820914,0 1.196975,-0.4035777 1.196975,-0.875947 0,-1.1694581 -1.976613,-0.6374693 -1.976613,-1.5180025 0,-0.3210277 0.261408,-0.582436 0.84843,-0.582436 0.284339,0 0.605367,0.087136 0.880533,0.2659944 L 20.392272,4.9589539 C 20.13545,4.7800956 19.759389,4.6746151 19.397086,4.6746151 c -0.816327,0 -1.183216,0.4081638 -1.183216,0.8805331 0,1.1878025 1.976613,0.6466416 1.976613,1.5271747 0,0.3164416 -0.261408,0.5686777 -0.862189,0.5686777 -0.421922,0 -0.830085,-0.1651 -1.059391,-0.3898194 l -0.132997,0.2614083 c 0.238478,0.2476499 0.710847,0.417336 1.192388,0.417336 z m 1.952271,-2.9672133 c 0.137584,0 0.238478,-0.1054805 0.238478,-0.2384777 0,-0.123825 -0.105481,-0.2247194 -0.238478,-0.2247194 -0.132997,0 -0.238477,0.1054806 -0.238477,0.2293055 0,0.1284111 0.10548,0.2338916 0.238477,0.2338916 z m 0.160514,2.9396966 V 5.5001149 H 21.115465 V 7.9124088 Z M 24.19133,5.963312 C 23.989541,5.6468704 23.640997,5.4817705 23.237419,5.4817705 c -0.687917,0 -1.210733,0.4723693 -1.210733,1.1648719 0,0.6925027 0.522816,1.1740442 1.210733,1.1740442 0.394405,0 0.738364,-0.1605138 0.940153,-0.4677832 v 0.3072694 c 0,0.5961943 -0.279753,0.875947 -0.889706,0.875947 -0.371475,0 -0.720019,-0.123825 -0.949325,-0.3301999 l -0.1651,0.2476499 c 0.252236,0.2384777 0.683331,0.3714749 1.123597,0.3714749 0.797984,0 1.206147,-0.376061 1.206147,-1.2061469 V 5.5001149 H 24.19133 Z m -0.921808,1.5684497 c -0.531989,0 -0.912636,-0.3623027 -0.912636,-0.8851193 0,-0.5228165 0.380647,-0.8805331 0.912636,-0.8805331 0.531989,0 0.917222,0.3577166 0.917222,0.8805331 0,0.5228166 -0.385233,0.8851193 -0.917222,0.8851193 z m 3.296006,-2.0499912 c -0.417336,0 -0.74295,0.169686 -0.917222,0.4631971 V 5.5001149 H 25.33645 v 2.4122939 h 0.325614 V 6.6466424 c 0,-0.5503332 0.325614,-0.8713609 0.843844,-0.8713609 0.458611,0 0.724606,0.2614083 0.724606,0.7704665 v 1.3666608 h 0.325614 V 6.5136452 c 0,-0.6925026 -0.403578,-1.0318747 -0.9906,-1.0318747 z m 3.17623,-0.5090583 c 0.137583,0 0.238478,-0.1054805 0.238478,-0.2384777 0,-0.123825 -0.105481,-0.2247194 -0.238478,-0.2247194 -0.132997,0 -0.238478,0.1054806 -0.238478,0.2293055 0,0.1284111 0.105481,0.2338916 0.238478,0.2338916 z m 0.160514,2.9396966 V 5.5001149 H 29.576658 V 7.9124088 Z M 31.96002,5.4817705 c -0.417336,0 -0.74295,0.169686 -0.917222,0.4631971 V 5.5001149 h -0.311856 v 2.4122939 h 0.325614 V 6.6466424 c 0,-0.5503332 0.325614,-0.8713609 0.843844,-0.8713609 0.458611,0 0.724606,0.2614083 0.724606,0.7704665 V 7.9124088 H 32.95062 V 6.5136452 c 0,-0.6925026 -0.403578,-1.0318747 -0.9906,-1.0318747 z M 37.447649,7.5501061 36.677182,5.5001149 H 36.397429 L 35.622377,7.5501061 34.865669,5.5001149 h -0.311856 l 0.90805,2.4122939 h 0.307269 l 0.761295,-1.9766134 0.761294,1.9766134 h 0.307269 l 0.912636,-2.4122939 h -0.298097 z m 1.640415,-2.5773939 c 0.137583,0 0.238477,-0.1054805 0.238477,-0.2384777 0,-0.123825 -0.10548,-0.2247194 -0.238477,-0.2247194 -0.132998,0 -0.238478,0.1054806 -0.238478,0.2293055 0,0.1284111 0.10548,0.2338916 0.238478,0.2338916 z m 0.160514,2.9396966 V 5.5001149 h -0.325614 v 2.4122939 z m 1.984371,-0.3806471 c -0.09172,0.08255 -0.224719,0.123825 -0.357717,0.123825 -0.27058,0 -0.417336,-0.1559278 -0.417336,-0.4402666 V 5.7752815 h 0.733778 V 5.5001149 H 40.457896 V 4.9727122 h -0.325614 v 0.5274027 h -0.431094 v 0.2751666 h 0.431094 v 1.458383 c 0,0.4448527 0.252237,0.7016749 0.706261,0.7016749 0.188031,0 0.380648,-0.055033 0.509059,-0.1696861 z m 1.855963,-2.0499912 c -0.408164,0 -0.724606,0.1605138 -0.903464,0.4402665 V 4.5095151 h -0.325614 v 3.4028937 h 0.325614 V 6.6466424 c 0,-0.5503332 0.325614,-0.8713609 0.843844,-0.8713609 0.458611,0 0.724606,0.2614083 0.724606,0.7704665 v 1.3666608 h 0.325614 V 6.5136452 c 0,-0.6925026 -0.403578,-1.0318747 -0.9906,-1.0318747 z" + id="path40" /><path + style="font-weight:bold;-inkscape-font-specification:'Montserrat, Bold'" + d="m 48.383925,6.2430647 c 0.261408,-0.1375833 0.426508,-0.3852332 0.426508,-0.7062609 0,-0.499886 -0.41275,-0.8346721 -1.215319,-0.8346721 h -1.56845 v 3.2102771 h 1.660172 c 0.843844,0 1.284111,-0.3210277 1.284111,-0.875947 0,-0.4035777 -0.229306,-0.6787443 -0.587022,-0.7933971 z M 47.503392,5.2616372 c 0.362302,0 0.559505,0.123825 0.559505,0.376061 0,0.2522361 -0.197203,0.3806472 -0.559505,0.3806472 H 46.765028 V 5.2616372 Z M 46.765028,7.3529034 V 6.5595063 h 0.866775 c 0.385233,0 0.591608,0.1284111 0.591608,0.3989916 0,0.2751666 -0.206375,0.3944055 -0.591608,0.3944055 z M 50.469192,7.1190118 49.776689,5.4450816 h -0.738364 l 1.068564,2.4856717 -0.0092,0.022931 c -0.09631,0.2201333 -0.206375,0.3072694 -0.403578,0.3072694 -0.142169,0 -0.293511,-0.059619 -0.403578,-0.1559277 l -0.261408,0.5090582 c 0.160514,0.1421694 0.43568,0.2247194 0.687917,0.2247194 0.444852,0 0.784224,-0.1788583 1.022702,-0.7750526 L 51.854197,5.4450816 H 51.16628 Z m 3.947232,-0.4310944 c 0,-0.793397 -0.559506,-1.2795247 -1.284111,-1.2795247 -0.752122,0 -1.316214,0.5319888 -1.316214,1.2703525 0,0.7337776 0.55492,1.2703525 1.407936,1.2703525 0.444853,0 0.788811,-0.1375833 1.018117,-0.3989916 L 53.861505,7.1373562 c -0.169686,0.1605139 -0.357717,0.2384777 -0.619125,0.2384777 -0.376061,0 -0.63747,-0.1880305 -0.706261,-0.4952998 h 1.866547 c 0.0046,-0.05962 0.01376,-0.1375834 0.01376,-0.1926167 z M 53.136899,5.9495537 c 0.321028,0 0.55492,0.2017888 0.605367,0.5136443 h -1.215319 c 0.05045,-0.3164416 0.284338,-0.5136443 0.609952,-0.5136443 z" + id="path41" /><path + style="font-weight:600;-inkscape-font-specification:'Montserrat, Semi-Bold'" + d="m 56.400799,7.9582699 c 0.527402,0 0.976841,-0.1880305 1.274938,-0.5365749 L 57.290504,7.0548062 c -0.233892,0.2568222 -0.522816,0.3806472 -0.857602,0.3806472 -0.664986,0 -1.146528,-0.4677833 -1.146528,-1.1281831 0,-0.6603999 0.481542,-1.1281831 1.146528,-1.1281831 0.334786,0 0.62371,0.123825 0.857602,0.376061 L 57.675737,5.1928455 C 57.37764,4.8443012 56.928201,4.6562706 56.405385,4.6562706 c -0.986014,0 -1.719791,0.6925027 -1.719791,1.6509997 0,0.958497 0.733777,1.6509996 1.715205,1.6509996 z m 2.722731,-0.013758 c 0.761295,0 1.307042,-0.5228166 1.307042,-1.2565942 0,-0.7337776 -0.545747,-1.252008 -1.307042,-1.252008 -0.752122,0 -1.302455,0.5182304 -1.302455,1.252008 0,0.7337776 0.550333,1.2565942 1.302455,1.2565942 z m 0,-0.4907138 c -0.41275,0 -0.724605,-0.2980971 -0.724605,-0.7658804 0,-0.4677832 0.311855,-0.7658804 0.724605,-0.7658804 0.417336,0 0.729192,0.2980972 0.729192,0.7658804 0,0.4677833 -0.311856,0.7658804 -0.729192,0.7658804 z M 61.447281,5.463426 h -0.545747 v 2.4489828 h 0.573263 V 6.7246063 c 0,-0.499886 0.275167,-0.7567082 0.710848,-0.7567082 0.04127,0 0.08255,0.00459 0.132997,0.013758 V 5.4359094 c -0.408164,0 -0.706261,0.128411 -0.871361,0.3852332 z m 2.635605,-0.027517 c -0.334786,0 -0.619125,0.1146527 -0.811741,0.3485443 V 5.463426 h -0.545747 v 3.3386882 h 0.573263 V 7.6143117 c 0.197203,0.2247194 0.47237,0.3301999 0.784225,0.3301999 0.715433,0 1.242836,-0.4952999 1.242836,-1.2565942 0,-0.7567081 -0.527403,-1.252008 -1.242836,-1.252008 z m -0.06421,2.0178884 c -0.41275,0 -0.729192,-0.2980971 -0.729192,-0.7658804 0,-0.4677832 0.316442,-0.7658804 0.729192,-0.7658804 0.41275,0 0.724605,0.2980972 0.724605,0.7658804 0,0.4677833 -0.311855,0.7658804 -0.724605,0.7658804 z m 2.530125,0.4907138 c 0.687916,0 1.109838,-0.2980972 1.109838,-0.7567082 0,-0.958497 -1.513416,-0.5182304 -1.513416,-1.0135303 0,-0.1605139 0.1651,-0.2751666 0.513644,-0.2751666 0.233892,0 0.467784,0.045861 0.701675,0.1834444 l 0.220134,-0.4356805 c -0.220134,-0.1329972 -0.591609,-0.210961 -0.917222,-0.210961 -0.6604,0 -1.077736,0.3026832 -1.077736,0.7658804 0,0.9768414 1.513416,0.5365748 1.513416,1.0043581 0,0.169686 -0.151342,0.2705805 -0.513644,0.2705805 -0.30727,0 -0.63747,-0.1008945 -0.853017,-0.2430639 L 65.512345,7.669345 c 0.220133,0.1559277 0.628297,0.2751666 1.036461,0.2751666 z" + id="path42" /><path + style="font-weight:normal;-inkscape-font-specification:'Montserrat, Normal';opacity:1" + d="M 69.775483,7.9124088 V 4.7021317 H 69.43611 v 3.2102771 z m 2.273299,0 c 1.027288,0 1.719791,-0.6603998 1.719791,-1.6051385 0,-0.9447387 -0.692503,-1.6051386 -1.719791,-1.6051386 H 70.74174 v 3.2102771 z m -0.96767,-2.916766 h 0.949325 c 0.853017,0 1.40335,0.541161 1.40335,1.3116275 0,0.7704665 -0.550333,1.3116275 -1.40335,1.3116275 h -0.949325 z" + id="path43" /></g></g></svg> diff --git a/head.php b/head.php index 1998630..5ea88ad 100644 --- a/head.php +++ b/head.php @@ -7,7 +7,7 @@ ></script> <title><?php if (isset($doc_title)) { echo $doc_title." | "; } ?>ByeCorps ID</title> -<link rel="shortcut icon" href="favicon.svg" type="image/svg" /> +<link rel="shortcut icon" href="/favicon.svg" type="image/svg" /> <link rel="manifest" href="manifest.json" /> 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 @@ +<?php + +if (isset($_GET['new_landing'])) { + goto new_landing; +} + +?> + <div class="hero"> <div class="hero-text"> <img src="/assets/bcid.svg" alt="ByeCorps ID Logo" class="logo"> @@ -5,10 +13,26 @@ <p>Log into ByeCorps and beyond with a single ID.</p> <!-- <p><input type="email" name="loginEmail" id="loginEmail" placeholder="Email" /></p> --> - <?php - if ( $_SESSION['auth']) { echo "<a href='/account' class='button primary'>Manage account</a>"; } - else { echo "<a href='/signin' class='button primary'>Sign in</a><a href='/signup' class='button'>Create an account</a>"; } + <?php + if ( $_SESSION['auth']) { echo "<a href='/account' class='button primary'>Manage account</a>"; } + else { echo "<a href='/signin' class='button primary'>Sign in</a><a href='/signup' class='button'>Create an account</a>"; } ?> </div> -</div> \ No newline at end of file +</div> + +<?php + +exit; + +new_landing: + +?> + +<div class="hero"> + <div class="hero-text"> + <img src="/assets/bcid.svg" alt="ByeCorps ID Logo" class="logo"> + <h1><span class="bc-1">Bye</span><span class="bc-2">Corps</span><span class="bc-3"> ID</span></h1> + <p>Log into ByeCorps and beyond with a single ID.</p> +</div> + 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: <img src="<?= $app['icon'] ?>" alt="<?= htmlspecialchars($user['title']) ?>'s avatar" /> </div> <h1>Sign into <?= htmlspecialchars($app['title']) ?></h1> - <p class="subtitle">Owned by <strong><?= get_display_name($app['owner_id'], put_bcid_in_parenthesis: true) ?></strong></p> + <p class="subtitle">Owned by <strong><?= htmlspecialchars( get_display_name($app['owner_id'], put_bcid_in_parenthesis: true) ) ?></strong></p> <!-- <p>--><?php //= htmlspecialchars($app['description']) ?><!--</p>--> <?php error_no_app: if ($error) { http_response_code($error[1]); echo " -<div class='error center'> -<span class='fa-regular fa-2xl center fa-xmark-circle'></span> +<div class='error center vertical-center'> +<span class='fg-error fa-regular fa-2xl center fa-xmark-circle'></span> <h2>Something went wrong!</h2> <p>Server returned error:<br /><code>$error[0]</code> (HTTP response code $error[1])</p> </div> @@ -110,9 +130,9 @@ login: goto dont_show_form; } ?> - <p><strong><?= $app['title'] ?></strong> uses ByeCorps ID for authentication.</p> + <p><strong><?= htmlspecialchars($app['title']) ?></strong> uses ByeCorps ID for authentication.</p> <p>Please double-check the information and avoid signing in with your BCID if you do not trust this app.</p> - <p>Please confirm that you'd like to sign into <strong><?= $app['title'] ?></strong>.</p> + <p>Please confirm that you'd like to sign into <strong><?= htmlspecialchars($app['title']) ?></strong>.</p> <?php if (null != $flash) { echo "<p class='flash'>$flash</p>"; @@ -131,11 +151,10 @@ login: <input type="email" autocomplete="email" name="email" id="email" placeholder="Email" /> <input type="password" name="password" id="password" placeholder="Password" /> <?php signedin: ?> - <button class="primary" type="submit">Sign into <?= $app['title']; ?></button> - <button class="secondary" type="reset">GET ME OUT OF HERE</button> + <button class="primary" type="submit">Sign into <?= htmlspecialchars($app['title']) ?></button> <p class="subtitle center"> - You will be brought to <strong><?= $query['callback'] ?></strong>. - <br /><?= $app['title'] ?> will be able to see your email and display name. + You will be brought to <strong><?= htmlspecialchars($query['callback']) ?></strong>. + <br /><strong><?= htmlspecialchars($app['title']) ?></strong> will be able to see your email and display name. </p> <input type="hidden" name="callback" value="<?= $query['callback'] ?>" /> </form> 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)) { ?> -<div id="profile"> - <img src="<?= $avatar ?>" class="avatar" alt="Avatar"> - <div class="info"> - <div class="displayname"><?= htmlspecialchars($display_name) ?></div> - <div class="bcid"><?= format_bcid( $profile['id'] ); ?></div> - </div> -</div> - -<div id="details"> - <div id="badges"> - <h2>Badges</h2> - <?php - if (empty($badges)) { - echo '<p>This profile has no badges :(</p>'; - } else { - foreach ($badges as $badge) { - echo "<div class='badge'> -<img src='". $badge['image'] ."' alt='". htmlspecialchars($badge['title']) ."' /> -<div class='details'> -<span class='title'>" . htmlspecialchars($badge['title']) . "</span> -<p>". htmlspecialchars($badge['description']) ."</p> -<p class='subtitle'>". htmlspecialchars($badge['description']) ."</p> -<p class='earned subtitle'>Earned " . $badge['earned'] . "</p> -</div> -</div>"; - } - } - ?> - </div> - - <div id="info"> - <h2>Info</h2> - - <table> - <tr> - <th>Joined</th> - <td><?= $user['created_date'] ?></td> - </tr> - <tr> - <th>Badges earned</th> - <td><?= count($badges) ?></td> - </tr> - </table> - - </div> -</div> 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 @@ +<?php + +if (empty($_SESSION)) { + http_response_code(307); + header('Location: /signin?callback=/dashboard'); + exit(); +} +if (!$_SESSION['auth']) { + http_response_code(307); + header('Location: /signin?callback=/dashboard'); + exit; +} + +?> + +<link href="/styles/settings.css" rel="stylesheet" /> + +<div id="settings_split"> + <div id="mini_profile" class="left"> + <div class="image_container" data-backgroundcolour="white"> + <img src="<?= get_avatar_url($user['id']) ?>" alt="<?= htmlspecialchars(get_display_name($user['id'])) ?>'s avatar"/> + </div> + <div class="texts"> + <span class="displayname"><?= htmlspecialchars(get_display_name($user['id'], false)) ?></span> + <span class="id bcid"><?= format_bcid($user['id']) ?></span> + </div> + </div> + + <div class="other"> + <h1>Account</h1> + <form method="post"> + <div class="container"> + <label for="display_name"><span id="display_name_label"></span> Display name</label> + <input type="text" name="display_name" id="display_name" data-field="account.display_name" placeholder="<?= htmlspecialchars(format_bcid($user['id'])) ?>" value="<?= htmlspecialchars($user['display_name']) ?>"> + </div> + + <button type="submit">Save</button> + </form> + </div> +</div> + +<style> + /*form label {*/ + /* padding-right: 1rem;*/ + /*}*/ +</style> + +<script> + const display_name_box = document.getElementById("display_name"); + + async function updateJsonSettings(data) { + const response = await fetch("https://id.byecorps.com/api/settings", { + method: "POST", // or 'PUT' + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(data), + }); + + const result = await response.json(); + console.log("Success:", result); + return result; + } + + display_name_box.onchange = _ => { + document.getElementById("display_name_label").classList = "fa-solid fa-spinner fa-spin-pulse"; + + updateJsonSettings({ + account: { + display_name: display_name_box.value, + } + }).then(_=>{ + document.getElementById("display_name_label").classList = "fa-solid fa-check"; + }).catch(_=>{ + document.getElementById("display_name_label").classList = "fa-solid fa-triangle-exclamation"; + }); + + } +</script> 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"; } -- GitLab