summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xadmin/admin.php89
-rwxr-xr-xadmin/index.php34
-rwxr-xr-xhtml/account.html1
-rwxr-xr-xhtml/admin.html69
-rwxr-xr-xhtml/forbidden.html21
-rwxr-xr-xhtml/profile.html21
-rwxr-xr-xhtml/unknown-user.html21
-rwxr-xr-xphp/header.php3
-rwxr-xr-xphp/render.php8
-rw-r--r--php/user.php49
-rwxr-xr-xprofile/index.php43
-rwxr-xr-xsignin/signin.php5
-rwxr-xr-xsignup/signup.php5
-rwxr-xr-xsignup/verify/verify.php9
14 files changed, 366 insertions, 12 deletions
diff --git a/admin/admin.php b/admin/admin.php
new file mode 100755
index 0000000..0a00cf3
--- /dev/null
+++ b/admin/admin.php
@@ -0,0 +1,89 @@
+<?php
+/*
+ * GNUfault.org - GNUfault's website
+ * Copyright (C) 2026 Connor Thomson
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+define('ROOT', rtrim($_SERVER['DOCUMENT_ROOT'], '/') . '/');
+
+require_once ROOT . '/php/user.php';
+
+if (!is_admin()) {
+ http_response_code(403);
+
+ echo "Forbidden";
+ exit;
+}
+
+if ($_SERVER["REQUEST_METHOD"] != "POST") {
+ header("Location: /admin");
+ exit;
+}
+
+$action = isset($_POST['action']) ? $_POST['action'] : '';
+$username = isset($_POST['username']) ? $_POST['username'] : '';
+
+try {
+ if (!find_user($username)) {
+ echo "User not found.";
+ exit;
+ }
+
+ if ($action == 'password') {
+ $password = $_POST['password'];
+ $confirmpassword = $_POST['confirmpassword'];
+
+ if ($confirmpassword != $password) {
+ echo "Passwords do not match!";
+ exit;
+ }
+
+ $sql = "UPDATE users SET password = :password WHERE username = :username";
+
+ query($sql, [
+ 'password' => password_hash($password, PASSWORD_DEFAULT),
+ 'username' => $username
+ ]);
+ } elseif ($action == 'status') {
+ $status = isset($_POST['status']) ? $_POST['status'] : '';
+
+ if (!in_array($status, USER_STATUSES, true)) {
+ echo "That is not a status!";
+ exit;
+ }
+
+ $sql = "UPDATE users SET status = :status WHERE username = :username";
+
+ query($sql, [
+ 'status' => $status,
+ 'username' => $username
+ ]);
+ } elseif ($action == 'remove') {
+ $sql = "DELETE FROM users WHERE username = :username";
+
+ query($sql, ['username' => $username]);
+ } else {
+ echo "That is not something I can do.";
+ exit;
+ }
+} catch (\PDOException $e) {
+ echo "Error: " . $e->getMessage();
+ exit;
+}
+
+header("Location: /admin");
+
+?>
diff --git a/admin/index.php b/admin/index.php
new file mode 100755
index 0000000..29c8873
--- /dev/null
+++ b/admin/index.php
@@ -0,0 +1,34 @@
+<?php
+/*
+ * GNUfault.org - GNUfault's website
+ * Copyright (C) 2026 Connor Thomson
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+define('ROOT', rtrim($_SERVER['DOCUMENT_ROOT'], '/') . '/');
+
+require_once ROOT . '/php/render.php';
+require_once ROOT . '/php/user.php';
+
+if (!is_admin()) {
+ http_response_code(403);
+
+ render_content(ROOT . '/html/forbidden.html');
+ exit;
+}
+
+render_content(ROOT . '/html/admin.html');
+
+?>
diff --git a/html/account.html b/html/account.html
index 0a4da65..ccba599 100755
--- a/html/account.html
+++ b/html/account.html
@@ -20,6 +20,7 @@
<input class="toggle" type="checkbox" id="account">
<label class="username" for="account">{{username}}</label>
<div class="menu">
+ <a href="/profile?username={{profile}}">Profile</a>
<a href="/signout">Sign-out</a>
</div>
</div>
diff --git a/html/admin.html b/html/admin.html
new file mode 100755
index 0000000..8ae34e2
--- /dev/null
+++ b/html/admin.html
@@ -0,0 +1,69 @@
+<!--
+ GNUfault.org - GNUfault's website
+ Copyright (C) 2026 Connor Thomson
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+-->
+
+<h2>Admin Panel</h2>
+<hr>
+
+<h3>Change user's password</h3>
+<form class="login" action="admin.php" method="POST">
+ <input type="hidden" name="action" value="password">
+ <div class="group">
+ <label for="password-username">Username:</label>
+ <input class="input" type="text" id="password-username" name="username" required>
+ </div>
+ <div class="group">
+ <label for="password">New password:</label>
+ <input class="input" type="password" id="password" name="password" required>
+ </div>
+ <div class="group">
+ <label for="confirmpassword">Confirm new password:</label>
+ <input class="input" type="password" id="confirmpassword" name="confirmpassword" required>
+ </div>
+ <button class="button" type="submit">Send</button>
+</form>
+<br>
+
+<h3>Change user's status</h3>
+<form class="login" action="admin.php" method="POST">
+ <input type="hidden" name="action" value="status">
+ <div class="group">
+ <label for="status-username">Username:</label>
+ <input class="input" type="text" id="status-username" name="username" required>
+ </div>
+ <div class="group">
+ <label for="status">Status:</label>
+ <select class="input" id="status" name="status">
+ <option value="none">none</option>
+ <option value="member">member</option>
+ <option value="mod">mod</option>
+ <option value="admin">admin</option>
+ </select>
+ </div>
+ <button class="button" type="submit">Send</button>
+</form>
+<br>
+
+<h3>Remove user</h3>
+<form class="login" action="admin.php" method="POST">
+ <input type="hidden" name="action" value="remove">
+ <div class="group">
+ <label for="remove-username">Username:</label>
+ <input class="input" type="text" id="remove-username" name="username" required>
+ </div>
+ <button class="button" type="submit">Send</button>
+</form>
diff --git a/html/forbidden.html b/html/forbidden.html
new file mode 100755
index 0000000..791fa4e
--- /dev/null
+++ b/html/forbidden.html
@@ -0,0 +1,21 @@
+<!--
+ GNUfault.org - GNUfault's website
+ Copyright (C) 2026 Connor Thomson
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+-->
+
+<h2>403 Forbidden</h2>
+<hr>
+<p>You do not have permission to view this page.</p>
diff --git a/html/profile.html b/html/profile.html
new file mode 100755
index 0000000..d86b5ac
--- /dev/null
+++ b/html/profile.html
@@ -0,0 +1,21 @@
+<!--
+ GNUfault.org - GNUfault's website
+ Copyright (C) 2026 Connor Thomson
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+-->
+
+<h2>{{username}}</h2>
+<hr>
+<p>Status: {{status}}</p>
diff --git a/html/unknown-user.html b/html/unknown-user.html
new file mode 100755
index 0000000..93bf3a2
--- /dev/null
+++ b/html/unknown-user.html
@@ -0,0 +1,21 @@
+<!--
+ GNUfault.org - GNUfault's website
+ Copyright (C) 2026 Connor Thomson
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+-->
+
+<h2>User not found</h2>
+<hr>
+<p>There is nobody signed up under that name.</p>
diff --git a/php/header.php b/php/header.php
index 8648b2a..0fd46df 100755
--- a/php/header.php
+++ b/php/header.php
@@ -26,7 +26,8 @@ if ($username === null) {
$account = import(ROOT . '/html/guest.html');
} else {
$account = replace(ROOT . '/html/account.html', [
- '{{username}}' => htmlspecialchars($username, ENT_QUOTES, 'UTF-8')
+ '{{username}}' => htmlspecialchars($username, ENT_QUOTES, 'UTF-8'),
+ '{{profile}}' => rawurlencode($username)
]);
}
diff --git a/php/render.php b/php/render.php
index 902d81b..e4986e2 100755
--- a/php/render.php
+++ b/php/render.php
@@ -20,13 +20,13 @@
require_once ROOT . '/php/replace.php';
require_once ROOT . '/php/execute.php';
-function render_content(string $page) {
+function render_page(string $content) {
$device = 'desktop';
$targets = [
'{{stylesheets}}' => import(ROOT . '/html/stylesheets.html'),
'{{header}}' => execute(ROOT . '/php/header.php'),
- '{{content}}' => import($page),
+ '{{content}}' => $content,
'{{footer}}' => execute(ROOT . '/php/footer.php'),
'{{device}}' => $device
];
@@ -36,4 +36,8 @@ function render_content(string $page) {
echo $main_html . "\n";
}
+function render_content(string $page) {
+ render_page(import($page));
+}
+
?>
diff --git a/php/user.php b/php/user.php
new file mode 100644
index 0000000..8a424e5
--- /dev/null
+++ b/php/user.php
@@ -0,0 +1,49 @@
+<?php
+/*
+ * GNUfault.org - GNUfault's website
+ * Copyright (C) 2026 Connor Thomson
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+require_once ROOT . '/php/session.php';
+require_once ROOT . '/php/database.php';
+
+const USER_STATUSES = ['none', 'member', 'mod', 'admin'];
+
+function find_user(string $username): ?array {
+ $sql = "SELECT id, username, status FROM users WHERE username = :username";
+
+ return fetch_row($sql, ['username' => $username]);
+}
+
+function current_user(): ?array {
+ $user_id = get_user_id();
+
+ if ($user_id === null) {
+ return null;
+ }
+
+ $sql = "SELECT id, username, status FROM users WHERE id = :id";
+
+ return fetch_row($sql, ['id' => $user_id]);
+}
+
+function is_admin(): bool {
+ $user = current_user();
+
+ return $user !== null && $user['status'] === 'admin';
+}
+
+?>
diff --git a/profile/index.php b/profile/index.php
new file mode 100755
index 0000000..89d8637
--- /dev/null
+++ b/profile/index.php
@@ -0,0 +1,43 @@
+<?php
+/*
+ * GNUfault.org - GNUfault's website
+ * Copyright (C) 2026 Connor Thomson
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+define('ROOT', rtrim($_SERVER['DOCUMENT_ROOT'], '/') . '/');
+
+require_once ROOT . '/php/render.php';
+require_once ROOT . '/php/user.php';
+
+$username = isset($_GET['username']) ? $_GET['username'] : '';
+
+$user = find_user($username);
+
+if (!$user) {
+ http_response_code(404);
+
+ render_content(ROOT . '/html/unknown-user.html');
+ exit;
+}
+
+$content = replace(ROOT . '/html/profile.html', [
+ '{{username}}' => htmlspecialchars($user['username'], ENT_QUOTES, 'UTF-8'),
+ '{{status}}' => htmlspecialchars($user['status'], ENT_QUOTES, 'UTF-8')
+]);
+
+render_page($content);
+
+?>
diff --git a/signin/signin.php b/signin/signin.php
index 6e88336..f7f3c23 100755
--- a/signin/signin.php
+++ b/signin/signin.php
@@ -28,7 +28,7 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
$remember = isset($_POST['remember']);
try {
- $sql = "SELECT id, username, password, verification_code FROM users WHERE username = :username";
+ $sql = "SELECT id, username, password, status FROM users WHERE username = :username";
$user = fetch_row($sql, ['username' => $username]);
} catch (\PDOException $e) {
@@ -36,13 +36,12 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
exit;
}
- // The same message either way, so it does not say which usernames exist
if (!$user || !password_verify($password, $user['password'])) {
echo "Username or password is not correct!";
exit;
}
- if ($user['verification_code'] != '0001') {
+ if ($user['status'] == 'none') {
set_user_id((int)$user['id']);
header("Location: /signup/verify");
diff --git a/signup/signup.php b/signup/signup.php
index a41454a..7648adf 100755
--- a/signup/signup.php
+++ b/signup/signup.php
@@ -39,13 +39,14 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
$code = rand(1000, 9999);
try {
- $sql = "INSERT INTO users (username, email, password, verification_code) VALUES (:username, :email, :password, :code)";
+ $sql = "INSERT INTO users (username, email, password, verification_code, status) VALUES (:username, :email, :password, :code, :status)";
$user_id = insert_row($sql, [
'username' => $username,
'email' => $email,
'password' => $hashed_password,
- 'code' => $code
+ 'code' => $code,
+ 'status' => 'none'
]);
set_user_id($user_id);
diff --git a/signup/verify/verify.php b/signup/verify/verify.php
index 592915f..9e22132 100755
--- a/signup/verify/verify.php
+++ b/signup/verify/verify.php
@@ -47,7 +47,7 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
exit;
}
- if ($real_code == '0001') {
+ if ($user['status'] == 'none') {
echo "Account is already verifed";
exit;
}
@@ -58,11 +58,12 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
}
try {
- $sql = "UPDATE users SET verification_code = :code WHERE id = :id";
+ $sql = "UPDATE users SET verification_code = :code, status = :status WHERE id = :id";
$statement = query($sql, [
- 'code' => '0001',
- 'id' => $user_id
+ 'code' => '0000',
+ 'status' => 'member',
+ 'id' => $user_id
]);
if ($statement->rowCount() == 0) {