Repository navigation
Expand file tree
/
Copy pathsignup.php
More file actions
136 lines (115 loc) · 6.16 KB
/
Copy pathsignup.php
File metadata and controls
136 lines (115 loc) · 6.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
<?php
require_once __DIR__ . '/autoload.php';
use App\Core\Bootstrap;
use App\Helpers\Html;
use App\Helpers\Layout;
use App\Helpers\SecurityHelper;
Bootstrap::init();
if (isset($_SESSION['user_id'])) {
header("Location: dashboard.php");
exit();
}
$error = "";
$success = "";
if ($_SERVER["REQUEST_METHOD"] == "POST") {
SecurityHelper::verifyCsrfToken($_POST['csrf_token'] ?? '');
$name = trim($_POST['name'] ?? '');
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
$family_name = trim($_POST['family_name'] ?? '');
$password = (string) ($_POST['password'] ?? '');
// Rate Limiting / Cooldown
$last_attempt = $_SESSION['last_signup_attempt'] ?? 0;
if (time() - $last_attempt < 5) { // 5 second cooldown for registration
$error = "Too many attempts. Please slow down.";
} elseif (empty($name) || !$email || empty($family_name) || $password === '') {
$error = "Please fill in all fields correctly.";
} else {
// Server-side password strength validation
$error = SecurityHelper::validatePassword($password) ?? '';
}
$_SESSION['last_signup_attempt'] = time();
if ($error === '') {
try {
// Check if email exists
$stmt = $pdo->prepare("SELECT COUNT(*) FROM users WHERE email = ?");
$stmt->execute([$email]);
if ($stmt->fetchColumn() > 0) {
$error = "Email already registered.";
} else {
$pdo->beginTransaction();
// 1. Create Tenant
$stmt = $pdo->prepare("INSERT INTO tenants (family_name) VALUES (?)");
$stmt->execute([$family_name]);
$tenant_id = $pdo->lastInsertId();
// 2. Create User as Family Admin
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
$stmt = $pdo->prepare("INSERT INTO users (name, email, password, role, tenant_id, permission) VALUES (?, ?, ?, 'family_admin', ?, 'edit')");
$stmt->execute([$name, $email, $hashed_password, $tenant_id]);
// 3. Optional: Create default User Preferences for the new user
$new_user_id = $pdo->lastInsertId();
$stmt = $pdo->prepare("INSERT INTO user_preferences (user_id, base_currency) VALUES (?, 'AED')");
$stmt->execute([$new_user_id]);
$pdo->commit();
$success = "Registration successful! You can now sign in.";
}
} catch (Exception $e) {
if ($pdo->inTransaction()) {
$pdo->rollBack();
}
error_log("Signup Error: " . $e->getMessage());
$error = "An error occurred during registration.";
}
}
}
Layout::authHeader('Sign Up');
?>
<h2 class="auth-title text-center">Join the Family</h2>
<p class="auth-subtitle text-center">Create your family account and start tracking.</p>
<?php if ($error): ?>
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<?php echo Html::e($error); ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php endif; ?>
<?php if ($success): ?>
<div class="alert alert-success alert-dismissible fade show" role="alert">
<?php echo Html::e($success); ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php endif; ?>
<form method="POST">
<input type="hidden" name="csrf_token" value="<?php echo SecurityHelper::generateCsrfToken(); ?>">
<div class="form-floating mb-3">
<input type="text" class="form-control" id="nameInput" name="name" placeholder="John Doe"
required maxlength="100" value="<?php echo Html::e($error ? ($_POST['name'] ?? '') : ''); ?>">
<label for="nameInput">Full Name</label>
</div>
<div class="form-floating mb-3">
<input type="email" class="form-control" id="emailInput" name="email"
placeholder="name@example.com" required autocomplete="username"
value="<?php echo Html::e($error ? ($_POST['email'] ?? '') : ''); ?>">
<label for="emailInput">Email address</label>
</div>
<div class="form-floating mb-3">
<input type="text" class="form-control" id="familyInput" name="family_name"
placeholder="The Does" required maxlength="100"
value="<?php echo Html::e($error ? ($_POST['family_name'] ?? '') : ''); ?>">
<label for="familyInput">Family Name (e.g., The Ibrahim Family)</label>
</div>
<div class="mb-4">
<div class="form-floating">
<input type="password" class="form-control" id="passwordInput" name="password"
placeholder="Password" required minlength="8" maxlength="72" autocomplete="new-password"
data-oninput="checkPasswordStrength" data-args="<?php echo Html::args('$value'); ?>">
<label for="passwordInput">Password</label>
</div>
<?php echo Layout::passwordRequirements(); ?>
</div>
<button type="submit" class="btn btn-primary w-100 py-3 mb-3">Create Family Account</button>
<div class="text-center">
<span class="text-muted small">Already have an account? </span>
<a href="index.php" class="text-decoration-none small fw-bold"
style="color: var(--primary-color);">Sign in</a>
</div>
</form>
<?php Layout::authFooter(); ?>