new system prototype
This commit is contained in:
236
manage_users.php
Normal file
236
manage_users.php
Normal file
@ -0,0 +1,236 @@
|
||||
<?php
|
||||
// /var/www/html/manage_users.php
|
||||
// Admin-only endpoint for user management.
|
||||
//
|
||||
// GET → list all users with role entity details + list of supervisors
|
||||
// POST → create a new user { username, password, role, location?, supervisorID? }
|
||||
// DELETE → delete a user { userID }
|
||||
//
|
||||
require_once __DIR__ . '/db_init.php';
|
||||
header('Content-Type: application/json; charset=UTF-8');
|
||||
|
||||
$tokenRec = require_valid_token();
|
||||
require_role(['admin'], $tokenRec);
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// GET: list users + supervisors (for the coach creation dropdown)
|
||||
// -----------------------------------------------------------------------
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
||||
try {
|
||||
[$pdo, $tmpDb, $lockFp] = qdb_open(false);
|
||||
|
||||
$users = $pdo->query(
|
||||
"SELECT u.userID, u.username, u.role, u.entityID, u.mustChangePassword, u.createdAt,
|
||||
COALESCE(a.location, s.location, '') AS location,
|
||||
c.supervisorID,
|
||||
sv.username AS supervisorUsername
|
||||
FROM users u
|
||||
LEFT JOIN admin a ON a.adminID = u.entityID AND u.role = 'admin'
|
||||
LEFT JOIN supervisor s ON s.supervisorID = u.entityID AND u.role = 'supervisor'
|
||||
LEFT JOIN coach c ON c.coachID = u.entityID AND u.role = 'coach'
|
||||
LEFT JOIN supervisor sv ON sv.supervisorID = c.supervisorID
|
||||
ORDER BY u.role, u.username"
|
||||
)->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$supervisors = $pdo->query(
|
||||
"SELECT supervisorID, username, location FROM supervisor ORDER BY username"
|
||||
)->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$pdo = null;
|
||||
qdb_discard($tmpDb, $lockFp);
|
||||
|
||||
echo json_encode(["users" => $users, "supervisors" => $supervisors]);
|
||||
|
||||
} catch (Throwable $e) {
|
||||
if (isset($tmpDb, $lockFp)) qdb_discard($tmpDb, $lockFp);
|
||||
http_response_code(500);
|
||||
echo json_encode(["error" => "Server error"]);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// POST: create a user
|
||||
// -----------------------------------------------------------------------
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$raw = file_get_contents("php://input");
|
||||
$in = json_decode($raw, true) ?: [];
|
||||
|
||||
$username = trim($in['username'] ?? '');
|
||||
$password = (string)($in['password'] ?? '');
|
||||
$role = strtolower(trim($in['role'] ?? ''));
|
||||
$location = trim($in['location'] ?? '');
|
||||
$supervisorID = trim($in['supervisorID'] ?? '');
|
||||
$mustChange = isset($in['mustChangePassword']) ? (int)(bool)$in['mustChangePassword'] : 1;
|
||||
|
||||
if ($username === '' || $password === '' || $role === '') {
|
||||
http_response_code(400);
|
||||
echo json_encode(["error" => "username, password, and role are required"]);
|
||||
exit;
|
||||
}
|
||||
if (!in_array($role, ['admin', 'supervisor', 'coach'], true)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(["error" => "role must be admin, supervisor, or coach"]);
|
||||
exit;
|
||||
}
|
||||
if (strlen($password) < 6) {
|
||||
http_response_code(400);
|
||||
echo json_encode(["error" => "Password must be at least 6 characters"]);
|
||||
exit;
|
||||
}
|
||||
if ($role === 'coach' && $supervisorID === '') {
|
||||
http_response_code(400);
|
||||
echo json_encode(["error" => "supervisorID is required for coaches"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
[$pdo, $tmpDb, $lockFp] = qdb_open(true);
|
||||
|
||||
$chk = $pdo->prepare("SELECT userID FROM users WHERE username = :u");
|
||||
$chk->execute([':u' => $username]);
|
||||
if ($chk->fetch()) {
|
||||
qdb_discard($tmpDb, $lockFp);
|
||||
http_response_code(409);
|
||||
echo json_encode(["error" => "Username already exists"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($role === 'coach') {
|
||||
$sv = $pdo->prepare("SELECT supervisorID FROM supervisor WHERE supervisorID = :sid");
|
||||
$sv->execute([':sid' => $supervisorID]);
|
||||
if (!$sv->fetch()) {
|
||||
qdb_discard($tmpDb, $lockFp);
|
||||
http_response_code(400);
|
||||
echo json_encode(["error" => "supervisorID not found"]);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
$entityID = bin2hex(random_bytes(16));
|
||||
$userID = bin2hex(random_bytes(16));
|
||||
$hash = password_hash($password, PASSWORD_DEFAULT);
|
||||
$now = time();
|
||||
|
||||
$pdo->beginTransaction();
|
||||
|
||||
switch ($role) {
|
||||
case 'admin':
|
||||
$pdo->prepare("INSERT INTO admin (adminID, username, location) VALUES (:id, :u, :loc)")
|
||||
->execute([':id' => $entityID, ':u' => $username, ':loc' => $location]);
|
||||
break;
|
||||
case 'supervisor':
|
||||
$pdo->prepare("INSERT INTO supervisor (supervisorID, username, location) VALUES (:id, :u, :loc)")
|
||||
->execute([':id' => $entityID, ':u' => $username, ':loc' => $location]);
|
||||
break;
|
||||
case 'coach':
|
||||
$pdo->prepare("INSERT INTO coach (coachID, supervisorID, username) VALUES (:id, :sid, :u)")
|
||||
->execute([':id' => $entityID, ':sid' => $supervisorID, ':u' => $username]);
|
||||
break;
|
||||
}
|
||||
|
||||
$pdo->prepare(
|
||||
"INSERT INTO users (userID, username, passwordHash, role, entityID, mustChangePassword, createdAt)
|
||||
VALUES (:uid, :u, :hash, :role, :eid, :mcp, :now)"
|
||||
)->execute([
|
||||
':uid' => $userID,
|
||||
':u' => $username,
|
||||
':hash' => $hash,
|
||||
':role' => $role,
|
||||
':eid' => $entityID,
|
||||
':mcp' => $mustChange,
|
||||
':now' => $now,
|
||||
]);
|
||||
|
||||
$pdo->commit();
|
||||
$pdo = null;
|
||||
qdb_save($tmpDb, $lockFp);
|
||||
|
||||
echo json_encode([
|
||||
"success" => true,
|
||||
"userID" => $userID,
|
||||
"entityID" => $entityID,
|
||||
"username" => $username,
|
||||
"role" => $role,
|
||||
]);
|
||||
|
||||
} catch (Throwable $e) {
|
||||
if (isset($tmpDb, $lockFp)) qdb_discard($tmpDb, $lockFp);
|
||||
http_response_code(500);
|
||||
echo json_encode(["error" => "Server error"]);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// DELETE: remove a user (and their role entity row)
|
||||
// -----------------------------------------------------------------------
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'DELETE') {
|
||||
$raw = file_get_contents("php://input");
|
||||
$in = json_decode($raw, true) ?: [];
|
||||
|
||||
$targetUserID = trim($in['userID'] ?? '');
|
||||
if ($targetUserID === '') {
|
||||
http_response_code(400);
|
||||
echo json_encode(["error" => "userID is required"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Prevent self-deletion
|
||||
if ($targetUserID === ($tokenRec['userID'] ?? '')) {
|
||||
http_response_code(400);
|
||||
echo json_encode(["error" => "Cannot delete your own account"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
[$pdo, $tmpDb, $lockFp] = qdb_open(true);
|
||||
|
||||
$row = $pdo->prepare("SELECT role, entityID FROM users WHERE userID = :uid");
|
||||
$row->execute([':uid' => $targetUserID]);
|
||||
$target = $row->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$target) {
|
||||
qdb_discard($tmpDb, $lockFp);
|
||||
http_response_code(404);
|
||||
echo json_encode(["error" => "User not found"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$pdo->beginTransaction();
|
||||
|
||||
$pdo->prepare("DELETE FROM users WHERE userID = :uid")
|
||||
->execute([':uid' => $targetUserID]);
|
||||
|
||||
switch ($target['role']) {
|
||||
case 'admin':
|
||||
$pdo->prepare("DELETE FROM admin WHERE adminID = :id")
|
||||
->execute([':id' => $target['entityID']]);
|
||||
break;
|
||||
case 'supervisor':
|
||||
$pdo->prepare("DELETE FROM supervisor WHERE supervisorID = :id")
|
||||
->execute([':id' => $target['entityID']]);
|
||||
break;
|
||||
case 'coach':
|
||||
$pdo->prepare("DELETE FROM coach WHERE coachID = :id")
|
||||
->execute([':id' => $target['entityID']]);
|
||||
break;
|
||||
}
|
||||
|
||||
$pdo->commit();
|
||||
$pdo = null;
|
||||
qdb_save($tmpDb, $lockFp);
|
||||
|
||||
echo json_encode(["success" => true]);
|
||||
|
||||
} catch (Throwable $e) {
|
||||
if (isset($tmpDb, $lockFp)) qdb_discard($tmpDb, $lockFp);
|
||||
http_response_code(500);
|
||||
error_log($e->getMessage());
|
||||
echo json_encode(["error" => "Server error"]);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
http_response_code(405);
|
||||
echo json_encode(["error" => "Method not allowed"]);
|
||||
Reference in New Issue
Block a user