0, 'message' => '']; // ─── CSRF ───────────────────────────────────────────────────────────────── if ($_SERVER['REQUEST_METHOD'] === 'POST') { $csrf = $_SERVER['HTTP_X_CSRF_TOKEN'] ?? ''; if (empty($csrf) || $csrf !== ($_SESSION['csrf_token'] ?? '')) { http_response_code(403); exit(json_encode(['message' => 'Invalid request.'])); } } $data = json_decode($_POST['json'] ?? '{}', true) ?: []; try { $name = trim($data['name'] ?? ''); $surname = trim($data['surname'] ?? ''); $username = strtolower(trim($data['username'] ?? '')); $email = strtolower(trim($data['email'] ?? '')); $password = $data['password'] ?? ''; $confirm = $data['confirm_password'] ?? ''; // ── Required fields ─────────────────────────────────────── if (!$name || !$surname || !$username || !$email || !$password || !$confirm) { $answer['message'] = 'All fields are required.'; http_response_code(422); exit(json_encode($answer)); } // ── Username format ─────────────────────────────────────── if (!preg_match('/^[a-z0-9_]+$/', $username)) { $answer['message'] = 'Username may only contain lowercase letters, numbers and underscores.'; http_response_code(422); exit(json_encode($answer)); } // ── Email format ────────────────────────────────────────── if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { $answer['message'] = 'Invalid email address.'; http_response_code(422); exit(json_encode($answer)); } // ── Password match ──────────────────────────────────────── if ($password !== $confirm) { $answer['message'] = 'Passwords do not match.'; http_response_code(422); exit(json_encode($answer)); } // ── Duplicate username ──────────────────────────────────── $sth = $pdo1->prepare('SELECT user_id FROM user WHERE username = :u LIMIT 1'); $sth->execute([':u' => $username]); db_check($sth, $answer); if ($sth->fetchColumn()) { $answer['message'] = 'Username is already taken.'; http_response_code(409); exit(json_encode($answer)); } // ── Duplicate email ─────────────────────────────────────── $sth = $pdo1->prepare('SELECT user_id FROM user WHERE email = :e LIMIT 1'); $sth->execute([':e' => $email]); db_check($sth, $answer); if ($sth->fetchColumn()) { $answer['message'] = 'An account with that email already exists.'; http_response_code(409); exit(json_encode($answer)); } // ── Password strength ───────────────────────────────────── $pm = new PasswordManager($pdo1, $include_url); $result = $pm->checkStrength($password, [$name, $surname, $username, $email]); if ($result['score'] < PasswordManager::MIN_SCORE) { $msg = $result['warning'] ?: ($result['suggestions'][0] ?? 'Please choose a stronger password.'); $answer['message'] = 'Password is too weak. ' . $msg; http_response_code(422); exit(json_encode($answer)); } // ── Insert user with status=pending ─────────────────────── $hashed = password_hash($password, PASSWORD_BCRYPT); $token = bin2hex(random_bytes(32)); $expires_at = date('Y-m-d H:i:s', strtotime('+30 days')); $sth = $pdo1->prepare(" INSERT INTO user (username, name, surname, email, password, status, profile_picture, verify_token, verify_expires_at) VALUES (:username, :name, :surname, :email, :password, 'pending', '', :token, :expires) "); $sth->execute([ ':username' => $username, ':name' => $name, ':surname' => $surname, ':email' => $email, ':password' => $hashed, ':token' => $token, ':expires' => $expires_at, ]); db_check($sth, $answer); // ── Send verification email via default SMTP ────────────── // Build absolute URL $base_url = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . rtrim($server_url, '/'); $verify_url = $base_url . '/login/verify.php?token=' . $token; require_once $include_url . 'assets/utils/module/mailer.php'; $mailer = new mailer(['pdo1' => $pdo1]); $mailer->send_email([ 'company_id' => 0, 'smtp' => $SMTP, 'to' => $email, 'subject' => 'Verify your email — WMS', 'message' => implode("\n", [ "Hi {$name},", "", "Thanks for registering. Please verify your email address by clicking the button below:", "", "Verify Email Address", "", "Or copy and paste this link into your browser:", "{$verify_url}", "", "This link will expire in 30 days.", "", "If you did not create an account, you can ignore this email.", ]), 'channel_name' => 'WMS', 'key' => $pinkey, ]); $answer['success'] = 1; $answer['message'] = 'Account created! Please check your email to verify your account.'; } catch (Exception $e) { error_log('[register] ' . $e->getMessage()); $answer['message'] = 'Registration failed. Please try again.'; http_response_code(500); } exit(json_encode($answer)); ?>