hasToken()) { header('Location: /'); return false; } if ($id = $this->getUserId()) { $sql = 'DELETE FROM active_tokens WHERE id=?'; $query = db()->prepare($sql); $query->execute([$id]); $messages = ['Your account has been activated.']; return view('user.login', ['messages' => $messages]); } header('HTTP/1.0 403 Forbidden'); die(); return false; } public function showCreate() { return view('user.register'); } public function showLogin() { return view('user.login'); } public function showSettings() { return view('user.settings'); } public function show($name, $page = '1') { $db = db(); $offset = ($page >= 1) ? ($page - 1) : 0; $offset *= 10; $sql = 'SELECT * FROM posts WHERE author IN ( ' . 'SELECT name FROM users WHERE name=? ) ' . 'ORDER BY create_at DESC LIMIT ?,10'; $query = $db->prepare($sql); $query->bindValue(1, $name); $query->bindValue(2, $offset, \PDO::PARAM_INT); $query->execute(); $posts = $query->fetchAll(\PDO::FETCH_CLASS, 'Core\\Record'); $offset += 10; $query->bindValue(2, $offset, \PDO::PARAM_INT); $query->execute(); $next = $query->fetchAll(\PDO::FETCH_CLASS, 'Core\\Record'); $sql = 'SELECT id, keyword, COUNT(id) AS num_of_posts FROM (' . 'tags JOIN post_tag ON id=tag_id) GROUP BY id ORDER BY keyword'; $query = $db->prepare($sql); $query->execute(); $tags = $query->fetchAll(\PDO::FETCH_CLASS, 'Core\\Record'); $is_last = count($next) == 0 ? true : false; return view('post.index', [ 'posts' => $posts, 'tags' => $tags, 'page' => $page, 'is_last' => $is_last, 'pager_uri' => preg_replace('/\/\d+$/', '', $_SERVER['REQUEST_URI']) ]); } public function create() { if (! $this->validator()) { header('Location: /user/register'); return false; } $active_token = \Illuminate\Support\Str::random(40); $id = $this->setUser($active_token); send_mail([ 'email' => $_POST['email'], 'title' => '[Blog App] Active Your Account!', 'body' => 'Click here to activate.' ]); $sql = 'SET global event_scheduler = 1;' . 'DROP EVENT IF EXISTS clear_unactive_user_:id;' . 'CREATE EVENT clear_unactive_user_:id ' . 'ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR ' . 'DO DELETE FROM users WHERE id=:id AND EXISTS (' . 'SELECT * FROM active_tokens WHERE id=:id)'; $query = db()->prepare($sql); $query->bindValue(':id', $id, \PDO::PARAM_INT); $query->execute(); $message = 'Check your email inbox. We\'ve sent you an activation mail.'; return view('redirect', ['message' => $message]); } public function update() { $validation = []; $usernameGiven = ($_POST['username'] != $_SESSION['username']); $passwordGiven = (! empty(trim($_POST['password']))); $emailGiven = ($_POST['email'] != $_SESSION['email']); if ($usernameGiven) { $validation['username'] = valid_username($_POST['username']); } if ($passwordGiven) { $validation['password'] = valid_password( $_POST['password'], $_POST['confirm-password'] ); } if ($emailGiven) { $validation['email'] = valid_email($_POST['email']); } if (count($validation) != 0 && ! $this->validator($validation)) { header('Location: /user/settings'); return false; } return $this->updateUser($usernameGiven, $passwordGiven, $emailGiven); } public function delete() { $sql = 'DELETE FROM users WHERE id=?'; $query = db()->prepare($sql); $query->execute([$_SESSION['id']]); return $this->logout(); } public function verifyEmail() { $db = db(); $sql = 'SELECT token FROM verify_tokens WHERE id=?'; $query = $db->prepare($sql); $query->execute([$_GET['id']]); $verify_token = $query->fetchAll(\PDO::FETCH_COLUMN, 0); if (count($verify_token) != 0) { $verify_token = $verify_token[0]; if ($verify_token == $_GET['verify_token']) { $sql = 'UPDATE users SET email=? WHERE id=?'; $query = $db->prepare($sql); $query->execute([$_GET['email'], $_GET['id']]); $sql = 'DELETE FROM verify_tokens WHERE id=?'; $query = $db->prepare($sql); $query->execute([$_GET['id']]); $_SESSION['messages'] = ['E-mail updated.']; $_SESSION['email'] = $_GET['email']; header('Location: /user/settings'); return false; } } header('HTTP/1.0 403 Forbidden'); die(); return false; } public function login() { $sql = 'SELECT u.id, u.name, u.email, u.password ' . 'FROM users AS u WHERE name=? AND NOT EXISTS (' . 'SELECT * FROM active_tokens AS t WHERE u.id=t.id)'; $query = db()->prepare($sql); $query->execute([$_POST['username']]); $user = $query->fetchAll(\PDO::FETCH_CLASS, 'Core\\Record'); if (count($user) != 0 && password_verify($_POST['password'], trim($user[0]->password)) ) { $_SESSION['is_auth'] = true; $_SESSION['id'] = $user[0]->id; $_SESSION['username'] = $user[0]->name; $_SESSION['email'] = $user[0]->email; header('Location: /'); return false; } $_SESSION['errors'] = ['Incorrect username or password.']; $_SESSION['inputs'] = [ 'username' => $_POST['username'] ]; header('Location: /user/login'); return false; } public function logout() { session_unset(); session_destroy(); header('Location: /'); return false; } private function hasToken() { if (isset($_GET['id']) && isset($_GET['active_token']) ) { return true; } return false; } private function getUserId() { $sql = 'SELECT u.id FROM (users AS u ' . 'JOIN active_tokens AS t ON u.id=t.id) ' . 'WHERE u.id=? AND t.token=?'; $query = db()->prepare($sql); $query->execute([$_GET['id'], $_GET['active_token']]); $user = $query->fetchAll(\PDO::FETCH_CLASS, 'Core\\Record'); if (count($user) != 0) { return $user[0]->id; } return null; } private function validator($validation = []) { if (count($validation) == 0) { $validation = [ 'username' => valid_username($_POST['username']), 'email' => valid_email($_POST['email']), 'password' => valid_password( $_POST['password'], $_POST['confirm-password'] ) ]; } $errors = []; foreach ($validation as $input => $result) { if (! $result) { array_push($errors, "Invalid $input."); } } if (count($errors) != 0) { $_SESSION['errors'] = $errors; if (isset($_POST['username'])) { $_SESSION['inputs'] = [ 'username' => $_POST['username'], 'email' => $_POST['email'] ]; } return false; } return true; } private function setUser($active_token) { $sql = 'INSERT INTO users VALUES (NULL, ?, ?, ?)'; $db = db(); $query = $db->prepare($sql); $query->execute([ $_POST['username'], $_POST['email'], password_hash($_POST['password'], PASSWORD_DEFAULT) ]); $id = $db->lastInsertId(); $sql = 'INSERT INTO active_tokens VALUES (:id, :token)'; $query = $db->prepare($sql); $query->bindValue(':id', $id, \PDO::PARAM_INT); $query->bindValue(':token', $active_token); $query->execute(); return $id; } private function updateUser($usernameGiven, $passwordGiven, $emailGiven) { $db = db(); if ($usernameGiven) { $sql = 'UPDATE users SET name=? WHERE id=?'; $query = $db->prepare($sql); $query->execute([$_POST['username'], $_POST['id']]); $_SESSION['messages'][] = 'Username updated.'; $_SESSION['username'] = $_POST['username']; } if ($passwordGiven) { $sql = 'UPDATE users SET password=? WHERE id=?'; $query = $db->prepare($sql); $query->execute([ password_hash($_POST['password'], PASSWORD_DEFAULT), $_POST['id'] ]); $_SESSION['messages'][] = 'Password updated.'; } if ($emailGiven) { if (! $this->requested($_POST['id'])) { $verify_token = \Illuminate\Support\Str::random(40); $sql = 'INSERT INTO verify_tokens VALUES (:id, :token)'; $query = $db->prepare($sql); $query->bindValue(':id', $_POST['id'], \PDO::PARAM_INT); $query->bindValue(':token', $verify_token); $query->execute(); send_mail([ 'email' => $_POST['email'], 'title' => '[Blog App] Verify Your E-mail!', 'body' => 'Click here to verify.' ]); $sql = 'SET global event_scheduler = 1;' . 'DROP EVENT IF EXISTS clear_unverify_email_:id;' . 'CREATE EVENT clear_unverify_email_:id ' . 'ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR ' . 'DO DELETE FROM verify_tokens WHERE id=:id'; $query = $db->prepare($sql); $query->bindValue(':id', $_POST['id'], \PDO::PARAM_INT); $query->execute(); } $_SESSION['messages'][] = 'Check your email inbox. ' . 'We\'ve sent you an verification mail ' . 'for email updating request.'; } header('Location: /user/settings'); return false; } private function requested($id) { $sql = 'SELECT * FROM verify_tokens WHERE id=?'; $query = db()->prepare($sql); $query->execute([$id]); $verify_token = $query->fetchAll(\PDO::FETCH_CLASS, 'Core\\Record'); if (count($verify_token) != 0) { return true; } return false; } }