331 lines
11 KiB
PHP
331 lines
11 KiB
PHP
|
<?php
|
||
|
|
||
|
namespace Controllers;
|
||
|
|
||
|
class User
|
||
|
{
|
||
|
public function activate()
|
||
|
{
|
||
|
if (! $this->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 <a href="http://localhost' . port() . '/user/activate?id=' . $id .
|
||
|
'&active_token=' . $active_token . '">here</a> 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 <a href="http://localhost' . port() . '/user/email/verify' .
|
||
|
'?id=' . $_SESSION['id'] .
|
||
|
'&email=' . $_POST['email'] .
|
||
|
'&verify_token=' . $verify_token . '">here</a> 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;
|
||
|
}
|
||
|
}
|