diff --git a/app/controllers/AuthController.php b/app/controllers/AuthController.php index f188111..bc361b5 100644 --- a/app/controllers/AuthController.php +++ b/app/controllers/AuthController.php @@ -1,19 +1,68 @@ 'Log In' - ]; - $view->render('auth/signin', $data); + if($_SERVER['REQUEST_METHOD'] === 'POST') { + $email = $_POST['email'] ?? ''; + $password = $_POST['password'] ?? ''; + + $user = new User(); + $result = $user->login($email, $password); + + if($result === true) { + $this->redirect('/dashboard'); + } else { + $this->view('auth/signin', ['error' => $result]); + } + } else { + $this->view('auth/signin', ['title' => 'Log In']); + } } - + public function signup() { - $view = new View(); - $data = [ - 'title' => 'Register' - ]; - $view->render('auth/signup', $data); - } + if ($_SERVER['REQUEST_METHOD'] === 'POST') { + $username = $_POST['username'] ?? ''; + $email = $_POST['email'] ?? ''; + $password = $_POST['password'] ?? ''; + $password2 = $_POST['password-2'] ?? ''; + + // Perform validations + $validator = new Validator(); + + $validator->required('username', $username); + $validator->email('email', $email); + $validator->required('password', $password); + $validator->minLength('password', $password, 8); + $validator->alphanumeric('password', $password); + + if ($password !== $password2) { + $validator->errors()['password_confirmation'] = 'Passwords do not match.'; + } + + if (!$validator->passes()) { + $this->view('auth/signup', [ + 'error' => 'Please correct the errors below.', + 'validationErrors' => $validator->errors() ?: [], + ]); + return; + } + + $user = new User(); + $result = $user->register($username, $email, $password); + + if ($result === true) { + $this->redirect('/auth/signin'); + } else { + $this->view('auth/signup', [ + 'error' => $result, + 'validationErrors' => [], + ]); + } + } else { + $this->view('auth/signup', [ + 'title' => 'Register', + 'validationErrors' => [], + ]); + } + } } diff --git a/app/models/User.php b/app/models/User.php new file mode 100644 index 0000000..d860b58 --- /dev/null +++ b/app/models/User.php @@ -0,0 +1,45 @@ +db = Database::getInstance()->getConnection(); + + if ($this->db) { + error_log("Database connection established successfully."); + } else { + error_log("Failed to connect to the database."); + } + } + + public function register($username, $email, $password) { + // Check if email already exists + $stmt = $this->db->prepare("SELECT id FROM users WHERE email = ?"); + $stmt->bind_param("s", $email); + $stmt->execute(); + $result = $stmt->get_result(); + $stmt->close(); + + if ($result->num_rows > 0) { + return "Email is already registered"; + } + + // Hash the password + $hashedPassword = password_hash($password, PASSWORD_BCRYPT); + + $stmt = $this->db->prepare("INSERT INTO users (username, email, password, points, created_at) VALUES (?, ?, ?, 0, NOW())"); + $stmt->bind_param("sss", $username, $email, $hashedPassword); + + if ($stmt->execute()) { + return true; + } else { + return "Error: " . $stmt->error; + } + } +} + +?> + diff --git a/app/views/auth/signup.php b/app/views/auth/signup.php index d55a20f..b937291 100644 --- a/app/views/auth/signup.php +++ b/app/views/auth/signup.php @@ -1,11 +1,33 @@
-
- - - - - - - -
+ get('error')): ?> +
get('error') ?>
+ + +
+ + + get('validationErrors')['username'])): ?> + get('validationErrors')['username'] ?> + + + + + get('validationErrors')['email'])): ?> + get('validationErrors')['email'] ?> + + + + + get('validationErrors')['password'])): ?> + get('validationErrors')['password'] ?> + + + + + get('validationErrors')['password_confirmation'])): ?> + get('validationErrors')['password_confirmation'] ?> + + + +
diff --git a/config/.gitignore b/config/.gitignore new file mode 100644 index 0000000..abf5021 --- /dev/null +++ b/config/.gitignore @@ -0,0 +1 @@ +environment.php diff --git a/core/Controller.php b/core/Controller.php index e69de29..5715db7 100644 --- a/core/Controller.php +++ b/core/Controller.php @@ -0,0 +1,23 @@ +render($viewName, $data); + } +} diff --git a/core/Database.php b/core/Database.php new file mode 100644 index 0000000..8bbde03 --- /dev/null +++ b/core/Database.php @@ -0,0 +1,101 @@ +initializeConnection(); + $this->checkAndCreateDatabase(); + $this->checkAndCreateTables(); + } + + /** + * Get the singleton instance of the Database + * @return Database + */ + public static function getInstance() { + if (self::$instance === null) { + self::$instance = new Database(); + } + + return self::$instance; + } + + /** + * Get the active database connection + * @return mysqli + */ + public function getConnection() { + return $this->connection; + } + + /** + * Initialize the connection to the database + */ + private function initializeConnection() { + $this->connection = new mysqli(DB_HOST, DB_USER, DB_PASS); + + if ($this->connection->connect_error) { + die("Database connection failed: " . $this->connection->connect_error); + } + } + + /** + * Check and create the database if it doesn't exist + */ + private function checkAndCreateDatabase() { + $query = "CREATE DATABASE IF NOT EXISTS `" . DB_NAME . "`"; + if (!$this->connection->query($query)) { + die("Failed to create or access database: " . $this->connection->error); + } + + $this->connection->select_db(DB_NAME); + } + + /** + * Check and create required tables if they don't exist + */ + private function checkAndCreateTables() { + // Create users table + $usersTableQuery = "CREATE TABLE IF NOT EXISTS users ( + id INT AUTO_INCREMENT PRIMARY KEY, + username VARCHAR(50) NOT NULL, + email VARCHAR(100) NOT NULL UNIQUE, + password VARCHAR(255) NOT NULL, + points INT DEFAULT 0, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ) ENGINE=InnoDB;"; + + if (!$this->connection->query($usersTableQuery)) { + die("Failed to create users table: " . $this->connection->error); + } + + // Create progress table + $progressTableQuery = "CREATE TABLE IF NOT EXISTS progress ( + id INT AUTO_INCREMENT PRIMARY KEY, + user_id INT NOT NULL, + habit_id INT NOT NULL, + date DATE NOT NULL, + status ENUM('Done', 'Pending') DEFAULT 'Pending', + FOREIGN KEY (user_id) REFERENCES users(id) + ) ENGINE=InnoDB;"; + + if (!$this->connection->query($progressTableQuery)) { + die("Failed to create progress table: " . $this->connection->error); + } + + // Add more table creation logic as needed + } + + /** + * Prevent cloning of the singleton instance + */ + private function __clone() {} + + /** + * Prevent unserialization of the singleton instance + */ + public function __wakeup() {} + +} diff --git a/core/Validator.php b/core/Validator.php new file mode 100644 index 0000000..ed5bdc5 --- /dev/null +++ b/core/Validator.php @@ -0,0 +1,55 @@ +errors[$field] = $message ?? "$field is required."; + } + } + + /** + * Check if a field meets minimum length + */ + public function minLength($field, $value, $length, $message = null) { + if (strlen($value) < $length) { + $this->errors[$field] = $message ?? "$field must be at least $length characters."; + } + } + + /** + * Check if a field contains letters and numbers + */ + public function alphanumeric($field, $value, $message = null) { + if (!preg_match('/^(?=.*[a-zA-Z])(?=.*\d).+$/', $value)) { + $this->errors[$field] = $message ?? "$field must contain letters and numbers."; + } + } + + /** + * Validate an email + */ + public function email($field, $value, $message = null) { + if (!filter_var($value, FILTER_VALIDATE_EMAIL)) { + $this->errors[$field] = $message ?? "Invalid email format."; + } + } + + /** + * Get validation errors + */ + public function errors() { + return $this->errors; + } + + /** + * Check if validation passed + */ + public function passes() { + return empty($this->errors); + } +} diff --git a/core/View.php b/core/View.php index 4cc6fb9..03a79ed 100644 --- a/core/View.php +++ b/core/View.php @@ -1,10 +1,11 @@ data = $data; // Capture the view content ob_start(); @@ -12,6 +13,13 @@ class View $content = ob_get_clean(); // Include the base layout and inject the view content - require_once views . "layouts/$layout.php"; + require_once views . "layouts/$layout.php"; + } + + /** + * Safely get a value from the data array + */ + public function get($key) { + return $this->data[$key] ?? null; } } diff --git a/public/index.php b/public/index.php index cf5aa12..eb90184 100644 --- a/public/index.php +++ b/public/index.php @@ -7,10 +7,17 @@ ini_set('error_log', '../storage/logs/error_log.log'); define('models', __DIR__ . '/../app/models/'); define('views', __DIR__ . '/../app/views/'); define('controllers', __DIR__ . '/../app/controllers/'); +define('config', __DIR__ . '/../config/'); +require_once config . 'environment.php'; + +require_once '../core/Validator.php'; require_once '../core/Router.php'; require_once '../core/View.php'; require_once '../core/Controller.php'; +require_once '../core/Database.php'; + +require_once models . 'User.php'; // Initialize router $router = new Router();