99 lines
3.1 KiB
PHP
99 lines
3.1 KiB
PHP
<?php
|
|
require 'db.php';
|
|
require 'auth.php';
|
|
|
|
header('Content-Type: application/json');
|
|
|
|
$data = json_decode(file_get_contents('php://input'), true);
|
|
$email = strtolower(trim($data['email'] ?? ''));
|
|
$usernameRaw = trim($data['username'] ?? '');
|
|
$username = $usernameRaw === '' ? null : strtolower($usernameRaw);
|
|
$password = strval($data['password'] ?? '');
|
|
|
|
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
|
http_response_code(400);
|
|
echo json_encode(['success' => false, 'error' => 'Invalid email']);
|
|
exit;
|
|
}
|
|
if (strlen($password) < 8) {
|
|
http_response_code(400);
|
|
echo json_encode(['success' => false, 'error' => 'Password must be at least 8 characters']);
|
|
exit;
|
|
}
|
|
|
|
// Optional username validation
|
|
if ($username !== null) {
|
|
if (strlen($username) < 3 || strlen($username) > 50) {
|
|
http_response_code(400);
|
|
echo json_encode(['success' => false, 'error' => 'Username must be between 3 and 50 characters']);
|
|
exit;
|
|
}
|
|
|
|
// letters/numbers + . _ - ; must start/end with letter/number
|
|
if (!preg_match('/^[a-z0-9](?:[a-z0-9._-]*[a-z0-9])?$/', $username)) {
|
|
http_response_code(400);
|
|
echo json_encode([
|
|
'success' => false,
|
|
'error' => 'Username may contain letters, numbers, underscore, hyphen, dot, and must start/end with a letter or number'
|
|
]);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
$hash = password_hash($password, PASSWORD_DEFAULT);
|
|
|
|
// Standard role id from roles table
|
|
$stmt = $pdo->prepare("SELECT id FROM roles WHERE name = 'standard' LIMIT 1");
|
|
$stmt->execute();
|
|
$role_id = (int)$stmt->fetchColumn();
|
|
|
|
if ($role_id <= 0) {
|
|
http_response_code(500);
|
|
echo json_encode(['success' => false, 'error' => "Role 'standard' not found"]);
|
|
exit;
|
|
}
|
|
|
|
try {
|
|
$pdo->beginTransaction();
|
|
|
|
// Friendly conflict checks (DB unique constraints should still exist)
|
|
$stmt = $pdo->prepare('SELECT 1 FROM users WHERE email = ? LIMIT 1');
|
|
$stmt->execute([$email]);
|
|
if ($stmt->fetchColumn()) {
|
|
$pdo->rollBack();
|
|
http_response_code(409);
|
|
echo json_encode(['success' => false, 'error' => 'Email already in use']);
|
|
exit;
|
|
}
|
|
|
|
if ($username !== null) {
|
|
$stmt = $pdo->prepare('SELECT 1 FROM users WHERE username = ? LIMIT 1');
|
|
$stmt->execute([$username]);
|
|
if ($stmt->fetchColumn()) {
|
|
$pdo->rollBack();
|
|
http_response_code(409);
|
|
echo json_encode(['success' => false, 'error' => 'Username already in use']);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
// Create user (username is nullable)
|
|
$stmt = $pdo->prepare("INSERT INTO users (email, username, password_hash, role_id) VALUES (?, ?, ?, ?)");
|
|
$stmt->execute([$email, $username, $hash, $role_id]);
|
|
$userId = (int)$pdo->lastInsertId();
|
|
|
|
// Create default profile for this user
|
|
$stmt = $pdo->prepare("INSERT INTO profiles (user_id, name, is_default) VALUES (?, 'Default', 1)");
|
|
$stmt->execute([$userId]);
|
|
|
|
$pdo->commit();
|
|
|
|
echo json_encode(['success' => true]);
|
|
|
|
} catch (Throwable $e) {
|
|
if ($pdo->inTransaction()) $pdo->rollBack();
|
|
|
|
http_response_code(409);
|
|
echo json_encode(['success' => false, 'error' => 'Account already exists']);
|
|
}
|