diff --git a/public/assets/css/style.css b/public/assets/css/style.css index 25d58f6..c4b6940 100755 --- a/public/assets/css/style.css +++ b/public/assets/css/style.css @@ -2112,6 +2112,24 @@ textarea.form-input { margin-bottom: 1.25rem; } +.auth-footer { + text-align: center; + margin-top: 1rem; + padding-top: 1rem; + border-top: 1px solid var(--border-color); + color: var(--text-muted); + font-size: 0.85rem; +} + +.auth-footer a { + color: var(--accent); + text-decoration: none; +} + +.auth-footer a:hover { + text-decoration: underline; +} + /* ========================================================================== Error Pages ========================================================================== */ diff --git a/routes/web.php b/routes/web.php index 67764cc..13892ec 100755 --- a/routes/web.php +++ b/routes/web.php @@ -23,6 +23,8 @@ $router->get('/dashboard/refresh-metrics', [DashboardController::class, 'refresh $router->get('/login', [AuthController::class, 'loginForm']); $router->post('/login', [AuthController::class, 'login'], [CSRFMiddleware::class, RateLimitMiddleware::class]); +$router->get('/register', [AuthController::class, 'registerForm']); +$router->post('/register', [AuthController::class, 'register'], [CSRFMiddleware::class]); $router->get('/logout', [AuthController::class, 'logout']); $router->get('/profile', [AuthController::class, 'profile'], [AuthMiddleware::class]); diff --git a/src/Controllers/AuthController.php b/src/Controllers/AuthController.php index 179b3c0..85939f4 100755 --- a/src/Controllers/AuthController.php +++ b/src/Controllers/AuthController.php @@ -80,6 +80,65 @@ class AuthController $this->view->redirect($intended); } + public function registerForm(): void + { + if (Session::has('user_id')) { + $this->view->redirect('/dashboard'); + } + + $this->view->setLayout('auth'); + $this->view->display('auth.register', [ + 'title' => 'Register - ServerManager', + ]); + } + + public function register(): void + { + $validator = new Validator(); + $rules = [ + 'username' => 'required|min:3|max:50', + 'email' => 'required|email', + 'password' => 'required|min:8', + 'confirm_password' => 'required|match:password', + ]; + + if (!$validator->validate($_POST, $rules)) { + Session::setFlash('error', $validator->getFirstError()); + $this->view->redirect('/register'); + } + + $username = $_POST['username']; + $email = $_POST['email']; + + $existing = $this->userModel->findByUsername($username); + if ($existing) { + Session::setFlash('error', 'Username already exists.'); + $this->view->redirect('/register'); + } + + $existingEmail = $this->userModel->findByEmail($email); + if ($existingEmail) { + Session::setFlash('error', 'Email already registered.'); + $this->view->redirect('/register'); + } + + $id = $this->userModel->create([ + 'username' => $username, + 'email' => $email, + 'password' => $_POST['password'], + 'role' => 'operator', + 'is_active' => 1, + ]); + + $this->auditService->log('user_registered', 'user', $id, [ + 'username' => $username, + 'role' => 'operator', + ]); + + Session::setFlash('success', 'Account created. You can now log in.'); + $this->view->redirect('/login'); + } + public function logout(): void { $this->auditService->log( diff --git a/views/auth/login.php b/views/auth/login.php index 2b6d609..f9f6c42 100755 --- a/views/auth/login.php +++ b/views/auth/login.php @@ -43,5 +43,8 @@ Sign In + diff --git a/views/auth/register.php b/views/auth/register.php new file mode 100644 index 0000000..a62ac17 --- /dev/null +++ b/views/auth/register.php @@ -0,0 +1,46 @@ +
+
+ +

ServerManager

+

Create your account

+
+ + +
+ + +
+ + +
+ + +
+ +
+ + +
+ +
+ +
+ + +
+
+ +
+ + +
+ +
+ +
+ + +
+