Files
4WDCSA.co.za/src/processors/register_user.php

148 lines
5.9 KiB
PHP

<?php
$rootPath = dirname(dirname(__DIR__));
require_once($rootPath . "/src/config/env.php");
require_once($rootPath . "/src/config/session.php");
require_once($rootPath . "/src/config/connection.php");
require_once($rootPath . "/src/config/functions.php");
require_once($rootPath . "/vendor/autoload.php");
use GuzzleHttp\Client;
// Create connection
$conn = openDatabaseConnection();
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// Form processing
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// CSRF Token Validation
if (!isset($_POST['csrf_token']) || !validateCSRFToken($_POST['csrf_token'])) {
auditLog(null, 'CSRF_VALIDATION_FAILED', 'users', null, ['endpoint' => 'register_user.php']);
echo json_encode(['status' => 'error', 'message' => 'Security token validation failed. Please try again.']);
exit();
}
// Check rate limiting on registration endpoint (by IP)
$ip = getClientIPAddress();
$cutoffTime = date('Y-m-d H:i:s', time() - (3600)); // Last hour
$stmt = $conn->prepare("SELECT COUNT(*) as count FROM audit_log WHERE action = 'REGISTRATION_ATTEMPT' AND ip_address = ? AND created_at > ?");
$stmt->bind_param('ss', $ip, $cutoffTime);
$stmt->execute();
$stmt->bind_result($regAttempts);
$stmt->fetch();
$stmt->close();
// Allow max 5 registration attempts per IP per hour
if ($regAttempts >= 5) {
auditLog(null, 'REGISTRATION_RATE_LIMIT_EXCEEDED', 'users', null, ['ip' => $ip, 'attempts' => $regAttempts]);
echo json_encode(['status' => 'error', 'message' => 'Too many registration attempts. Please try again later.']);
exit();
}
// Validate and sanitize first name
$first_name = validateName($_POST['first_name'] ?? '');
if ($first_name === false) {
auditLog(null, 'REGISTRATION_INVALID_FIRST_NAME', 'users');
echo json_encode(['status' => 'error', 'message' => 'Invalid first name. Only letters, spaces, hyphens, and apostrophes allowed (2-100 characters).']);
exit();
}
// Validate and sanitize last name
$last_name = validateName($_POST['last_name'] ?? '');
if ($last_name === false) {
auditLog(null, 'REGISTRATION_INVALID_LAST_NAME', 'users');
echo json_encode(['status' => 'error', 'message' => 'Invalid last name. Only letters, spaces, hyphens, and apostrophes allowed (2-100 characters).']);
exit();
}
// Validate and sanitize phone number
$phone_number = validatePhoneNumber($_POST['phone_number'] ?? '');
if ($phone_number === false) {
auditLog(null, 'REGISTRATION_INVALID_PHONE', 'users');
echo json_encode(['status' => 'error', 'message' => 'Invalid phone number format.']);
exit();
}
// Validate email
$email = validateEmail($_POST['email'] ?? '');
if ($email === false) {
auditLog(null, 'REGISTRATION_INVALID_EMAIL', 'users');
echo json_encode(['status' => 'error', 'message' => 'Invalid email format.']);
exit();
}
$password = $_POST['password'] ?? '';
$password_confirm = $_POST['password_confirm'] ?? '';
// Validate password strength (minimum 8 characters, must contain uppercase, lowercase, number, special char)
if (strlen($password) < 8) {
echo json_encode(['status' => 'error', 'message' => 'Password must be at least 8 characters long.']);
exit();
}
if (!preg_match('/[A-Z]/', $password) || !preg_match('/[a-z]/', $password) ||
!preg_match('/[0-9]/', $password) || !preg_match('/[!@#$%^&*]/', $password)) {
echo json_encode(['status' => 'error', 'message' => 'Password must contain uppercase, lowercase, number, and special character (!@#$%^&*).']);
exit();
}
if ($password !== $password_confirm) {
echo json_encode(['status' => 'error', 'message' => 'Passwords do not match.']);
exit();
}
// Check if the email is already registered
$stmt = $conn->prepare('SELECT user_id FROM users WHERE email = ?');
$stmt->bind_param('s', $email);
$stmt->execute();
$stmt->store_result();
if ($stmt->num_rows > 0) {
auditLog(null, 'REGISTRATION_EMAIL_EXISTS', 'users', null, ['email' => $email]);
echo json_encode(['status' => 'error', 'message' => 'Email is already registered.']);
$stmt->close();
$conn->close();
exit();
}
$stmt->close();
// Hash password
$hashed_password = password_hash($password, PASSWORD_BCRYPT);
// Generate email verification token
$token = bin2hex(random_bytes(50));
// Prepare and execute query
$stmt = $conn->prepare('INSERT INTO users (first_name, last_name, phone_number, email, password, token, is_verified, type) VALUES (?, ?, ?, ?, ?, ?, ?, ?)');
$is_verified = 0; // Not verified
$type = 'credentials';
$stmt->bind_param('ssssssis', $first_name, $last_name, $phone_number, $email, $hashed_password, $token, $is_verified, $type);
if ($stmt->execute()) {
$newUser_id = $conn->insert_id;
processLegacyMembership($newUser_id);
auditLog($newUser_id, 'USER_REGISTRATION', 'users', $newUser_id, ['email' => $email]);
if (sendVerificationEmail($email, $first_name . ' ' . $last_name, $token)) {
sendEmail($_ENV['ADMIN_EMAIL'], '4WDCSA: New User Registration', $first_name . ' ' . $last_name . ' (' . $email . ') has just created an account using Credentials.');
echo json_encode(['status' => 'success', 'message' => 'Registration successful. Please check your email to verify your account.']);
} else {
echo json_encode(['status' => 'error', 'message' => 'Failed to send verification email.']);
}
} else {
auditLog(null, 'REGISTRATION_DATABASE_ERROR', 'users', null, ['email' => $email]);
echo json_encode(['status' => 'error', 'message' => 'Failed to register user.']);
}
$stmt->close();
}
$conn->close();