summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorilotterytea <iltsu@alright.party>2025-08-15 22:41:54 +0500
committerilotterytea <iltsu@alright.party>2025-08-15 22:41:54 +0500
commit0d7ecc616d669f824f8416b47a0a986b46fa579b (patch)
tree4c5143d404e272f341876945bed7f42dc7d75238
parente971d763cb649a51d26f75e8764ffbcb2d9d7a2b (diff)
feat: registration page
-rw-r--r--lib/partials.php11
-rw-r--r--lib/utils.php11
-rw-r--r--register.php105
-rw-r--r--static/style.css113
4 files changed, 240 insertions, 0 deletions
diff --git a/lib/partials.php b/lib/partials.php
new file mode 100644
index 0000000..e11e194
--- /dev/null
+++ b/lib/partials.php
@@ -0,0 +1,11 @@
+<?php
+function html_navbar()
+{
+ echo '' ?>
+ <header>
+ <a href="/">
+ <img src="/static/brand/big.webp" alt="ilt.su">
+ </a>
+ </header>
+ <?php ;
+} \ No newline at end of file
diff --git a/lib/utils.php b/lib/utils.php
new file mode 100644
index 0000000..b81ddda
--- /dev/null
+++ b/lib/utils.php
@@ -0,0 +1,11 @@
+<?php
+function json_response(int $code, string|null $message, mixed $data)
+{
+ header('Content-Type: application/json');
+ http_response_code($code);
+ return json_encode([
+ 'status_code' => $code,
+ 'message' => $message,
+ 'data' => $data
+ ], JSON_UNESCAPED_SLASHES);
+} \ No newline at end of file
diff --git a/register.php b/register.php
new file mode 100644
index 0000000..0804d3d
--- /dev/null
+++ b/register.php
@@ -0,0 +1,105 @@
+<?php
+include_once $_SERVER['DOCUMENT_ROOT'] . '/lib/partials.php';
+include_once $_SERVER['DOCUMENT_ROOT'] . '/lib/utils.php';
+include_once $_SERVER['DOCUMENT_ROOT'] . '/lib/config.php';
+
+if ($_SERVER['REQUEST_METHOD'] == 'POST') {
+ $username = $_POST['username'] ?? null;
+ $password = $_POST['password'] ?? null;
+
+ if (!isset($username, $password)) {
+ exit(json_response(400, 'Username and password must be sent!', null));
+ }
+
+ $username = trim($username);
+
+ if (!preg_match('/^[a-zA-Z0-9_]+$/', $username)) {
+ exit(json_response(400, 'Your username must contain only letters and numbers!', null));
+ }
+
+ $username_len = strlen($username);
+
+ if ($username_len < 4 || $username_len > 20) {
+ exit(json_response(400, 'Your username must be between 4 and 20 characters long', null));
+ }
+
+ if (strlen($password) < 8) {
+ exit(json_response(400, 'Your password must be at least 8 characters long', null));
+ }
+
+ $db = new PDO(DB_URL, DB_USER, DB_PASS);
+
+ // checking for already existing accounts
+ $stmt = $db->prepare('SELECT id FROM users WHERE username = ?');
+ $stmt->execute([$username]);
+ if ($stmt->rowCount() > 0) {
+ exit(json_response(409, 'This username has been taken.', null));
+ }
+
+ $userid = 0;
+ do {
+ $userid = random_int(90_000_000_000_000_000, 99_000_000_000_000_000);
+ $stmt = $db->prepare('SELECT username FROM users WHERE id = ?');
+ $stmt->execute([$userid]);
+ } while ($stmt->rowCount() > 0);
+
+ $password = password_hash($password, PASSWORD_DEFAULT);
+ $db->prepare('INSERT INTO users(id, username, `password`) VALUES (?, ?, ?)')
+ ->execute([$userid, $username, $password]);
+
+ $stmt = $db->prepare('SELECT id, username, joined_at FROM users WHERE id = ?');
+ $stmt->execute([$userid]);
+ $user = $stmt->fetch(PDO::FETCH_ASSOC) ?: null;
+
+ exit(json_response(200, null, $user));
+}
+?>
+<!DOCTYPE html>
+<html>
+
+<head>
+ <title>Register - id</title>
+ <link rel="stylesheet" href="/static/style.css">
+</head>
+
+<body>
+ <main>
+ <?php html_navbar(); ?>
+
+ <form action="/register.php" method="post" class="column gap-16">
+ <h1>Register new ilt.su account</h1>
+
+ <div class="row">
+ <div class="box">
+ <div class="tab">
+ <p>Account credentials</p>
+ </div>
+ <div class="content column gap-8">
+ <div class="column">
+ <label for="username">Username</label>
+ <input type="text" name="username" id="username" placeholder="Username"
+ pattern="^[a-zA-Z0-9_]+$" required>
+ </div>
+ <div class="row gap-8">
+ <div class="column">
+ <label for="password">Password</label>
+ <input type="password" name="password" id="password" placeholder="Enter password"
+ required>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div>
+ <input type="checkbox" name="tos" id="tos" required>
+ <label for="tos">I accept the <a href="/static/txt/TOS.txt">TOS</a>, including <a
+ href="/static/txt/PRIVACY.txt">Privacy Policy</a></label>
+ </div>
+ <div>
+ <button type="submit">Register</button>
+ </div>
+ </form>
+ </main>
+</body>
+
+</html> \ No newline at end of file
diff --git a/static/style.css b/static/style.css
new file mode 100644
index 0000000..e2c5064
--- /dev/null
+++ b/static/style.css
@@ -0,0 +1,113 @@
+:root {
+ --anchor: #584800;
+ --anchor-hover: #8a7000;
+
+ --box-primary-color: #ccb800;
+ --box-secondary-color: #8b6600;
+
+ --button-submit-background: linear-gradient(0deg, #ccb800, #ffe600);
+ --button-submit-background-hover: linear-gradient(180deg, #ccb800, #ffe600);
+ --button-submit-border: #8b6600;
+ --button-submit-color: #302300;
+}
+
+* {
+ margin: 0;
+ padding: 0;
+}
+
+body {
+ width: 100%;
+ min-height: 100vh;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+main {
+ display: flex;
+ flex-direction: column;
+ width: 50%;
+}
+
+header {
+ margin: 32px 0;
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+}
+
+a {
+ color: var(--anchor);
+ font-weight: bold;
+}
+
+a:hover {
+ color: var(--anchor-hover);
+ cursor: pointer;
+}
+
+input[type=text],
+input[type=password] {
+ padding: 4px;
+ border: 1px solid var(--box-primary-color);
+}
+
+button[type=submit] {
+ padding: 4px 32px;
+ font-size: 24px;
+ background: var(--button-submit-background);
+ color: var(--button-submit-color);
+ border: 1px solid var(--button-submit-border);
+ border-radius: 4px;
+ text-shadow: 0 1px 0 var(--button-submit-border);
+}
+
+button[type=submit]:hover {
+ background: var(--button-submit-background-hover);
+ text-shadow: 0 -1px 0 var(--button-submit-border);
+ cursor: pointer;
+}
+
+.box {
+ padding: 8px;
+ border: 1px solid var(--box-primary-color);
+}
+
+.box:has(.content) {
+ padding: 0;
+}
+
+.box>.tab {
+ display: flex;
+ flex-direction: row;
+ background: var(--box-primary-color);
+ color: var(--box-secondary-color);
+ padding: 4px;
+ text-transform: uppercase;
+ font-size: 10px;
+}
+
+.box>.content {
+ padding: 16px;
+}
+
+.column {
+ display: flex;
+ flex-direction: column;
+}
+
+.row {
+ display: flex;
+ flex-direction: row;
+}
+
+.gap-8 {
+ gap: 8px;
+}
+
+.gap-16 {
+ gap: 16px;
+} \ No newline at end of file